diff --git a/extensions/src/libadalang-gpr_utils.adb b/extensions/src/libadalang-gpr_utils.adb index 7baf74afd..931aad340 100644 --- a/extensions/src/libadalang-gpr_utils.adb +++ b/extensions/src/libadalang-gpr_utils.adb @@ -745,4 +745,63 @@ package body Libadalang.GPR_Utils is return Result; end Closure; + ----------------------- + -- Unit_Location_For -- + ----------------------- + + function Unit_Location_For + (Self : GPR2.Project.View.Object; + Name : String; + Kind : Analysis_Unit_Kind) + return GPR2.Build.Compilation_Unit.Unit_Location + is + use type GPR2.Name_Type; + + Req_Name : constant GPR2.Name_Type := GPR2.Name_Type (Name); + Unit : constant GPR2.Build.Compilation_Unit.Object := + Self.Unit (Req_Name); + begin + if Unit.Is_Defined then + + -- If we got a unit, but not the one we requested, we are likely + -- requesting a subunit: in that case, extract the subunit name and + -- request it separately. + + if Req_Name = Unit.Name then + case Kind is + when Unit_Specification => + if Unit.Has_Part (GPR2.S_Spec) then + return Unit.Spec; + end if; + when Unit_Body => + if Unit.Has_Part (GPR2.S_Body) then + return Unit.Main_Body; + end if; + end case; + + else + pragma Assert (Kind = Unit_Body); + declare + -- Requested unit name is "[ROOT].[SEP]", the name of the unit + -- we got is "[ROOT]": skip it plus the "dot" to extract only + -- the "[SEP]" part. + + Prefix_Last : constant Positive := + Req_Name'First + Unit.Name'Length; + + pragma Assert + (Req_Name (Req_Name'First .. Prefix_Last) + = GPR2."&" (Unit.Name, ".")); + Subunit_Name : constant GPR2.Name_Type := + Req_Name (Prefix_Last + 1 .. Req_Name'Last); + begin + return + Unit.Get (GPR2.S_Separate, Subunit_Name); + end; + end if; + end if; + + return GPR2.Build.Compilation_Unit.No_Unit; + end Unit_Location_For; + end Libadalang.GPR_Utils; diff --git a/extensions/src/libadalang-gpr_utils.ads b/extensions/src/libadalang-gpr_utils.ads index 451d67353..a6b292f92 100644 --- a/extensions/src/libadalang-gpr_utils.ads +++ b/extensions/src/libadalang-gpr_utils.ads @@ -11,11 +11,14 @@ with Ada.Containers.Vectors; with GNATCOLL.File_Paths; use GNATCOLL.File_Paths; with GNATCOLL.Projects; with GNATCOLL.Strings; use GNATCOLL.Strings; +with GPR2.Build.Compilation_Unit; with GPR2.Project.Registry.Attribute; with GPR2.Project.Tree; with GPR2.Project.View; with GPR2.Project.View.Vector; +with Libadalang.Common; use Libadalang.Common; + private package Libadalang.GPR_Utils is package GPR1 renames GNATCOLL.Projects; @@ -203,4 +206,15 @@ private package Libadalang.GPR_Utils is (Self : GPR2.Project.View.Object) return GPR2.Project.View.Vector.Object; -- Return the list of all views reachable from ``Self``, self included + function Unit_Location_For + (Self : GPR2.Project.View.Object; + Name : String; + Kind : Analysis_Unit_Kind) + return GPR2.Build.Compilation_Unit.Unit_Location; + -- Look in ``Self`` for the location of the ``Name``/``Kind`` unit and + -- return it. Return ``No_Unit`` if it is not found. + -- + -- TODO??? (eng/gpr/gpr-issues#338) Remove this function once an equivalent + -- one is included in LibGPR2. + end Libadalang.GPR_Utils; diff --git a/extensions/src/libadalang-project_provider.adb b/extensions/src/libadalang-project_provider.adb index 229f440a8..f378456b7 100644 --- a/extensions/src/libadalang-project_provider.adb +++ b/extensions/src/libadalang-project_provider.adb @@ -747,53 +747,33 @@ package body Libadalang.Project_Provider is end; when GPR2_Kind => - declare - procedure Set (SUI : GPR2.Build.Compilation_Unit.Unit_Location); - -- Set ``Filename`` and ``PLE_Root_Index`` from ``SUI``'s - - Unit_Name : constant GPR2.Name_Type := GPR2.Name_Type (Str_Name); - --------- - -- Set -- - --------- + -- Look for the requested unit in all the projects that this + -- provider handles. - procedure Set (SUI : GPR2.Build.Compilation_Unit.Unit_Location) is + for View of Provider.Projects loop + declare + use type GPR2.Build.Compilation_Unit.Unit_Location; use type GPR2.Unit_Index; - begin - -- GPR2 sets the CU index to 0 when there is no "at N" clause - -- in the project file. This is equivalont to "at 1", which is - -- what we need here since PLE_Root_Index is a Positive. - - Filename := US.To_Unbounded_String (String (SUI.Source.Value)); - PLE_Root_Index := - (if SUI.Index = 0 then 1 else Positive (SUI.Index)); - end Set; - begin - -- Look for the requested unit in all the projects that this - -- provider handles. - for View of Provider.Projects loop - declare - Unit : constant GPR2.Build.Compilation_Unit.Object := - View.GPR2_Value.Unit (Unit_Name); - begin - if Unit.Is_Defined then - case Kind is - when Unit_Specification => - if Unit.Has_Part (GPR2.S_Spec) then - Set (Unit.Spec); - return; - end if; - when Unit_Body => - if Unit.Has_Part (GPR2.S_Body) then - Set (Unit.Main_Body); - return; - end if; - end case; - end if; - end; - end loop; - end; + Unit : constant GPR2.Build.Compilation_Unit.Unit_Location := + Unit_Location_For (View.GPR2_Value, Str_Name, Kind); + begin + if Unit /= GPR2.Build.Compilation_Unit.No_Unit then + + -- GPR2 sets the CU index to 0 when there is no "at N" + -- clause in the project file. This is equivalont to "at + -- 1", which is what we need here since PLE_Root_Index is + -- a Positive. + + Filename := + US.To_Unbounded_String (String (Unit.Source.Value)); + PLE_Root_Index := + (if Unit.Index = 0 then 1 else Positive (Unit.Index)); + return; + end if; + end; + end loop; end case; -- If we reach this point, we have not found a unit handled by this diff --git a/testsuite/tests/ada_api/gpr2_project_unit_provider/main.adb b/testsuite/tests/ada_api/gpr2_project_unit_provider/main.adb index 247fa8292..018cb9efb 100644 --- a/testsuite/tests/ada_api/gpr2_project_unit_provider/main.adb +++ b/testsuite/tests/ada_api/gpr2_project_unit_provider/main.adb @@ -14,7 +14,6 @@ with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Common; use Libadalang.Common; -with Libadalang.Iterators; use Libadalang.Iterators; with Libadalang.Project_Provider; use Libadalang.Project_Provider; procedure Main is @@ -79,7 +78,49 @@ procedure Main is -- Resolve -- ------------- - procedure Resolve (Project : String; Unit_Name : Text_Type) is + procedure Resolve + (Project : String; + Unit_Name : Text_Type; + Kind : Analysis_Unit_Kind := Unit_Specification) + is + function Process (N : Ada_Node'Class) return Visit_Status; + -- If ``N`` has a reference whose resolution must be tested, do it + + ------------- + -- Process -- + ------------- + + function Process (N : Ada_Node'Class) return Visit_Status is + Ref, Decl : Ada_Node; + begin + Ref := N.As_Ada_Node; + case N.Kind is + when Ada_Object_Decl => + Ref := + N + .As_Object_Decl + .F_Type_Expr + .As_Ada_Node; + Decl := + Ref + .As_Subtype_Indication + .P_Designated_Type_Decl_From (N.As_Ada_Node) + .As_Ada_Node; + + when Ada_Subp_Body_Stub => + Decl := Ref.As_Subp_Body_Stub.P_Next_Part_For_Decl.As_Ada_Node; + + when others => + Ref := No_Ada_Node; + end case; + + if not Ref.Is_Null then + Put_Line (Ref.Image & " resolves to:"); + Put_Line (" " & Decl.Image); + end if; + + return Into; + end Process; begin Put_Line ("== Resolutions in " & Project & " =="); New_Line; @@ -87,18 +128,9 @@ procedure Main is Ctx : constant Analysis_Context := Create_Context (Unit_Provider => Load_Project (Project)); Unit : constant Analysis_Unit := - Get_From_Provider (Ctx, Unit_Name, Unit_Specification); - Root : constant Ada_Node := Unit.Root; - - Subtype_Ind : constant Subtype_Indication := Find_First - (Root, Kind_Is (Ada_Subtype_Indication)).As_Subtype_Indication; - Res_Type : constant Ada_Node_Array := - Subtype_Ind.F_Name.P_Matching_Nodes; + Get_From_Provider (Ctx, Unit_Name, Kind); begin - Put_Line (Subtype_Ind.Image & " resolves to:"); - for E of Res_Type loop - Put_Line (" " & E.Image); - end loop; + Unit.Root.Traverse (Process'Access); end; New_Line; end Resolve; @@ -116,6 +148,7 @@ begin New_Line; Resolve ("p.gpr", "p2"); + Resolve ("p.gpr", "p3", Unit_Body); Resolve ("multi_unit_files_1.gpr", "objects"); Resolve ("multi_unit_files_2.gpr", "objects"); Resolve ("extending.gpr", "ext"); diff --git a/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3-p.adb b/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3-p.adb new file mode 100644 index 000000000..3553faac3 --- /dev/null +++ b/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3-p.adb @@ -0,0 +1,5 @@ +separate (P3) +procedure P is +begin + null; +end P; diff --git a/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3.ada_specification b/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3.ada_specification new file mode 100644 index 000000000..115b44248 --- /dev/null +++ b/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3.ada_specification @@ -0,0 +1,3 @@ +package P3 is + procedure P; +end P3; diff --git a/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3.adb b/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3.adb new file mode 100644 index 000000000..b8cd45f53 --- /dev/null +++ b/testsuite/tests/ada_api/gpr2_project_unit_provider/src1/p3.adb @@ -0,0 +1,3 @@ +package body P3 is + procedure P is separate; +end; diff --git a/testsuite/tests/ada_api/gpr2_project_unit_provider/test.out b/testsuite/tests/ada_api/gpr2_project_unit_provider/test.out index 171cc4789..3df4038a6 100644 --- a/testsuite/tests/ada_api/gpr2_project_unit_provider/test.out +++ b/testsuite/tests/ada_api/gpr2_project_unit_provider/test.out @@ -25,6 +25,12 @@ Loading p.gpr... resolves to: +== Resolutions in p.gpr == + +Loading p.gpr... + resolves to: + + == Resolutions in multi_unit_files_1.gpr == Loading multi_unit_files_1.gpr...