Skip to content

Commit e93b107

Browse files
committed
Merge branch 'mr/issue_1464' into 'master'
Import indentation estimation logic from GNATpp Closes #1464 See merge request eng/ide/ada_language_server!1879
2 parents 3de76d5 + b7f77b2 commit e93b107

27 files changed

+629
-57
lines changed

source/ada/lsp-ada_documents.adb

Lines changed: 205 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -995,20 +995,214 @@ package body LSP.Ada_Documents is
995995
Input_Range =>
996996
Self.To_Source_Location_Range ((Position, Position))));
997997

998-
---------------------
999-
-- Get_Indentation --
1000-
---------------------
998+
--------------------------
999+
-- Estimate_Indentation --
1000+
--------------------------
10011001

1002-
function Get_Indentation
1003-
(Self : Document;
1004-
Context : LSP.Ada_Contexts.Context;
1005-
Line : Positive)
1002+
function Estimate_Indentation
1003+
(Self : Document; Context : LSP.Ada_Contexts.Context; Line : Positive)
10061004
return VSS.Strings.Character_Count
10071005
is
1008-
(VSS.Strings.Character_Count
1009-
(Laltools.Partial_GNATPP.Estimate_Indentation
1010-
(Self.Unit (Context),
1011-
Self.To_Source_Location ((Line, 1)).Line)));
1006+
use Langkit_Support.Slocs;
1007+
use Libadalang.Analysis;
1008+
use Libadalang.Common;
1009+
1010+
function Get_Relevant_Parents
1011+
(Unit : Libadalang.Analysis.Analysis_Unit;
1012+
Token : Token_Reference) return Ada_Node_Array;
1013+
-- Analyze where in the tree this Token is and returns the appropriate
1014+
-- parent nodes that influence indentation.
1015+
1016+
function Parent_Based_Indentation
1017+
(Parents : Ada_Node_Array;
1018+
Indentation : Positive := 3;
1019+
Indentation_Continuation : Positive := 2) return Natural;
1020+
-- Estimate the indentation starting at zero and incrementing based on
1021+
-- that Parents kind. Returns earlier if it finds a parent that always
1022+
-- sets indentation, for instance, a parameter list.
1023+
1024+
------------------------------
1025+
-- Parent_Based_Indentation --
1026+
------------------------------
1027+
1028+
function Parent_Based_Indentation
1029+
(Parents : Ada_Node_Array;
1030+
Indentation : Positive := 3;
1031+
Indentation_Continuation : Positive := 2) return Natural
1032+
is
1033+
Current_Indentation : Natural := 0;
1034+
1035+
begin
1036+
for Parent of Parents loop
1037+
case Parent.Kind is
1038+
when Ada_Loop_Stmt_Range
1039+
| Ada_For_Loop_Stmt_Range
1040+
| Ada_While_Loop_Stmt_Range
1041+
| Ada_If_Stmt_Range
1042+
| Ada_Case_Stmt_Range
1043+
| Ada_Case_Stmt_Alternative_Range
1044+
| Ada_Record_Type_Def_Range
1045+
| Ada_Generic_Formal_Part_Range
1046+
| Ada_Begin_Block_Range
1047+
| Ada_Decl_Block_Range
1048+
=>
1049+
Current_Indentation := Current_Indentation + Indentation;
1050+
1051+
when Ada_Declarative_Part_Range =>
1052+
-- When we type declare, a DeclBlock is created but not a
1053+
-- DeclarativePart one. Only when you close the block with
1054+
-- an end the node is created.
1055+
-- DeclarativePart is a node that adds indentation.
1056+
-- We cannot simply make DeclBlock also add indentation
1057+
-- because it would double indent. So only add indentation
1058+
-- to DeclarativeParts if their parent is not DeclBlock.
1059+
if Parent.Parent.Kind not in Ada_Decl_Block_Range then
1060+
Current_Indentation := Current_Indentation + Indentation;
1061+
end if;
1062+
1063+
when Ada_Handled_Stmts_Range =>
1064+
-- HandledStmts can be children of DeclBlock and BeginBlock.
1065+
-- These two add indentation, so HandledStmts should not
1066+
-- double add if its their child.
1067+
if Parent.Parent.Kind not in
1068+
Ada_Begin_Block_Range
1069+
| Ada_Decl_Block_Range
1070+
then
1071+
Current_Indentation := Current_Indentation + Indentation;
1072+
end if;
1073+
1074+
when Ada_Subp_Spec_Range | Ada_Assign_Stmt_Range =>
1075+
Current_Indentation :=
1076+
Current_Indentation + Indentation_Continuation;
1077+
1078+
when Ada_Dotted_Name_Range =>
1079+
Current_Indentation :=
1080+
Natural (Parent.Sloc_Range.Start_Column) - 1
1081+
+ Indentation_Continuation;
1082+
exit;
1083+
1084+
when Ada_Params_Range =>
1085+
Current_Indentation :=
1086+
Natural (Parent.Sloc_Range.Start_Column) - 1 + 1;
1087+
exit;
1088+
1089+
when Ada_Assoc_List_Range | Ada_Component_List_Range =>
1090+
Current_Indentation :=
1091+
Natural (Parent.Sloc_Range.Start_Column) - 1;
1092+
exit;
1093+
1094+
when others =>
1095+
null;
1096+
end case;
1097+
end loop;
1098+
1099+
return Current_Indentation;
1100+
end Parent_Based_Indentation;
1101+
1102+
--------------------------
1103+
-- Get_Relevant_Parents --
1104+
--------------------------
1105+
1106+
function Get_Relevant_Parents
1107+
(Unit : Libadalang.Analysis.Analysis_Unit;
1108+
Token : Token_Reference) return Ada_Node_Array
1109+
is
1110+
Previous : Token_Reference :=
1111+
(if Token = No_Token then No_Token
1112+
else Libadalang.Common.Previous (Token, Exclude_Trivia => True));
1113+
1114+
begin
1115+
if Previous = No_Token then
1116+
return [];
1117+
end if;
1118+
1119+
if Kind (Data (Previous)) in Ada_Comma | Ada_Dot then
1120+
Previous :=
1121+
Libadalang.Common.Previous (Previous, Exclude_Trivia => True);
1122+
end if;
1123+
1124+
declare
1125+
Node : constant Ada_Node :=
1126+
Unit.Root.Lookup (Start_Sloc (Sloc_Range (Data (Previous))));
1127+
1128+
begin
1129+
if (Node.Kind in Ada_Begin_Block_Range
1130+
and Kind (Data (Previous)) in Ada_Begin)
1131+
or (Node.Kind in Ada_Decl_Block_Range
1132+
and Kind (Data (Previous)) in Ada_Declare)
1133+
or Kind (Data (Previous)) in Ada_Brack_Open
1134+
or Node.Kind in Ada_Params_Range
1135+
then
1136+
return Node.Parents;
1137+
1138+
elsif Node.Kind in Ada_Subp_Body_Range then
1139+
if Kind (Data (Previous)) in Ada_Is then
1140+
return Node.As_Subp_Body.F_Decls.Parents;
1141+
1142+
elsif Kind (Data (Previous)) in Ada_Begin then
1143+
return Node.As_Subp_Body.F_Stmts.Parents;
1144+
end if;
1145+
1146+
elsif Node.Kind in Ada_Package_Body_Range then
1147+
if Kind (Data (Previous)) in Ada_Is then
1148+
return Node.As_Package_Body.F_Decls.Parents;
1149+
1150+
elsif Kind (Data (Previous)) in Ada_Begin then
1151+
return Node.As_Package_Body.F_Stmts.Parents;
1152+
end if;
1153+
1154+
elsif Node.Kind in Ada_Package_Decl_Range then
1155+
if Kind (Data (Previous)) in Ada_Is then
1156+
return Node.As_Package_Decl.F_Public_Part.Parents;
1157+
1158+
elsif Kind (Data (Previous)) in Ada_Private then
1159+
return Node.As_Package_Decl.F_Private_Part.Parents;
1160+
end if;
1161+
1162+
elsif Node.Kind in Ada_Generic_Package_Internal_Range then
1163+
if Kind (Data (Previous)) in Ada_Is then
1164+
return
1165+
Node.As_Generic_Package_Internal.F_Public_Part.Parents;
1166+
1167+
elsif Kind (Data (Previous)) in Ada_Private then
1168+
return
1169+
Node.As_Generic_Package_Internal.F_Private_Part.Parents;
1170+
end if;
1171+
1172+
elsif Node.Kind in Ada_Generic_Formal_Part_Range then
1173+
if Kind (Data (Previous)) in Ada_Generic then
1174+
return Node.As_Generic_Formal_Part.F_Decls.Parents;
1175+
end if;
1176+
end if;
1177+
1178+
return Node.Parents (With_Self => False);
1179+
end;
1180+
end Get_Relevant_Parents;
1181+
1182+
Unit : constant Analysis_Unit := Self.Unit (Context);
1183+
Line_Number : constant Langkit_Support.Slocs.Line_Number :=
1184+
Self.To_Source_Location ((Line, 1)).Line;
1185+
Token : constant Token_Reference :=
1186+
Unit.Lookup_Token (Source_Location'(Line_Number, 1));
1187+
1188+
Format_Options : constant Gnatformat.Configuration.Format_Options_Type :=
1189+
Context.Get_Format_Options;
1190+
1191+
Indentation : constant Positive :=
1192+
Gnatformat.Configuration.Get_Indentation
1193+
(Format_Options, Unit.Get_Filename);
1194+
Indentation_Continuation : constant Positive :=
1195+
Gnatformat.Configuration.Get_Indentation_Continuation
1196+
(Format_Options, Unit.Get_Filename);
1197+
1198+
begin
1199+
return
1200+
VSS.Strings.Character_Count
1201+
(Parent_Based_Indentation
1202+
(Parents => Get_Relevant_Parents (Unit, Token),
1203+
Indentation => Indentation,
1204+
Indentation_Continuation => Indentation_Continuation));
1205+
end Estimate_Indentation;
10121206

10131207
-----------------
10141208
-- Get_Node_At --

source/ada/lsp-ada_documents.ads

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,8 @@ package LSP.Ada_Documents is
106106
Result : out LSP.Structures.DocumentSymbol_Vector);
107107
-- Populate Result with a symbol hierarchy from the document.
108108

