Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,6 @@ Please read through the [Prerequisites](./README.md#hammer_and_wrench-prerequisi
Then open your browser and login to your [local Neo4j Web UI](http://localhost:7474/browser) with "neo4j" as user and the initial password you've chosen.

👉 See [scripts/examples/analyzeAxonFramework.sh](./scripts/examples/analyzeAxonFramework.sh) as an example script that combines all the above steps for a Java Project.
👉 See [scripts/examples/analyzeReactRouter.sh](./scripts/examples/analyzeReactRouter.sh) as an example script that combines all the above steps for a Typescript Project.
👉 See [Code Structure Analysis Pipeline](./.github/workflows/java-code-analysis.yml) on how to do this within a GitHub Actions Workflow.
👉 See [scripts/examples/analyzeReactRouter.sh](./scripts/examples/analyzeReactRouter.sh) as an example script that combines all the above steps for a Typescript Project.
👉 See [scripts/examples/analyzeAntDesign.sh](./scripts/examples/analyzeAntDesign.sh) as an example script that combines all the above steps for a large scale monorepo Typescript Project.
👉 See [Code Structure Analysis Pipeline](./.github/workflows/java-code-analysis.yml) on how to do this within a GitHub Actions Workflow.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Explore Typescript nodes with globalFqn property by their label, count and if they came from the node_modules folder

MATCH (typescript:TS)
WHERE typescript.globalFqn IS NOT NULL
RETURN labels(file)[0..4] AS nodeType
,(typescript.globalFqn contains '/node_modules/') AS isNodeModule
,count(*) AS numberOfNodes
,collect(DISTINCT typescript.globalFqn)[0..9] AS examples
ORDER BY nodeType ASC, numberOfNodes DESC
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// External Typescript module usage overall

MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
WITH count(DISTINCT internalElement.globalFqn) AS allInternalElements
,count(DISTINCT internalModule.globalFqn) AS allModules
,collect(DISTINCT internalElement) AS internalElementList
UNWIND internalElementList AS internalElement
MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
WHERE externalDeclaration.isExternalImport = true
MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
WITH allInternalElements
,allModules
,coalesce(nullIf(externalModule.namespace, '') + '/' + externalModule.name, externalModule.name) AS externalModuleName
,count(DISTINCT internalModule.globalFqn) AS numberOfExternalCallerModules
,count(DISTINCT internalElement.globalFqn) AS numberOfExternalCallerElements
,count(externalDependency) AS numberOfExternalDeclarationCalls
,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCallsWeighted
,collect('<' + internalElement.name
+ '> of module <'
+ internalModule.name
+ '> imports <'
+ externalDeclaration.name
+ '> from external module <'
+ externalModule.name + '>')[0..4] AS exampleStories
RETURN externalModuleName
,numberOfExternalCallerModules
,numberOfExternalCallerElements
,numberOfExternalDeclarationCalls
,numberOfExternalDeclarationCallsWeighted
,allModules
,allInternalElements
,exampleStories
ORDER BY numberOfExternalCallerModules DESC, externalModuleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// External Typescript module usage per interal module aggregated

// Get the overall internal module statistics first
MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
WITH internalModule.name AS internalModuleName
,internalModule.communityLeidenId AS leidenCommunityId
,count(DISTINCT internalElement.globalFqn) AS internalModuleElementsCount
,collect(DISTINCT internalElement) AS internalElementList

// Get the external dependencies for each internal internalElement
UNWIND internalElementList AS internalElement
MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
MATCH (internalModule:Module)-[:EXPORTS]->(internalElement)
MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
WHERE externalDeclaration.isExternalImport = true
WITH internalModuleName
,leidenCommunityId
,internalModuleElementsCount
,internalModule.globalFqn AS fullInternalModuleName
,internalElement.globalFqn AS fullInternalElementName
,coalesce(
nullIf(externalModule.namespace, '') + '/' + externalModule.name,
externalModule.name) AS externalModuleName

// Group by internalModule and external internalElement
WITH internalModuleName
,leidenCommunityId
,internalModuleElementsCount
,externalModuleName
,count(DISTINCT fullInternalModuleName) AS internalModulesCount
,COLLECT(DISTINCT fullInternalModuleName)[0..9] AS internalModulesExamples
,count(DISTINCT fullInternalElementName) AS internalElementsCount
,COLLECT(DISTINCT fullInternalElementName)[0..9] AS internalElementsExamples
,100.0 / internalModuleElementsCount * count(DISTINCT fullInternalElementName) AS internalElementsCallingExternalRate

// Pre order the results by number of packages that use the external package dependency descending
ORDER BY internalModulesCount DESC, internalModuleName ASC

// Optionally filter out external dependencies that are only used by one internal module
// WHERE internalModulesCount > 1

// Group by internalModule, aggregate statistics and return the results
RETURN internalModuleName
,leidenCommunityId
,internalModuleElementsCount
,count(DISTINCT externalModuleName) AS numberOfExternalModules

// Statistics about the packages and their external package usage count
,min(internalModulesCount) AS minNumberOfInternalModules
,max(internalModulesCount) AS maxNumberOfInternalModules
,percentileCont(internalModulesCount, 0.5) AS medNumberOfInternalModules
,avg(internalModulesCount) AS avgNumberOfInternalModules
,stDev(internalModulesCount) AS stdNumberOfInternalModules

// Statistics about the types and their external package usage count
,min(internalElementsCount) AS minNumberOfInternalElements
,max(internalElementsCount) AS maxNumberOfInternalElements
,percentileCont(internalElementsCount, 0.5) AS medNumberOfInternalElements
,avg(internalElementsCount) AS avgNumberOfInternalElements
,stDev(internalElementsCount) AS stdNumberOfInternalElements

// Statistics about the types and their external package usage count percentage
,min(internalElementsCallingExternalRate) AS minNumberOfInternalElementsPercentage
,max(internalElementsCallingExternalRate) AS maxNumberOfInternalElementsPercentage
,percentileCont(internalElementsCallingExternalRate, 0.5) AS medNumberOfInternalElementsPercentage
,avg(internalElementsCallingExternalRate) AS avgNumberOfInternalElementsPercentage
,stDev(internalElementsCallingExternalRate) AS stdNumberOfInternalElementsPercentage

// Examples of external packages, caller packages and caller types
,collect(externalModuleName)[0..9] AS top10ExternalPackageNamesByUsageDescending
,COLLECT(internalModulesExamples)[0] AS internalModulesExamples
,COLLECT(internalElementsExamples)[0] AS internalElementsExamples

ORDER BY maxNumberOfInternalModules DESC, internalModuleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// External Typescript module usage distribution for internal modules

MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
WITH internalModule.name AS internalModuleName
,count(DISTINCT internalElement.globalFqn) AS numberOfAllInternalElements
,collect(DISTINCT internalElement) AS internalElementList
UNWIND internalElementList AS internalElement
MATCH (internalElement)-[:DEPENDS_ON]->(externalElement:ExternalDeclaration)
WHERE externalElement.isExternalImport = true
MATCH (internalModule:Module)-[:EXPORTS]->(internalElement)
MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalElement)
WITH internalModuleName
,numberOfAllInternalElements
,internalModule.globalFqn AS fullInternalModuleName
,internalElement.globalFqn AS fullInternalElementName
,coalesce(
nullIf(externalModule.namespace, '') + '/' + externalModule.name,
externalModule.name) AS externalModuleName
WITH internalModuleName
,numberOfAllInternalElements
,count(DISTINCT externalModuleName) AS externalModuleCount
,COLLECT(DISTINCT externalModuleName)[0..9] AS externalModuleExamples
,count(DISTINCT fullInternalElementName) AS internalElementCount
,COLLECT(DISTINCT fullInternalElementName)[0..9] AS internalElementExamples
RETURN internalModuleName
,numberOfAllInternalElements
,externalModuleCount
,internalElementCount
,100.0 / numberOfAllInternalElements * internalElementCount AS internalElementsCallingExternalRate
,externalModuleExamples
,internalElementExamples
ORDER BY internalElementCount DESC, internalModuleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// External Typescript module usage per internal module sorted by external usage descending

MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
OPTIONAL MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
WHERE externalDeclaration.isExternalImport = true
OPTIONAL MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
WITH internalModule.name AS internalModuleName
,count(DISTINCT internalElement.globalFqn) AS numberOfAllElementsInInternalModule
,count(DISTINCT externalDeclaration.globalFqn) AS numberOfAllExternalDeclarationsUsedInInternalModule
,count(DISTINCT externalModule.globalFqn) AS numberOfAllExternalModulesUsedInInternalModule
,collect(DISTINCT internalElement) AS internalElementList
UNWIND internalElementList AS internalElement
MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
WHERE externalDeclaration.isExternalImport = true
MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
WITH numberOfAllElementsInInternalModule
,numberOfAllExternalDeclarationsUsedInInternalModule
,numberOfAllExternalModulesUsedInInternalModule
,100.0 / numberOfAllElementsInInternalModule * numberOfAllExternalDeclarationsUsedInInternalModule AS externalDeclarationRate
,externalDependency
,internalModuleName
,internalElement.globalFqn AS fullInternalElementName
,internalElement.name AS internalElementName
,coalesce(
nullIf(externalModule.namespace, '') + '/' + externalModule.name,
externalModule.name) AS externalModuleName
,externalDeclaration.name AS externalDeclarationName
WITH numberOfAllElementsInInternalModule
,numberOfAllExternalDeclarationsUsedInInternalModule
,numberOfAllExternalModulesUsedInInternalModule
,externalDeclarationRate
,internalModuleName
,externalModuleName
,count(externalDependency) AS numberOfExternalDeclarationCaller
,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCalls
,collect(DISTINCT externalDeclarationName) AS externalDeclarationNames
RETURN internalModuleName
,externalModuleName
,numberOfExternalDeclarationCaller
,numberOfExternalDeclarationCalls
,numberOfAllElementsInInternalModule
,numberOfAllExternalDeclarationsUsedInInternalModule
,numberOfAllExternalModulesUsedInInternalModule
,externalDeclarationRate
,externalDeclarationNames
ORDER BY externalDeclarationRate DESC
,internalModuleName ASC
,numberOfExternalDeclarationCaller DESC
,externalModuleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// External Typescript module usage spread

// Get the overall internal modules statistics first
MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
WITH count(DISTINCT internalModule.globalFqn) AS internalModulesCountOverall
,count(DISTINCT internalElement.globalFqn) AS internalElementsCountOverall
,collect(DISTINCT internalElement) AS internalElementList

// Get the external declarations for each internal element
UNWIND internalElementList AS internalElement
MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
WHERE externalDeclaration.isExternalImport = true
MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
MATCH (externalModule:TS:ExternalModule)-[:EXPORTS]->(externalDeclaration)
WITH internalModulesCountOverall
,internalElementsCountOverall
,coalesce(nullIf(externalModule.namespace, '') + '/' + externalModule.name, externalModule.name) AS externalModuleName
,coalesce(nullIf(internalModule.namespace, '') + '/' + internalModule.name, internalModule.name) AS internalModuleName

// Gathering counts for every internal element and the external module it uses
,count (DISTINCT externalDeclaration.globalFqn) AS externalDeclarationsCount
,COLLECT(DISTINCT externalDeclaration.globalFqn )[0..9] AS externalDeclarationsExamples
,count (DISTINCT internalElement.globalFqn) AS internalElementsCount
,COLLECT(DISTINCT internalElement.globalFqn )[0..9] AS internalElementsExamples
,100.0 / internalModulesCountOverall
* count(DISTINCT internalElement.globalFqn) AS internalElementsCallingExternalRate

// Group by external module
RETURN externalModuleName
,count(DISTINCT internalModuleName) AS numberOfInternalModules

// Statistics about how many internal modules are using that external module
,sum(externalDeclarationsCount) AS sumNumberOfUsedExternalDeclarations
,min(externalDeclarationsCount) AS minNumberOfUsedExternalDeclarations
,max(externalDeclarationsCount) AS maxNumberOfUsedExternalDeclarations
,percentileCont(externalDeclarationsCount, 0.5) AS medNumberOfUsedExternalDeclarations
,avg(externalDeclarationsCount) AS avgNumberOfUsedExternalDeclarations
,stDev(externalDeclarationsCount) AS stdNumberOfUsedExternalDeclarations

// Statistics about the internal elements and their external module usage
,sum(internalElementsCount) AS sumNumberOfInternalElements
,min(internalElementsCount) AS minNumberOfInternalElements
,max(internalElementsCount) AS maxNumberOfInternalElements
,percentileCont(internalElementsCount, 0.5) AS medNumberOfInternalElements
,avg(internalElementsCount) AS avgNumberOfInternalElements
,stDev(internalElementsCount) AS stdNumberOfInternalElements

// Statistics about the types and their external package usage count percentage
,min(internalElementsCallingExternalRate) AS minNumberOfInternalElementsPercentage
,max(internalElementsCallingExternalRate) AS maxNumberOfInternalElementsPercentage
,percentileCont(internalElementsCallingExternalRate, 0.5) AS medNumberOfInternalElementsPercentage
,avg(internalElementsCallingExternalRate) AS avgNumberOfInternalElementsPercentage
,stDev(internalElementsCallingExternalRate) AS stdNumberOfInternalElementsPercentage

,collect(DISTINCT internalModuleName)[0..4] AS internalModuleExamples

// Order the results descending by the number of internal modules that use the external module
ORDER BY numberOfInternalModules DESC, externalModuleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// External Typescript namespace usage overall

MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
WITH count(DISTINCT internalElement.globalFqn) AS allInternalElements
,count(DISTINCT internalModule.globalFqn) AS allModules
,collect(DISTINCT internalElement) AS internalElementList
UNWIND internalElementList AS internalElement
MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
WHERE externalDeclaration.isExternalImport = true
MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
WITH allInternalElements
,allModules
,externalModule.namespace AS externalNamespaceName
,count(DISTINCT internalModule.globalFqn) AS numberOfExternalCallerModules
,count(DISTINCT internalElement.globalFqn) AS numberOfExternalCallerElements
,count(externalDependency) AS numberOfExternalDeclarationCalls
,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCallsWeighted
,collect('<' + internalElement.name
+ '> of module <'
+ internalModule.name
+ '> imports <'
+ externalDeclaration.name
+ '> from external namespace <'
+ externalModule.namespace + '>')[0..4] AS exampleStories
RETURN externalNamespaceName
,numberOfExternalCallerModules
,numberOfExternalCallerElements
,numberOfExternalDeclarationCalls
,numberOfExternalDeclarationCallsWeighted
,allModules
,allInternalElements
,exampleStories
ORDER BY numberOfExternalCallerModules DESC, externalNamespaceName ASC
Loading