1
# This file adds support for AdaControl
3
# If you are using GPS 3.x, change "true" to "false" in the next line:
6
#######################################################################
7
import GPS, os, glob, re, sets
9
# Clean-up various windows before running AdaControl
11
GPS.MDI.save_all (GPS.Preference ("force-save").get())
13
GPS.Locations.remove_category (C)
14
GPS.MDI.get("Messages").raise_window()
16
# Clean-up after running AdaControl
18
if GPS.Preference ("delete-trees").get():
19
del_tree (confirm=False)
21
# Get the command name for AdaControl
23
result = GPS.Project.root().get_attribute_as_string("compiler_command", "Ide", "AdaControl")
29
# Builds the options string
30
# Options -f and @ are defined as switches for the convenience of the user
31
# but they are actually passed as explicit parameters depending on the way
32
# Adacontrol is launched. We must therefore remove these options from the
33
# switches string provided by GPS.
34
# Similarly, the -o option depends on the setting of the (pseudo) switch
37
opt_list=GPS.Project.root().get_tool_switches_as_list("AdaControl")
46
result= result + ' ' + O
52
elif O == "-F" and gps:
59
result= result + ' ' + O
65
result= result + ' ' + O
69
GPS.MDI.dialog ("Result file is not defined, please set it in Project properties/Switches/AdaControl")
71
elif len (glob.glob(outfile)) != 0:
72
if GPS.MDI.yes_no_dialog ("File " + outfile + " exists, override?"):
73
result= result + " -w"
77
result = result + " --"
78
for I in GPS.Project.dependencies (GPS.Project.root(), recursive=True) :
79
for J in GPS.Project.source_dirs(I) :
80
result=result + ' -I' + J.replace("\\", "/")
85
# Make a '+'-separated list of all units in the project
87
files=GPS.Project.root().sources()
91
if GPS.File.language (f) == "ada":
92
name= os.path.splitext(os.path.basename (f.name()))[0]
93
name= re.sub("-", ".", name)
95
result= result + '+' + name
99
# Compare two source references
100
# If the references are the same, keep the original order
101
# (for the case of error messages that span several lines)
103
"Compare SLOC references (file:line:col)"
107
# Presumably, we have a "C:"...
112
if len(ls) < 5+Offset and len(rs) < 3+Offset:
113
# No reference =>Keep order
115
if len(ls) < 5+Offset:
116
# Reference only in r: put references ahead
118
if len(rs) < 5+Offset:
119
# Reference only in l: put references ahead
122
if ls[0+Offset] != rs [0+Offset]:
123
return cmp (ls[0+Offset], rs[0+Offset])
124
if ls[1+Offset] != rs[1+Offset]:
125
return cmp (int(ls[1+Offset]), int(rs[1+Offset]))
126
return cmp (int(ls[2+Offset]), int(rs[2+Offset]))
128
# Sort and parse the result of running Adacontrol
131
list=output.splitlines()
134
category = "Adacontrol"
135
adactl_cats = sets.Set()
138
if re.match ("^(.+):(\\d+):(\\d+): (Found:|Error:|Parameter:|Syntax:).*$", Mess):
139
# Regular AdaCtl message
140
if GPS.Preference ("separate-rules").get():
141
category = re.sub (r"^.+:\d+:\d+: \w+: (.*?):.*$", r"\1", Mess)
142
adactl_cats.add (category)
143
GPS.Locations.parse (Mess,
145
"^(.+):(\\d+):(\\d+): (((Found:)|(Error:|Parameter:|Syntax:)).*)$",
150
elif re.match ("^(\\d+: )?(Found:|Error:|Parameter:|Syntax:).*$", Mess):
151
# AdaCtl message without location, or just a column location (syntax error in interactive command)
152
if GPS.Preference ("separate-rules").get():
153
category = re.sub (r"^(\\d+: )?\w+: (.*?):.*$", r"\2", Mess)
154
adactl_cats.add (category)
155
message = re.sub (r"^(\\d+: )?(\w+: ).*?:(.*)$", r"\2", Mess) + re.sub (r"^(\\d+: )?\w+: .*?:(.*)$", r"\2", Mess)
157
GPS.Locations.add (category, GPS.File("none"), 1, 1, message)
159
# Always an exception, since file "none" does not exist (presumably)
161
elif re.match (r"^.*: ((Check: \d+, Search: \d+, Count: \d+)|(not triggered))$", Mess):
163
adactl_cats.add ("Counts summary")
165
GPS.Locations.add ("Counts summary", GPS.File(re.sub(r"^(.*): ((Check: \d+, Search: \d+, Count: \d+)|(not triggered))$", r"\1", Mess)), 1, 1, Mess)
167
# Always an exception, since file does not exist
170
# Assume it is a compilation message
172
for Other in list[max (0,pos-5):pos-1]:
177
GPS.Locations.parse (Mess, "Compilation")
178
adactl_cats.add ("Compilation")
180
# Ask for confirmation, then delete tree files (and possibly .ali files)
181
def del_tree (confirm):
183
ali_also = GPS.Preference ("delete-ali").get()
188
if not confirm or GPS.MDI.yes_no_dialog ("Remove all tree "
190
+ "files from " + dir + "?"):
191
for I in glob.glob (os.path.join (dir, "*.adt")):
194
for I in glob.glob (os.path.join (dir, "*.ali")):
197
# Create adp file from project
199
name= GPS.Project.file(GPS.Project.root()).name()[:-4]+".adp"
200
if GPS.MDI.yes_no_dialog ("Create " + name + "?"):
202
for I in [GPS.Project.root()] + GPS.Project.dependencies (GPS.Project.root()) :
203
for J in GPS.Project.source_dirs(I) :
204
f.write ("src_dir=" + J + "\n")
205
for J in GPS.Project.object_dirs(I) :
206
f.write ("obj_dir=" + J + "\n")
208
print ("Project file " + name + " created")
210
# Return the units file
211
def get_units_file ():
212
opt_list=GPS.Project.root().get_tool_switches_as_list("AdaControl")
218
# Is the units file defined?
219
def units_file_defined ():
220
if get_units_file() == "":
226
def get_rules_file ():
227
opt_list=GPS.Project.root().get_tool_switches_as_list("AdaControl")
236
# Is the rules file defined?
237
def rules_file_defined ():
238
if get_rules_file() == "":
244
# rules = "ask" | "file"
245
# files = "current" | "list" | "project" | "" (means: depending on button definition)
246
def run (rules, files):
247
global previous_command
250
tmp = GPS.Preference ("button-target").get();
251
if tmp == "Current File":
253
elif tmp == "Root Project":
255
else: # Units from list
258
if files == "current":
260
win = GPS.current_context().file()
262
GPS.MDI.dialog ("no active window")
264
if win.language() != "ada" :
265
GPS.MDI.dialog ("active window is not Ada")
267
files_param = win.name()
268
elif files == "list":
269
files_param = "@" + get_units_file()
271
files_param = Project_units()
274
value=GPS.MDI.input_dialog ("Interactive run", "Command(s)=" + previous_command)
275
if value != [] and value [0] != "":
276
previous_command= value[0]
277
rules_param = "-l \"" + re.sub('"', '~', previous_command) + "\""
281
if rules_file_defined () == "false" :
282
GPS.MDI.dialog ("no rules file defined")
284
rules_param = "-f " + get_rules_file()
288
GPS.execute_asynchronous_action ("AdaControl", command_name(), rules_param + ' ' + files_param + ' ' + options() )
290
GPS.execute_action ("AdaControl", command_name(), rules_param + ' ' + files_param + ' ' + options() )
292
# Displays help for a given rule, and launcher
293
def display_help (proc, status, mess):
294
GPS.MDI.dialog (mess)
296
def Help_On_Rule (self):
297
if GPS.Preference ("help-format").get() == "Pop-up":
298
GPS.Process ("adactl -h " + self.name, on_exit = display_help)
300
GPS.HTML.browse ("adacontrol_ug.html", self.name, navigation = False)
302
# Add a new entry to the "help on rule" menu
303
def Add_Rule_Menu (self, matched, unmatched):
304
entry=GPS.Menu.create ("Help/AdaControl/Help on rule/" + matched, Help_On_Rule);
307
# Hook on preference changes
308
def on_pref_changed (H):
309
if GPS.Preference ("delete-ali").get():
310
DelTree_Menu.rename("Delete Tree and .ali Files")
312
DelTree_Menu.rename("Delete Tree Files")
314
################################################################
315
# Initialization actions
318
adactl_cats= sets.Set()
321
# Colors used in highliting the results
322
GPS.Editor.register_highlighting ("Adactl_check", "red", "True")
323
GPS.Editor.register_highlighting ("Adactl_found", "orange", "True")
325
# We must define the buttons here in order to compute the place of the icons from
326
# the GPS directory, but we cannot call GPS.Button(), because it does not allow
327
# the declaration of an icon (hence we use parse_xml).
329
<button action='Check_Unknown_File'>
330
<title>Launch AdaControl (rules file)</title>
332
+ GPS.get_system_dir()
333
+ """share/gps/plug-ins/adactl.gif</pixmap>
335
<button action='Check_Unknown_Ask'>
336
<title>Launch AdaControl (interactive)</title>
338
+ GPS.get_system_dir()
339
+ """share/gps/plug-ins/adactl_ask.gif</pixmap>
343
# Create the Help/Adacontrol/Help rule menu
344
GPS.Process ("adactl -h list", ".+", Add_Rule_Menu)
346
# Create hook on preference changes, and keep the "Delete Tree" menu in it
347
GPS.Hook("preferences_changed").add (on_pref_changed)
348
DelTree_Menu = GPS.Menu.get ("AdaControl/Delete Tree Files")
349
on_pref_changed (GPS.Hook("preferences_changed"))