Skip to content

Commit 90fd3b1

Browse files
Merge branch 'topic/#1686' into 'master'
Allow navigation queries right after entities See merge request eng/ide/ada_language_server!2051
2 parents 3bbc319 + bea55ba commit 90fd3b1

File tree

9 files changed

+238
-234
lines changed

9 files changed

+238
-234
lines changed

source/ada/lsp-ada_documents.adb

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,10 +1202,70 @@ package body LSP.Ada_Documents is
12021202
Context : LSP.Ada_Contexts.Context;
12031203
Position : LSP.Structures.Position) return Libadalang.Analysis.Ada_Node
12041204
is
1205-
Unit : constant Libadalang.Analysis.Analysis_Unit := Self.Unit (Context);
1205+
use Langkit_Support.Slocs;
1206+
1207+
Unit : constant Libadalang.Analysis.Analysis_Unit :=
1208+
Self.Unit (Context);
1209+
1210+
function Get_Sloc return Langkit_Support.Slocs.Source_Location;
1211+
-- Return the source location corresponding to Position.
1212+
-- This function handles properly the case where the position is
1213+
-- at the end of an indentifier token and at the start of the next
1214+
-- token (e.g: 'An_Identifier^;' where '^' is the cursor's position):
1215+
-- in that case we want to retrieve the node corresponding to
1216+
-- the previous identifier token.
1217+
1218+
--------------
1219+
-- Get_Sloc --
1220+
--------------
1221+
1222+
function Get_Sloc return Langkit_Support.Slocs.Source_Location is
1223+
use type Langkit_Support.Slocs.Source_Location;
1224+
use Libadalang.Common;
1225+
1226+
Initial_Sloc : constant Langkit_Support.Slocs.Source_Location :=
1227+
Self.To_Source_Location (Position);
1228+
Token : constant Libadalang.Common.Token_Reference :=
1229+
Self.Get_Token_At (Context, Position);
1230+
Prev_Token : constant Libadalang.Common.Token_Reference :=
1231+
(if Token /= No_Token
1232+
then Libadalang.Common.Previous (Token)
1233+
else No_Token);
1234+
begin
1235+
-- No previous token, return the initial SLOC
1236+
if Prev_Token = No_Token then
1237+
return Initial_Sloc;
1238+
end if;
1239+
1240+
declare
1241+
Token_Data : constant Libadalang.Common.Token_Data_Type :=
1242+
Libadalang.Common.Data (Token);
1243+
Token_Range :
1244+
constant Libadalang.Slocs.Source_Location_Range :=
1245+
Token_Data.Sloc_Range;
1246+
Prev_Token_Data : constant Libadalang.Common.Token_Data_Type :=
1247+
Libadalang.Common.Data (Prev_Token);
1248+
Prev_Token_Range :
1249+
constant Libadalang.Slocs.Source_Location_Range :=
1250+
Prev_Token_Data.Sloc_Range;
1251+
begin
1252+
-- The current token is an identifier and its start SLOC and
1253+
-- the previous one's end SLOC are equal: consider that the query
1254+
-- is being done on the previous identifier token.
1255+
if Prev_Token_Data.Kind = Ada_Identifier
1256+
and then Initial_Sloc = Token_Range.Start_Sloc
1257+
and then Initial_Sloc = Prev_Token_Range.End_Sloc
1258+
then
1259+
return Prev_Token_Range.Start_Sloc;
1260+
else
1261+
return Initial_Sloc;
1262+
end if;
1263+
end;
1264+
end Get_Sloc;
1265+
12061266
begin
12071267
return (if Unit.Root.Is_Null then Libadalang.Analysis.No_Ada_Node
1208-
else Unit.Root.Lookup (Self.To_Source_Location (Position)));
1268+
else Unit.Root.Lookup (Get_Sloc));
12091269
end Get_Node_At;
12101270

12111271
--------------------------

source/ada/lsp-ada_handlers.adb

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3370,6 +3370,8 @@ package body LSP.Ada_Handlers is
33703370
----------------------
33713371

33723372
procedure Compute_Response is
3373+
use Libadalang.Common;
3374+
33733375
Context : constant LSP.Ada_Context_Sets.Context_Access :=
33743376
Self.Contexts.Get_Best_Context (Value.textDocument.uri);
33753377
Document : constant LSP.Ada_Documents.Document_Access :=
@@ -3379,15 +3381,9 @@ package body LSP.Ada_Handlers is
33793381

