@futpib/parser 1.0.3 → 1.0.6
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/.claude/settings.local.json +24 -0
- package/.github/workflows/main.yml +1 -0
- package/build/androidPackageParser.js +30 -32
- package/build/arbitraryDalvikBytecode.d.ts +3 -3
- package/build/arbitraryDalvikBytecode.js +33 -27
- package/build/arbitraryDalvikExecutable.js +55 -17
- package/build/arbitraryJava.d.ts +31 -0
- package/build/arbitraryJava.js +532 -0
- package/build/arbitraryJavaScript.d.ts +3 -0
- package/build/arbitraryJavaScript.js +263 -0
- package/build/arbitraryJavascript.d.ts +3 -0
- package/build/arbitraryJavascript.js +263 -0
- package/build/arbitraryZig.d.ts +3 -0
- package/build/arbitraryZig.js +240 -0
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arrayParser.js +72 -13
- package/build/backsmali.d.ts +4 -3
- package/build/backsmali.js +26 -6
- package/build/bash.d.ts +89 -0
- package/build/bash.js +1 -0
- package/build/bashParser.d.ts +6 -0
- package/build/bashParser.js +335 -0
- package/build/bashParser.test.d.ts +1 -0
- package/build/bashParser.test.js +343 -0
- package/build/bashParserEdgeCases.test.d.ts +1 -0
- package/build/bashParserEdgeCases.test.js +117 -0
- package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
- package/build/dalvikBytecodeParser/addressConversion.js +334 -0
- package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
- package/build/dalvikBytecodeParser/formatParsers.js +13 -14
- package/build/dalvikBytecodeParser.d.ts +60 -31
- package/build/dalvikBytecodeParser.js +92 -35
- package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
- package/build/dalvikBytecodeParser.test-d.js +268 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
- package/build/dalvikBytecodeUnparser.d.ts +2 -2
- package/build/dalvikBytecodeUnparser.js +23 -23
- package/build/dalvikBytecodeUnparser.test.js +7 -7
- package/build/dalvikExecutable.d.ts +3 -3
- package/build/dalvikExecutable.test-d.d.ts +1 -0
- package/build/dalvikExecutable.test-d.js +59 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
- package/build/dalvikExecutableParser/typedNumbers.js +3 -0
- package/build/dalvikExecutableParser.d.ts +2 -1
- package/build/dalvikExecutableParser.js +96 -77
- package/build/dalvikExecutableParser.test.js +24 -3
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
- package/build/dalvikExecutableUnparser.d.ts +2 -2
- package/build/dalvikExecutableUnparser.test.js +2 -1
- package/build/disjunctionParser.d.ts +5 -3
- package/build/disjunctionParser.js +79 -17
- package/build/disjunctionParser.test-d.d.ts +1 -0
- package/build/disjunctionParser.test-d.js +72 -0
- package/build/elementSwitchParser.d.ts +4 -0
- package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
- package/build/elementSwitchParser.test-d.d.ts +1 -0
- package/build/elementSwitchParser.test-d.js +44 -0
- package/build/exactSequenceParser.d.ts +4 -2
- package/build/exactSequenceParser.test-d.d.ts +1 -0
- package/build/exactSequenceParser.test-d.js +36 -0
- package/build/fetchCid.js +2 -66
- package/build/index.d.ts +25 -2
- package/build/index.js +23 -1
- package/build/index.test.js +16 -1
- package/build/inputReader.d.ts +10 -0
- package/build/inputReader.js +36 -0
- package/build/java.d.ts +502 -0
- package/build/java.js +2 -0
- package/build/javaKeyStoreParser.js +14 -17
- package/build/javaParser.d.ts +51 -0
- package/build/javaParser.js +1538 -0
- package/build/javaParser.test.d.ts +1 -0
- package/build/javaParser.test.js +1287 -0
- package/build/javaScript.d.ts +35 -0
- package/build/javaScript.js +1 -0
- package/build/javaScriptParser.d.ts +9 -0
- package/build/javaScriptParser.js +34 -0
- package/build/javaScriptUnparser.d.ts +3 -0
- package/build/javaScriptUnparser.js +4 -0
- package/build/javaScriptUnparser.test.d.ts +1 -0
- package/build/javaScriptUnparser.test.js +24 -0
- package/build/javaUnparser.d.ts +2 -0
- package/build/javaUnparser.js +519 -0
- package/build/javaUnparser.test.d.ts +1 -0
- package/build/javaUnparser.test.js +24 -0
- package/build/javascript.d.ts +35 -0
- package/build/javascript.js +1 -0
- package/build/javascriptParser.d.ts +9 -0
- package/build/javascriptParser.js +34 -0
- package/build/javascriptUnparser.d.ts +3 -0
- package/build/javascriptUnparser.js +4 -0
- package/build/javascriptUnparser.test.d.ts +1 -0
- package/build/javascriptUnparser.test.js +24 -0
- package/build/jsonParser.js +2 -12
- package/build/lazyMessageError.d.ts +3 -0
- package/build/lookaheadParser.js +60 -3
- package/build/negativeLookaheadParser.js +70 -11
- package/build/nonEmptyArrayParser.js +72 -13
- package/build/objectParser.d.ts +12 -0
- package/build/objectParser.js +31 -0
- package/build/objectParser.test-d.d.ts +1 -0
- package/build/objectParser.test-d.js +112 -0
- package/build/objectParser.test.d.ts +1 -0
- package/build/objectParser.test.js +55 -0
- package/build/optionalParser.js +69 -10
- package/build/parser.d.ts +4 -0
- package/build/parser.js +3 -1
- package/build/parser.test.js +114 -1
- package/build/parserConsumedSequenceParser.js +66 -7
- package/build/parserContext.d.ts +6 -0
- package/build/parserContext.js +20 -11
- package/build/parserError.d.ts +119 -27
- package/build/parserError.js +16 -8
- package/build/regexpParser.d.ts +2 -0
- package/build/regexpParser.js +101 -0
- package/build/regexpParser.test.d.ts +1 -0
- package/build/regexpParser.test.js +114 -0
- package/build/regularExpression.d.ts +63 -0
- package/build/regularExpression.js +1 -0
- package/build/regularExpressionParser.d.ts +3 -0
- package/build/regularExpressionParser.js +600 -0
- package/build/regularExpressionParser.test.d.ts +1 -0
- package/build/regularExpressionParser.test.js +89 -0
- package/build/separatedArrayParser.js +73 -14
- package/build/separatedNonEmptyArrayParser.js +73 -14
- package/build/sliceBoundedParser.js +62 -5
- package/build/smaliParser.d.ts +7 -7
- package/build/smaliParser.js +185 -268
- package/build/smaliParser.test.js +58 -0
- package/build/stringEscapes.d.ts +5 -0
- package/build/stringEscapes.js +244 -0
- package/build/symbolicExpression.d.ts +29 -0
- package/build/symbolicExpression.js +1 -0
- package/build/symbolicExpressionParser.d.ts +4 -0
- package/build/symbolicExpressionParser.js +123 -0
- package/build/symbolicExpressionParser.test.d.ts +1 -0
- package/build/symbolicExpressionParser.test.js +289 -0
- package/build/terminatedArrayParser.js +113 -38
- package/build/terminatedArrayParser.test.js +4 -2
- package/build/tupleParser.d.ts +7 -15
- package/build/tupleParser.js +1 -0
- package/build/unionParser.d.ts +5 -3
- package/build/unionParser.js +7 -2
- package/build/unionParser.test-d.d.ts +1 -0
- package/build/unionParser.test-d.js +72 -0
- package/build/unionParser.test.js +10 -11
- package/build/zig.d.ts +280 -0
- package/build/zig.js +2 -0
- package/build/zigParser.d.ts +3 -0
- package/build/zigParser.js +1119 -0
- package/build/zigParser.test.d.ts +1 -0
- package/build/zigParser.test.js +1590 -0
- package/build/zigUnparser.d.ts +2 -0
- package/build/zigUnparser.js +460 -0
- package/build/zigUnparser.test.d.ts +1 -0
- package/build/zigUnparser.test.js +24 -0
- package/build/zipParser.js +19 -32
- package/build/zipUnparser.js +19 -7
- package/build/zipUnparser.test.js +1 -1
- package/node_modules-@types/s-expression/index.d.ts +5 -0
- package/package.json +25 -6
- package/src/androidPackageParser.ts +33 -60
- package/src/arbitraryDalvikBytecode.ts +39 -31
- package/src/arbitraryDalvikExecutable.ts +65 -20
- package/src/arbitraryJava.ts +804 -0
- package/src/arbitraryJavaScript.ts +410 -0
- package/src/arbitraryZig.ts +380 -0
- package/src/arrayParser.ts +1 -3
- package/src/backsmali.ts +35 -4
- package/src/bash.ts +127 -0
- package/src/bashParser.test.ts +590 -0
- package/src/bashParser.ts +498 -0
- package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
- package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
- package/src/dalvikBytecodeParser.test-d.ts +310 -0
- package/src/dalvikBytecodeParser.ts +194 -69
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
- package/src/dalvikBytecodeUnparser.test.ts +7 -7
- package/src/dalvikBytecodeUnparser.ts +31 -30
- package/src/dalvikExecutable.test-d.ts +132 -0
- package/src/dalvikExecutable.ts +3 -3
- package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
- package/src/dalvikExecutableParser.test.ts +37 -3
- package/src/dalvikExecutableParser.test.ts.md +163 -2
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +121 -139
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
- package/src/dalvikExecutableUnparser.test.ts +3 -2
- package/src/dalvikExecutableUnparser.ts +4 -4
- package/src/disjunctionParser.test-d.ts +105 -0
- package/src/disjunctionParser.ts +18 -15
- package/src/elementSwitchParser.test-d.ts +74 -0
- package/src/elementSwitchParser.ts +51 -0
- package/src/exactSequenceParser.test-d.ts +43 -0
- package/src/exactSequenceParser.ts +13 -8
- package/src/fetchCid.ts +2 -76
- package/src/index.test.ts +22 -1
- package/src/index.ts +119 -2
- package/src/inputReader.ts +53 -0
- package/src/java.ts +708 -0
- package/src/javaKeyStoreParser.ts +18 -32
- package/src/javaParser.test.ts +1592 -0
- package/src/javaParser.ts +2640 -0
- package/src/javaScript.ts +36 -0
- package/src/javaScriptParser.ts +57 -0
- package/src/javaScriptUnparser.test.ts +37 -0
- package/src/javaScriptUnparser.ts +7 -0
- package/src/javaUnparser.test.ts +37 -0
- package/src/javaUnparser.ts +640 -0
- package/src/jsonParser.ts +6 -27
- package/src/lookaheadParser.ts +2 -6
- package/src/negativeLookaheadParser.ts +1 -3
- package/src/nonEmptyArrayParser.ts +1 -3
- package/src/objectParser.test-d.ts +152 -0
- package/src/objectParser.test.ts +71 -0
- package/src/objectParser.ts +69 -0
- package/src/optionalParser.ts +1 -3
- package/src/parser.test.ts +151 -4
- package/src/parser.ts +11 -1
- package/src/parserConsumedSequenceParser.ts +2 -4
- package/src/parserContext.ts +26 -11
- package/src/parserError.ts +17 -3
- package/src/regexpParser.test.ts +264 -0
- package/src/regexpParser.ts +126 -0
- package/src/regularExpression.ts +24 -0
- package/src/regularExpressionParser.test.ts +102 -0
- package/src/regularExpressionParser.ts +920 -0
- package/src/separatedArrayParser.ts +1 -3
- package/src/separatedNonEmptyArrayParser.ts +1 -3
- package/src/sliceBoundedParser.test.ts +2 -2
- package/src/sliceBoundedParser.ts +15 -19
- package/src/smaliParser.test.ts +64 -0
- package/src/smaliParser.test.ts.md +12 -12
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +246 -534
- package/src/stringEscapes.ts +253 -0
- package/src/symbolicExpression.ts +17 -0
- package/src/symbolicExpressionParser.test.ts +466 -0
- package/src/symbolicExpressionParser.ts +190 -0
- package/src/terminatedArrayParser.test.ts +9 -6
- package/src/terminatedArrayParser.ts +25 -29
- package/src/tupleParser.ts +21 -18
- package/src/unionParser.test-d.ts +105 -0
- package/src/unionParser.test.ts +18 -17
- package/src/unionParser.ts +28 -16
- package/src/zig.ts +411 -0
- package/src/zigParser.test.ts +1693 -0
- package/src/zigParser.ts +1745 -0
- package/src/zigUnparser.test.ts +37 -0
- package/src/zigUnparser.ts +615 -0
- package/src/zipParser.ts +20 -56
- package/src/zipUnparser.test.ts +1 -1
- package/src/zipUnparser.ts +22 -7
- package/tsconfig.json +2 -2
- package/build/exactElementSwitchParser.d.ts +0 -3
- package/src/exactElementSwitchParser.ts +0 -41
|
@@ -0,0 +1,1287 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
53
|
+
import * as fs from 'node:fs/promises';
|
|
54
|
+
import * as path from 'node:path';
|
|
55
|
+
import test from 'ava';
|
|
56
|
+
import envPaths from 'env-paths';
|
|
57
|
+
import { execa } from 'execa';
|
|
58
|
+
import PromiseMutex from 'p-mutex';
|
|
59
|
+
import { temporaryDirectory } from 'tempy';
|
|
60
|
+
import { hasExecutable } from './hasExecutable.js';
|
|
61
|
+
import { runParser } from './parser.js';
|
|
62
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
63
|
+
import { javaCompilationUnitParser } from './javaParser.js';
|
|
64
|
+
const paths = envPaths('parser.futpib.github.io');
|
|
65
|
+
const hasMvnPromise = hasExecutable('mvn');
|
|
66
|
+
const javaparserCommit = '6232a2103ebdbb0dd5b32d11e2c36ab62777b8f6';
|
|
67
|
+
const javaparserGitCacheMutex = new PromiseMutex();
|
|
68
|
+
async function ensureJavaparserGitCache() {
|
|
69
|
+
return javaparserGitCacheMutex.withLock(async () => {
|
|
70
|
+
const cacheDir = path.join(paths.cache, 'javaparser.git');
|
|
71
|
+
try {
|
|
72
|
+
await fs.access(cacheDir);
|
|
73
|
+
return cacheDir;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Cache miss, clone the bare repo
|
|
77
|
+
}
|
|
78
|
+
await fs.mkdir(path.dirname(cacheDir), { recursive: true });
|
|
79
|
+
const tempDir = `${cacheDir}.tmp`;
|
|
80
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
81
|
+
await execa('git', ['clone', '--bare', 'https://github.com/javaparser/javaparser', tempDir]);
|
|
82
|
+
await fs.rename(tempDir, cacheDir);
|
|
83
|
+
return cacheDir;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async function cloneJavaparserRepo() {
|
|
87
|
+
const gitDir = await ensureJavaparserGitCache();
|
|
88
|
+
// Fetch the specific commit if not already present
|
|
89
|
+
try {
|
|
90
|
+
await execa('git', ['cat-file', '-e', javaparserCommit], { cwd: gitDir });
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
await execa('git', ['fetch', 'origin', javaparserCommit], { cwd: gitDir });
|
|
94
|
+
}
|
|
95
|
+
// Checkout to a temporary worktree
|
|
96
|
+
const worktree = temporaryDirectory();
|
|
97
|
+
await execa('git', ['--git-dir', gitDir, 'worktree', 'add', '--detach', worktree, javaparserCommit]);
|
|
98
|
+
return {
|
|
99
|
+
path: worktree,
|
|
100
|
+
[Symbol.asyncDispose]: async () => {
|
|
101
|
+
await execa('git', ['--git-dir', gitDir, 'worktree', 'remove', '--force', worktree]);
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const jbangInstallMutex = new PromiseMutex();
|
|
106
|
+
async function ensureJbangInstalled() {
|
|
107
|
+
return jbangInstallMutex.withLock(async () => {
|
|
108
|
+
const jbangDir = path.join(paths.cache, 'jbang');
|
|
109
|
+
const jbangBin = path.join(jbangDir, '.jbang', 'jbang', 'bin', 'jbang');
|
|
110
|
+
try {
|
|
111
|
+
await fs.access(jbangBin);
|
|
112
|
+
return jbangBin;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Use maven plugin to bootstrap jbang installation
|
|
116
|
+
}
|
|
117
|
+
const dir = temporaryDirectory();
|
|
118
|
+
try {
|
|
119
|
+
const pomXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
120
|
+
<project>
|
|
121
|
+
<modelVersion>4.0.0</modelVersion>
|
|
122
|
+
<groupId>test</groupId>
|
|
123
|
+
<artifactId>test</artifactId>
|
|
124
|
+
<version>1.0</version>
|
|
125
|
+
<build>
|
|
126
|
+
<plugins>
|
|
127
|
+
<plugin>
|
|
128
|
+
<groupId>dev.jbang</groupId>
|
|
129
|
+
<artifactId>jbang-maven-plugin</artifactId>
|
|
130
|
+
<version>0.0.8</version>
|
|
131
|
+
<configuration>
|
|
132
|
+
<script>--version</script>
|
|
133
|
+
<jbangInstallDir>${jbangDir}</jbangInstallDir>
|
|
134
|
+
</configuration>
|
|
135
|
+
</plugin>
|
|
136
|
+
</plugins>
|
|
137
|
+
</build>
|
|
138
|
+
</project>`;
|
|
139
|
+
await fs.writeFile(path.join(dir, 'pom.xml'), pomXml);
|
|
140
|
+
await execa('mvn', ['jbang:run', '-q'], { cwd: dir });
|
|
141
|
+
return jbangBin;
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async function runJavaSnippet(code, args = []) {
|
|
149
|
+
const jbangBin = await ensureJbangInstalled();
|
|
150
|
+
const dir = temporaryDirectory();
|
|
151
|
+
const file = path.join(dir, 'Main.java');
|
|
152
|
+
await fs.writeFile(file, code);
|
|
153
|
+
try {
|
|
154
|
+
const result = await execa(jbangBin, ['--quiet', 'run', file, ...args], { cwd: dir });
|
|
155
|
+
return result.stdout.trim();
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const javaparserSnippet = `
|
|
162
|
+
//DEPS com.github.javaparser:javaparser-core:3.26.4
|
|
163
|
+
|
|
164
|
+
import com.github.javaparser.StaticJavaParser;
|
|
165
|
+
import com.github.javaparser.ast.*;
|
|
166
|
+
import com.github.javaparser.ast.body.*;
|
|
167
|
+
import com.github.javaparser.ast.expr.*;
|
|
168
|
+
import com.github.javaparser.ast.type.*;
|
|
169
|
+
import com.github.javaparser.metamodel.*;
|
|
170
|
+
import java.nio.file.Path;
|
|
171
|
+
import java.util.*;
|
|
172
|
+
|
|
173
|
+
class Main {
|
|
174
|
+
public static void main(String[] args) throws Exception {
|
|
175
|
+
Path filePath = Path.of(args[0]);
|
|
176
|
+
CompilationUnit cu = StaticJavaParser.parse(filePath);
|
|
177
|
+
System.out.println(toJson(cu));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static String toJson(Node node) {
|
|
181
|
+
StringBuilder sb = new StringBuilder();
|
|
182
|
+
sb.append("{");
|
|
183
|
+
sb.append("\\"type\\":\\"").append(node.getClass().getSimpleName()).append("\\"");
|
|
184
|
+
|
|
185
|
+
node.getMetaModel().getAllPropertyMetaModels().forEach(prop -> {
|
|
186
|
+
String name = prop.getName();
|
|
187
|
+
if (name.equals("comment") || name.equals("parentNode")) return;
|
|
188
|
+
|
|
189
|
+
Object value = prop.getValue(node);
|
|
190
|
+
if (value == null) return;
|
|
191
|
+
|
|
192
|
+
// Rename 'type' property to 'type_' to avoid collision with node class name
|
|
193
|
+
String outputName = name.equals("type") ? "type_" : name;
|
|
194
|
+
sb.append(",\\"").append(outputName).append("\\":");
|
|
195
|
+
|
|
196
|
+
if (value instanceof Node) {
|
|
197
|
+
sb.append(toJson((Node) value));
|
|
198
|
+
} else if (value instanceof NodeList) {
|
|
199
|
+
sb.append("[");
|
|
200
|
+
NodeList<?> list = (NodeList<?>) value;
|
|
201
|
+
for (int i = 0; i < list.size(); i++) {
|
|
202
|
+
if (i > 0) sb.append(",");
|
|
203
|
+
sb.append(toJson((Node) list.get(i)));
|
|
204
|
+
}
|
|
205
|
+
sb.append("]");
|
|
206
|
+
} else if (value instanceof Optional) {
|
|
207
|
+
Optional<?> opt = (Optional<?>) value;
|
|
208
|
+
if (opt.isPresent() && opt.get() instanceof Node) {
|
|
209
|
+
sb.append(toJson((Node) opt.get()));
|
|
210
|
+
} else if (opt.isPresent()) {
|
|
211
|
+
sb.append("\\"").append(opt.get().toString().replace("\\"", "\\\\\\"")).append("\\"");
|
|
212
|
+
} else {
|
|
213
|
+
sb.append("null");
|
|
214
|
+
}
|
|
215
|
+
} else if (value instanceof Boolean) {
|
|
216
|
+
sb.append(value.toString());
|
|
217
|
+
} else {
|
|
218
|
+
sb.append("\\"").append(value.toString().replace("\\"", "\\\\\\"").replace("\\n", "\\\\n")).append("\\"");
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
sb.append("}");
|
|
223
|
+
return sb.toString();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
`;
|
|
227
|
+
const compareWithJavaparser = test.macro({
|
|
228
|
+
title: (_, relativePath) => `compare: ${relativePath}`,
|
|
229
|
+
exec: async (t, relativePath) => {
|
|
230
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
231
|
+
try {
|
|
232
|
+
if (!await hasMvnPromise) {
|
|
233
|
+
t.pass('skipping test because mvn is not available');
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const repo = __addDisposableResource(env_1, await cloneJavaparserRepo(), true);
|
|
237
|
+
const filePath = path.join(repo.path, relativePath);
|
|
238
|
+
// Parse with javaparser (reference)
|
|
239
|
+
const javaparserOutput = await runJavaSnippet(javaparserSnippet, [filePath]);
|
|
240
|
+
const expected = JSON.parse(javaparserOutput);
|
|
241
|
+
// Parse with our parser
|
|
242
|
+
const source = await fs.readFile(filePath, 'utf-8');
|
|
243
|
+
const actual = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
244
|
+
// Compare full AST
|
|
245
|
+
t.deepEqual(actual, expected);
|
|
246
|
+
}
|
|
247
|
+
catch (e_1) {
|
|
248
|
+
env_1.error = e_1;
|
|
249
|
+
env_1.hasError = true;
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
const result_1 = __disposeResources(env_1);
|
|
253
|
+
if (result_1)
|
|
254
|
+
await result_1;
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
test('empty file', async (t) => {
|
|
259
|
+
const result = await runParser(javaCompilationUnitParser, '', stringParserInputCompanion);
|
|
260
|
+
t.deepEqual(result, {
|
|
261
|
+
type: 'CompilationUnit',
|
|
262
|
+
packageDeclaration: undefined,
|
|
263
|
+
imports: [],
|
|
264
|
+
types: [],
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
test('package declaration only', async (t) => {
|
|
268
|
+
const result = await runParser(javaCompilationUnitParser, 'package com.example;', stringParserInputCompanion);
|
|
269
|
+
t.deepEqual(result, {
|
|
270
|
+
type: 'CompilationUnit',
|
|
271
|
+
packageDeclaration: {
|
|
272
|
+
type: 'PackageDeclaration',
|
|
273
|
+
annotations: [],
|
|
274
|
+
name: {
|
|
275
|
+
type: 'Name',
|
|
276
|
+
identifier: 'example',
|
|
277
|
+
qualifier: { type: 'Name', identifier: 'com' },
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
imports: [],
|
|
281
|
+
types: [],
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
test('single import', async (t) => {
|
|
285
|
+
const result = await runParser(javaCompilationUnitParser, 'import java.util.List;', stringParserInputCompanion);
|
|
286
|
+
t.deepEqual(result, {
|
|
287
|
+
type: 'CompilationUnit',
|
|
288
|
+
packageDeclaration: undefined,
|
|
289
|
+
imports: [{
|
|
290
|
+
type: 'ImportDeclaration',
|
|
291
|
+
isStatic: false,
|
|
292
|
+
isAsterisk: false,
|
|
293
|
+
name: {
|
|
294
|
+
type: 'Name',
|
|
295
|
+
identifier: 'List',
|
|
296
|
+
qualifier: {
|
|
297
|
+
type: 'Name',
|
|
298
|
+
identifier: 'util',
|
|
299
|
+
qualifier: { type: 'Name', identifier: 'java' },
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
}],
|
|
303
|
+
types: [],
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
test('wildcard import', async (t) => {
|
|
307
|
+
const result = await runParser(javaCompilationUnitParser, 'import java.util.*;', stringParserInputCompanion);
|
|
308
|
+
t.deepEqual(result, {
|
|
309
|
+
type: 'CompilationUnit',
|
|
310
|
+
packageDeclaration: undefined,
|
|
311
|
+
imports: [{
|
|
312
|
+
type: 'ImportDeclaration',
|
|
313
|
+
isStatic: false,
|
|
314
|
+
isAsterisk: true,
|
|
315
|
+
name: {
|
|
316
|
+
type: 'Name',
|
|
317
|
+
identifier: 'util',
|
|
318
|
+
qualifier: { type: 'Name', identifier: 'java' },
|
|
319
|
+
},
|
|
320
|
+
}],
|
|
321
|
+
types: [],
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
test('static import', async (t) => {
|
|
325
|
+
const result = await runParser(javaCompilationUnitParser, 'import static java.lang.Math.PI;', stringParserInputCompanion);
|
|
326
|
+
t.deepEqual(result, {
|
|
327
|
+
type: 'CompilationUnit',
|
|
328
|
+
packageDeclaration: undefined,
|
|
329
|
+
imports: [{
|
|
330
|
+
type: 'ImportDeclaration',
|
|
331
|
+
isStatic: true,
|
|
332
|
+
isAsterisk: false,
|
|
333
|
+
name: {
|
|
334
|
+
type: 'Name',
|
|
335
|
+
identifier: 'PI',
|
|
336
|
+
qualifier: {
|
|
337
|
+
type: 'Name',
|
|
338
|
+
identifier: 'Math',
|
|
339
|
+
qualifier: {
|
|
340
|
+
type: 'Name',
|
|
341
|
+
identifier: 'lang',
|
|
342
|
+
qualifier: { type: 'Name', identifier: 'java' },
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
}],
|
|
347
|
+
types: [],
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
test('simple class declaration', async (t) => {
|
|
351
|
+
const result = await runParser(javaCompilationUnitParser, 'public class Foo {}', stringParserInputCompanion);
|
|
352
|
+
t.deepEqual(result, {
|
|
353
|
+
type: 'CompilationUnit',
|
|
354
|
+
packageDeclaration: undefined,
|
|
355
|
+
imports: [],
|
|
356
|
+
types: [{
|
|
357
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
358
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
359
|
+
annotations: [],
|
|
360
|
+
name: { type: 'SimpleName', identifier: 'Foo' },
|
|
361
|
+
isInterface: false,
|
|
362
|
+
typeParameters: [],
|
|
363
|
+
extendedTypes: [],
|
|
364
|
+
implementedTypes: [],
|
|
365
|
+
permittedTypes: [],
|
|
366
|
+
members: [],
|
|
367
|
+
}],
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
test('interface declaration', async (t) => {
|
|
371
|
+
const result = await runParser(javaCompilationUnitParser, 'public interface Bar {}', stringParserInputCompanion);
|
|
372
|
+
t.deepEqual(result, {
|
|
373
|
+
type: 'CompilationUnit',
|
|
374
|
+
packageDeclaration: undefined,
|
|
375
|
+
imports: [],
|
|
376
|
+
types: [{
|
|
377
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
378
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
379
|
+
annotations: [],
|
|
380
|
+
name: { type: 'SimpleName', identifier: 'Bar' },
|
|
381
|
+
isInterface: true,
|
|
382
|
+
typeParameters: [],
|
|
383
|
+
extendedTypes: [],
|
|
384
|
+
implementedTypes: [],
|
|
385
|
+
permittedTypes: [],
|
|
386
|
+
members: [],
|
|
387
|
+
}],
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
test('enum declaration', async (t) => {
|
|
391
|
+
const result = await runParser(javaCompilationUnitParser, 'public enum Status {}', stringParserInputCompanion);
|
|
392
|
+
t.deepEqual(result, {
|
|
393
|
+
type: 'CompilationUnit',
|
|
394
|
+
packageDeclaration: undefined,
|
|
395
|
+
imports: [],
|
|
396
|
+
types: [{
|
|
397
|
+
type: 'EnumDeclaration',
|
|
398
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
399
|
+
annotations: [],
|
|
400
|
+
name: { type: 'SimpleName', identifier: 'Status' },
|
|
401
|
+
implementedTypes: [],
|
|
402
|
+
entries: [],
|
|
403
|
+
members: [],
|
|
404
|
+
}],
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
test('annotated class', async (t) => {
|
|
408
|
+
const result = await runParser(javaCompilationUnitParser, '@Deprecated public class OldClass {}', stringParserInputCompanion);
|
|
409
|
+
t.deepEqual(result, {
|
|
410
|
+
type: 'CompilationUnit',
|
|
411
|
+
packageDeclaration: undefined,
|
|
412
|
+
imports: [],
|
|
413
|
+
types: [{
|
|
414
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
415
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
416
|
+
annotations: [{ type: 'MarkerAnnotationExpr', name: { type: 'Name', identifier: 'Deprecated' } }],
|
|
417
|
+
name: { type: 'SimpleName', identifier: 'OldClass' },
|
|
418
|
+
isInterface: false,
|
|
419
|
+
typeParameters: [],
|
|
420
|
+
extendedTypes: [],
|
|
421
|
+
implementedTypes: [],
|
|
422
|
+
permittedTypes: [],
|
|
423
|
+
members: [],
|
|
424
|
+
}],
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
test('full compilation unit', async (t) => {
|
|
428
|
+
const source = `
|
|
429
|
+
package com.example;
|
|
430
|
+
|
|
431
|
+
import java.util.List;
|
|
432
|
+
import java.util.Map;
|
|
433
|
+
|
|
434
|
+
public class MyClass {}
|
|
435
|
+
`;
|
|
436
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
437
|
+
t.deepEqual(result, {
|
|
438
|
+
type: 'CompilationUnit',
|
|
439
|
+
packageDeclaration: {
|
|
440
|
+
type: 'PackageDeclaration',
|
|
441
|
+
annotations: [],
|
|
442
|
+
name: {
|
|
443
|
+
type: 'Name',
|
|
444
|
+
identifier: 'example',
|
|
445
|
+
qualifier: { type: 'Name', identifier: 'com' },
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
imports: [
|
|
449
|
+
{
|
|
450
|
+
type: 'ImportDeclaration',
|
|
451
|
+
isStatic: false,
|
|
452
|
+
isAsterisk: false,
|
|
453
|
+
name: {
|
|
454
|
+
type: 'Name',
|
|
455
|
+
identifier: 'List',
|
|
456
|
+
qualifier: {
|
|
457
|
+
type: 'Name',
|
|
458
|
+
identifier: 'util',
|
|
459
|
+
qualifier: { type: 'Name', identifier: 'java' },
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
type: 'ImportDeclaration',
|
|
465
|
+
isStatic: false,
|
|
466
|
+
isAsterisk: false,
|
|
467
|
+
name: {
|
|
468
|
+
type: 'Name',
|
|
469
|
+
identifier: 'Map',
|
|
470
|
+
qualifier: {
|
|
471
|
+
type: 'Name',
|
|
472
|
+
identifier: 'util',
|
|
473
|
+
qualifier: { type: 'Name', identifier: 'java' },
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
],
|
|
478
|
+
types: [{
|
|
479
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
480
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
481
|
+
annotations: [],
|
|
482
|
+
name: { type: 'SimpleName', identifier: 'MyClass' },
|
|
483
|
+
isInterface: false,
|
|
484
|
+
typeParameters: [],
|
|
485
|
+
extendedTypes: [],
|
|
486
|
+
implementedTypes: [],
|
|
487
|
+
permittedTypes: [],
|
|
488
|
+
members: [],
|
|
489
|
+
}],
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
test('class with method', async (t) => {
|
|
493
|
+
const source = `
|
|
494
|
+
public class Foo {
|
|
495
|
+
public void bar() {}
|
|
496
|
+
}
|
|
497
|
+
`;
|
|
498
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
499
|
+
t.deepEqual(result, {
|
|
500
|
+
type: 'CompilationUnit',
|
|
501
|
+
packageDeclaration: undefined,
|
|
502
|
+
imports: [],
|
|
503
|
+
types: [{
|
|
504
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
505
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
506
|
+
annotations: [],
|
|
507
|
+
name: { type: 'SimpleName', identifier: 'Foo' },
|
|
508
|
+
isInterface: false,
|
|
509
|
+
typeParameters: [],
|
|
510
|
+
extendedTypes: [],
|
|
511
|
+
implementedTypes: [],
|
|
512
|
+
permittedTypes: [],
|
|
513
|
+
members: [{
|
|
514
|
+
type: 'MethodDeclaration',
|
|
515
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
516
|
+
annotations: [],
|
|
517
|
+
typeParameters: [],
|
|
518
|
+
type_: { type: 'VoidType', annotations: [] },
|
|
519
|
+
name: { type: 'SimpleName', identifier: 'bar' },
|
|
520
|
+
parameters: [],
|
|
521
|
+
thrownExceptions: [],
|
|
522
|
+
body: { type: 'BlockStmt', statements: [] },
|
|
523
|
+
}],
|
|
524
|
+
}],
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
test('class with field', async (t) => {
|
|
528
|
+
const source = `
|
|
529
|
+
public class Foo {
|
|
530
|
+
private int x;
|
|
531
|
+
}
|
|
532
|
+
`;
|
|
533
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
534
|
+
t.deepEqual(result, {
|
|
535
|
+
type: 'CompilationUnit',
|
|
536
|
+
packageDeclaration: undefined,
|
|
537
|
+
imports: [],
|
|
538
|
+
types: [{
|
|
539
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
540
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
541
|
+
annotations: [],
|
|
542
|
+
name: { type: 'SimpleName', identifier: 'Foo' },
|
|
543
|
+
isInterface: false,
|
|
544
|
+
typeParameters: [],
|
|
545
|
+
extendedTypes: [],
|
|
546
|
+
implementedTypes: [],
|
|
547
|
+
permittedTypes: [],
|
|
548
|
+
members: [{
|
|
549
|
+
type: 'FieldDeclaration',
|
|
550
|
+
modifiers: [{ type: 'Modifier', keyword: 'PRIVATE' }],
|
|
551
|
+
annotations: [],
|
|
552
|
+
variables: [{
|
|
553
|
+
type: 'VariableDeclarator',
|
|
554
|
+
name: { type: 'SimpleName', identifier: 'x' },
|
|
555
|
+
type_: { type: 'PrimitiveType', type_: 'INT', annotations: [] },
|
|
556
|
+
}],
|
|
557
|
+
}],
|
|
558
|
+
}],
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
test('class with method and parameters', async (t) => {
|
|
562
|
+
const source = `
|
|
563
|
+
public class Foo {
|
|
564
|
+
public int add(int a, int b) {}
|
|
565
|
+
}
|
|
566
|
+
`;
|
|
567
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
568
|
+
t.deepEqual(result, {
|
|
569
|
+
type: 'CompilationUnit',
|
|
570
|
+
packageDeclaration: undefined,
|
|
571
|
+
imports: [],
|
|
572
|
+
types: [{
|
|
573
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
574
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
575
|
+
annotations: [],
|
|
576
|
+
name: { type: 'SimpleName', identifier: 'Foo' },
|
|
577
|
+
isInterface: false,
|
|
578
|
+
typeParameters: [],
|
|
579
|
+
extendedTypes: [],
|
|
580
|
+
implementedTypes: [],
|
|
581
|
+
permittedTypes: [],
|
|
582
|
+
members: [{
|
|
583
|
+
type: 'MethodDeclaration',
|
|
584
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
585
|
+
annotations: [],
|
|
586
|
+
typeParameters: [],
|
|
587
|
+
type_: { type: 'PrimitiveType', type_: 'INT', annotations: [] },
|
|
588
|
+
name: { type: 'SimpleName', identifier: 'add' },
|
|
589
|
+
parameters: [
|
|
590
|
+
{
|
|
591
|
+
type: 'Parameter',
|
|
592
|
+
modifiers: [],
|
|
593
|
+
annotations: [],
|
|
594
|
+
type_: { type: 'PrimitiveType', type_: 'INT', annotations: [] },
|
|
595
|
+
isVarArgs: false,
|
|
596
|
+
varArgsAnnotations: [],
|
|
597
|
+
name: { type: 'SimpleName', identifier: 'a' },
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
type: 'Parameter',
|
|
601
|
+
modifiers: [],
|
|
602
|
+
annotations: [],
|
|
603
|
+
type_: { type: 'PrimitiveType', type_: 'INT', annotations: [] },
|
|
604
|
+
isVarArgs: false,
|
|
605
|
+
varArgsAnnotations: [],
|
|
606
|
+
name: { type: 'SimpleName', identifier: 'b' },
|
|
607
|
+
},
|
|
608
|
+
],
|
|
609
|
+
thrownExceptions: [],
|
|
610
|
+
body: { type: 'BlockStmt', statements: [] },
|
|
611
|
+
}],
|
|
612
|
+
}],
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
test('class with generic type field', async (t) => {
|
|
616
|
+
const source = `
|
|
617
|
+
public class Foo {
|
|
618
|
+
private List<String> items;
|
|
619
|
+
}
|
|
620
|
+
`;
|
|
621
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
622
|
+
t.deepEqual(result, {
|
|
623
|
+
type: 'CompilationUnit',
|
|
624
|
+
packageDeclaration: undefined,
|
|
625
|
+
imports: [],
|
|
626
|
+
types: [{
|
|
627
|
+
type: 'ClassOrInterfaceDeclaration',
|
|
628
|
+
modifiers: [{ type: 'Modifier', keyword: 'PUBLIC' }],
|
|
629
|
+
annotations: [],
|
|
630
|
+
name: { type: 'SimpleName', identifier: 'Foo' },
|
|
631
|
+
isInterface: false,
|
|
632
|
+
typeParameters: [],
|
|
633
|
+
extendedTypes: [],
|
|
634
|
+
implementedTypes: [],
|
|
635
|
+
permittedTypes: [],
|
|
636
|
+
members: [{
|
|
637
|
+
type: 'FieldDeclaration',
|
|
638
|
+
modifiers: [{ type: 'Modifier', keyword: 'PRIVATE' }],
|
|
639
|
+
annotations: [],
|
|
640
|
+
variables: [{
|
|
641
|
+
type: 'VariableDeclarator',
|
|
642
|
+
name: { type: 'SimpleName', identifier: 'items' },
|
|
643
|
+
type_: {
|
|
644
|
+
type: 'ClassOrInterfaceType',
|
|
645
|
+
name: { type: 'SimpleName', identifier: 'List' },
|
|
646
|
+
typeArguments: [{
|
|
647
|
+
type: 'ClassOrInterfaceType',
|
|
648
|
+
name: { type: 'SimpleName', identifier: 'String' },
|
|
649
|
+
annotations: [],
|
|
650
|
+
}],
|
|
651
|
+
annotations: [],
|
|
652
|
+
},
|
|
653
|
+
}],
|
|
654
|
+
}],
|
|
655
|
+
}],
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
test('class with field initializer', async (t) => {
|
|
659
|
+
const source = `
|
|
660
|
+
public class Foo {
|
|
661
|
+
private static final String NAME = "test";
|
|
662
|
+
}
|
|
663
|
+
`;
|
|
664
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
665
|
+
const classDecl = result.types[0];
|
|
666
|
+
t.is(classDecl.members.length, 1);
|
|
667
|
+
t.is(classDecl.members[0].type, 'FieldDeclaration');
|
|
668
|
+
});
|
|
669
|
+
test('class with complex field initializer', async (t) => {
|
|
670
|
+
const source = `
|
|
671
|
+
public class Foo {
|
|
672
|
+
private static final ThreadLocal<Config> config = ThreadLocal.withInitial(Config::new);
|
|
673
|
+
}
|
|
674
|
+
`;
|
|
675
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
676
|
+
const classDecl = result.types[0];
|
|
677
|
+
t.is(classDecl.members.length, 1);
|
|
678
|
+
t.is(classDecl.members[0].type, 'FieldDeclaration');
|
|
679
|
+
});
|
|
680
|
+
test('class with annotated method', async (t) => {
|
|
681
|
+
const source = `
|
|
682
|
+
public class Foo {
|
|
683
|
+
@Deprecated
|
|
684
|
+
public void bar() {}
|
|
685
|
+
}
|
|
686
|
+
`;
|
|
687
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
688
|
+
const classDecl = result.types[0];
|
|
689
|
+
t.is(classDecl.members.length, 1);
|
|
690
|
+
t.is(classDecl.members[0].type, 'MethodDeclaration');
|
|
691
|
+
t.is(classDecl.members[0].annotations.length, 1);
|
|
692
|
+
});
|
|
693
|
+
test('class with field and method', async (t) => {
|
|
694
|
+
const source = `
|
|
695
|
+
public class Foo {
|
|
696
|
+
private int x;
|
|
697
|
+
public int getX() {}
|
|
698
|
+
}
|
|
699
|
+
`;
|
|
700
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
701
|
+
const classDecl = result.types[0];
|
|
702
|
+
t.is(classDecl.members.length, 2);
|
|
703
|
+
t.is(classDecl.members[0].type, 'FieldDeclaration');
|
|
704
|
+
t.is(classDecl.members[1].type, 'MethodDeclaration');
|
|
705
|
+
});
|
|
706
|
+
test('class with multiline field initializer', async (t) => {
|
|
707
|
+
const source = `
|
|
708
|
+
public class Foo {
|
|
709
|
+
private static final ThreadLocal<Config> config =
|
|
710
|
+
ThreadLocal.withInitial(Config::new);
|
|
711
|
+
}
|
|
712
|
+
`;
|
|
713
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
714
|
+
const classDecl = result.types[0];
|
|
715
|
+
t.is(classDecl.members.length, 1);
|
|
716
|
+
t.is(classDecl.members[0].type, 'FieldDeclaration');
|
|
717
|
+
});
|
|
718
|
+
test('generic method', async (t) => {
|
|
719
|
+
const source = `public class Foo {
|
|
720
|
+
public static <T extends Expression> T parseExpression(String expression) {
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
}`;
|
|
724
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
725
|
+
t.is(result.types.length, 1);
|
|
726
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
727
|
+
});
|
|
728
|
+
test('wildcard type', async (t) => {
|
|
729
|
+
const source = `public class Foo {
|
|
730
|
+
public static BodyDeclaration<?> parse(String body) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
}`;
|
|
734
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
735
|
+
t.is(result.types.length, 1);
|
|
736
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
737
|
+
});
|
|
738
|
+
test('class with javadoc', async (t) => {
|
|
739
|
+
const source = `
|
|
740
|
+
/**
|
|
741
|
+
* A test class.
|
|
742
|
+
*/
|
|
743
|
+
public class Foo {
|
|
744
|
+
public void bar() {}
|
|
745
|
+
}
|
|
746
|
+
`;
|
|
747
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
748
|
+
t.is(result.types.length, 1);
|
|
749
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
750
|
+
const classDecl = result.types[0];
|
|
751
|
+
t.is(classDecl.members.length, 1);
|
|
752
|
+
});
|
|
753
|
+
test('public final class', async (t) => {
|
|
754
|
+
const source = `
|
|
755
|
+
package com.example;
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* A test class.
|
|
759
|
+
*/
|
|
760
|
+
public final class Foo {
|
|
761
|
+
}
|
|
762
|
+
`;
|
|
763
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
764
|
+
t.is(result.types.length, 1);
|
|
765
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
766
|
+
});
|
|
767
|
+
test('class with imports and javadoc', async (t) => {
|
|
768
|
+
const source = `
|
|
769
|
+
package com.example;
|
|
770
|
+
|
|
771
|
+
import java.io.*;
|
|
772
|
+
import java.util.List;
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* A test class.
|
|
776
|
+
*/
|
|
777
|
+
public final class Foo {
|
|
778
|
+
}
|
|
779
|
+
`;
|
|
780
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
781
|
+
t.is(result.imports.length, 2);
|
|
782
|
+
t.is(result.types.length, 1);
|
|
783
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
784
|
+
});
|
|
785
|
+
test('class with link in javadoc', async (t) => {
|
|
786
|
+
const source = `
|
|
787
|
+
package com.example;
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* A simpler, static API than {@link JavaParser}.
|
|
791
|
+
*/
|
|
792
|
+
public final class Foo {
|
|
793
|
+
}
|
|
794
|
+
`;
|
|
795
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
796
|
+
t.is(result.types.length, 1);
|
|
797
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
798
|
+
});
|
|
799
|
+
test('class with many imports', async (t) => {
|
|
800
|
+
const source = `
|
|
801
|
+
package com.github.javaparser;
|
|
802
|
+
|
|
803
|
+
import com.github.javaparser.ast.CompilationUnit;
|
|
804
|
+
import com.github.javaparser.ast.ImportDeclaration;
|
|
805
|
+
import com.github.javaparser.ast.Node;
|
|
806
|
+
import com.github.javaparser.ast.PackageDeclaration;
|
|
807
|
+
import com.github.javaparser.ast.body.BodyDeclaration;
|
|
808
|
+
import com.github.javaparser.ast.body.MethodDeclaration;
|
|
809
|
+
import com.github.javaparser.ast.body.Parameter;
|
|
810
|
+
import com.github.javaparser.ast.body.TypeDeclaration;
|
|
811
|
+
import com.github.javaparser.ast.expr.*;
|
|
812
|
+
import com.github.javaparser.ast.modules.ModuleDeclaration;
|
|
813
|
+
import com.github.javaparser.ast.modules.ModuleDirective;
|
|
814
|
+
import com.github.javaparser.ast.stmt.BlockStmt;
|
|
815
|
+
import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
|
|
816
|
+
import com.github.javaparser.ast.stmt.Statement;
|
|
817
|
+
import com.github.javaparser.ast.type.ClassOrInterfaceType;
|
|
818
|
+
import com.github.javaparser.ast.type.Type;
|
|
819
|
+
import com.github.javaparser.ast.type.TypeParameter;
|
|
820
|
+
import com.github.javaparser.javadoc.Javadoc;
|
|
821
|
+
import com.github.javaparser.quality.NotNull;
|
|
822
|
+
import com.github.javaparser.quality.Preconditions;
|
|
823
|
+
import java.io.*;
|
|
824
|
+
import java.nio.charset.Charset;
|
|
825
|
+
import java.nio.file.Path;
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* A simpler, static API than {@link JavaParser}.
|
|
829
|
+
*/
|
|
830
|
+
public final class StaticJavaParser {
|
|
831
|
+
}
|
|
832
|
+
`;
|
|
833
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
834
|
+
t.is(result.imports.length, 23);
|
|
835
|
+
t.is(result.types.length, 1);
|
|
836
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
837
|
+
});
|
|
838
|
+
test('class with method body', async (t) => {
|
|
839
|
+
const source = `public class Foo {
|
|
840
|
+
public void test() {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
}`;
|
|
844
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
845
|
+
t.is(result.types.length, 1);
|
|
846
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
847
|
+
const classDecl = result.types[0];
|
|
848
|
+
t.is(classDecl.members.length, 1);
|
|
849
|
+
t.is(classDecl.members[0].type, 'MethodDeclaration');
|
|
850
|
+
t.truthy(classDecl.members[0].body);
|
|
851
|
+
t.is(classDecl.members[0].body.statements.length, 1);
|
|
852
|
+
});
|
|
853
|
+
test('class with field and line comment', async (t) => {
|
|
854
|
+
const source = `public final class StaticJavaParser {
|
|
855
|
+
|
|
856
|
+
// use ThreadLocal to resolve possible concurrency issues.
|
|
857
|
+
private static final ThreadLocal<ParserConfiguration> localConfiguration =
|
|
858
|
+
ThreadLocal.withInitial(ParserConfiguration::new);
|
|
859
|
+
}`;
|
|
860
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
861
|
+
t.is(result.types.length, 1);
|
|
862
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
863
|
+
});
|
|
864
|
+
test('class with copyright header and imports', async (t) => {
|
|
865
|
+
const source = `/*
|
|
866
|
+
* Copyright (C) 2007-2010 Júlio Vilmar Gesser.
|
|
867
|
+
*/
|
|
868
|
+
package com.github.javaparser;
|
|
869
|
+
|
|
870
|
+
import java.io.*;
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* A simpler, static API than {@link JavaParser}.
|
|
874
|
+
*/
|
|
875
|
+
public final class StaticJavaParser {
|
|
876
|
+
|
|
877
|
+
// use ThreadLocal to resolve possible concurrency issues.
|
|
878
|
+
private static final ThreadLocal<ParserConfiguration> localConfiguration =
|
|
879
|
+
ThreadLocal.withInitial(ParserConfiguration::new);
|
|
880
|
+
}`;
|
|
881
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
882
|
+
t.is(result.types.length, 1);
|
|
883
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
884
|
+
});
|
|
885
|
+
test('read file and parse', async (t) => {
|
|
886
|
+
// Write a file with the same content and read it back
|
|
887
|
+
const source = `/*
|
|
888
|
+
* Copyright (C) 2007-2010 Júlio Vilmar Gesser.
|
|
889
|
+
*/
|
|
890
|
+
package com.github.javaparser;
|
|
891
|
+
|
|
892
|
+
import java.io.*;
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* A simpler, static API than {@link JavaParser}.
|
|
896
|
+
*/
|
|
897
|
+
public final class StaticJavaParser {
|
|
898
|
+
|
|
899
|
+
// use ThreadLocal to resolve possible concurrency issues.
|
|
900
|
+
private static final ThreadLocal<ParserConfiguration> localConfiguration =
|
|
901
|
+
ThreadLocal.withInitial(ParserConfiguration::new);
|
|
902
|
+
}`;
|
|
903
|
+
const tmpDir = temporaryDirectory();
|
|
904
|
+
const tmpFile = path.join(tmpDir, 'Test.java');
|
|
905
|
+
try {
|
|
906
|
+
await fs.writeFile(tmpFile, source, 'utf-8');
|
|
907
|
+
const readSource = await fs.readFile(tmpFile, 'utf-8');
|
|
908
|
+
const result = await runParser(javaCompilationUnitParser, readSource, stringParserInputCompanion);
|
|
909
|
+
t.is(result.types.length, 1);
|
|
910
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
911
|
+
}
|
|
912
|
+
finally {
|
|
913
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
test('StaticJavaParser minimal', async (t) => {
|
|
917
|
+
const source = `public class Foo {
|
|
918
|
+
public void test() {
|
|
919
|
+
throw new Exception();
|
|
920
|
+
}
|
|
921
|
+
}`;
|
|
922
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
923
|
+
t.is(result.types.length, 1);
|
|
924
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
925
|
+
});
|
|
926
|
+
test('class with constructor calling this', async (t) => {
|
|
927
|
+
const source = `public class Foo {
|
|
928
|
+
public Foo() {
|
|
929
|
+
this(1);
|
|
930
|
+
}
|
|
931
|
+
public Foo(int x) {
|
|
932
|
+
}
|
|
933
|
+
}`;
|
|
934
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
935
|
+
t.is(result.types.length, 1);
|
|
936
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
937
|
+
});
|
|
938
|
+
test('class with try-catch', async (t) => {
|
|
939
|
+
const source = `public class Foo {
|
|
940
|
+
public void test() {
|
|
941
|
+
try {
|
|
942
|
+
throw new Exception();
|
|
943
|
+
} catch (Exception e) {
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}`;
|
|
947
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
948
|
+
t.is(result.types.length, 1);
|
|
949
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
950
|
+
});
|
|
951
|
+
test('class with generic method', async (t) => {
|
|
952
|
+
const source = `public class Foo {
|
|
953
|
+
public <N extends Node> N parse(N start) {
|
|
954
|
+
return start;
|
|
955
|
+
}
|
|
956
|
+
}`;
|
|
957
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
958
|
+
t.is(result.types.length, 1);
|
|
959
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
960
|
+
});
|
|
961
|
+
test('method with throws clause', async (t) => {
|
|
962
|
+
const source = `public class Foo {
|
|
963
|
+
public void test() throws Exception {
|
|
964
|
+
}
|
|
965
|
+
}`;
|
|
966
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
967
|
+
t.is(result.types.length, 1);
|
|
968
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
969
|
+
});
|
|
970
|
+
test('deprecated method', async (t) => {
|
|
971
|
+
const source = `public class Foo {
|
|
972
|
+
@Deprecated
|
|
973
|
+
public void test() {
|
|
974
|
+
}
|
|
975
|
+
}`;
|
|
976
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
977
|
+
t.is(result.types.length, 1);
|
|
978
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
979
|
+
});
|
|
980
|
+
test('try-finally without catch', async (t) => {
|
|
981
|
+
const source = `public class Foo {
|
|
982
|
+
public void test() {
|
|
983
|
+
try {
|
|
984
|
+
} finally {
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}`;
|
|
988
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
989
|
+
t.is(result.types.length, 1);
|
|
990
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
991
|
+
});
|
|
992
|
+
test('nested class', async (t) => {
|
|
993
|
+
const source = `public class Foo {
|
|
994
|
+
class Inner {}
|
|
995
|
+
}`;
|
|
996
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
997
|
+
t.is(result.types.length, 1);
|
|
998
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
999
|
+
});
|
|
1000
|
+
test('class with final field and null initializer', async (t) => {
|
|
1001
|
+
const source = `public class Foo {
|
|
1002
|
+
private final ParserConfiguration configuration;
|
|
1003
|
+
private GeneratedJavaParser astParser = null;
|
|
1004
|
+
}`;
|
|
1005
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1006
|
+
t.is(result.types.length, 1);
|
|
1007
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1008
|
+
});
|
|
1009
|
+
test('class with constructor and this assignment', async (t) => {
|
|
1010
|
+
const source = `public class Foo {
|
|
1011
|
+
private int configuration;
|
|
1012
|
+
public Foo(int configuration) {
|
|
1013
|
+
this.configuration = configuration;
|
|
1014
|
+
}
|
|
1015
|
+
}`;
|
|
1016
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1017
|
+
t.is(result.types.length, 1);
|
|
1018
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1019
|
+
});
|
|
1020
|
+
test('class with if null check', async (t) => {
|
|
1021
|
+
const source = `public class Foo {
|
|
1022
|
+
private Object x;
|
|
1023
|
+
public void test() {
|
|
1024
|
+
if (x == null) {
|
|
1025
|
+
x = new Object();
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}`;
|
|
1029
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1030
|
+
t.is(result.types.length, 1);
|
|
1031
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1032
|
+
});
|
|
1033
|
+
test('qualified type in local var', async (t) => {
|
|
1034
|
+
const source = `public class Foo {
|
|
1035
|
+
public void test() {
|
|
1036
|
+
ParserConfig.Level level = null;
|
|
1037
|
+
}
|
|
1038
|
+
}`;
|
|
1039
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1040
|
+
t.is(result.types.length, 1);
|
|
1041
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1042
|
+
});
|
|
1043
|
+
test('method chaining with collect', async (t) => {
|
|
1044
|
+
const source = `public class Foo {
|
|
1045
|
+
public void test() {
|
|
1046
|
+
List<String> x = list.stream().map(Supplier::get).collect(toList());
|
|
1047
|
+
}
|
|
1048
|
+
}`;
|
|
1049
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1050
|
+
t.is(result.types.length, 1);
|
|
1051
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1052
|
+
});
|
|
1053
|
+
test('reassignment in for loop', async (t) => {
|
|
1054
|
+
const source = `public class Foo {
|
|
1055
|
+
public void test() {
|
|
1056
|
+
Object x = null;
|
|
1057
|
+
for (Object o : list) {
|
|
1058
|
+
x = o.process(x);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}`;
|
|
1062
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1063
|
+
t.is(result.types.length, 1);
|
|
1064
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1065
|
+
});
|
|
1066
|
+
test('lambda passed to method', async (t) => {
|
|
1067
|
+
const source = `public class Foo {
|
|
1068
|
+
public void test() {
|
|
1069
|
+
result.ifPresent(cu -> cu.setStorage(path));
|
|
1070
|
+
}
|
|
1071
|
+
}`;
|
|
1072
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1073
|
+
t.is(result.types.length, 1);
|
|
1074
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1075
|
+
});
|
|
1076
|
+
test('method with multiple throws', async (t) => {
|
|
1077
|
+
const source = `public class Foo {
|
|
1078
|
+
public void test() throws IOException, ParseException {
|
|
1079
|
+
}
|
|
1080
|
+
}`;
|
|
1081
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1082
|
+
t.is(result.types.length, 1);
|
|
1083
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1084
|
+
});
|
|
1085
|
+
test('generic return type', async (t) => {
|
|
1086
|
+
const source = `public class Foo {
|
|
1087
|
+
public ParseResult<CompilationUnit> parse() {
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
}`;
|
|
1091
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1092
|
+
t.is(result.types.length, 1);
|
|
1093
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1094
|
+
});
|
|
1095
|
+
test('JavaParser-like structure', async (t) => {
|
|
1096
|
+
const source = `public final class JavaParser {
|
|
1097
|
+
private final ParserConfiguration configuration;
|
|
1098
|
+
private GeneratedJavaParser astParser = null;
|
|
1099
|
+
|
|
1100
|
+
public JavaParser() {
|
|
1101
|
+
this(new ParserConfiguration());
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
public JavaParser(ParserConfiguration configuration) {
|
|
1105
|
+
this.configuration = configuration;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
public ParserConfiguration getParserConfiguration() {
|
|
1109
|
+
return this.configuration;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
private GeneratedJavaParser getParserForProvider(Provider provider) {
|
|
1113
|
+
if (astParser == null) {
|
|
1114
|
+
astParser = new GeneratedJavaParser(provider);
|
|
1115
|
+
} else {
|
|
1116
|
+
astParser.reset(provider);
|
|
1117
|
+
}
|
|
1118
|
+
astParser.setTabSize(configuration.getTabSize());
|
|
1119
|
+
return astParser;
|
|
1120
|
+
}
|
|
1121
|
+
}`;
|
|
1122
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1123
|
+
t.is(result.types.length, 1);
|
|
1124
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1125
|
+
});
|
|
1126
|
+
test('generic method with type variable in return type', async (t) => {
|
|
1127
|
+
const source = `public class Foo {
|
|
1128
|
+
public <N extends Node> ParseResult<N> parse(N start) {
|
|
1129
|
+
return null;
|
|
1130
|
+
}
|
|
1131
|
+
}`;
|
|
1132
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1133
|
+
t.is(result.types.length, 1);
|
|
1134
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1135
|
+
});
|
|
1136
|
+
test('generic method with two generic params', async (t) => {
|
|
1137
|
+
const source = `public class Foo {
|
|
1138
|
+
public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provider) {
|
|
1139
|
+
return null;
|
|
1140
|
+
}
|
|
1141
|
+
}`;
|
|
1142
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1143
|
+
t.is(result.types.length, 1);
|
|
1144
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1145
|
+
});
|
|
1146
|
+
test('ternary expression', async (t) => {
|
|
1147
|
+
const source = `public class Foo {
|
|
1148
|
+
public void test() {
|
|
1149
|
+
String x = y == null ? "a" : "b";
|
|
1150
|
+
}
|
|
1151
|
+
}`;
|
|
1152
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1153
|
+
t.is(result.types.length, 1);
|
|
1154
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1155
|
+
});
|
|
1156
|
+
test('ternary with method calls', async (t) => {
|
|
1157
|
+
const source = `public class Foo {
|
|
1158
|
+
public void test(Exception e) {
|
|
1159
|
+
final String message = e.getMessage() == null ? "Unknown error" : e.getMessage();
|
|
1160
|
+
}
|
|
1161
|
+
}`;
|
|
1162
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1163
|
+
t.is(result.types.length, 1);
|
|
1164
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1165
|
+
});
|
|
1166
|
+
test('method body with final local var', async (t) => {
|
|
1167
|
+
const source = `public class Foo {
|
|
1168
|
+
public void test() {
|
|
1169
|
+
final String x = getValue();
|
|
1170
|
+
try {
|
|
1171
|
+
doSomething(x);
|
|
1172
|
+
} catch (Exception e) {
|
|
1173
|
+
final String message = e.getMessage();
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}`;
|
|
1177
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1178
|
+
t.is(result.types.length, 1);
|
|
1179
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1180
|
+
});
|
|
1181
|
+
test('method with for and processor', async (t) => {
|
|
1182
|
+
const source = `public class Foo {
|
|
1183
|
+
public void test() {
|
|
1184
|
+
List<Processor> processors = getProcessors();
|
|
1185
|
+
for (Processor processor : processors) {
|
|
1186
|
+
provider = processor.preProcess(provider);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}`;
|
|
1190
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1191
|
+
t.is(result.types.length, 1);
|
|
1192
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1193
|
+
});
|
|
1194
|
+
test('constructor new with type arg', async (t) => {
|
|
1195
|
+
const source = `public class Foo {
|
|
1196
|
+
public void test() {
|
|
1197
|
+
Result<N> result = new Result<>(x, y);
|
|
1198
|
+
}
|
|
1199
|
+
}`;
|
|
1200
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1201
|
+
t.is(result.types.length, 1);
|
|
1202
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1203
|
+
});
|
|
1204
|
+
test('class with implements', async (t) => {
|
|
1205
|
+
const source = `package com.github.javaparser;
|
|
1206
|
+
|
|
1207
|
+
import static com.github.javaparser.utils.Utils.assertNotNull;
|
|
1208
|
+
|
|
1209
|
+
import java.util.Objects;
|
|
1210
|
+
|
|
1211
|
+
public class Position implements Comparable<Position> {
|
|
1212
|
+
|
|
1213
|
+
public final int line;
|
|
1214
|
+
|
|
1215
|
+
public final int column;
|
|
1216
|
+
}`;
|
|
1217
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1218
|
+
t.is(result.types.length, 1);
|
|
1219
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1220
|
+
});
|
|
1221
|
+
test('class with static method returning method call', async (t) => {
|
|
1222
|
+
const source = `public final class Foo {
|
|
1223
|
+
public static Config getConfig() {
|
|
1224
|
+
return getParserConfiguration();
|
|
1225
|
+
}
|
|
1226
|
+
}`;
|
|
1227
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1228
|
+
t.is(result.types.length, 1);
|
|
1229
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1230
|
+
});
|
|
1231
|
+
test('class with return method call', async (t) => {
|
|
1232
|
+
const source = `public class Foo {
|
|
1233
|
+
public Config getConfig() {
|
|
1234
|
+
return getConfiguration();
|
|
1235
|
+
}
|
|
1236
|
+
}`;
|
|
1237
|
+
const result = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
|
|
1238
|
+
t.is(result.types.length, 1);
|
|
1239
|
+
t.is(result.types[0].type, 'ClassOrInterfaceDeclaration');
|
|
1240
|
+
const classDecl = result.types[0];
|
|
1241
|
+
t.is(classDecl.members.length, 1);
|
|
1242
|
+
t.is(classDecl.members[0].type, 'MethodDeclaration');
|
|
1243
|
+
t.truthy(classDecl.members[0].body);
|
|
1244
|
+
t.is(classDecl.members[0].body.statements.length, 1);
|
|
1245
|
+
});
|
|
1246
|
+
test('clone javaparser repo and list files', async (t) => {
|
|
1247
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
1248
|
+
try {
|
|
1249
|
+
const repo = __addDisposableResource(env_2, await cloneJavaparserRepo(), true);
|
|
1250
|
+
const { stdout } = await execa('find', [repo.path, '-name', '*.java', '-type', 'f'], { cwd: repo.path });
|
|
1251
|
+
const files = stdout.split('\n').filter(Boolean);
|
|
1252
|
+
t.true(files.length > 0, 'should find java files');
|
|
1253
|
+
}
|
|
1254
|
+
catch (e_2) {
|
|
1255
|
+
env_2.error = e_2;
|
|
1256
|
+
env_2.hasError = true;
|
|
1257
|
+
}
|
|
1258
|
+
finally {
|
|
1259
|
+
const result_2 = __disposeResources(env_2);
|
|
1260
|
+
if (result_2)
|
|
1261
|
+
await result_2;
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
test('run java snippet', async (t) => {
|
|
1265
|
+
if (!await hasMvnPromise) {
|
|
1266
|
+
t.pass('skipping test because mvn is not available');
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
const code = `
|
|
1270
|
+
class Main {
|
|
1271
|
+
public static void main(String[] args) {
|
|
1272
|
+
System.out.println("Hello from Java!");
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
`;
|
|
1276
|
+
const output = await runJavaSnippet(code);
|
|
1277
|
+
t.is(output, 'Hello from Java!');
|
|
1278
|
+
});
|
|
1279
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/StaticJavaParser.java');
|
|
1280
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/Position.java');
|
|
1281
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/Range.java');
|
|
1282
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/Problem.java');
|
|
1283
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/ParseResult.java');
|
|
1284
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/Providers.java');
|
|
1285
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java');
|
|
1286
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/ParseProblemException.java');
|
|
1287
|
+
test(compareWithJavaparser, 'javaparser-core/src/main/java/com/github/javaparser/HasParentNode.java');
|