Skip to content

Commit c5556a8

Browse files
authored
Merge pull request #88 from JohT/feature/refine-content
Minor improvements and refinements
2 parents b42308f + ec9fdf2 commit c5556a8

File tree

8 files changed

+88
-9
lines changed

8 files changed

+88
-9
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ Contained within this repository is a comprehensive and automated code graph ana
88

99
## ✨ Features
1010

11-
- Analyze static code structure as a graph
11+
- Analyze static Java code structure as a graph
1212
- Fully automated [pipeline](./.github/workflows/code-structure-analysis.yml) from tool installation to report generation
13-
- Comprehensive reports including dependencies, metrics and graph structure visualization
13+
- 130 CSV reports including dependencies, metrics, cycles, annotations, algorithms and many more
14+
- 9 Jupyter notebook reports including dependencies, metrics, visibility and many more
15+
- Graph structure visualization
1416
- Automated reference document generation
1517
- Runtime and library independent automation using [shell scripts](./scripts/SCRIPTS.md)
1618
- Tested on MacOS (zsh), Linux (bash) and Windows (Git Bash)
@@ -172,3 +174,15 @@ The [Code Structure Analysis Pipeline](./.github/workflows/code-structure-analys
172174
```shell
173175
ENABLE_JUPYTER_NOTEBOOK_PDF_GENERATION=true ./../../scripts/analysis/analyze.sh
174176
```
177+
178+
## 🕸 Web References
179+
180+
- [Graph Data Science 101: Understanding Graphs and Graph Data Science](https://techfirst.medium.com/graph-data-science-101-understanding-graphs-and-graph-data-science-c25055a9db01)
181+
- [The Story behind Russian Twitter Trolls](https://neo4j.com/blog/story-behind-russian-twitter-trolls)
182+
- [Graphs for Data Science and Machine Learning](https://de.slideshare.net/neo4j/graphs-for-data-science-and-machine-learning)
183+
- [Modularity](https://www.cs.cmu.edu/~ckingsf/bioinfo-lectures/modularity.pdf)
184+
- [Graph Data Science Centrality Algorithms](https://neo4j.com/docs/graph-data-science/2.5/algorithms/centrality)
185+
- [Graph Data Science Community Detection Algorithms](https://neo4j.com/docs/graph-data-science/2.5/algorithms/community)
186+
- [Graph Data Science Community Similarity Algorithms](https://neo4j.com/docs/graph-data-science/2.5/algorithms/similarity)
187+
- [Graph Data Science Community Topological Sort Algorithm](https://neo4j.com/docs/graph-data-science/2.5/algorithms/dag/topological-sort)
188+
- [Node embeddings for Beginners](https://towardsdatascience.com/node-embeddings-for-beginners-554ab1625d98)

cypher/Java/Java_Reflection_usage.cypher

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
MATCH (dependentArtifact:Artifact)-[:CONTAINS]-(dependentType:Type)
44
WITH replace(last(split(dependentArtifact.fileName, '/')), '.jar', '') AS dependentArtifactName
5-
,dependentType AS dependentType
5+
,dependentType
66
OPTIONAL MATCH (dependentType)-[:DEPENDS_ON]->(reflectionType:Type)
77
WHERE reflectionType.fqn STARTS WITH 'java.lang.reflect.'
88
OPTIONAL MATCH (dependentType)-[:DECLARES]->(dependentMethod:Method)-[:INVOKES]->(classForName:Method)
99
WHERE classForName.signature STARTS WITH 'java.lang.Class forName'
1010
WITH dependentArtifactName
11-
,collect(DISTINCT coalesce(reflectionType.fqn, 'Class.forName')) AS reflectionTypes
11+
,collect(DISTINCT coalesce(reflectionType.fqn, 'Class.' + classForName.name)) AS reflectionTypes
1212
,collect(DISTINCT dependentType.fqn) AS reflectionCaller
1313
,count(DISTINCT dependentType.fqn) AS numberOfReflectionCaller
1414
RETURN dependentArtifactName
1515
,numberOfReflectionCaller
16+
,reflectionCaller[0..19] AS someReflectionCaller
1617
,reflectionTypes[0..19] AS someReflectionTypes
17-
,reflectionCaller[0..19] AS someDependentTypes
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Query all types that use Java Reflection or "Class.forName"
2+
3+
MATCH (dependentArtifact:Artifact)-[:CONTAINS]-(dependentType:Type)
4+
WITH replace(last(split(dependentArtifact.fileName, '/')), '.jar', '') AS dependentArtifactName
5+
,dependentType
6+
OPTIONAL MATCH (dependentType)-[:DEPENDS_ON]->(reflectionType:Type)
7+
WHERE reflectionType.fqn STARTS WITH 'java.lang.reflect.'
8+
OPTIONAL MATCH (dependentType)-[:DECLARES]->(dependentMethod:Method)-[:INVOKES]->(classForName:Method)
9+
WHERE classForName.signature STARTS WITH 'java.lang.Class forName'
10+
WITH dependentArtifactName
11+
,dependentType.fqn AS reflectionCallerTypeName
12+
,collect(DISTINCT coalesce(reflectionType.fqn, 'Class.' + classForName.name)) AS reflectionTypes
13+
WHERE size(reflectionTypes) > 0
14+
RETURN dependentArtifactName
15+
,reflectionCallerTypeName
16+
,reflectionTypes[0..19] AS reflectionTypes
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// List all non deprecated elements (types, members) that call deprecated elements
2+
3+
MATCH (annotated)-[:ANNOTATED_BY]->(:Annotation)-[:OF_TYPE]->(:Type{fqn:'java.lang.Deprecated'})
4+
OPTIONAL MATCH (artifactReadsDeprecated:Artifact)-[:CONTAINS]->(typeReadsDeprecated:Type)-[:DECLARES]->(readsDeprecated:Method)-[:READS]->(annotated:Field)
5+
OPTIONAL MATCH (artifactInvokesDeprecated:Artifact)-[:CONTAINS]->(typeInvokesDeprecated:Type)-[:DECLARES]->(invokesDeprecated:Method)-[:INVOKES]->(annotated:Method)
6+
OPTIONAL MATCH (artifactInvokesParameterDeprecated:Artifact)-[:CONTAINS]->(typeInvokesParameterDeprecated:Type)-[:DECLARES]->(invokesParameterDeprecated:Method)-[:INVOKES]->(parameterAnnotatedMethod:Method)-[:HAS]->(annotated:Parameter)
7+
OPTIONAL MATCH (artifactDependsOnDeprecated:Artifact)-[:CONTAINS]->(typeDependsOnDeprecated:Type)-[:DEPENDS_ON]->(annotated:Type)
8+
WITH coalesce(artifactReadsDeprecated, artifactInvokesDeprecated, artifactInvokesParameterDeprecated, artifactDependsOnDeprecated) AS artifact
9+
,coalesce(typeReadsDeprecated, typeInvokesDeprecated, typeInvokesParameterDeprecated, typeDependsOnDeprecated) AS type
10+
,coalesce(readsDeprecated, invokesDeprecated, invokesParameterDeprecated) AS method
11+
,coalesce(annotated.fqn, annotated.signature, annotated.name) AS deprecatedElement
12+
,CASE WHEN 'Annotation' IN labels(annotated) THEN 'Annotation'
13+
WHEN 'Parameter' IN labels(annotated) THEN 'Parameter'
14+
WHEN 'Field' IN labels(annotated) THEN 'Field'
15+
WHEN 'Constructor' IN labels(annotated) THEN 'Constructor'
16+
WHEN 'Method' IN labels(annotated) THEN 'Method'
17+
WHEN 'Member' IN labels(annotated) THEN 'Member'
18+
WHEN 'Class' IN labels(annotated) THEN 'Class'
19+
WHEN 'Interface' IN labels(annotated) THEN 'Interface'
20+
WHEN 'Enum' IN labels(annotated) THEN 'Enum'
21+
WHEN 'Type' IN labels(annotated) THEN 'Type'
22+
ELSE 'Unexpected'
23+
END AS deprecatedElementType
24+
,coalesce(typeReadsDeprecated.fqn + '.' + readsDeprecated.name
25+
,typeInvokesDeprecated.fqn + '.' + invokesDeprecated.name
26+
,typeInvokesParameterDeprecated.fqn + '.' + invokesParameterDeprecated.name
27+
,typeDependsOnDeprecated.fqn
28+
) AS elementUsingDeprecatedElement
29+
WHERE artifact IS NOT NULL
30+
AND NOT (type)-[:ANNOTATED_BY]->(:Annotation)-[:OF_TYPE]->(:Type{fqn:'java.lang.Deprecated'})
31+
AND NOT (method)-[:ANNOTATED_BY]->(:Annotation)-[:OF_TYPE]->(:Type{fqn:'java.lang.Deprecated'})
32+
RETURN replace(last(split(artifact.fileName, '/')), '.jar', '') AS artifactName
33+
,deprecatedElementType
34+
,elementUsingDeprecatedElement
35+
,deprecatedElement
36+
ORDER BY artifactName ASCENDING
37+
,elementUsingDeprecatedElement ASCENDING

reports/java-csv/ReflectionUsage.csv

Whitespace-only changes.

scripts/reports/CommunityCsv.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,13 @@ calculateCommunityMetrics() {
363363
writeLeidenModularity() {
364364
local COMMUNITY_DETECTION_CYPHER_DIR="${CYPHER_DIR}/Community_Detection"
365365
local writePropertyName="dependencies_projection_write_property=communityLeidenId"
366-
execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_7e_Write_Modularity.cypher" "${@}" "${writePropertyName}"
366+
local writtenModularity
367+
if writtenModularity=$( execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_7e_Write_Modularity.cypher" "${@}" "${writePropertyName}" ); then
368+
echo "${writtenModularity}"
369+
echo "communityCsv: Successfully written Leiden Modularity per node with parameters ${*}"
370+
else
371+
echo "communityCsv: Error: Failed to write Leiden Modularity per node with parameters ${*}"
372+
fi
367373
}
368374

369375
# Compare the results of different community detection algorighms
@@ -419,7 +425,7 @@ PACKAGE_GAMMA="dependencies_leiden_gamma=1.14" # default = 1.00
419425
PACKAGE_KCUT="dependencies_maxkcut=20" # default = 2
420426

421427
# Package Community Detection
422-
echo "communityCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') communityCsv: Processing package dependencies..."
428+
echo "communityCsv: $(date +'%Y-%m-%dT%H:%M:%S%z'): Processing package dependencies..."
423429
createProjection "${PACKAGE_PROJECTION}" "${PACKAGE_NODE}" "${PACKAGE_WEIGHT}"
424430
detectCommunities "${PACKAGE_PROJECTION}" "${PACKAGE_NODE}" "${PACKAGE_WEIGHT}" "${PACKAGE_GAMMA}" "${PACKAGE_KCUT}"
425431
writeLeidenModularity "${PACKAGE_PROJECTION}" "${PACKAGE_NODE}" "${PACKAGE_WEIGHT}"

scripts/reports/JavaCsv.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,13 @@ mkdir -p "${FULL_REPORT_DIRECTORY}"
3737
# Local Constants
3838
JAVA_CYPHER_DIR="${CYPHER_DIR}/Java"
3939

40+
echo "JavaCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Executing Queries..."
41+
4042
execute_cypher "${JAVA_CYPHER_DIR}/Java_Reflection_usage.cypher" > "${FULL_REPORT_DIRECTORY}/ReflectionUsage.csv"
43+
execute_cypher "${JAVA_CYPHER_DIR}/Java_Reflection_usage_detailed.cypher" > "${FULL_REPORT_DIRECTORY}/ReflectionUsageDetailed.csv"
4144
execute_cypher "${JAVA_CYPHER_DIR}/Java_deprecated_element_usage.cypher" > "${FULL_REPORT_DIRECTORY}/DeprecatedElementUsage.csv"
45+
execute_cypher "${JAVA_CYPHER_DIR}/Java_deprecated_element_usage_detailed.cypher" > "${FULL_REPORT_DIRECTORY}/DeprecatedElementUsageDetailed.csv"
4246
execute_cypher "${JAVA_CYPHER_DIR}/Annotated_code_elements.cypher" > "${FULL_REPORT_DIRECTORY}/AnnotatedCodeElements.csv"
43-
execute_cypher "${JAVA_CYPHER_DIR}/Annotated_code_elements_per_artifact.cypher" > "${FULL_REPORT_DIRECTORY}/AnnotatedCodeElementsPerArtifact.csv"
47+
execute_cypher "${JAVA_CYPHER_DIR}/Annotated_code_elements_per_artifact.cypher" > "${FULL_REPORT_DIRECTORY}/AnnotatedCodeElementsPerArtifact.csv"
48+
49+
echo "JavaCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Successfully finished"

scripts/reports/TopologicalSortCsv.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ topologicalSort() {
7676
# Stream to CSV
7777
local nodeLabel
7878
nodeLabel=$( extractQueryParameter "dependencies_projection_node" "${@}" )
79-
execute_cypher "${TOPOLOGICAL_SORT_DIR}/Topological_Sort_Query.cypher" "${@}" > "${FULL_REPORT_DIRECTORY}/${nodeLabel}_Topolical_Sort.csv"
79+
execute_cypher "${TOPOLOGICAL_SORT_DIR}/Topological_Sort_Query.cypher" "${@}" > "${FULL_REPORT_DIRECTORY}/${nodeLabel}_Topological_Sort.csv"
8080
}
8181

8282
# ---------------------------------------------------------------

0 commit comments

Comments
 (0)