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
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Cyclic Dependencies Breakdown Backward-Only for Typescript

MATCH (module:TS:Module)-[:EXPORTS]->(forwardSource:TS)-[:DEPENDS_ON]->(forwardTarget:TS)<-[:EXPORTS]-(dependentModule:TS:Module)
MATCH (dependentModule)-[:EXPORTS]->(backwardSource:TS)-[:DEPENDS_ON]->(backwardTarget:TS)<-[:EXPORTS]-(module)
// Get the project of the module if available
OPTIONAL MATCH (project:Directory)<-[:HAS_ROOT]-(:TS:Project)-[:CONTAINS]->(module)
OPTIONAL MATCH (dependentProject:Directory)<-[:HAS_ROOT]-(:TS:Project)-[:CONTAINS]->(dependentModule)
WHERE module.globalFqn <> dependentModule.globalFqn
WITH project.absoluteFileName AS projectFileName
,replace(
module.globalFqn
,project.absoluteFileName + '/', ''
) AS moduleName
,dependentProject.absoluteFileName AS dependentProjectFileName
,replace(
dependentModule.globalFqn
,dependentProject.absoluteFileName + '/', ''
) AS dependentModulePathName
,collect(DISTINCT forwardSource.name + '->' + forwardTarget.name) AS forwardDependencies
,collect(DISTINCT backwardTarget.name + '<-' + backwardSource.name) AS backwardDependencies
WITH projectFileName
,moduleName
,dependentProjectFileName
,dependentModulePathName
,forwardDependencies
,backwardDependencies
,size(forwardDependencies) AS numberOfForwardDependencies
,size(backwardDependencies) AS numberOfBackwardDependencies
,size(forwardDependencies) + size(backwardDependencies) AS numberOfAllCyclicDependencies
WHERE (size(forwardDependencies) > size(backwardDependencies)
OR (size(forwardDependencies) = size(backwardDependencies)
AND size(moduleName) >= size(dependentModulePathName)))
UNWIND backwardDependencies AS dependency
RETURN projectFileName
,moduleName
,dependentProjectFileName
,dependentModulePathName
,dependency
,toFloat(ABS(numberOfForwardDependencies - numberOfBackwardDependencies)) / numberOfAllCyclicDependencies AS forwardToBackwardBalance
,numberOfForwardDependencies AS numberForward
,numberOfBackwardDependencies AS numberBackward
ORDER BY forwardToBackwardBalance DESC, moduleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Cyclic Dependencies Breakdown for Typescript

MATCH (module:TS:Module)-[:EXPORTS]->(forwardSource:TS)-[:DEPENDS_ON]->(forwardTarget:TS)<-[:EXPORTS]-(dependentModule:TS:Module)
MATCH (dependentModule)-[:EXPORTS]->(backwardSource:TS)-[:DEPENDS_ON]->(backwardTarget:TS)<-[:EXPORTS]-(module)
// Get the project of the module if available
OPTIONAL MATCH (project:Directory)<-[:HAS_ROOT]-(:TS:Project)-[:CONTAINS]->(module)
OPTIONAL MATCH (dependentProject:Directory)<-[:HAS_ROOT]-(:TS:Project)-[:CONTAINS]->(dependentModule)
WHERE module.globalFqn <> dependentModule.globalFqn
WITH project.absoluteFileName AS projectFileName
,replace(
module.globalFqn
,project.absoluteFileName + '/', ''
) AS moduleName
,dependentProject.absoluteFileName AS dependentProjectFileName
,replace(
dependentModule.globalFqn
,dependentProject.absoluteFileName + '/', ''
) AS dependentModulePathName
,collect(DISTINCT forwardSource.name + '->' + forwardTarget.name) AS forwardDependencies
,collect(DISTINCT backwardTarget.name + '<-' + backwardSource.name) AS backwardDependencies
WITH projectFileName
,moduleName
,dependentProjectFileName
,dependentModulePathName
,forwardDependencies
,backwardDependencies
,size(forwardDependencies) AS numberOfForwardDependencies
,size(backwardDependencies) AS numberOfBackwardDependencies
,size(forwardDependencies) + size(backwardDependencies) AS numberOfAllCyclicDependencies
WHERE (size(forwardDependencies) > size(backwardDependencies)
OR (size(forwardDependencies) = size(backwardDependencies)
AND size(moduleName) >= size(dependentModulePathName)))
UNWIND (backwardDependencies + forwardDependencies) AS dependency
RETURN projectFileName
,moduleName
,dependentProjectFileName
,dependentModulePathName
,dependency
,toFloat(ABS(numberOfForwardDependencies - numberOfBackwardDependencies)) / numberOfAllCyclicDependencies AS forwardToBackwardBalance
,numberOfForwardDependencies AS numberForward
,numberOfBackwardDependencies AS numberBackward
ORDER BY forwardToBackwardBalance DESC, moduleName ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//Cyclic Dependencies as List for Typescript

