diff --git a/cypher/Create_Typescript_index_for_name.cypher b/cypher/Create_Typescript_index_for_name.cypher new file mode 100644 index 000000000..0c4f251be --- /dev/null +++ b/cypher/Create_Typescript_index_for_name.cypher @@ -0,0 +1,3 @@ +// Create index for the name for Typescript nodes + +CREATE INDEX INDEX_TYPESCRIPT_NAME IF NOT EXISTS FOR (typescript:TS) ON (typescript.name) \ No newline at end of file diff --git a/cypher/Typescript_Enrichment/Add_DEPENDS_ON_relationship_to_resolved_modules.cypher b/cypher/Typescript_Enrichment/Add_DEPENDS_ON_relationship_to_resolved_modules.cypher index c607c8885..8c9c25492 100644 --- a/cypher/Typescript_Enrichment/Add_DEPENDS_ON_relationship_to_resolved_modules.cypher +++ b/cypher/Typescript_Enrichment/Add_DEPENDS_ON_relationship_to_resolved_modules.cypher @@ -1,5 +1,5 @@ // Propagates "DEPENDS_ON" relations between modules to their resolved modules with a property "resolved:true". -// Inspired by https://github.com/jQAssistant/jqa-java-plugin/blob/f092122b62bb13d597840b64b73b2010bd074d1f/src/main/resources/META-INF/jqassistant-rules/java-classpath.xml#L59 +// Inspired by https://github.com/jQAssistant/jqassistant/blob/4cd7face5d6d2953449d8e6ff5b484f00ffbdc2f/plugin/java/src/main/resources/META-INF/jqassistant-rules/java-classpath.xml#L5 MATCH (module:TS:Module)-[dependsOn:DEPENDS_ON]->(externalModule:TS:ExternalModule) MATCH (externalModule)-[:RESOLVES_TO]->(resolvedModule:TS:Module) diff --git a/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_declarations.cypher b/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_declarations.cypher index af9c20935..d53cc8d00 100644 --- a/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_declarations.cypher +++ b/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_declarations.cypher @@ -1,5 +1,5 @@ // Adds a relation "RESOLVES_TO" from a Typescript element to an external declaration if their global fully qualified names match. -// Inspired by https://github.com/jQAssistant/jqa-java-plugin/blob/f092122b62bb13d597840b64b73b2010bd074d1f/src/main/resources/META-INF/jqassistant-rules/java-classpath.xml#L5 +// Inspired by https://github.com/jQAssistant/jqassistant/blob/4cd7face5d6d2953449d8e6ff5b484f00ffbdc2f/plugin/java/src/main/resources/META-INF/jqassistant-rules/java-classpath.xml#L5 // Related to https://github.com/jqassistant-plugin/jqassistant-typescript-plugin/issues/35 MATCH (element:TS&!ExternalDeclaration) diff --git a/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_modules.cypher b/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_modules.cypher index 744b524ad..e548fc55f 100644 --- a/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_modules.cypher +++ b/cypher/Typescript_Enrichment/Add_RESOLVES_TO_relationship_for_matching_modules.cypher @@ -1,5 +1,6 @@ // Adds a relation "RESOLVES_TO" from an external module to a module if their global fully qualified names match. -// Inspired by https://github.com/jQAssistant/jqa-java-plugin/blob/f092122b62bb13d597840b64b73b2010bd074d1f/src/main/resources/META-INF/jqassistant-rules/java-classpath.xml#L5 +// Depends on "Add_module_properties.cypher" to be run first +// Inspired by https://github.com/jQAssistant/jqassistant/blob/4cd7face5d6d2953449d8e6ff5b484f00ffbdc2f/plugin/java/src/main/resources/META-INF/jqassistant-rules/java-classpath.xml#L5 // Related to https://github.com/jqassistant-plugin/jqassistant-typescript-plugin/issues/35 MATCH (module:TS:Module) @@ -9,6 +10,7 @@ WHERE module.globalFqn IS NOT NULL AND (module.globalFqn = externalModule.globalFqn OR module.globalFqn = split(externalModule.globalFqn, '/index.')[0] OR externalModule.globalFqn = split(module.globalFqn, '/index.')[0] + OR (externalModule.name = module.name AND externalModule.namespace = module.namespace) ) AND module <> externalModule CALL { WITH module, externalModule diff --git a/cypher/Typescript_Enrichment/Add_name_to_property_on_projects.cypher b/cypher/Typescript_Enrichment/Add_name_to_property_on_projects.cypher new file mode 100644 index 000000000..5978cb6b0 --- /dev/null +++ b/cypher/Typescript_Enrichment/Add_name_to_property_on_projects.cypher @@ -0,0 +1,7 @@ +// Set name property on Typescript project nodes + + MATCH (project:TS:Project)-[:HAS_ROOT]->(root:Directory) + WITH project + ,reverse(split(reverse(root.absoluteFileName), '/')[0]) AS projectName + SET project.name = projectName +RETURN count(*) AS numberOfNamesProjects \ No newline at end of file diff --git a/cypher/Typescript_Enrichment/Add_name_to_property_on_scan_nodes.cypher b/cypher/Typescript_Enrichment/Add_name_to_property_on_scan_nodes.cypher new file mode 100644 index 000000000..91fba0296 --- /dev/null +++ b/cypher/Typescript_Enrichment/Add_name_to_property_on_scan_nodes.cypher @@ -0,0 +1,7 @@ +// Set name property on Typescript scan nodes + + MATCH (typescriptScan:TS:Scan) + WITH typescriptScan + ,replace(reverse(split(reverse(typescriptScan.fileName), '/')[0]), '.json', '') AS scanName + SET typescriptScan.name = scanName +RETURN count(*) AS numberOfNamesScans \ No newline at end of file diff --git a/cypher/Typescript_Enrichment/Link_projects_to_npm_packages.cypher b/cypher/Typescript_Enrichment/Link_projects_to_npm_packages.cypher new file mode 100644 index 000000000..a99e2c9c4 --- /dev/null +++ b/cypher/Typescript_Enrichment/Link_projects_to_npm_packages.cypher @@ -0,0 +1,32 @@ +// Link Typescript projects to npm packages + +MATCH (npmPackage:NPM:Package) + WITH npmPackage +// Remove the first ("/npm-package-json/")" and the last part ("/package.json") +// of the file name to get the actual relative path to the directory +// that contains the package.json file + ,replace( + replace(npmPackage.fileName, '/' + split(npmPackage.fileName, '/')[1], '') + , '/package.json' + , '' + ) AS relativeNpmPackageDirectory + MATCH (project:TS:Project)-[:HAS_ROOT]->(projectRoot:Directory) + WHERE projectRoot.absoluteFileName ENDS WITH relativeNpmPackageDirectory + WITH npmPackage + ,relativeNpmPackageDirectory + ,collect(DISTINCT project) AS projects + ,collect(DISTINCT projectRoot) AS projectRoots +// Assure that the found connection is unique and not ambiguous + WHERE size(projects) = 1 + AND size(projectRoots) = 1 + UNWIND projects AS project +// Create a HAS_NPM_PACKAGE relationship between the Typescript project and the npm package + MERGE (project)-[:HAS_NPM_PACKAGE]->(npmPackage) +// Set the "relativeFileDirectory" on the npm package to the relative directory +// that contains the package.json file + SET npmPackage.relativeFileDirectory = relativeNpmPackageDirectory + RETURN count(*) AS numberOfCreatedNpmPackageRelationships +// Detailed results for debugging +//RETURN npmPackage.fileName AS npmPackageFileName +// ,projectRoots[0].absoluteFileName AS projectRootDirectory +// ,relativeNpmPackageDirectory \ No newline at end of file diff --git a/scripts/downloader/downloadTypescriptProject.sh b/scripts/downloader/downloadTypescriptProject.sh index 2addcb2cc..e7b418b3f 100755 --- a/scripts/downloader/downloadTypescriptProject.sh +++ b/scripts/downloader/downloadTypescriptProject.sh @@ -139,8 +139,9 @@ usePackageManagerToInstallDependencies() { case "${packageManager}" in npm) # npm ci is not sufficient for projects like "ant-design" that rely on generating the package-lock - # Even if this is not standard, this is an acceptable solution for standard and edge cases. - npm install --ignore-scripts --verbose || exit + # Even if this is not standard, this is an acceptable solution since it is only used to prepare scanning. + # The same applies to "--force" which shouldn't be done normally. + npm install --ignore-scripts --force --verbose || exit ;; pnpm) pnpm install --frozen-lockfile || exit @@ -177,8 +178,8 @@ fi cd "${fullSourceDirectory}" || exit usePackageManagerToInstallDependencies echo "downloadTypescriptProject: Scanning Typescript source using @jqassistant/ts-lce..." - npx --yes @jqassistant/ts-lce@1.2.0 >"./../../runtime/logs/jqassistant-typescript-scan-${projectName}.log" 2>&1 || exit + npx --yes @jqassistant/ts-lce@1.2.0 --extension React >"./../../runtime/logs/jqassistant-typescript-scan-${projectName}.log" 2>&1 || exit ) echo "downloadTypescriptProject: Moving scanned results into the artifacts/typescript directory..." mkdir -p artifacts/typescript -mv -nv "${fullSourceDirectory}/.reports/jqa/ts-output.json" "artifacts/typescript/${fullProjectName}.json" \ No newline at end of file +mv -fv "${fullSourceDirectory}/.reports/jqa/ts-output.json" "artifacts/typescript/${fullProjectName}.json" \ No newline at end of file diff --git a/scripts/prepareAnalysis.sh b/scripts/prepareAnalysis.sh index 06ffc501a..a654df218 100644 --- a/scripts/prepareAnalysis.sh +++ b/scripts/prepareAnalysis.sh @@ -50,15 +50,23 @@ fi # Preparation - Create indices execute_cypher "${CYPHER_DIR}/Create_Java_Type_index_for_full_qualified_name.cypher" execute_cypher "${CYPHER_DIR}/Create_Typescript_index_for_full_qualified_name.cypher" +execute_cypher "${CYPHER_DIR}/Create_Typescript_index_for_name.cypher" # Preparation - Enrich Graph for Typescript by adding "module" and "name" properties execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_module_properties.cypher" +# Preparation - Enrich Graph for Typescript by adding a name properties +execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_name_to_property_on_projects.cypher" +execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_name_to_property_on_scan_nodes.cypher" + # Preparation - Enrich Graph for Typescript by adding relationships between Modules with the same globalFqn execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_RESOLVES_TO_relationship_for_matching_modules.cypher" execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_RESOLVES_TO_relationship_for_matching_declarations.cypher" execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_DEPENDS_ON_relationship_to_resolved_modules.cypher" +# Preparation - Enrich Graph for Typescript by adding relationships between corresponding TS:Project and NPM:Package nodes +execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Link_projects_to_npm_packages.cypher" + # Preparation - Add weights to Java Package DEPENDS_ON relationships execute_cypher_summarized "${DEPENDS_ON_CYPHER_DIR}/Add_weight_property_for_Java_Interface_Dependencies_to_Package_DEPENDS_ON_Relationship.cypher" execute_cypher_summarized "${DEPENDS_ON_CYPHER_DIR}/Add_weight_property_to_Java_Package_DEPENDS_ON_Relationship.cypher"