1
-------------------------------------------------------------------------------
3
-- This file is part of AdaBrowse.
5
-- <STRONG>Copyright (c) 2002 by Thomas Wolf.</STRONG>
7
-- AdaBrowse is free software; you can redistribute it and/or modify it
8
-- under the terms of the GNU General Public License as published by the
9
-- Free Software Foundation; either version 2, or (at your option) any
10
-- later version. AdaBrowse is distributed in the hope that it will be
11
-- useful, but <EM>without any warranty</EM>; without even the implied
12
-- warranty of <EM>merchantability or fitness for a particular purpose.</EM>
13
-- See the GNU General Public License for more details. You should have
14
-- received a copy of the GNU General Public License with this distribution,
15
-- see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
16
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21
-- Author:</STRONG><DD>
23
-- <ADDRESS><A HREF="mailto:twolf@acm.org">twolf@acm.org</A></ADDRESS></DL>
26
-- Purpose:</STRONG><DD>
27
-- Singled out crossreference setup from AD.Writers.</DL>
32
-- 20-AUG-2002 TW Initial version.
33
-- 27-AUG-2002 TW Improved 'Crossref_Exp' to cater for implicitly
34
-- inherited subprograms and enumeration literals for
35
-- which AdaBrowse V2.13 and earlier generated empty
36
-- crossrefs (<A HREF="">Name</A>). We now try to generate
37
-- a crossref to the explicit declaration the item was
39
-- 06-JUN-2003 TW Moved 'Set_Standard_Units' and 'Crossref_To_Unit' here
41
-- 09-JUL-2003 TW New operation 'Crossref_Special' for pragmas and rep
44
-------------------------------------------------------------------------------
48
with Ada.Characters.Handling;
50
with Ada.Strings.Wide_Unbounded;
54
with Asis.Compilation_Units;
55
with Asis.Declarations;
63
with Asis2.Declarations;
69
package body AD.Crossrefs is
71
package ACH renames Ada.Characters.Handling;
72
package WASU renames Ada.Strings.Wide_Unbounded;
75
use Asis.Declarations;
78
Do_Standard_Too : Boolean := False;
80
procedure Set_Standard_Units
81
(Do_Them : in Boolean)
84
Do_Standard_Too := Do_Them;
85
end Set_Standard_Units;
87
function Crossref_To_Unit
88
(Unit : in Asis.Compilation_Unit)
92
if Asis.Compilation_Units.Unit_Origin (Unit) /= An_Application_Unit then
93
-- Non-application units.
94
if not Do_Standard_Too or else
95
Asis2.Units.Is_Standard (Unit)
101
not AD.Exclusions.No_XRef
104
(Asis2.Naming.Full_Unit_Name (Unit))));
105
end Crossref_To_Unit;
107
function Crossref_Name
108
(Name : in Asis.Defining_Name;
109
This_Unit : in Asis.Declaration;
110
Reporter : access AD.Messages.Error_Reporter'Class)
111
return Cross_Reference
113
Def : constant Defining_Name :=
114
AD.Queries.Expand_Generic (Name, Reporter);
115
Decl : constant Declaration :=
116
Asis2.Declarations.Enclosing_Declaration (Def);
117
Unit : constant Compilation_Unit :=
118
Enclosing_Compilation_Unit (Def);
119
Unit_Decl : constant Declaration :=
120
Unit_Declaration (Unit);
121
Result : Cross_Reference;
123
Result.Ignore := not Crossref_To_Unit (Unit);
124
Result.Is_Top_Unit := Is_Equal (Decl, Unit_Decl);
125
Result.Is_Local := Is_Equal (Unit_Decl, This_Unit);
126
Result.Full_Unit_Name :=
127
WASU.To_Unbounded_Wide_String (Asis2.Naming.Full_Unit_Name (Unit));
128
Result.Position := Asis2.Spans.Start (Asis2.Spans.Get_Span (Def));
130
WASU.To_Unbounded_Wide_String
131
(Asis2.Naming.Name_Definition_Image (Def));
132
-- We may use the image of 'Def' even if 'Name' is the current unit's
133
-- name, for in this case, Def = Name.
137
function Crossref_Special
138
(Element : in Asis.Element;
139
This_Unit : in Asis.Declaration)
140
return Cross_Reference
142
Unit : constant Compilation_Unit :=
143
Enclosing_Compilation_Unit (Element);
144
Unit_Decl : constant Declaration :=
145
Unit_Declaration (Unit);
146
Result : Cross_Reference;
148
Result.Ignore := not Crossref_To_Unit (Unit);
149
Result.Is_Top_Unit := False;
150
Result.Is_Local := Is_Equal (Unit_Decl, This_Unit);
151
Result.Full_Unit_Name :=
152
WASU.To_Unbounded_Wide_String (Asis2.Naming.Full_Unit_Name (Unit));
154
Asis2.Spans.Start (Asis2.Spans.Get_Span (Element));
155
case Element_Kind (Element) is
158
WASU.To_Unbounded_Wide_String (Pragma_Name_Image (Element));
160
case Representation_Clause_Kind (Element) is
161
when An_Attribute_Definition_Clause |
162
An_Enumeration_Representation_Clause |
163
A_Record_Representation_Clause =>
165
WASU.To_Unbounded_Wide_String
166
(Asis2.Naming.Name_Expression_Image
167
(Asis.Clauses.Representation_Clause_Name (Element)));
169
Ada.Exceptions.Raise_Exception
170
(Asis.Exceptions.ASIS_Inappropriate_Element'Identity,
171
"Unexpected rep clause kind " &
172
Representation_Clause_Kinds'Image
173
(Representation_Clause_Kind (Element)) &
174
" in AD.Crossrefs.Crossref_Special.");
177
Ada.Exceptions.Raise_Exception
178
(Asis.Exceptions.ASIS_Inappropriate_Element'Identity,
179
"Unexpected element kind " &
180
Element_Kinds'Image (Element_Kind (Element)) &
181
" in AD.Crossrefs.Crossref_Special.");
184
end Crossref_Special;
186
function Crossref_Exp
187
(Name : in Asis.Expression;
188
This_Unit : in Asis.Declaration;
189
Reporter : access AD.Messages.Error_Reporter'Class)
190
return Cross_Reference
194
True_Name : Defining_Name;
195
Unit : Asis.Compilation_Unit;
196
Unit_Decl : Asis.Declaration;
197
Kind : constant Expression_Kinds := Expression_Kind (Name);
199
Kind = An_Identifier or else
200
Kind = An_Enumeration_Literal;
202
Def := Asis2.Declarations.Name_Definition (Name);
204
-- We may also legally get a Nil_Element here; e.g. if 'Name'
205
-- refers to a dispatching call.
206
return Null_Crossref;
208
Decl := Asis2.Declarations.Enclosing_Declaration (Def);
209
True_Name := AD.Queries.Expand_Generic (Def, Reporter);
211
True_Decl : Asis.Declaration :=
212
Asis2.Declarations.Enclosing_Declaration (True_Name);
214
case Declaration_Origin (True_Decl) is
215
when An_Explicit_Declaration =>
217
when An_Implicit_Predefined_Declaration =>
219
-- We couldn't generate any meaningful crossref anyway.
220
when An_Implicit_Inherited_Declaration =>
221
-- Oh well... let's try to find the explicit declaration from
222
-- which we inherited the item. Note: it must be a function or
223
-- procedure declaration, or an enumeration literal
225
case Declaration_Kind (True_Decl) is
226
when A_Procedure_Declaration |
227
A_Function_Declaration |
228
An_Enumeration_Literal_Specification =>
230
Asis2.Declarations.Real_Declaration (True_Decl);
231
if not Is_Nil (True_Decl) and then
232
not Asis.Text.Is_Nil (Asis2.Spans.Get_Span (True_Decl))
235
True_Name := Asis2.Naming.Get_Name (Decl);
236
-- We don't need to worry about defining expanded
240
AD.Messages.Report_Error
242
"Missing case value in AD.Crossrefs.Crossref_Exp for "
244
Asis.Declaration_Kinds'Image
245
(Declaration_Kind (True_Decl)));
252
-- Special handling for references that go to items inside a generic
253
-- formal package: if we have "with package X is new Y (<>)", and a
254
-- reference such as "X.Z", we want to generate for 'Z' a reference
257
-- ASIS-for-GNAT 3.14p returns an element that obviously has a source
258
-- position that corresponds to the one in 'Y', but the enclosing
259
-- unit delaration is not 'Y', but the one containing the formal
260
-- package declaration of 'X'. Also, neither 'X', nor 'Y', nor 'Z'
261
-- have Is_Part_Of_Instance.
263
-- I do not know whether or not this is a bug in ASIS-for-GNAT.
264
-- Anyway, we handle this case specially here: if we find that a
265
-- reference is inside a formal package, we use the corresponding
266
-- generic unit to generate the cross-reference, *not* the unit
267
-- containing the formal package declaration.
269
Outer : Asis.Element := Enclosing_Element (Decl);
271
while not Is_Nil (Outer) loop
272
if Element_Kind (Outer) = A_Declaration then
273
case Declaration_Kind (Outer) is
274
when A_Formal_Package_Declaration |
275
A_Formal_Package_Declaration_With_Box =>
281
Outer := Enclosing_Element (Outer);
283
if Is_Nil (Outer) then
284
Unit := Enclosing_Compilation_Unit (True_Name);
285
Unit_Decl := Unit_Declaration (Unit);
288
Asis2.Declarations.Name_Declaration (Generic_Unit_Name (Outer));
289
Unit := Enclosing_Compilation_Unit (Unit_Decl);
293
-- Revert to the default behavior:
294
Unit := Enclosing_Compilation_Unit (True_Name);
295
Unit_Decl := Unit_Declaration (Unit);
298
-- Asis sometimes returns the wrong name. Shouldn't actually happen
299
-- anymore with the correction in Asis2.Naming.
300
Asis2.Naming.Verify_Name_Definition (Def, Name);
301
Use_Def := not Is_Nil (Def);
303
AD.Messages.Report_Error
304
(Reporter.all, "ASIS returns the wrong name here!");
308
Result : Cross_Reference;
311
Is_Equal (Decl, This_Unit) or else
312
not Crossref_To_Unit (Unit);
313
Result.Is_Top_Unit := Is_Equal (Decl, Unit_Decl);
314
Result.Is_Local := Is_Equal (Unit_Decl, This_Unit);
315
Result.Full_Unit_Name :=
316
WASU.To_Unbounded_Wide_String (Asis2.Naming.Full_Unit_Name (Unit));
318
Asis2.Spans.Start (Asis2.Spans.Get_Span (True_Name));
321
WASU.To_Unbounded_Wide_String
322
(Asis2.Naming.Name_Definition_Image (Def));
323
-- We may use the image of 'Def' even if 'Name' is the current
324
-- unit's name, for in this case, Def = Name.
326
Result.Image := WASU.Null_Unbounded_Wide_String;