diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index ca7fa6c06c0e..7247489ee693 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -394,7 +394,7 @@ private void setupFilters() { for (FileType filetype : defaultExtract) for (String extension : filetype.getExtensions()) patterns.add("**/*" + extension); - // include .eslintrc files, .xsaccess files, package.json files, + // include .eslintrc files, .xsaccess files, package.json files, // tsconfig.json files, and codeql-javascript-*.json files patterns.add("**/.eslintrc*"); patterns.add("**/.xsaccess"); @@ -895,7 +895,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set // For named packages, find the main file. String name = packageJson.getName(); if (name != null) { - Path entryPoint = null; + Path entryPoint = null; try { entryPoint = guessPackageMainFile(path, packageJson, FileType.TYPESCRIPT.getExtensions()); if (entryPoint == null) { @@ -1108,6 +1108,10 @@ private boolean hasTypeScriptFiles(Set filesToExtract) { return false; } + public static boolean treatAsTSConfig(String basename) { + return basename.contains("tsconfig.") && basename.endsWith(".json"); + } + private void findFilesToExtract( FileExtractor extractor, final Set filesToExtract, final List tsconfigFiles) throws IOException { @@ -1140,7 +1144,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) // extract TypeScript projects from 'tsconfig.json' if (typeScriptMode == TypeScriptMode.FULL - && file.getFileName().endsWith("tsconfig.json") + && treatAsTSConfig(file.getFileName().toString()) && !excludes.contains(file) && isFileIncluded(file)) { tsconfigFiles.add(file); diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 57198709460e..4fbfa1518188 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -539,7 +539,7 @@ private void collectFiles(File root, boolean explicit) { } if (extractorConfig.getTypeScriptMode() == TypeScriptMode.FULL - && root.getName().equals("tsconfig.json") + && AutoBuild.treatAsTSConfig(root.getName()) && !excludeMatcher.matches(path)) { projectFiles.add(root); } diff --git a/javascript/ql/src/change-notes/2025-01-30-typescript-tsconfig-names.md b/javascript/ql/src/change-notes/2025-01-30-typescript-tsconfig-names.md new file mode 100644 index 000000000000..3f7c572d0742 --- /dev/null +++ b/javascript/ql/src/change-notes/2025-01-30-typescript-tsconfig-names.md @@ -0,0 +1,5 @@ +--- +category: majorAnalysis +--- +* TypeScript extraction is now better at analyzing projects where the main `tsconfig.json` file does not include any + source files, but references other `tsconfig.json`-like files that do include source files. diff --git a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/src/main.ts b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/src/main.ts new file mode 100644 index 000000000000..403c78e0d0d5 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/src/main.ts @@ -0,0 +1,4 @@ +export function main(foo: string) { + let x = foo; + console.log(x); +} diff --git a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected new file mode 100644 index 000000000000..18dbed450ba1 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected @@ -0,0 +1,9 @@ +types +| (...data: any[]) => void | +| (foo: string) => void | +| Console | +| any | +| any[] | +| string | +| void | +jsonFiles diff --git a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.ql b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.ql new file mode 100644 index 000000000000..25ace33c8a38 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.ql @@ -0,0 +1,5 @@ +import javascript + +query predicate types(Type type) { any() } + +query predicate jsonFiles(File file) { file.getExtension() = "json" } diff --git a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/tsconfig.foo.json b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/tsconfig.foo.json new file mode 100644 index 000000000000..658aef62ac0e --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/tsconfig.foo.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "include": [ + "src" + ], + "compilerOptions": { + "composite": true + } +} diff --git a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/tsconfig.json b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/tsconfig.json new file mode 100644 index 000000000000..b0f85a63f5f2 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/tsconfig.json @@ -0,0 +1,7 @@ +{ + "include": [], + "files": [], + "references": [ + { "path": "./tsconfig.foo.json" }, + ], +}