MATCH (module:TS:Module)-[:EXPORTS]->(forwardSource:TS)-[:DEPENDS_ON]->(forwardTarget:TS)<-[:EXPORTS]-(dependentModule:TS:Module)
MATCH (dependentModule)-[:EXPORTS]->(backwardSource:TS)-[:DEPENDS_ON]->(backwardTarget:TS)<-[:EXPORTS]-(module)
// Get the project of the module if available
OPTIONAL MATCH (project:Directory)<-[:HAS_ROOT]-(:TS:Project)-[:CONTAINS]->(module)
OPTIONAL MATCH (dependentProject:Directory)<-[:HAS_ROOT]-(:TS:Project)-[:CONTAINS]->(dependentModule)
WHERE module.globalFqn <> dependentModule.globalFqn
WITH project.absoluteFileName AS projectFileName
,replace(
module.globalFqn
,project.absoluteFileName + '/', ''
) AS moduleName
,dependentProject.absoluteFileName AS dependentProjectFileName
,replace(
dependentModule.globalFqn
,dependentProject.absoluteFileName + '/', ''
) AS dependentModulePathName
,collect(DISTINCT forwardSource.name + '->' + forwardTarget.name) AS forwardDependencies
,collect(DISTINCT backwardTarget.name + '<-' + backwardSource.name) AS backwardDependencies
WITH projectFileName
,moduleName
,dependentProjectFileName
,dependentModulePathName
,forwardDependencies
,backwardDependencies
,size(forwardDependencies) AS numberOfForwardDependencies
,size(backwardDependencies) AS numberOfBackwardDependencies
,size(forwardDependencies) + size(backwardDependencies) AS numberOfAllCyclicDependencies
WHERE (size(forwardDependencies) > size(backwardDependencies)
OR (size(forwardDependencies) = size(backwardDependencies)
AND size(moduleName) >= size(dependentModulePathName)))
RETURN projectFileName
,moduleName
,dependentProjectFileName
,dependentModulePathName
,toFloat(ABS(numberOfForwardDependencies - numberOfBackwardDependencies)) / numberOfAllCyclicDependencies AS forwardToBackwardBalance
,numberOfForwardDependencies AS numberForward
,numberOfBackwardDependencies AS numberBackward
,forwardDependencies[0..9] AS forwardDependencyExamples
,backwardDependencies[0..9] AS backwardDependencyExamples
ORDER BY forwardToBackwardBalance DESC, moduleName ASC
14 changes: 14 additions & 0 deletions cypher/Exploration/Explore_common_globalfqn_prefix.cypher
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Get common global full qualified name prefix

MATCH (module:TS)
WHERE module.globalFqn STARTS WITH '/'
WITH count(module.globalFqn) AS numberOfAllModules
,collect(module) AS modules
UNWIND modules AS module
WITH numberOfAllModules
,module.globalFqn AS moduleFullQualifiedName
,split(module.globalFqn, '/') AS paths
UNWIND paths AS path
WITH path, numberOfAllModules, count(*) AS numberOfModulesUsingThePath
WHERE numberOfAllModules = numberOfModulesUsingThePath
RETURN apoc.text.join(collect(path), '/') AS commonPath
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// How many elements compared to all existing are used by dependent Typescript modules?

