The Dependency Graph Extractor generates a GraphML file with dependency information derived from the Ada source files contained within the given project files.
Run the Dependency Graph Extractor as follows:
dependency_graph_extractor.exe -o output.graphml [-p directory] project_1.gpr ... project_n.gpr
-h, --help Display help
-o, --output=ARG The output GraphML file
-p, --prefix=ARG Directory prefix stripped from the file names in the output graph
The output GraphML file is required, as is at least one GPR file. If the output GraphML file already exists, it will be overwritten.
Optionally, a directory prefix can be passed to the extractor using the -p
option. When done so, the extractor removes the prefix from every filename in the generated GraphML file. Note that, if a filename does not start with the specified prefix, it wil occur in the GraphML file as-is.
Note. Although Dependency Graph Extractor can analyse multiple projects, it can't analyze an aggregate project with more than one sub-project.
Suppose we want to extract source code dependency information from the GPR project named rejuvenation.gpr
,
which is located in C:\path\to\Renaissance-Ada\src\libraries\rejuvenation
.
Moreover, suppose we do not want have the C:\path\to\Renaissance-Ada\src\libraries\rejuvenation
prefix occurring in the generated GraphML file.
To achieve this, we can run the Dependency Graph Extractor
directly from alire
as follows:
alr run --args="-o rejuvenation.graphml -p C:\path\to\Renaissance-Ada\src\libraries\rejuvenation C:\path\to\Renaissance-Ada\src\libraries\rejuvenation\rejuvenation.gpr"
Or just as a normal program:
dependency_graph_extractor.exe -o rejuvenation.graphml -p C:\path\to\Renaissance-Ada\src\libraries\rejuvenation C:\path\to\Renaissance-Ada\src\libraries\rejuvenation\rejuvenation.gpr
when either dependency_graph_extractor.exe
is on the system PATH
or the current directory is the obj
directory of the Dependency_Graph_Extractor project.
This will create the GraphML file rejuvenation.graphml
in the current directory.
Open the generated graphml
file with Neo4j according to the import instructions.
Note, your cypher query should resemble
CALL apoc.import.graphml("movies.graphml", {readLabels: true})
Prepare yourself by reading the Node and Edge Types present in the graph database.
You can now interactively query the graph database using Cypher. For more info on Cypher, see the Cypher resources, including the Neo4j Cypher refcard.
Below, you find some example Cypher queries.
Note that all example queries are rather general.
So add LIMIT 25
to the end of the queries
whenever your code base contains a lot of matches to still get a fast response.
Run the Cypher query
MATCH (f)-[:Calls]->(f) RETURN *
to find all recursive functions.
Run the Cypher query
MATCH (f)-[:Calls*]->(f) RETURN *
to find all recursion.
Run the Cypher query
MATCH (a)-[:Calls*]->(b)-[:Calls*]->(a) RETURN *
to find indirect recursion only.
Run the Cypher query
MATCH
p = (decl_begin:AdaDeclaration)-[:References*]->(decl_end:AdaDeclaration),
(decl_begin)-[source_begin:Source]->(file_begin:File),
(decl_end)-[source_end:Source]->(file_end:File)
WHERE
file_begin.relativeName = "rejuvenation-patterns.adb" AND
file_end.relativeName = "rejuvenation-simple_factory.ads"
RETURN p
to find all chains of references that begin with a declaration in "rejuvenation-patterns.adb" and end on a declaration in "rejuvenation-simple_factory.ads"
Run the Cypher query
CALL
{
MATCH
(provider:AdaDeclaration)-[:Source]->(adsFile:AdaSpecificationFile)
WHERE
adsFile.name ENDS WITH "rejuvenation-string_utils.ads"
RETURN provider
}
WITH provider,
size (()-[:References]->(provider)) as refCount
RETURN provider.relativeName, refCount ORDER BY refCount DESC
to get a table of all declarations in "rejuvenation-string_utils.ads" and how often each declaration is directly referenced.
Run the Cypher query
MATCH
(provider:AdaDeclaration)-[:Source]->(adsFile:AdaSpecificationFile),
(user)-[:References]->(provider)
WHERE
adsFile.name ENDS WITH "rejuvenation-string_utils.ads"
RETURN user, provider
to get the declarations in "rejuvenation-string_utils.ads" that are referenced together with the refering entities.
Run the Cypher query
MATCH
(depProject:GnatProject)-[:Contains]->(depFile)<-[:Source]-(dep:AdaDeclaration),
(dge)-[:References]->(dep),
(dgeProject:GnatProject)-[:Contains]->(dgeFile)<-[:Source]-(dge:AdaDeclaration)
WHERE
depProject.relativeName <> "Dependency_Graph_Extractor" AND
dgeProject.relativeName = "Dependency_Graph_Extractor"
RETURN
dep.fullyQualifiedName, count(dge) as depCount
ORDER BY depCount DESC
to get the declarations outside the Dependency_Graph_Extractor project, that are used by the Dependency_Graph_Extractor project together with their number of references. The textual output is similar to
╒══════════════════════════════════════════════════════════════════════╤══════════╕
│"dep.fullyQualifiedName" │"depCount"│
╞══════════════════════════════════════════════════════════════════════╪══════════╡
│"Libadalang.Analysis.Ada_Node" │67 │
├──────────────────────────────────────────────────────────────────────┼──────────┤
│"Libadalang.Analysis.Basic_Decl" │61 │
├──────────────────────────────────────────────────────────────────────┼──────────┤
│"GNATCOLL.VFS.Virtual_File" │46 │
├──────────────────────────────────────────────────────────────────────┼──────────┤
│"Libadalang.Analysis.Kind" │41 │
├──────────────────────────────────────────────────────────────────────┼──────────┤
│"GNATCOLL.Projects.Project_Type" │24 │
├──────────────────────────────────────────────────────────────────────┼──────────┤
│"Libadalang.Analysis.Defining_Name" │23 │
├──────────────────────────────────────────────────────────────────────┼──────────┤
...
- Install Alire.
- Install Git.
- Clone the Dependency Graph Extractor project:
git clone https://github.com/TNO/Dependency_Graph_Extractor-Ada.git
. - Start the
PowerShell
terminal withAlire
in the environmentPATH
(installed by Alire by default on your desktop). - Navigate to the directory containing the Dependency Graph Extractor.
- Ensure alire has the latest information by running
alr update --online
in that directory. - Execute
alr build
in that directory.