diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 230f6da5b3d8..08dac06c4d94 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -754,7 +754,11 @@ private CompletableFuture extractSource() throws IOException { continue; } Path odir = cfg.getParent().resolve(root.getCompilerOptions().getOutDir()).toAbsolutePath().normalize(); - outDirs.add(odir); + // Only exclude outDirs that are proper subdirectories of the source root + // This prevents excluding all code when outDir points outside the source root or to the source root itself + if (tryRelativize(LGTM_SRC, odir) != null && !odir.equals(LGTM_SRC)) { + outDirs.add(odir); + } } } catch (Exception e) { // ignore malformed tsconfig or missing fields diff --git a/javascript/extractor/test/com/semmle/js/extractor/test/AutoBuildTests.java b/javascript/extractor/test/com/semmle/js/extractor/test/AutoBuildTests.java index b972355d91d6..e6b168ac340c 100644 --- a/javascript/extractor/test/com/semmle/js/extractor/test/AutoBuildTests.java +++ b/javascript/extractor/test/com/semmle/js/extractor/test/AutoBuildTests.java @@ -235,6 +235,51 @@ public void skipFilesInTsconfigOutDir() throws IOException { runTest(); } + @Test + public void skipFilesInTsconfigOutDirPointingToParent() throws IOException { + // Test that outDir pointing to parent directory (outside source root) is ignored + addFile(true, LGTM_SRC, "tsconfig.json"); + Path config = Paths.get(LGTM_SRC.toString(), "tsconfig.json"); + Files.write(config, + "{\"compilerOptions\":{\"outDir\":\"..\"}}".getBytes(StandardCharsets.UTF_8)); + + // All files should be extracted since outDir pointing outside source root should be ignored + addFile(true, LGTM_SRC, "src", "app.ts"); + addFile(true, LGTM_SRC, "main.js"); + + runTest(); + } + + @Test + public void skipFilesInTsconfigOutDirPointingToSourceRoot() throws IOException { + // Test that outDir pointing to source root itself is ignored + addFile(true, LGTM_SRC, "tsconfig.json"); + Path config = Paths.get(LGTM_SRC.toString(), "tsconfig.json"); + Files.write(config, + "{\"compilerOptions\":{\"outDir\":\".\"}}".getBytes(StandardCharsets.UTF_8)); + + // All files should be extracted since outDir pointing to source root should be ignored + addFile(true, LGTM_SRC, "src", "app.ts"); + addFile(true, LGTM_SRC, "main.js"); + + runTest(); + } + + @Test + public void skipFilesInTsconfigOutDirWithRelativePath() throws IOException { + // Test that outDir with relative path "somedir/.." (resolves to root) is ignored + addFile(true, LGTM_SRC, "tsconfig.json"); + Path config = Paths.get(LGTM_SRC.toString(), "tsconfig.json"); + Files.write(config, + "{\"compilerOptions\":{\"outDir\":\"somedir/..\"}}".getBytes(StandardCharsets.UTF_8)); + + // All files should be extracted since outDir resolving to root should be ignored + addFile(true, LGTM_SRC, "src", "app.ts"); + addFile(true, LGTM_SRC, "main.js"); + + runTest(); + } + @Test public void includeFile() throws IOException { envVars.put("LGTM_INDEX_INCLUDE", "tst.js"); diff --git a/javascript/ql/lib/change-notes/2025-07-11-ignore-outdirs-that-would-exclude-everything.md b/javascript/ql/lib/change-notes/2025-07-11-ignore-outdirs-that-would-exclude-everything.md new file mode 100644 index 000000000000..aeffaebb477d --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-07-11-ignore-outdirs-that-would-exclude-everything.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* The JavaScript extractor no longer ignores source files specified in the `tsconfig.json` compiler options `outDir` if doing so would result in excluding all source code.