MATCH (sourceModule:TS&Module)-[:EXPORTS]-(sourceElement:TS)
MATCH (sourceElement)-[:DEPENDS_ON]->(dependentElement:TS&!Module&!ExternalModule)
MATCH (dependentModule:TS&Module)-[:EXPORTS]->(dependentElement)
WHERE sourceModule <> dependentModule
MATCH (dependentModule)-[:EXPORTS]->(dependentModuleElement:TS)
WITH sourceModule.name AS sourceModuleName
,dependentModule.name AS dependentModuleName
,COUNT(DISTINCT dependentElement.globalFqn) AS dependentElementsCount
,COUNT(DISTINCT dependentModuleElement.globalFqn) AS dependentModuleElementsCount
,collect(DISTINCT dependentElement.globalFqn)[0..4] AS dependentElementFullNameExamples
,collect(DISTINCT dependentElement.name)[0..4] AS dependentElementNameExamples
RETURN sourceModuleName
,dependentModuleName
,dependentElementsCount
,dependentModuleElementsCount
,toFloat(dependentElementsCount) / (dependentModuleElementsCount + 1E-38) AS elementUsagePercentage
,dependentElementFullNameExamples
,dependentElementNameExamples
ORDER BY elementUsagePercentage ASC
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// List all existing internal Typescript modules

MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
WITH internalModule.name AS moduleName
,internalModule.globalFqn AS moduleFullQualifiedName
,internalModule.incomingDependencies AS incomingDependencies
,internalModule.outgoingDependencies AS outgoingDependencies
,COUNT(DISTINCT internalElement.globalFqn) AS numberOfElements
RETURN moduleName, numberOfElements, incomingDependencies, outgoingDependencies, moduleFullQualifiedName
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// List elements that are used by many different modules

MATCH (sourceModule:TS&Module)-[:EXPORTS]->(sourceElement:TS)
MATCH (sourceElement)-[:DEPENDS_ON]->(dependentElement:TS&!Module&!ExternalModule)
MATCH (dependentModule:TS&Module)-[:EXPORTS]->(dependentElement)
WHERE sourceModule <> dependentModule
WITH dependentElement
,labels(dependentElement) AS dependentElementLabels
,COUNT(DISTINCT sourceModule.globalFqn) AS numberOfUsingModules
UNWIND dependentElementLabels AS dependentElementLabel
WITH *
WHERE NOT dependentElementLabel = 'TS' // Filter out generic TS label
RETURN dependentElement.globalFqn AS fullQualifiedDependentElementName
,dependentElement.moduleName AS dependentElementModuleName
,dependentElement.name AS dependentElementName
,dependentElementLabel AS dependentElementLabels
,numberOfUsingModules
ORDER BY numberOfUsingModules DESC, dependentElementName ASC
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Set incoming Typscript Module dependencies