109-
function Get_Indentation
110-
(Self : Document;
111-
Context : LSP.Ada_Contexts.Context;
112-
Line : Positive)
109+
function Estimate_Indentation
110+
(Self : Document; Context : LSP.Ada_Contexts.Context; Line : Positive)
113111
return VSS.Strings.Character_Count;
114112
-- Estimates the indention a line should have
115113

source/ada/lsp-ada_handlers.adb

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,10 @@ package body LSP.Ada_Handlers is
25772577
use type VSS.Strings.Virtual_String;
25782578

25792579
procedure Compute_Response;
2580+
-- Determines if how this document needs to be handled based on its
2581+
-- diagnostics and ALS settings. Dispatches to
2582+
-- Handle_Document_With_Diagnostics and
2583+
-- Handle_Document_Without_Diagnostics accordingly.
25802584

25812585
procedure Handle_Document_With_Diagnostics;
25822586
-- Simply adds indentation to the new line
@@ -2593,19 +2597,18 @@ package body LSP.Ada_Handlers is
25932597
Response : LSP.Structures.TextEdit_Vector_Or_Null;
25942598
Indentation : constant VSS.Strings.Character_Count :=
25952599
(declare
2596-
Indentation_First_Guess : constant VSS.Strings.Character_Count :=
2597-
Document.Get_Indentation (Context.all, Value.position.line);
2600+
Indentation_First_Guess : constant VSS.Strings.Character_Count :=
2601+
Document.Estimate_Indentation (Context.all, Value.position.line);
25982602

25992603
begin
26002604
(if Indentation_First_Guess
2601-
>= VSS.Strings.Character_Count (Value.position.character)
2602-
then Indentation_First_Guess
2603-
- VSS.Strings.Character_Count (Value.position.character)
2605+
>= VSS.Strings.Character_Count (Value.position.character)
2606+
then
2607+
Indentation_First_Guess
2608+
- VSS.Strings.Character_Count (Value.position.character)
26042609
else 0));
26052610
-- Do not add any indentation if the current cursor position is greater
26062611
-- than the calculated one.
2607-
-- XXX position.character is counted as UTF-16 code units, actual
2608-
-- position need to be computed.
26092612

