我使用ASIS分析一个大型的Ada项目。我需要做的一件事是在记录变量中找到字符串字段的'First
和'Last
表达式。
如果我的Discrete_Range
A_Discrete_Simple_Expression_Range
不是Lower_Bound
(可以直接使用函数Upper_Bound
和A_Discrete_Range_Attribute_Reference
而是with Ada.Text_IO;
procedure Minimal_Example is
type R is
record
F : String (1 .. 5);
end record;
V : R;
subtype S is String (V.F'Range); -- It would have been nice if they didn't do like this.
function F return S is ("12345");
begin
Ada.Text_IO.Put_Line (F);
end Minimal_Example;
),我的问题会发生,而是{{ 1}}。
我分析的源代码示例基本上如下:
-- Standard library packages:
with Ada.Wide_Text_IO;
-- ASIS packages:
with Asis;
with Asis.Ada_Environments;
with Asis.Compilation_Units;
with Asis.Declarations;
with Asis.Definitions;
with Asis.Elements;
with Asis.Expressions;
with Asis.Implementation;
with Asis.Iterator;
with Asis.Statements;
with Asis.Text;
procedure Minimal_Analyzer is
procedure Pre_Operation (Element : in Asis.Element;
Control : in out Asis.Traverse_Control;
State : in out Boolean) is
pragma Unreferenced (Control, State);
use all type Asis.Element_Kinds;
use all type Asis.Statement_Kinds;
begin
if Asis.Elements.Element_Kind (Element) = A_Statement and then
Asis.Elements.Statement_Kind (Element) = A_Procedure_Call_Statement
then
for Parameter_Association of Asis.Statements.Call_Statement_Parameters (Statement => Element,
Normalized => True) loop
declare
Actual_Parameter : Asis.Element;
Type_Of_Expression : Asis.Element;
Type_Definition : Asis.Definition;
Constraint : Asis.Constraint;
begin
Actual_Parameter := Asis.Expressions.Actual_Parameter (Parameter_Association);
Type_Of_Expression := Asis.Expressions.Corresponding_Expression_Type (Actual_Parameter);
Type_Definition := Asis.Declarations.Type_Declaration_View (Declaration => Type_Of_Expression);
Constraint := Asis.Definitions.Subtype_Constraint (Type_Definition);
for Index_Range of Asis.Definitions.Discrete_Ranges (Constraint) loop
declare
Range_Attribute : Asis.Definition;
Range_Prefix : Asis.Element;
begin
Range_Attribute := Asis.Definitions.Range_Attribute (Index_Range);
Range_Prefix := Asis.Expressions.Prefix (Range_Attribute);
Ada.Wide_Text_IO.Put_Line (Asis.Elements.Debug_Image (Range_Prefix));
Ada.Wide_Text_IO.Put_Line (Asis.Text.Element_Image (Range_Prefix));
end;
end loop;
end;
end loop;
end if;
end Pre_Operation;
procedure Post_Operation (Element : in Asis.Element;
Control : in out Asis.Traverse_Control;
State : in out Boolean) is null;
procedure Traverse_Declaration is
new Asis.Iterator.Traverse_Element (State_Information => Boolean,
Pre_Operation => Pre_Operation,
Post_Operation => Post_Operation);
Context : Asis.Context;
begin
Asis.Implementation.Initialize ("");
Asis.Ada_Environments.Associate (The_Context => Context,
Name => "CLPG",
Parameters => "-CA -FM");
Asis.Ada_Environments.Open (The_Context => Context);
Analyze :
declare
Complation_Unit_Body : Asis.Compilation_Unit;
Complation_Unit_Body_Declaration : Asis.Declaration;
Process_Control : Asis.Traverse_Control := Asis.Continue;
State : Boolean := False;
begin
Complation_Unit_Body := Asis.Compilation_Units.Compilation_Unit_Body (Name => "Minimal_Example",
The_Context => Context);
Complation_Unit_Body_Declaration := Asis.Elements.Unit_Declaration (Compilation_Unit => Complation_Unit_Body);
Traverse_Declaration (Element => Complation_Unit_Body_Declaration,
Control => Process_Control,
State => State);
end Analyze;
Asis.Ada_Environments.Close (The_Context => Context);
Asis.Ada_Environments.Dissociate (The_Context => Context);
Asis.Implementation.Finalize (Parameters => "");
end Minimal_Analyzer;
以下是我用于执行分析的程序的最小化版本:
with "asis";
project Build is
for Main use ("minimal_analyzer.adb",
"minimal_example.adb");
for Source_Dirs use (".");
for Object_Dir use "obj";
for Exec_Dir use "bin";
package Builder is
for Default_Switches ("Ada") use ("-m", -- Do not recompile if only comments have changed
"-s", -- Recompile if switches change
"-j0"); -- Build concurrently
end Builder;
package Compiler is
for Default_Switches ("Ada") use ("-gnatoU",
"-gnat2012",
"-funwind-tables",
"-fstack-check",
"-gnata");
end Compiler;
end Build;
项目文件:
gprbuild -j0 -p -P build.gpr
构建命令:
minimal_analyzer
您需要安装ASIS才能构建该工具。如果您从minimal_example.adb
所在的目录运行Element Debug_Image:
A_SELECTED_COMPONENT
located in Minimal_Example (body, Unit_Id = 2, Context_Id = 1)
text position : minimal_example.adb:8:40
Nodes:
Node : 2332 - N_SELECTED_COMPONENT
R_Node : 2332 - N_SELECTED_COMPONENT
Node_Field_1 : 0 - N_EMPTY
Node_Field_2 : 0 - N_EMPTY
Rel_Sloc : 157
obtained from the tree /tmp/minimal_example.adt (Tree_Id = 1)
V.F
,则会获得输出:
V.F
...但是如何才能了解Discrete_Simple_Expression_Range
的定义,以便我可以提取1 .. 5
@Repository
public interface TestRepository extends CrudRepository<com.example.demo.Test, Long> {
}
?
答案 0 :(得分:4)
我找到了解决方案:
诀窍是知道何时使用ASIS.Expressions.Corresponding_Name_Declaration
...
-- Standard library packages:
with Ada.Wide_Text_IO;
-- ASIS packages:
with ASIS;
with ASIS.Ada_Environments;
with ASIS.Compilation_Units;
with ASIS.Declarations;
with ASIS.Definitions;
with ASIS.Elements;
with ASIS.Expressions;
with ASIS.Implementation;
with ASIS.Iterator;
with ASIS.Statements;
with ASIS.Text;
procedure Minimal_Analyzer is
procedure Pre_Operation (Element : in ASIS.Element;
Control : in out ASIS.Traverse_Control;
State : in out Boolean) is
pragma Unreferenced (Control, State);
use all type ASIS.Element_Kinds;
use all type ASIS.Statement_Kinds;
begin
if ASIS.Elements.Element_Kind (Element) = A_Statement and then
ASIS.Elements.Statement_Kind (Element) = A_Procedure_Call_Statement
then
for Parameter_Association of ASIS.Statements.Call_Statement_Parameters (Statement => Element,
Normalized => True) loop
declare
Actual_Parameter : ASIS.Element;
Type_Of_Expression : ASIS.Element;
Type_Definition : ASIS.Definition;
Constraint : ASIS.Constraint;
begin
Actual_Parameter := ASIS.Expressions.Actual_Parameter (Parameter_Association);
Type_Of_Expression := ASIS.Expressions.Corresponding_Expression_Type (Actual_Parameter);
Type_Definition := ASIS.Declarations.Type_Declaration_View (Declaration => Type_Of_Expression);
Constraint := ASIS.Definitions.Subtype_Constraint (Type_Definition);
for Index_Range of ASIS.Definitions.Discrete_Ranges (Constraint) loop
declare
Range_Attribute : ASIS.Definition;
Range_Prefix : ASIS.Element;
Field_Name : ASIS.Defining_Name;
Field_Declaration : ASIS.Element;
Field_Definition : ASIS.Definition;
Field_Type_Definition : ASIS.Definition;
Constraint : ASIS.Constraint;
begin
Range_Attribute := ASIS.Definitions.Range_Attribute (Index_Range);
Range_Prefix := ASIS.Expressions.Prefix (Range_Attribute);
Field_Name := ASIS.Expressions.Selector (Range_Prefix);
Field_Declaration := ASIS.Expressions.Corresponding_Name_Declaration (Field_Name);
Field_Definition := ASIS.Declarations.Object_Declaration_View (Field_Declaration);
Field_Type_Definition := ASIS.Definitions.Component_Definition_View (Component_Definition => Field_Definition);
Constraint := ASIS.Definitions.Subtype_Constraint (Field_Type_Definition);
for Index_Range of ASIS.Definitions.Discrete_Ranges (Constraint) loop
declare
First, Last : ASIS.Expression;
begin
First := ASIS.Definitions.Lower_Bound (Index_Range);
Last := ASIS.Definitions.Upper_Bound (Index_Range);
Ada.Wide_Text_IO.Put_Line (ASIS.Elements.Debug_Image (First));
Ada.Wide_Text_IO.Put_Line (ASIS.Text.Element_Image (First));
Ada.Wide_Text_IO.Put_Line (ASIS.Elements.Debug_Image (Last));
Ada.Wide_Text_IO.Put_Line (ASIS.Text.Element_Image (Last));
end;
end loop;
end;
end loop;
end;
end loop;
end if;
end Pre_Operation;
procedure Post_Operation (Element : in ASIS.Element;
Control : in out ASIS.Traverse_Control;
State : in out Boolean) is null;
procedure Traverse_Declaration is
new ASIS.Iterator.Traverse_Element (State_Information => Boolean,
Pre_Operation => Pre_Operation,
Post_Operation => Post_Operation);
Context : ASIS.Context;
begin
ASIS.Implementation.Initialize ("");
ASIS.Ada_Environments.Associate (The_Context => Context,
Name => "CLPG",
Parameters => "-CA -FM");
ASIS.Ada_Environments.Open (The_Context => Context);
Analyze :
declare
Complation_Unit_Body : ASIS.Compilation_Unit;
Complation_Unit_Body_Declaration : ASIS.Declaration;
Process_Control : ASIS.Traverse_Control := ASIS.Continue;
State : Boolean := False;
begin
Complation_Unit_Body := ASIS.Compilation_Units.Compilation_Unit_Body (Name => "Minimal_Example",
The_Context => Context);
Complation_Unit_Body_Declaration := ASIS.Elements.Unit_Declaration (Compilation_Unit => Complation_Unit_Body);
Traverse_Declaration (Element => Complation_Unit_Body_Declaration,
Control => Process_Control,
State => State);
end Analyze;
ASIS.Ada_Environments.Close (The_Context => Context);
ASIS.Ada_Environments.Dissociate (The_Context => Context);
ASIS.Implementation.Finalize (Parameters => "");
end Minimal_Analyzer;