33803382
Position : LSP.Structures.Position := Value.position;
33813383
Node : Libadalang.Analysis.Ada_Node;
3382-
3384+
Token : Libadalang.Common.Token_Reference :=
3385+
Document.Get_Token_At (Context.all, Position);
33833386
begin
3384-
-- Move the cursor to the previous character: this is more resilient
3385-
-- to invalid code.
3386-
3387-
if Position.character > 0 then
3388-
Position.character := @ - 1;
3389-
end if;
3390-
33913387
Node := Document.Get_Node_At (Context.all, Position);
33923388

33933389
declare
@@ -3414,8 +3410,8 @@ package body LSP.Ada_Handlers is
34143410
end if;
34153411
end;
34163412

3417-
-- Try to get signatures before the cursor location
3418-
-- i.e "Foo (1,|" => "Foo (1|,"
3413+
-- Try to get signatures at the the cursor location
3414+
-- i.e "Foo (1,|"
34193415

34203416
LSP.Ada_Completions.Parameters.Propose_Signatures
34213417
(Context => Context,
@@ -3424,37 +3420,41 @@ package body LSP.Ada_Handlers is
34243420
Prev_Signatures => Value.context,
34253421
Res => Response.Value);
34263422

3427-
-- Retry to get signature in the previous non whitespace token
3428-
-- i.e. "Foo (1, 2 + |" => "Foo (1, 2 +|"
3429-
34303423
if Response.Value.signatures.Is_Empty then
3431-
declare
3432-
use all type Libadalang.Common.Token_Kind;
3433-
use type Libadalang.Common.Token_Reference;
34343424

3435-
Token : Libadalang.Common.Token_Reference :=
3436-
Document.Get_Token_At (Context.all, Position);
3425+
-- Retry to get matching signatures from the previous non whitespace/non comma
3426+
-- token.
3427+
-- This is more resilient on invalid code, since we'll have more chances to
3428+
-- retrieve a valid CallExpr node, rather than an ErrorStmt one.
3429+
-- i.e. "Foo (1, 2 + |" => "Foo (1, 2 +|" or "Foo (1, 2,|" => "Foo (1, 2|,"
34373430

3438-
begin
3439-
if Token /= Libadalang.Common.No_Token
3440-
and then Libadalang.Common.Kind
3441-
(Libadalang.Common.Data (Token)) = Ada_Whitespace
3442-
then
3431+
if Token /= No_Token
3432+
and then Position.character > 0
3433+
and then (Token.Data.Is_Trivia
3434+
or else Token.Data.Kind = Ada_Comma)
3435+
then
3436+
declare
3437+
Prev_Token : constant Token_Reference :=
3438+
Libadalang.Common.Previous (Token, Exclude_Trivia => True);
3439+
begin
34433440
Token :=
3444-
Libadalang.Common.Previous
3445-
(Token, Exclude_Trivia => True);
3446-
end if;
3447-
3448-
Position := LSP.Ada_Handlers.Locations.Start_Position (Token);
3449-
end;
3450-
3451-
Node := Document.Get_Node_At (Context.all, Position);
3452-
LSP.Ada_Completions.Parameters.Propose_Signatures
3453-
(Context => Context,
3454-
Node => Node,
3455-
Cursor => Location,
3456-
Prev_Signatures => Value.context,
3457-
Res => Response.Value);
3441+
(if Prev_Token /= No_Token then Prev_Token else Token);
3442+
3443+
-- Recompute the position from the new token and retrieve
3444+
-- the corresponding node.
3445+
Position :=
3446+
LSP.Ada_Handlers.Locations.Start_Position (Token);
3447+
Node := Document.Get_Node_At (Context.all, Position);
3448+
3449+
-- Get the matching signatures
3450+
LSP.Ada_Completions.Parameters.Propose_Signatures
3451+
(Context => Context,
3452+
Node => Node,
3453+
Cursor => Location,
3454+
Prev_Signatures => Value.context,
3455+
Res => Response.Value);
3456+
end;
3457+
end if;
34583458
end if;
34593459

34603460
-- Retry to get signatures in the cursor position.

0 commit comments

Comments
 (0)