@@ -24,6 +24,7 @@ with Libadalang.Common;
2424with Laltools.Common ;
2525
2626with LSP.Ada_Context_Sets ;
27+ with LSP.Ada_Documents ;
2728with LSP.Ada_Handlers.Locations ;
2829with LSP.Ada_Request_Jobs ;
2930with LSP.Client_Message_Receivers ;
@@ -124,6 +125,132 @@ package body LSP.Ada_Definition is
124125 Decl_For_Find_Overrides : Libadalang.Analysis.Basic_Decl;
125126
126127 Ignore : Boolean;
128+
129+ procedure Retrieve_Alternate_Part_Location ;
130+ -- Retrieve the location of the alternate part of a package, task,
131+ -- protected type, or subprogram.
132+ -- This is used when the user queries the definition of a token that
133+ -- does not belong to a defining name.
134+ -- If the queried token is equal to 'is', retrieve the location of the
135+ -- private part of the package, task, protected type, or the begin
136+ -- of the subprogram body.
137+
138+ procedure Retrieve_Alternate_Part_Location is
139+ use Libadalang.Common;
140+
141+ procedure Append_Prev_Token_Location
142+ (Node : Libadalang.Analysis.Ada_Node'Class);
143+ -- Append the previous token's location to the response.
144+
145+ -- ---------------------
146+ -- Append_Prev_Token --
147+ -- ---------------------
148+
149+ procedure Append_Prev_Token_Location
150+ (Node : Libadalang.Analysis.Ada_Node'Class) is
151+ begin
152+ if not Node.Is_Null then
153+ declare
154+ Prev : constant Libadalang.Common.Token_Reference :=
155+ Libadalang.Common.Previous (Node.Token_Start, True);
156+ begin
157+ Self.Parent.Context.Append_Location
158+ (Result => Self.Response,
159+ Filter => Self.Filter,
160+ Unit => Node.Unit,
161+ Token => Prev);
162+ end ;
163+ end if ;
164+ end Append_Prev_Token_Location ;
165+
166+ Document : constant LSP.Ada_Documents.Document_Access :=
167+ Self.Parent.Context.Get_Open_Document (Value.textDocument.uri);
168+ Token : Libadalang.Common.Token_Reference :=
169+ Document.Get_Token_At (Context.all , Value.position);
170+ Node : Libadalang.Analysis.Ada_Node;
171+ Position : LSP.Structures.Position;
172+ begin
173+ if Token /= No_Token then
174+ if Token.Data.Kind = Ada_Is then
175+ Node := Document.Get_Node_At (Context => Context.all , Position => Value.position);
176+
177+ if not Node.Is_Null and then Node.Kind in Ada_Subp_Body_Range
178+ then
179+ -- We are on the 'is' of a subprogram body: retrieve the
180+ -- enclosing subprogram's defining name instead of checking
181+ -- for the previous token's node since it might refer to the
182+ -- subprogram's parameter list.
183+ Definition := Node.As_Subp_Body.P_Defining_Name;
184+ else
185+ -- We are on the 'is' of a package, task, or protected type: retrieve
186+ -- the previous token's node, which should be the defining name.
187+ Token := Token.Previous (True);
188+
189+ if Token = No_Token then
190+ -- Return if there is no previous token.
191+ return ;
192+ end if ;
193+
194+ Position :=
195+ Document.To_A_Range (Token.Data.Sloc_Range).start;
196+ Node :=
197+ Document.Get_Node_At
198+ (Context => Context.all , Position => Position);
199+
200+ Definition := Laltools.Common.Resolve_Name_Precisely (Node.As_Name);
201+ end if ;
202+
203+ -- Append private part, begin locations to the response
204+ for Part of Definition.P_Basic_Decl.P_All_Parts loop
205+ case Part.Kind is
206+
207+ when Libadalang.Common.Ada_Package_Body_Range =>
208+ Append_Prev_Token_Location (Part.As_Package_Body.F_Stmts);
209+
210+ when Libadalang.Common.Ada_Subp_Body_Range =>
211+ Append_Prev_Token_Location (Part.As_Subp_Body.F_Stmts);
212+
213+ when Libadalang.Common.Ada_Task_Body_Range =>
214+ Append_Prev_Token_Location (Part.As_Task_Body.F_Stmts);
215+
216+ when Libadalang.Common.Ada_Base_Package_Decl =>
217+ Append_Prev_Token_Location
218+ (Part.As_Base_Package_Decl.F_Private_Part);
219+
220+ when Libadalang.Common.Ada_Protected_Type_Decl_Range =>
221+ Append_Prev_Token_Location
222+ (Part
223+ .As_Protected_Type_Decl
224+ .F_Definition
225+ .F_Private_Part);
226+
227+ when Libadalang.Common.Ada_Single_Protected_Decl_Range =>
228+ Append_Prev_Token_Location
229+ (Part
230+ .As_Single_Protected_Decl
231+ .F_Definition
232+ .F_Private_Part);
233+
234+ when Libadalang.Common.Ada_Task_Type_Decl_Range =>
235+ Append_Prev_Token_Location
236+ (Part.As_Task_Type_Decl.F_Definition.F_Private_Part);
237+
238+ when Libadalang.Common.Ada_Single_Task_Decl_Range =>
239+ Append_Prev_Token_Location
240+ (Part
241+ .As_Single_Task_Decl
242+ .F_Task_Type
243+ .F_Definition
244+ .F_Private_Part);
245+
246+ when others =>
247+ null ;
248+ end case ;
249+ end loop ;
250+ end if ;
251+ end if ;
252+ end Retrieve_Alternate_Part_Location ;
253+
127254 begin
128255 if Self.Contexts.Is_Empty then
129256 -- No more contexts to process, sort and return collected results
@@ -148,6 +275,7 @@ package body LSP.Ada_Definition is
148275 (Self.Parent.Context.Get_Node_At (Context.all , Value));
149276
150277 if Name_Node.Is_Null then
278+ Retrieve_Alternate_Part_Location;
151279 return ;
152280 end if ;
153281
0 commit comments