@@ -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 --
0 commit comments