Skip to content

Commit 6db5781

Browse files
committed
JS: Add helper for doing path resolution with JS rules
1 parent bdc8ef7 commit 6db5781

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

  • javascript/ql/lib/semmle/javascript/internal/paths
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Provides predicates for use in `Folder::ResolveSig` in order to resolve
3+
* paths using JavaScript semantics.
4+
*/
5+
6+
private import javascript
7+
private import semmle.javascript.TSConfig
8+
9+
/**
10+
* Gets a folder name that is a common source folder name.
11+
*/
12+
string getASrcFolderName() { result = ["ts", "js", "src", "lib"] }
13+
14+
/**
15+
* Gets a folder name that is a common build output folder name.
16+
*/
17+
string getABuildOutputFolderName() { result = ["dist", "build", "out", "lib"] }
18+
19+
/**
20+
* Provides predicates for use in a `Folder::ResolveSig` in order to resolve
21+
* paths using JavaScript semantics.
22+
*
23+
* This accounts for two things:
24+
* - automatic file extensions (e.g `./foo` may resolve to `./foo.js`)
25+
* - mapping compiled-generated files back to their original source files
26+
*/
27+
module JSPaths {
28+
/**
29+
* Gets an additional child of `base` to include when resolving JS paths.
30+
*/
31+
pragma[nomagic]
32+
Container getAnAdditionalChild(Container base, string name) {
33+
// Automatically fill in file extensions
34+
result = base.(Folder).getJavaScriptFileOrTypings(name)
35+
or
36+
// When importing a .js file, map to the original file that compiles to the .js file.
37+
exists(string stem |
38+
result = base.(Folder).getJavaScriptFileOrTypings(stem) and
39+
name = stem + ".js"
40+
)
41+
or
42+
// Redirect './bar' to 'foo' given a tsconfig like:
43+
//
44+
// { include: ["foo"], compilerOptions: { outDir: "./bar" }}
45+
//
46+
exists(TSConfig tsconfig, Container includeTarget |
47+
name =
48+
tsconfig.getCompilerOptions().getPropStringValue("outDir").regexpReplaceAll("^\\./", "") and
49+
base = tsconfig.getFolder() and
50+
includeTarget = tsconfig.getAnIncludePathTarget()
51+
|
52+
result = includeTarget.(Folder)
53+
or
54+
result = includeTarget.(File).getParentContainer()
55+
)
56+
or
57+
// Heuristic version of the above based on commonly used source and build folder names
58+
exists(Folder folder | base = folder |
59+
folder = any(PackageJson pkg).getFolder() and
60+
name = getABuildOutputFolderName() and
61+
not exists(folder.getChildContainer(name)) and
62+
(
63+
result = folder.getChildContainer(getASrcFolderName())
64+
or
65+
result = folder
66+
)
67+
)
68+
}
69+
}

0 commit comments

Comments
 (0)