@appthreat/atom 2.1.12 → 2.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -4
- package/plugins/bin/atom +1 -1
- package/plugins/bin/atom.bat +1 -1
- package/plugins/composer/installed.php +6 -6
- package/plugins/lib/com.lihaoyi.ujson_3-4.1.0.jar +0 -0
- package/plugins/lib/com.lihaoyi.upack_3-4.1.0.jar +0 -0
- package/plugins/lib/com.lihaoyi.upickle-core_3-4.1.0.jar +0 -0
- package/plugins/lib/com.lihaoyi.upickle-implicits_3-4.1.0.jar +0 -0
- package/plugins/lib/com.lihaoyi.upickle_3-4.1.0.jar +0 -0
- package/plugins/lib/io.appthreat.atom-2.1.14-classpath.jar +0 -0
- package/plugins/lib/{io.appthreat.atom-2.1.12.jar → io.appthreat.atom-2.1.14.jar} +0 -0
- package/plugins/lib/{io.appthreat.c2cpg_3-2.3.2.jar → io.appthreat.c2cpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.dataflowengineoss_3-2.3.2.jar → io.appthreat.dataflowengineoss_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.javasrc2cpg_3-2.3.2.jar → io.appthreat.javasrc2cpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.jimple2cpg_3-2.3.2.jar → io.appthreat.jimple2cpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.jssrc2cpg_3-2.3.2.jar → io.appthreat.jssrc2cpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.php2atom_3-2.3.2.jar → io.appthreat.php2atom_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.pysrc2cpg_3-2.3.2.jar → io.appthreat.pysrc2cpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.ruby2atom_3-2.3.2.jar → io.appthreat.ruby2atom_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.semanticcpg_3-2.3.2.jar → io.appthreat.semanticcpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{io.appthreat.x2cpg_3-2.3.2.jar → io.appthreat.x2cpg_3-2.3.5.jar} +0 -0
- package/plugins/lib/{org.scala-lang.modules.scala-parallel-collections_3-1.1.0.jar → org.scala-lang.modules.scala-parallel-collections_3-1.2.0.jar} +0 -0
- package/plugins/lib/{org.slf4j.slf4j-api-2.0.16.jar → org.slf4j.slf4j-api-2.0.17.jar} +0 -0
- package/plugins/lib/org.slf4j.slf4j-nop-2.0.17.jar +0 -0
- package/plugins/rubyastgen/bundle/ruby/3.4.0/bundler/gems/ruby_ast_gen-d8b6ffa44317/ruby_ast_gen.gemspec +1 -1
- package/plugins/rubyastgen/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/racc-1.8.1/gem_make.out +5 -5
- package/scalasem.js +365 -0
- package/utils.mjs +27 -2
- package/plugins/lib/com.lihaoyi.ujson_3-4.0.2.jar +0 -0
- package/plugins/lib/com.lihaoyi.upack_3-4.0.2.jar +0 -0
- package/plugins/lib/com.lihaoyi.upickle-core_3-4.0.2.jar +0 -0
- package/plugins/lib/com.lihaoyi.upickle-implicits_3-4.0.2.jar +0 -0
- package/plugins/lib/com.lihaoyi.upickle_3-4.0.2.jar +0 -0
- package/plugins/lib/io.appthreat.atom-2.1.12-classpath.jar +0 -0
- package/plugins/lib/org.slf4j.slf4j-nop-2.0.16.jar +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appthreat/atom",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.14",
|
|
4
4
|
"description": "Create atom (⚛) representation for your application, packages and libraries",
|
|
5
5
|
"exports": "./index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"lint": "eslint *.mjs *.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@babel/parser": "^7.26.
|
|
13
|
-
"typescript": "^5.
|
|
12
|
+
"@babel/parser": "^7.26.9",
|
|
13
|
+
"typescript": "^5.8.2",
|
|
14
14
|
"yargs": "^17.7.2"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"atom": "index.js",
|
|
21
21
|
"astgen": "astgen.js",
|
|
22
22
|
"phpastgen": "phpastgen.js",
|
|
23
|
-
"rbastgen": "rbastgen.js"
|
|
23
|
+
"rbastgen": "rbastgen.js",
|
|
24
|
+
"scalasem": "scalasem.js"
|
|
24
25
|
},
|
|
25
26
|
"engines": {
|
|
26
27
|
"node": ">=16.0.0"
|
package/plugins/bin/atom
CHANGED
|
@@ -360,7 +360,7 @@ declare -r lib_dir="$(realpath "${app_home}/../lib")"
|
|
|
360
360
|
declare -a app_mainclass=('io.appthreat.atom.Atom')
|
|
361
361
|
|
|
362
362
|
declare -r script_conf_file="${app_home}/../conf/application.ini"
|
|
363
|
-
declare -r app_classpath="$lib_dir/io.appthreat.atom-2.1.
|
|
363
|
+
declare -r app_classpath="$lib_dir/io.appthreat.atom-2.1.14-classpath.jar"
|
|
364
364
|
|
|
365
365
|
# java_cmd is overrode in process_args when -java-home is used
|
|
366
366
|
declare java_cmd=$(get_java_cmd)
|
package/plugins/bin/atom.bat
CHANGED
|
@@ -40,7 +40,7 @@ rem "-J" is stripped, "-D" is left as is, and everything is appended to JAVA_OPT
|
|
|
40
40
|
set _JAVA_PARAMS=
|
|
41
41
|
set _APP_ARGS=
|
|
42
42
|
|
|
43
|
-
set "APP_CLASSPATH=%APP_LIB_DIR%\io.appthreat.atom-2.1.
|
|
43
|
+
set "APP_CLASSPATH=%APP_LIB_DIR%\io.appthreat.atom-2.1.14-classpath.jar"
|
|
44
44
|
set "APP_MAIN_CLASS=io.appthreat.atom.Atom"
|
|
45
45
|
set "SCRIPT_CONF_FILE=%APP_HOME%\conf\application.ini"
|
|
46
46
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<?php return array(
|
|
2
2
|
'root' => array(
|
|
3
3
|
'name' => '__root__',
|
|
4
|
-
'pretty_version' => 'v2.1.
|
|
5
|
-
'version' => '2.1.
|
|
6
|
-
'reference' => '
|
|
4
|
+
'pretty_version' => 'v2.1.14',
|
|
5
|
+
'version' => '2.1.14.0',
|
|
6
|
+
'reference' => 'd1252e282dc3ddc3b51914f8e21fe48fd40d01ba',
|
|
7
7
|
'type' => 'library',
|
|
8
8
|
'install_path' => __DIR__ . '/../../',
|
|
9
9
|
'aliases' => array(),
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
),
|
|
12
12
|
'versions' => array(
|
|
13
13
|
'__root__' => array(
|
|
14
|
-
'pretty_version' => 'v2.1.
|
|
15
|
-
'version' => '2.1.
|
|
16
|
-
'reference' => '
|
|
14
|
+
'pretty_version' => 'v2.1.14',
|
|
15
|
+
'version' => '2.1.14.0',
|
|
16
|
+
'reference' => 'd1252e282dc3ddc3b51914f8e21fe48fd40d01ba',
|
|
17
17
|
'type' => 'library',
|
|
18
18
|
'install_path' => __DIR__ . '/../../',
|
|
19
19
|
'aliases' => array(),
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/plugins/lib/{io.appthreat.javasrc2cpg_3-2.3.2.jar → io.appthreat.javasrc2cpg_3-2.3.5.jar}
RENAMED
|
Binary file
|
package/plugins/lib/{io.appthreat.jimple2cpg_3-2.3.2.jar → io.appthreat.jimple2cpg_3-2.3.5.jar}
RENAMED
|
Binary file
|
package/plugins/lib/{io.appthreat.jssrc2cpg_3-2.3.2.jar → io.appthreat.jssrc2cpg_3-2.3.5.jar}
RENAMED
|
Binary file
|
|
Binary file
|
package/plugins/lib/{io.appthreat.pysrc2cpg_3-2.3.2.jar → io.appthreat.pysrc2cpg_3-2.3.5.jar}
RENAMED
|
Binary file
|
package/plugins/lib/{io.appthreat.ruby2atom_3-2.3.2.jar → io.appthreat.ruby2atom_3-2.3.5.jar}
RENAMED
|
Binary file
|
package/plugins/lib/{io.appthreat.semanticcpg_3-2.3.2.jar → io.appthreat.semanticcpg_3-2.3.5.jar}
RENAMED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
|
10
10
|
s.require_paths = ["lib".freeze]
|
|
11
11
|
s.authors = ["David Baker Effendi".freeze, "Andrei Dreyer".freeze, "Team AppThreat".freeze]
|
|
12
12
|
s.bindir = "exe".freeze
|
|
13
|
-
s.date = "2025-
|
|
13
|
+
s.date = "2025-03-10"
|
|
14
14
|
s.description = "A Ruby parser than dumps the AST as JSON output for atom `rubysrc2cpg` frontend".freeze
|
|
15
15
|
s.email = ["dave@whirlylabs.com".freeze, "andrei@whirlylabs.com".freeze, "hello@appthreat.com".freeze]
|
|
16
16
|
s.executables = ["ruby_ast_gen".freeze]
|
package/plugins/rubyastgen/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/racc-1.8.1/gem_make.out
CHANGED
|
@@ -3,16 +3,16 @@ current directory: /home/runner/work/atom/atom/wrapper/nodejs/plugins/rubyastgen
|
|
|
3
3
|
creating Makefile
|
|
4
4
|
|
|
5
5
|
current directory: /home/runner/work/atom/atom/wrapper/nodejs/plugins/rubyastgen/bundle/ruby/3.4.0/gems/racc-1.8.1/ext/racc/cparse
|
|
6
|
-
make DESTDIR\= sitearchdir\=./.gem.
|
|
6
|
+
make DESTDIR\= sitearchdir\=./.gem.20250310-2778-ho21ul sitelibdir\=./.gem.20250310-2778-ho21ul clean
|
|
7
7
|
|
|
8
8
|
current directory: /home/runner/work/atom/atom/wrapper/nodejs/plugins/rubyastgen/bundle/ruby/3.4.0/gems/racc-1.8.1/ext/racc/cparse
|
|
9
|
-
make DESTDIR\= sitearchdir\=./.gem.
|
|
9
|
+
make DESTDIR\= sitearchdir\=./.gem.20250310-2778-ho21ul sitelibdir\=./.gem.20250310-2778-ho21ul
|
|
10
10
|
compiling cparse.c
|
|
11
11
|
linking shared-object racc/cparse.so
|
|
12
12
|
|
|
13
13
|
current directory: /home/runner/work/atom/atom/wrapper/nodejs/plugins/rubyastgen/bundle/ruby/3.4.0/gems/racc-1.8.1/ext/racc/cparse
|
|
14
|
-
make DESTDIR\= sitearchdir\=./.gem.
|
|
15
|
-
/usr/bin/install -c -m 0755 cparse.so ./.gem.
|
|
14
|
+
make DESTDIR\= sitearchdir\=./.gem.20250310-2778-ho21ul sitelibdir\=./.gem.20250310-2778-ho21ul install
|
|
15
|
+
/usr/bin/install -c -m 0755 cparse.so ./.gem.20250310-2778-ho21ul/racc
|
|
16
16
|
|
|
17
17
|
current directory: /home/runner/work/atom/atom/wrapper/nodejs/plugins/rubyastgen/bundle/ruby/3.4.0/gems/racc-1.8.1/ext/racc/cparse
|
|
18
|
-
make DESTDIR\= sitearchdir\=./.gem.
|
|
18
|
+
make DESTDIR\= sitearchdir\=./.gem.20250310-2778-ho21ul sitelibdir\=./.gem.20250310-2778-ho21ul clean
|
package/scalasem.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Usage: scalasem $(pwd) slices.json
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { basename, dirname, join, relative } from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { detectScala, detectScalac, getAllFiles } from "./utils.mjs";
|
|
7
|
+
import process from "node:process";
|
|
8
|
+
import {
|
|
9
|
+
existsSync,
|
|
10
|
+
mkdtempSync,
|
|
11
|
+
mkdirSync,
|
|
12
|
+
readFileSync,
|
|
13
|
+
rmSync,
|
|
14
|
+
writeFileSync
|
|
15
|
+
} from "node:fs";
|
|
16
|
+
|
|
17
|
+
function main(argvs) {
|
|
18
|
+
if (!detectScala() && !detectScalac()) {
|
|
19
|
+
console.warn("Scala is not installed!");
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
let configFiles = getAllFiles(argvs[0], "routes");
|
|
23
|
+
configFiles = configFiles.concat(getAllFiles(argvs[0], ".conf"));
|
|
24
|
+
let tastyFiles = getAllFiles(argvs[0], ".tasty");
|
|
25
|
+
if (!tastyFiles.length) {
|
|
26
|
+
let buildTool = "sbt";
|
|
27
|
+
const millFiles = getAllFiles(argvs[0], "build.mill");
|
|
28
|
+
if (millFiles.length) {
|
|
29
|
+
buildTool = "mill";
|
|
30
|
+
}
|
|
31
|
+
const cwd = process.env.ATOM_CWD || process.cwd();
|
|
32
|
+
let compileCommand =
|
|
33
|
+
process?.env[`${buildTool.toUpperCase()}_COMPILE_COMMAND`] || "compile";
|
|
34
|
+
if (process.env.SCALA_VERSION && buildTool === "sbt") {
|
|
35
|
+
compileCommand = `++${process.env.SCALA_VERSION} ${compileCommand}`;
|
|
36
|
+
} else {
|
|
37
|
+
// Detect crossScalaVersions
|
|
38
|
+
const scalaVersion = findScalaVersion(cwd);
|
|
39
|
+
if (scalaVersion) {
|
|
40
|
+
compileCommand = `++${scalaVersion} ${compileCommand}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log(`Executing '${buildTool} ${compileCommand}' in ${argvs[0]}`);
|
|
44
|
+
const result = spawnSync(buildTool, compileCommand.split(" "), {
|
|
45
|
+
encoding: "utf-8",
|
|
46
|
+
cwd,
|
|
47
|
+
stdio: "ignore",
|
|
48
|
+
stderr: "inherit",
|
|
49
|
+
env: process.env,
|
|
50
|
+
timeout: process.env.ATOM_TIMEOUT || process.env.ASTGEN_TIMEOUT
|
|
51
|
+
});
|
|
52
|
+
if (result.error || result.status !== 0) {
|
|
53
|
+
if (result.stderr) {
|
|
54
|
+
console.log(result.stderr);
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
tastyFiles = getAllFiles(argvs[0], ".tasty");
|
|
59
|
+
console.log(`Obtained ${tastyFiles.length} IR files after compilation.`);
|
|
60
|
+
}
|
|
61
|
+
const slicesFile =
|
|
62
|
+
argvs.length > 1 ? argvs[1] : join(argvs[0], "slices.json");
|
|
63
|
+
createSemanticSlices(tastyFiles, configFiles, slicesFile);
|
|
64
|
+
}
|
|
65
|
+
main(process.argv.slice(2));
|
|
66
|
+
|
|
67
|
+
function findScalaVersion(cwd) {
|
|
68
|
+
let scalaVersion;
|
|
69
|
+
const buildSbtFile = join(cwd, "build.sbt");
|
|
70
|
+
if (existsSync(buildSbtFile)) {
|
|
71
|
+
const buildData = readFileSync(buildSbtFile, "utf-8");
|
|
72
|
+
for (let line of buildData.split("\n")) {
|
|
73
|
+
if (line.trim().includes("val ") && line.includes("scala")) {
|
|
74
|
+
const match = line.match(/"(3\.[^"]+)"/);
|
|
75
|
+
if (match) {
|
|
76
|
+
return match[1];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (line.trim().includes("crossScalaVersions")) {
|
|
80
|
+
const crossVersions = line.split("crossScalaVersions").pop().trim();
|
|
81
|
+
if (crossVersions.includes("3.")) {
|
|
82
|
+
const match = crossVersions.match(/"(3\.[^"]+)"/);
|
|
83
|
+
if (match) {
|
|
84
|
+
return match[1];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return scalaVersion;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function createSemanticSlices(tastyFiles, configFiles, slicesFile) {
|
|
94
|
+
const outDir = mkdtempSync(join(tmpdir(), "scalasem-"));
|
|
95
|
+
const MAX_BUFFER =
|
|
96
|
+
Number.parseInt(process.env.ATOM_MAX_BUFFER) || 100 * 1024 * 1024;
|
|
97
|
+
const cwd = process.env.ATOM_CWD || process.cwd();
|
|
98
|
+
const slices = {};
|
|
99
|
+
slices.config = parseConfigFiles(configFiles);
|
|
100
|
+
for (const af of tastyFiles) {
|
|
101
|
+
const result = spawnSync(
|
|
102
|
+
process.env.SCALAC_CMD || "scalac",
|
|
103
|
+
["-color:never", "-print-tasty", af],
|
|
104
|
+
{
|
|
105
|
+
encoding: "utf-8",
|
|
106
|
+
cwd,
|
|
107
|
+
env: process.env,
|
|
108
|
+
maxBuffer: MAX_BUFFER,
|
|
109
|
+
timeout: process.env.ATOM_TIMEOUT || process.env.ASTGEN_TIMEOUT
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
if (result.error || result.status !== 0) {
|
|
113
|
+
if (result.stderr) {
|
|
114
|
+
console.log(result.stderr);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (result.stdout) {
|
|
118
|
+
let fileOutDir = join(outDir, relative(cwd, dirname(af)));
|
|
119
|
+
const scalaDir = relative(cwd, dirname(af)).replace(
|
|
120
|
+
new RegExp("target/scala-(.)*/classes"),
|
|
121
|
+
""
|
|
122
|
+
);
|
|
123
|
+
if (fileOutDir.includes("classes")) {
|
|
124
|
+
fileOutDir = fileOutDir.replace(
|
|
125
|
+
new RegExp("target/scala-(.)*/classes"),
|
|
126
|
+
""
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
mkdirSync(fileOutDir, { recursive: true });
|
|
130
|
+
const astFile = join(
|
|
131
|
+
fileOutDir,
|
|
132
|
+
basename(af).replace(".tasty", ".scala.ast")
|
|
133
|
+
);
|
|
134
|
+
const scalaFile = join(
|
|
135
|
+
scalaDir,
|
|
136
|
+
basename(af).replace(".tasty", ".scala")
|
|
137
|
+
);
|
|
138
|
+
writeFileSync(astFile, Buffer.from(result.stdout).toString());
|
|
139
|
+
const usages = parseTasty(astFile);
|
|
140
|
+
slices[usages.sourceFile || scalaFile] = usages;
|
|
141
|
+
rmSync(astFile);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const slicesJson = JSON.stringify(slices, null, null);
|
|
145
|
+
writeFileSync(slicesFile, slicesJson);
|
|
146
|
+
if (!Object.keys(slices).length) {
|
|
147
|
+
console.log("Empty slices file created.");
|
|
148
|
+
} else {
|
|
149
|
+
console.log(
|
|
150
|
+
`Slices file ${slicesFile} created successfully with ${
|
|
151
|
+
Object.keys(slices).length
|
|
152
|
+
} entries.`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
if (outDir?.startsWith(tmpdir())) {
|
|
156
|
+
rmSync(outDir, { recursive: true });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function parseTasty(tastyAstFile) {
|
|
161
|
+
const astData = readFileSync(tastyAstFile, "utf-8");
|
|
162
|
+
let namesMode = false;
|
|
163
|
+
let treesMode = false;
|
|
164
|
+
let sourcePathsMode = false;
|
|
165
|
+
const literals = new Set();
|
|
166
|
+
const usedTypes = new Set();
|
|
167
|
+
const tags = new Set();
|
|
168
|
+
let sourceFile;
|
|
169
|
+
for (let line of astData.split("\n")) {
|
|
170
|
+
line = line.replace("\r", "").trim();
|
|
171
|
+
if (!line.length || line.startsWith("---")) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (line.startsWith("Names ") || line.startsWith("Names:")) {
|
|
175
|
+
namesMode = true;
|
|
176
|
+
}
|
|
177
|
+
if (line.startsWith("Trees ") || line.startsWith("Trees:")) {
|
|
178
|
+
namesMode = false;
|
|
179
|
+
treesMode = true;
|
|
180
|
+
}
|
|
181
|
+
if (line.startsWith("Positions ") || line.startsWith("positions:")) {
|
|
182
|
+
namesMode = false;
|
|
183
|
+
treesMode = false;
|
|
184
|
+
}
|
|
185
|
+
if (namesMode) {
|
|
186
|
+
// 3: api
|
|
187
|
+
if (line.includes(": ")) {
|
|
188
|
+
const literal = line.split(": ").pop().trim();
|
|
189
|
+
if (literal.length > 1) {
|
|
190
|
+
literals.add(literal);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (treesMode && line.includes(" Signature(")) {
|
|
195
|
+
// 139: SELECTin(12) 38 [<init>[Signed Signature(List(play.api.mvc.MessagesControllerComponents),play.api.mvc.MessagesAbstractController) @<init>]]
|
|
196
|
+
const signatureTypes = line
|
|
197
|
+
.split(" Signature(")
|
|
198
|
+
.pop()
|
|
199
|
+
.split(") ")[0]
|
|
200
|
+
.replaceAll("List(", "")
|
|
201
|
+
.replaceAll(")", "")
|
|
202
|
+
.split(",");
|
|
203
|
+
for (let sig of signatureTypes) {
|
|
204
|
+
sig = sig.trim();
|
|
205
|
+
if (
|
|
206
|
+
sig.length > 3 &&
|
|
207
|
+
!sig.startsWith("scala.") &&
|
|
208
|
+
!sig.startsWith("java.") &&
|
|
209
|
+
!sig.startsWith("javax.inject.")
|
|
210
|
+
) {
|
|
211
|
+
usedTypes.add(sig);
|
|
212
|
+
if (sig.startsWith("play.api.")) {
|
|
213
|
+
tags.add("framework");
|
|
214
|
+
}
|
|
215
|
+
if (
|
|
216
|
+
sig.startsWith("play.api.data.Form") ||
|
|
217
|
+
sig.startsWith("play.api.mvc.Request") ||
|
|
218
|
+
sig.startsWith("play.twirl.api")
|
|
219
|
+
) {
|
|
220
|
+
tags.add("framework-input");
|
|
221
|
+
}
|
|
222
|
+
if (
|
|
223
|
+
sig.startsWith("play.twirl.api.Html") ||
|
|
224
|
+
sig.startsWith("play.api.mvc.Result") ||
|
|
225
|
+
sig.startsWith("play.api.mvc.Action")
|
|
226
|
+
) {
|
|
227
|
+
tags.add("framework-output");
|
|
228
|
+
}
|
|
229
|
+
if (
|
|
230
|
+
sig.startsWith("play.api.routing.") ||
|
|
231
|
+
sig.startsWith("play.core.routing") ||
|
|
232
|
+
sig.startsWith("router.RoutesPrefix")
|
|
233
|
+
) {
|
|
234
|
+
tags.add("framework-route");
|
|
235
|
+
}
|
|
236
|
+
if (
|
|
237
|
+
sig.startsWith("slick.sql.") ||
|
|
238
|
+
sig.startsWith("play.db.") ||
|
|
239
|
+
sig.startsWith("slick.jdbc.")
|
|
240
|
+
) {
|
|
241
|
+
tags.add("database");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (line.includes("source paths:")) {
|
|
247
|
+
sourcePathsMode = true;
|
|
248
|
+
}
|
|
249
|
+
if (sourcePathsMode) {
|
|
250
|
+
if (line.includes(" [") && line.endsWith("]")) {
|
|
251
|
+
sourceFile = line.split(" [").pop().replace(/]/g, "");
|
|
252
|
+
sourcePathsMode = false;
|
|
253
|
+
} else if (line.includes(".scala") && line.includes(": ")) {
|
|
254
|
+
sourceFile = line.split(": ").pop().trim();
|
|
255
|
+
sourcePathsMode = false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (!namesMode && !treesMode && !sourcePathsMode) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (sourceFile?.includes("target")) {
|
|
263
|
+
tags.add("generated");
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
sourceFile,
|
|
267
|
+
tags: Array.from(tags).sort(),
|
|
268
|
+
usedTypes: Array.from(usedTypes).sort(),
|
|
269
|
+
literals: Array.from(literals)
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function parseConfigFiles(configFiles) {
|
|
274
|
+
const configMetadata = { routes: [] };
|
|
275
|
+
for (const aconfig of configFiles) {
|
|
276
|
+
if (aconfig.endsWith("routes")) {
|
|
277
|
+
const routes = parseRoutes(aconfig);
|
|
278
|
+
if (routes?.length) {
|
|
279
|
+
for (const aroute of routes) {
|
|
280
|
+
let duplicate = false;
|
|
281
|
+
for (const exisRoute of configMetadata.routes) {
|
|
282
|
+
if (
|
|
283
|
+
exisRoute.method === aroute.method &&
|
|
284
|
+
exisRoute.pattern === aroute.pattern
|
|
285
|
+
) {
|
|
286
|
+
if (
|
|
287
|
+
exisRoute.controllerMethod &&
|
|
288
|
+
exisRoute.controllerMethod === aroute.controllerMethod
|
|
289
|
+
) {
|
|
290
|
+
duplicate = true;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (!duplicate) {
|
|
296
|
+
configMetadata["routes"].push(aroute);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (configMetadata.routes.length) {
|
|
303
|
+
console.log("Found", configMetadata.routes.length, "routes.");
|
|
304
|
+
}
|
|
305
|
+
return configMetadata;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function parseRoutes(routesFile) {
|
|
309
|
+
const routes = [];
|
|
310
|
+
const routesData = readFileSync(routesFile, "utf-8");
|
|
311
|
+
for (let aline of routesData.split("\n")) {
|
|
312
|
+
aline = aline.replace("\r", "").trim();
|
|
313
|
+
if (aline.startsWith("#") || aline.startsWith("+")) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const tmpA = aline.split(/\s+/);
|
|
317
|
+
if (tmpA.length < 2) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
// Ignore static assets
|
|
321
|
+
if (["/webjars"].includes(tmpA[1])) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (
|
|
325
|
+
[
|
|
326
|
+
"GET",
|
|
327
|
+
"PATCH",
|
|
328
|
+
"POST",
|
|
329
|
+
"OPTIONS",
|
|
330
|
+
"HEAD",
|
|
331
|
+
"DELETE",
|
|
332
|
+
"PUT",
|
|
333
|
+
"->"
|
|
334
|
+
].includes(tmpA[0].toUpperCase())
|
|
335
|
+
) {
|
|
336
|
+
let controllerMethod = tmpA.length > 2 ? tmpA[2] : undefined;
|
|
337
|
+
if (controllerMethod.includes("(")) {
|
|
338
|
+
controllerMethod = controllerMethod.split("(")[0];
|
|
339
|
+
}
|
|
340
|
+
// Exclude webjars
|
|
341
|
+
if (controllerMethod.startsWith("webjars.")) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
// Handle wildcards
|
|
345
|
+
if (tmpA[0] === "->") {
|
|
346
|
+
// We now need to parse a method called "routes" in the controllerMethod to identify the list of http methods
|
|
347
|
+
// Let's keep things simple for now
|
|
348
|
+
for (const m of ["GET", "PATCH", "POST", "DELETE", "PUT"]) {
|
|
349
|
+
routes.push({
|
|
350
|
+
method: m,
|
|
351
|
+
pattern: tmpA[1],
|
|
352
|
+
controllerMethod
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
} else {
|
|
356
|
+
routes.push({
|
|
357
|
+
method: tmpA[0],
|
|
358
|
+
pattern: tmpA[1],
|
|
359
|
+
controllerMethod
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return routes;
|
|
365
|
+
}
|
package/utils.mjs
CHANGED
|
@@ -28,7 +28,7 @@ const IGNORE_DIRS = process.env.ASTGEN_IGNORE_DIRS
|
|
|
28
28
|
|
|
29
29
|
const IGNORE_FILE_PATTERN = new RegExp(
|
|
30
30
|
process.env.ASTGEN_IGNORE_FILE_PATTERN ||
|
|
31
|
-
"(
|
|
31
|
+
"(test|spec|min|three|\\.d)\\.(js|ts|jsx|tsx)$",
|
|
32
32
|
"i"
|
|
33
33
|
);
|
|
34
34
|
|
|
@@ -69,7 +69,12 @@ export const getAllFiles = (dir, extn, files, result, regex) => {
|
|
|
69
69
|
// ignore
|
|
70
70
|
}
|
|
71
71
|
} else {
|
|
72
|
-
if (
|
|
72
|
+
if (
|
|
73
|
+
regex.test(fileWithDir) ||
|
|
74
|
+
(extn &&
|
|
75
|
+
!extn.includes(".") &&
|
|
76
|
+
fileWithDir.toLowerCase().endsWith(extn.toLowerCase()))
|
|
77
|
+
) {
|
|
73
78
|
result.push(fileWithDir);
|
|
74
79
|
}
|
|
75
80
|
}
|
|
@@ -112,3 +117,23 @@ export const detectRuby = (versionNeeded) => {
|
|
|
112
117
|
}
|
|
113
118
|
return true;
|
|
114
119
|
};
|
|
120
|
+
|
|
121
|
+
export const detectScala = () => {
|
|
122
|
+
let result = spawnSync(process.env.SCALA_CMD || "scala", ["--version"], {
|
|
123
|
+
encoding: "utf-8"
|
|
124
|
+
});
|
|
125
|
+
if (result.status !== 0 || result.error) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const detectScalac = () => {
|
|
132
|
+
let result = spawnSync(process.env.SCALAC_CMD || "scalac", ["--version"], {
|
|
133
|
+
encoding: "utf-8"
|
|
134
|
+
});
|
|
135
|
+
if (result.status !== 0 || result.error) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
return true;
|
|
139
|
+
};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|