@@ -995,20 +995,213 @@ 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 LSP.Utils.Previous_Non_Trivia (Token));
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 := LSP.Utils.Previous_Non_Trivia (Previous);
1121+ end if ;
1122+
1123+ declare
1124+ Node : constant Ada_Node :=
1125+ Unit.Root.Lookup (Start_Sloc (Sloc_Range (Data (Previous))));
1126+
1127+ begin
1128+ if (Node.Kind in Ada_Begin_Block_Range
1129+ and Kind (Data (Previous)) in Ada_Begin)
1130+ or (Node.Kind in Ada_Decl_Block_Range
1131+ and Kind (Data (Previous)) in Ada_Declare)
1132+ or Kind (Data (Previous)) in Ada_Brack_Open
1133+ or Node.Kind in Ada_Params_Range
1134+ then
1135+ return Node.Parents;
1136+
1137+ elsif Node.Kind in Ada_Subp_Body_Range then
1138+ if Kind (Data (Previous)) in Ada_Is then
1139+ return Node.As_Subp_Body.F_Decls.Parents;
1140+
1141+ elsif Kind (Data (Previous)) in Ada_Begin then
1142+ return Node.As_Subp_Body.F_Stmts.Parents;
1143+ end if ;
1144+
1145+ elsif Node.Kind in Ada_Package_Body_Range then
1146+ if Kind (Data (Previous)) in Ada_Is then
1147+ return Node.As_Package_Body.F_Decls.Parents;
1148+
1149+ elsif Kind (Data (Previous)) in Ada_Begin then
1150+ return Node.As_Package_Body.F_Stmts.Parents;
1151+ end if ;
1152+
1153+ elsif Node.Kind in Ada_Package_Decl_Range then
1154+ if Kind (Data (Previous)) in Ada_Is then
1155+ return Node.As_Package_Decl.F_Public_Part.Parents;
1156+
1157+ elsif Kind (Data (Previous)) in Ada_Private then
1158+ return Node.As_Package_Decl.F_Private_Part.Parents;
1159+ end if ;
1160+
1161+ elsif Node.Kind in Ada_Generic_Package_Internal_Range then
1162+ if Kind (Data (Previous)) in Ada_Is then
1163+ return
1164+ Node.As_Generic_Package_Internal.F_Public_Part.Parents;
1165+
1166+ elsif Kind (Data (Previous)) in Ada_Private then
1167+ return
1168+ Node.As_Generic_Package_Internal.F_Private_Part.Parents;
1169+ end if ;
1170+
1171+ elsif Node.Kind in Ada_Generic_Formal_Part_Range then
1172+ if Kind (Data (Previous)) in Ada_Generic then
1173+ return Node.As_Generic_Formal_Part.F_Decls.Parents;
1174+ end if ;
1175+ end if ;
1176+
1177+ return Node.Parents (With_Self => False);
1178+ end ;
1179+ end Get_Relevant_Parents ;
1180+
1181+ Unit : constant Analysis_Unit := Self.Unit (Context);
1182+ Line_Number : constant Langkit_Support.Slocs.Line_Number :=
1183+ Self.To_Source_Location ((Line, 1 )).Line;
1184+ Token : constant Token_Reference :=
1185+ Unit.Lookup_Token (Source_Location'(Line_Number, 1 ));
1186+
1187+ Format_Options : constant Gnatformat.Configuration.Format_Options_Type :=
1188+ Context.Get_Format_Options;
1189+
1190+ Indentation : constant Positive :=
1191+ Gnatformat.Configuration.Get_Indentation
1192+ (Format_Options, Unit.Get_Filename);
1193+ Indentation_Continuation : constant Positive :=
1194+ Gnatformat.Configuration.Get_Indentation_Continuation
1195+ (Format_Options, Unit.Get_Filename);
1196+
1197+ begin
1198+ return
1199+ VSS.Strings.Character_Count
1200+ (Parent_Based_Indentation
1201+ (Parents => Get_Relevant_Parents (Unit, Token),
1202+ Indentation => Indentation,
1203+ Indentation_Continuation => Indentation_Continuation));
1204+ end Estimate_Indentation ;
10121205
10131206 -- ---------------
10141207 -- Get_Node_At --
0 commit comments