26102613
----------------------
26112614
-- Compute_Response --
@@ -2615,8 +2618,8 @@ package body LSP.Ada_Handlers is
26152618
begin
26162619
if not LSP.Ada_Configurations.On_Type_Formatting then
26172620
Self.Tracer.Trace
2618-
("'onTypeFormatting' is not active, yet, ALS received a request - "
2619-
& "exiting earlier");
2621+
("'onTypeFormatting' is not active, yet, ALS received a request "
2622+
& " - exiting earlier");
26202623

26212624
return;
26222625
end if;
@@ -2634,8 +2637,7 @@ package body LSP.Ada_Handlers is
26342637
if Document.Has_Diagnostics (Context.all) then
26352638
-- This is the unhappy path: when this Document has diagnostics.
26362639
-- Get the previous node (based on the previous non whitespace
2637-
-- token), compute the indentation and format it (if configured to
2638-
-- to so).
2640+
-- token) and compute the indentation.
26392641

26402642
Self.Tracer.Trace ("Document has diagnostics");
26412643
Handle_Document_With_Diagnostics;
@@ -2644,13 +2646,12 @@ package body LSP.Ada_Handlers is
26442646
-- This is the happy path: when this Document does not have any
26452647
-- diagnostics.
26462648
-- Get the previous node (based on the previous non whitespace
2647-
-- token) and compute the indentation.
2649+
-- token), compute the indentation and format it (if configured to
2650+
-- to so).
26482651