// Get the top level dependency between a Typescript module and an external modules it uses
// Get the top level dependency between a Typescript module and other modules that uses it
MATCH (source:TS:Module)
OPTIONAL MATCH (source)<-[:RESOLVES_TO]-(sourceExternal:ExternalModule)<-[moduleDependency:DEPENDS_ON]-(target:TS:Module)
OPTIONAL MATCH (source)<-[moduleDependency:DEPENDS_ON]-(target:TS:Module)
WHERE source <> target
// Get the project of the external module if available
OPTIONAL MATCH (projectdir:Directory)<-[:HAS_ROOT]-(project:TS:Project)-[:CONTAINS]->(target)
Expand All @@ -21,9 +21,6 @@ OPTIONAL MATCH (projectdir:Directory)<-[:HAS_ROOT]-(project:TS:Project)-[:CONTAI
,source.incomingDependentAbstractTypeWeight = abstractTypeCardinality
,source.incomingDependentModules = externalModuleCount
,source.incomingDependentPackages = size(projectNames)
// Incoming dependencies properties can't easily be set on sourceExternal nodes
// since there might be more than one per source. If this is needed in future
// assure that there is no regression for the source nodes.
RETURN source.globalFqn AS fullQualifiedModuleName
,source.name AS moduleName
,declarationCount AS incomingDependencies
Expand Down
32 changes: 20 additions & 12 deletions cypher/Typescript_Enrichment/Add_module_properties.cypher
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
// Add "namespace", "module" and "name" properties to Typescript nodes that have a globalFqn property

// Add extended properties to Typescript nodes with a globalFqn like "namespace", "module", "name" and "extension" as well as markers like "isNodeModule", "isUnresolvedImport" and "isExternalImport"
MATCH (ts:TS)
WHERE ts.globalFqn IS NOT NULL
OPTIONAL MATCH (class:TS:Class)-[:DECLARES]->(ts)
WITH ts
,replace(split(ts.globalFqn, '".')[0],'"', '') AS moduleName
,replace(split(ts.globalFqn, '/index')[0],'"', '') AS moduleNameWithoutIndex
,split(ts.globalFqn, '".')[1] AS symbolName
,split(nullif(reverse(split(reverse(ts.globalFqn), '@')[0]), ts.globalFqn), '/')[0] AS namespaceName
,(ts.globalFqn contains '/node_modules/') AS isNodeModule
,((NOT ts.globalFqn STARTS WITH '/') AND size(split(ts.globalFqn, '/')) < 3) AS isUnresolvedImport
,replace(split(ts.globalFqn, '".')[0],'"', '') AS modulePathName
,reverse(split(reverse(replace(split(ts.globalFqn, '".')[0],'"', '')), '/')[0]) AS moduleName
,replace(split(split(ts.globalFqn, '/index')[0], '.default')[0],'"', '') AS modulePathNameWithoutIndexAndDefault
,nullif(split(ts.globalFqn, '".')[1], 'default') AS symbolName
,split(nullif(reverse(split(reverse(ts.globalFqn), '@')[0]), ts.globalFqn), '/')[0] AS namespaceName
,(ts.globalFqn contains '/node_modules/') AS isNodeModule
,((NOT ts.globalFqn STARTS WITH '/') AND size(split(ts.globalFqn, '/')) < 3) AS isUnresolvedImport
,reverse(split(reverse(class.globalFqn), '.')[0]) AS optionalClassName
WITH *
,reverse(split(reverse(moduleNameWithoutIndex), '/')[0]) AS indexedName
,coalesce('@' + nullif(namespaceName, ''), '') AS namespaceNameWithAtPrefixed
,split(reverse(split(reverse(modulePathNameWithoutIndexAndDefault), '/')[0]), '.')[0] AS indexAndExtensionOmittedName
,replace(moduleName, nullif(split(moduleName, '.')[0], moduleName) + '.', '') AS moduleNameExtensionExtended
,nullif(reverse(split(reverse(moduleName), '.')[0]), moduleName) AS moduleNameExtension
,coalesce('@' + nullif(namespaceName, ''), '') AS namespaceNameWithAtPrefixed
,replace(symbolName, coalesce(optionalClassName + '.', ''), '') AS symbolNameWithoutClassName
SET ts.namespace = namespaceNameWithAtPrefixed
,ts.module = moduleName
,ts.name = coalesce(symbolName, indexedName)
,ts.module = modulePathName
,ts.moduleName = moduleName
,ts.name = coalesce(symbolNameWithoutClassName, indexAndExtensionOmittedName)
,ts.extensionExtended = moduleNameExtensionExtended
,ts.extension = moduleNameExtension
,ts.isNodeModule = isNodeModule
,ts.isUnresolvedImport = isUnresolvedImport
,ts.isExternalImport = isNodeModule OR isUnresolvedImport
Expand Down
8 changes: 4 additions & 4 deletions jupyter/InternalDependenciesJava.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
"List the artifacts this notebook is based on. Different sorting variations help finding artifacts by their features and support larger code bases where the list of all artifacts gets too long.\n",
"\n",
"Only the top 30 entries are shown. The whole table can be found in the following CSV report: \n",
"`List_all_existing_java_artifacts`"
"`List_all_Java_artifacts`"
]
},
{
Expand All @@ -121,7 +121,7 @@
"metadata": {},
"outputs": [],
"source": [
"artifacts = query_cypher_to_data_frame(\"../cypher/List_all_existing_java_artifacts.cypher\")"
"artifacts = query_cypher_to_data_frame(\"../cypher/Internal_Dependencies/List_all_Java_artifacts.cypher\")"
]
},
{
Expand Down Expand Up @@ -431,7 +431,7 @@
},
"outputs": [],
"source": [
"interface_segregation_candidates=query_cypher_to_data_frame(\"../cypher/Candidates_for_Interface_Segregation.cypher\", limit=40)\n",
"interface_segregation_candidates=query_cypher_to_data_frame(\"../cypher/Internal_Dependencies/Candidates_for_Interface_Segregation.cypher\", limit=40)\n",
"interface_segregation_candidates"
]
},
Expand Down Expand Up @@ -586,7 +586,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.11.9"
},
"title": "Object Oriented Design Quality Metrics for Java with Neo4j"
},
Expand Down
Loading