You've already forked gnatstudio
mirror of
https://github.com/AdaCore/gnatstudio.git
synced 2026-02-12 12:42:33 -08:00
272 lines
7.8 KiB
Python
272 lines
7.8 KiB
Python
"""
|
|
This file provides support for displaying Ada expanded code as generated by
|
|
GNAT (-gnatGL switch).
|
|
"""
|
|
|
|
|
|
import os
|
|
import distutils.dep_util
|
|
import GPS
|
|
from gs_utils import in_ada_file, interactive
|
|
|
|
|
|
def create_dg(f, str):
|
|
res = open(f, "w")
|
|
first = (
|
|
str.find("\n", str.find("\n", str.find("Source recreated from tree")) + 1) + 2
|
|
)
|
|
|
|
if first > 2:
|
|
last = str.find("Source recreated from tree", first)
|
|
res.write(str[first : last - 1])
|
|
|
|
res.close()
|
|
|
|
|
|
expanded_code_marks = {}
|
|
# A dictionary that associates a source filename with a list of marks
|
|
|
|
highlighting = "Editor code annotations"
|
|
# Name of the style we want to apply for expanded code
|
|
|
|
|
|
def subprogram_bounds(cursor):
|
|
"""Return the first and last line of the current subprogram, and (0,0) if
|
|
the current subprogram could not be determined."""
|
|
blocks = {
|
|
"CAT_PROCEDURE": 1,
|
|
"CAT_FUNCTION": 1,
|
|
"CAT_ENTRY": 1,
|
|
"CAT_PROTECTED": 1,
|
|
"CAT_TASK": 1,
|
|
"CAT_PACKAGE": 1,
|
|
}
|
|
|
|
if cursor.block_type() == "CAT_UNKNOWN":
|
|
return 0, 0
|
|
|
|
min = cursor.buffer().beginning_of_buffer()
|
|
while not (cursor.block_type() in blocks) and cursor > min:
|
|
cursor = cursor.block_start() - 1
|
|
|
|
if cursor > min:
|
|
return cursor.block_start_line(), cursor.block_end_line()
|
|
else:
|
|
return 0, 0
|
|
|
|
|
|
def clear_dg(source_filename):
|
|
"""Clear dg information for filename"""
|
|
global expanded_code_marks
|
|
|
|
if source_filename in expanded_code_marks:
|
|
# Remove special lines
|
|
|
|
srcbuf = GPS.EditorBuffer.get(GPS.File(source_filename))
|
|
|
|
for mark, lines in expanded_code_marks[source_filename]:
|
|
srcbuf.remove_special_lines(mark, lines)
|
|
|
|
# Empty entry in the dictionary
|
|
|
|
expanded_code_marks[source_filename] = []
|
|
|
|
|
|
def edit_dg(dg, source_filename, line, for_subprogram, in_external_editor):
|
|
global highlighting, expanded_code_marks
|
|
|
|
# If we are showing the dg in an external editor, simply open this editor
|
|
# and jump to the line
|
|
if in_external_editor:
|
|
buf = GPS.EditorBuffer.get(GPS.File(dg))
|
|
loc = buf.at(1, 1)
|
|
try:
|
|
(frm, to) = loc.search("^-- " + repr(line) + ":", regexp=True)
|
|
if frm:
|
|
buf.current_view().goto(frm.forward_line(1))
|
|
except Exception:
|
|
pass
|
|
|
|
return
|
|
|
|
clear_dg(source_filename)
|
|
|
|
srcbuf = GPS.EditorBuffer.get(GPS.File(source_filename))
|
|
|
|
if for_subprogram:
|
|
(block_first, block_last) = subprogram_bounds(srcbuf.current_view().cursor())
|
|
else:
|
|
(block_first, block_last) = (0, 0)
|
|
|
|
# Read the text of the dg file
|
|
f = open(dg)
|
|
txt = f.read()
|
|
f.close()
|
|
|
|
current_code = []
|
|
current_line = 1
|
|
lines = 0
|
|
|
|
for line in txt.split("\n"):
|
|
if line.startswith("-- "):
|
|
if current_code:
|
|
if block_first == 0 or (block_first < current_line <= block_last):
|
|
mark = srcbuf.add_special_line(
|
|
current_line + 1, "\n".join(current_code), highlighting
|
|
)
|
|
|
|
# Add mark to the list of marks
|
|
|
|
mark_num = (mark, len(current_code))
|
|
|
|
if source_filename in expanded_code_marks:
|
|
expanded_code_marks[source_filename] += [mark_num]
|
|
else:
|
|
expanded_code_marks[source_filename] = [mark_num]
|
|
elif current_line == block_last:
|
|
break
|
|
current_line = int(line[3 : line.find(":")])
|
|
current_code = []
|
|
else:
|
|
if line != "":
|
|
lines += 1
|
|
current_code.append(line)
|
|
# The above algorithm only displays the expanded lines after finding a line
|
|
# of code => it will lost the expanded lines located after the last line
|
|
# of the current block.
|
|
if current_code:
|
|
if block_first == 0 or (current_line <= block_last):
|
|
mark = srcbuf.add_special_line(
|
|
current_line + 1, "\n".join(current_code), highlighting
|
|
)
|
|
|
|
# Add mark to the list of marks
|
|
|
|
mark_num = (mark, len(current_code))
|
|
|
|
if source_filename in expanded_code_marks:
|
|
expanded_code_marks[source_filename] += [mark_num]
|
|
else:
|
|
expanded_code_marks[source_filename] = [mark_num]
|
|
|
|
|
|
# noinspection PyUnusedLocal
|
|
def on_exit(process, status, full_output):
|
|
if status:
|
|
GPS.Console("Messages").write(process.get_result(), mode="error")
|
|
else:
|
|
create_dg(process.dg, full_output)
|
|
edit_dg(
|
|
process.dg,
|
|
process.source_filename,
|
|
process.line,
|
|
process.for_subprogram,
|
|
process.in_external_editor,
|
|
)
|
|
|
|
|
|
def show_gnatdg(for_subprogram=False, in_external_editor=False):
|
|
"""Show the .dg file of the current file"""
|
|
GPS.MDI.save_all(False)
|
|
context = GPS.current_context()
|
|
local_file = context.file().path
|
|
file = context.file().name("Build_Server")
|
|
line = context.location().line()
|
|
|
|
try:
|
|
if context.project():
|
|
list_dir = context.project().object_dirs(False)
|
|
prj = ' -P """' + GPS.Project.root().file().name("Build_Server") + '"""'
|
|
else:
|
|
list_dir = GPS.Project.root().object_dirs(False)
|
|
prj = " -a"
|
|
except Exception:
|
|
GPS.Console("Messages").write(
|
|
"Could not obtain project information for this file"
|
|
)
|
|
return
|
|
|
|
if list_dir:
|
|
objdir = list_dir[0]
|
|
else:
|
|
objdir = GPS.get_tmp_dir()
|
|
GPS.Console("Messages").write(
|
|
"Could not find an object directory for %s, reverting to %s"
|
|
% (file, objdir)
|
|
)
|
|
|
|
dg = os.path.join(objdir, os.path.basename(local_file)) + ".dg"
|
|
|
|
if distutils.dep_util.newer(local_file, dg):
|
|
file_name = '"""%s"""' % file
|
|
scenario = GPS.Project.root().scenario_variables_cmd_line("-X")
|
|
cmd = "gprbuild -q %s -f -c -u -gnatcdx -gnatws -gnatGL" % prj
|
|
cmd += " " + file_name
|
|
if scenario:
|
|
cmd += " " + scenario
|
|
|
|
GPS.Console("Messages").write("Generating " + dg + "...\n")
|
|
proc = GPS.Process(cmd, on_exit=on_exit, remote_server="Build_Server")
|
|
proc.source_filename = local_file
|
|
proc.dg = dg
|
|
proc.line = line
|
|
proc.for_subprogram = for_subprogram
|
|
proc.in_external_editor = in_external_editor
|
|
else:
|
|
edit_dg(dg, local_file, line, for_subprogram, in_external_editor)
|
|
|
|
|
|
#################################
|
|
# Register the contextual menus #
|
|
#################################
|
|
|
|
|
|
@interactive(
|
|
"Ada",
|
|
in_ada_file,
|
|
contextual="Expanded code/Show subprogram",
|
|
name="show expanded code for subprogram",
|
|
contextual_group=GPS.Contextual.Group.EXTRA_INFORMATION,
|
|
)
|
|
def show_gnatdg_subprogram():
|
|
"""Show the expanded code of the current subprogram"""
|
|
show_gnatdg(True)
|
|
|
|
|
|
@interactive(
|
|
"Ada",
|
|
in_ada_file,
|
|
contextual="Expanded code/Show entire file",
|
|
name="show expanded code for file",
|
|
contextual_group=GPS.Contextual.Group.EXTRA_INFORMATION,
|
|
)
|
|
def show_gnatdg_file():
|
|
"""Show the .dg file of the current file"""
|
|
show_gnatdg(False)
|
|
|
|
|
|
@interactive(
|
|
"Ada",
|
|
in_ada_file,
|
|
contextual="Expanded code/Show in separate editor",
|
|
name="show expanded code in separate editor",
|
|
contextual_group=GPS.Contextual.Group.EXTRA_INFORMATION,
|
|
)
|
|
def show_gnatdg_separate_editor():
|
|
"""Show the expanded code of the current subprogram"""
|
|
show_gnatdg(False, True)
|
|
|
|
|
|
@interactive(
|
|
"Ada",
|
|
in_ada_file,
|
|
contextual="Expanded code/Clear",
|
|
name="clear expanded code",
|
|
contextual_group=GPS.Contextual.Group.EXTRA_INFORMATION,
|
|
)
|
|
def clear_expanded_code():
|
|
"""Show the expanded code of the current subprogram"""
|
|
|
|
context = GPS.current_context()
|
|
clear_dg(context.file().path)
|