26492652
Self.Tracer.Trace ("Document does not have any diagnostics");
26502653
Handle_Document_Without_Diagnostics;
26512654
end if;
2652-
2653-
Self.Tracer.Trace ("Exiting 'onTypeFormatting' Request");
26542655
end Compute_Response;
26552656

26562657
--------------------------------------
@@ -2661,9 +2662,7 @@ package body LSP.Ada_Handlers is
26612662
begin
26622663
Response.Append
26632664
(LSP.Structures.TextEdit'
2664-
(a_range =>
2665-
(start => Value.position,
2666-
an_end => Value.position),
2665+
(a_range => (start => Value.position, an_end => Value.position),
26672666
newText => Indentation * VSS.Characters.Latin.Space));
26682667
end Handle_Document_With_Diagnostics;
26692668

@@ -2778,37 +2777,24 @@ package body LSP.Ada_Handlers is
27782777
Response => Response,
27792778
Error => Error);
27802779

2781-
if Success then
2782-
-- Result contains the Range_Format result.
2783-
-- Add indentation to the next line.
2784-
2785-
Response.Append
2786-
(LSP.Structures.TextEdit'
2787-
(a_range =>
2788-
(start => Value.position,
2789-
an_end => Value.position),
2790-
newText => Indentation * ' '));
2791-
2792-
return;
2780+
if not Success then
2781+
Self.Tracer.Trace
2782+
("The 'onTypeFormatting' has failed because of a "
2783+
& "Range_Format error");
27932784
end if;
27942785

2795-
Self.Tracer.Trace
2796-
("The 'onTypeFormatting' has failed because of a "
2797-
& "Range_Format error");
2798-
27992786
Response.Append
28002787
(LSP.Structures.TextEdit'
28012788
(a_range =>
2802-
(start => Value.position,
2803-
an_end => Value.position),
2789+
(start => Value.position, an_end => Value.position),
28042790
newText => Indentation * ' '));
28052791
end;
28062792
end Handle_Document_Without_Diagnostics;
28072793

28082794
begin
28092795
Self.Tracer.Trace ("On 'onTypeFormatting' Request");
2810-
28112796
Compute_Response;
2797+
Self.Tracer.Trace ("Exiting 'onTypeFormatting' Request");
28122798

28132799
Self.Sender.On_OnTypeFormatting_Response (Id, Response);
28142800
end On_OnTypeFormatting_Request;

source/ada/lsp-utils.ads

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,25 @@
1717

1818
-- This package provides some utility subprograms.
1919

20-
with VSS.Strings.Conversions;
21-
2220
with GNATCOLL.VFS;
23-
with GPR2.Path_Name;
21+
2422
with GPR2.Message;
23+
with GPR2.Path_Name;
2524
with GPR2.Source_Reference;
26-
with Libadalang.Analysis;
25+
26+
with LSP.Enumerations;
27+
with LSP.Structures;
28+
2729
with Langkit_Support.Slocs;
30+
31+
with Libadalang.Analysis;
32+
2833
with Pp.Scanner;
34+
2935
with Utils.Char_Vectors;
3036
with Utils.Command_Lines;
3137

32-
with LSP.Enumerations;
33-
with LSP.Structures;
38+
with VSS.Strings.Conversions;
3439

3540
package LSP.Utils is
3641

0 commit comments

Comments
 (0)