@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.
Files changed (262) hide show
  1. package/.claude/settings.local.json +24 -0
  2. package/.github/workflows/main.yml +1 -0
  3. package/build/androidPackageParser.js +30 -32
  4. package/build/arbitraryDalvikBytecode.d.ts +3 -3
  5. package/build/arbitraryDalvikBytecode.js +33 -27
  6. package/build/arbitraryDalvikExecutable.js +55 -17
  7. package/build/arbitraryJava.d.ts +31 -0
  8. package/build/arbitraryJava.js +532 -0
  9. package/build/arbitraryJavaScript.d.ts +3 -0
  10. package/build/arbitraryJavaScript.js +263 -0
  11. package/build/arbitraryJavascript.d.ts +3 -0
  12. package/build/arbitraryJavascript.js +263 -0
  13. package/build/arbitraryZig.d.ts +3 -0
  14. package/build/arbitraryZig.js +240 -0
  15. package/build/arbitraryZipStream.d.ts +1 -1
  16. package/build/arrayParser.js +72 -13
  17. package/build/backsmali.d.ts +4 -3
  18. package/build/backsmali.js +26 -6
  19. package/build/bash.d.ts +89 -0
  20. package/build/bash.js +1 -0
  21. package/build/bashParser.d.ts +6 -0
  22. package/build/bashParser.js +335 -0
  23. package/build/bashParser.test.d.ts +1 -0
  24. package/build/bashParser.test.js +343 -0
  25. package/build/bashParserEdgeCases.test.d.ts +1 -0
  26. package/build/bashParserEdgeCases.test.js +117 -0
  27. package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
  28. package/build/dalvikBytecodeParser/addressConversion.js +334 -0
  29. package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
  30. package/build/dalvikBytecodeParser/formatParsers.js +13 -14
  31. package/build/dalvikBytecodeParser.d.ts +60 -31
  32. package/build/dalvikBytecodeParser.js +92 -35
  33. package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
  34. package/build/dalvikBytecodeParser.test-d.js +268 -0
  35. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
  36. package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
  37. package/build/dalvikBytecodeUnparser.d.ts +2 -2
  38. package/build/dalvikBytecodeUnparser.js +23 -23
  39. package/build/dalvikBytecodeUnparser.test.js +7 -7
  40. package/build/dalvikExecutable.d.ts +3 -3
  41. package/build/dalvikExecutable.test-d.d.ts +1 -0
  42. package/build/dalvikExecutable.test-d.js +59 -0
  43. package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
  44. package/build/dalvikExecutableParser/typedNumbers.js +3 -0
  45. package/build/dalvikExecutableParser.d.ts +2 -1
  46. package/build/dalvikExecutableParser.js +96 -77
  47. package/build/dalvikExecutableParser.test.js +24 -3
  48. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
  49. package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
  50. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
  51. package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
  52. package/build/dalvikExecutableUnparser.d.ts +2 -2
  53. package/build/dalvikExecutableUnparser.test.js +2 -1
  54. package/build/disjunctionParser.d.ts +5 -3
  55. package/build/disjunctionParser.js +79 -17
  56. package/build/disjunctionParser.test-d.d.ts +1 -0
  57. package/build/disjunctionParser.test-d.js +72 -0
  58. package/build/elementSwitchParser.d.ts +4 -0
  59. package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
  60. package/build/elementSwitchParser.test-d.d.ts +1 -0
  61. package/build/elementSwitchParser.test-d.js +44 -0
  62. package/build/exactSequenceParser.d.ts +4 -2
  63. package/build/exactSequenceParser.test-d.d.ts +1 -0
  64. package/build/exactSequenceParser.test-d.js +36 -0
  65. package/build/fetchCid.js +2 -66
  66. package/build/index.d.ts +25 -2
  67. package/build/index.js +23 -1
  68. package/build/index.test.js +16 -1
  69. package/build/inputReader.d.ts +10 -0
  70. package/build/inputReader.js +36 -0
  71. package/build/java.d.ts +502 -0
  72. package/build/java.js +2 -0
  73. package/build/javaKeyStoreParser.js +14 -17
  74. package/build/javaParser.d.ts +51 -0
  75. package/build/javaParser.js +1538 -0
  76. package/build/javaParser.test.d.ts +1 -0
  77. package/build/javaParser.test.js +1287 -0
  78. package/build/javaScript.d.ts +35 -0
  79. package/build/javaScript.js +1 -0
  80. package/build/javaScriptParser.d.ts +9 -0
  81. package/build/javaScriptParser.js +34 -0
  82. package/build/javaScriptUnparser.d.ts +3 -0
  83. package/build/javaScriptUnparser.js +4 -0
  84. package/build/javaScriptUnparser.test.d.ts +1 -0
  85. package/build/javaScriptUnparser.test.js +24 -0
  86. package/build/javaUnparser.d.ts +2 -0
  87. package/build/javaUnparser.js +519 -0
  88. package/build/javaUnparser.test.d.ts +1 -0
  89. package/build/javaUnparser.test.js +24 -0
  90. package/build/javascript.d.ts +35 -0
  91. package/build/javascript.js +1 -0
  92. package/build/javascriptParser.d.ts +9 -0
  93. package/build/javascriptParser.js +34 -0
  94. package/build/javascriptUnparser.d.ts +3 -0
  95. package/build/javascriptUnparser.js +4 -0
  96. package/build/javascriptUnparser.test.d.ts +1 -0
  97. package/build/javascriptUnparser.test.js +24 -0
  98. package/build/jsonParser.js +2 -12
  99. package/build/lazyMessageError.d.ts +3 -0
  100. package/build/lookaheadParser.js +60 -3
  101. package/build/negativeLookaheadParser.js +70 -11
  102. package/build/nonEmptyArrayParser.js +72 -13
  103. package/build/objectParser.d.ts +12 -0
  104. package/build/objectParser.js +31 -0
  105. package/build/objectParser.test-d.d.ts +1 -0
  106. package/build/objectParser.test-d.js +112 -0
  107. package/build/objectParser.test.d.ts +1 -0
  108. package/build/objectParser.test.js +55 -0
  109. package/build/optionalParser.js +69 -10
  110. package/build/parser.d.ts +4 -0
  111. package/build/parser.js +3 -1
  112. package/build/parser.test.js +114 -1
  113. package/build/parserConsumedSequenceParser.js +66 -7
  114. package/build/parserContext.d.ts +6 -0
  115. package/build/parserContext.js +20 -11
  116. package/build/parserError.d.ts +119 -27
  117. package/build/parserError.js +16 -8
  118. package/build/regexpParser.d.ts +2 -0
  119. package/build/regexpParser.js +101 -0
  120. package/build/regexpParser.test.d.ts +1 -0
  121. package/build/regexpParser.test.js +114 -0
  122. package/build/regularExpression.d.ts +63 -0
  123. package/build/regularExpression.js +1 -0
  124. package/build/regularExpressionParser.d.ts +3 -0
  125. package/build/regularExpressionParser.js +600 -0
  126. package/build/regularExpressionParser.test.d.ts +1 -0
  127. package/build/regularExpressionParser.test.js +89 -0
  128. package/build/separatedArrayParser.js +73 -14
  129. package/build/separatedNonEmptyArrayParser.js +73 -14
  130. package/build/sliceBoundedParser.js +62 -5
  131. package/build/smaliParser.d.ts +7 -7
  132. package/build/smaliParser.js +185 -268
  133. package/build/smaliParser.test.js +58 -0
  134. package/build/stringEscapes.d.ts +5 -0
  135. package/build/stringEscapes.js +244 -0
  136. package/build/symbolicExpression.d.ts +29 -0
  137. package/build/symbolicExpression.js +1 -0
  138. package/build/symbolicExpressionParser.d.ts +4 -0
  139. package/build/symbolicExpressionParser.js +123 -0
  140. package/build/symbolicExpressionParser.test.d.ts +1 -0
  141. package/build/symbolicExpressionParser.test.js +289 -0
  142. package/build/terminatedArrayParser.js +113 -38
  143. package/build/terminatedArrayParser.test.js +4 -2
  144. package/build/tupleParser.d.ts +7 -15
  145. package/build/tupleParser.js +1 -0
  146. package/build/unionParser.d.ts +5 -3
  147. package/build/unionParser.js +7 -2
  148. package/build/unionParser.test-d.d.ts +1 -0
  149. package/build/unionParser.test-d.js +72 -0
  150. package/build/unionParser.test.js +10 -11
  151. package/build/zig.d.ts +280 -0
  152. package/build/zig.js +2 -0
  153. package/build/zigParser.d.ts +3 -0
  154. package/build/zigParser.js +1119 -0
  155. package/build/zigParser.test.d.ts +1 -0
  156. package/build/zigParser.test.js +1590 -0
  157. package/build/zigUnparser.d.ts +2 -0
  158. package/build/zigUnparser.js +460 -0
  159. package/build/zigUnparser.test.d.ts +1 -0
  160. package/build/zigUnparser.test.js +24 -0
  161. package/build/zipParser.js +19 -32
  162. package/build/zipUnparser.js +19 -7
  163. package/build/zipUnparser.test.js +1 -1
  164. package/node_modules-@types/s-expression/index.d.ts +5 -0
  165. package/package.json +25 -6
  166. package/src/androidPackageParser.ts +33 -60
  167. package/src/arbitraryDalvikBytecode.ts +39 -31
  168. package/src/arbitraryDalvikExecutable.ts +65 -20
  169. package/src/arbitraryJava.ts +804 -0
  170. package/src/arbitraryJavaScript.ts +410 -0
  171. package/src/arbitraryZig.ts +380 -0
  172. package/src/arrayParser.ts +1 -3
  173. package/src/backsmali.ts +35 -4
  174. package/src/bash.ts +127 -0
  175. package/src/bashParser.test.ts +590 -0
  176. package/src/bashParser.ts +498 -0
  177. package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
  178. package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
  179. package/src/dalvikBytecodeParser.test-d.ts +310 -0
  180. package/src/dalvikBytecodeParser.ts +194 -69
  181. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
  182. package/src/dalvikBytecodeUnparser.test.ts +7 -7
  183. package/src/dalvikBytecodeUnparser.ts +31 -30
  184. package/src/dalvikExecutable.test-d.ts +132 -0
  185. package/src/dalvikExecutable.ts +3 -3
  186. package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
  187. package/src/dalvikExecutableParser.test.ts +37 -3
  188. package/src/dalvikExecutableParser.test.ts.md +163 -2
  189. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  190. package/src/dalvikExecutableParser.ts +121 -139
  191. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
  192. package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
  193. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
  194. package/src/dalvikExecutableUnparser.test.ts +3 -2
  195. package/src/dalvikExecutableUnparser.ts +4 -4
  196. package/src/disjunctionParser.test-d.ts +105 -0
  197. package/src/disjunctionParser.ts +18 -15
  198. package/src/elementSwitchParser.test-d.ts +74 -0
  199. package/src/elementSwitchParser.ts +51 -0
  200. package/src/exactSequenceParser.test-d.ts +43 -0
  201. package/src/exactSequenceParser.ts +13 -8
  202. package/src/fetchCid.ts +2 -76
  203. package/src/index.test.ts +22 -1
  204. package/src/index.ts +119 -2
  205. package/src/inputReader.ts +53 -0
  206. package/src/java.ts +708 -0
  207. package/src/javaKeyStoreParser.ts +18 -32
  208. package/src/javaParser.test.ts +1592 -0
  209. package/src/javaParser.ts +2640 -0
  210. package/src/javaScript.ts +36 -0
  211. package/src/javaScriptParser.ts +57 -0
  212. package/src/javaScriptUnparser.test.ts +37 -0
  213. package/src/javaScriptUnparser.ts +7 -0
  214. package/src/javaUnparser.test.ts +37 -0
  215. package/src/javaUnparser.ts +640 -0
  216. package/src/jsonParser.ts +6 -27
  217. package/src/lookaheadParser.ts +2 -6
  218. package/src/negativeLookaheadParser.ts +1 -3
  219. package/src/nonEmptyArrayParser.ts +1 -3
  220. package/src/objectParser.test-d.ts +152 -0
  221. package/src/objectParser.test.ts +71 -0
  222. package/src/objectParser.ts +69 -0
  223. package/src/optionalParser.ts +1 -3
  224. package/src/parser.test.ts +151 -4
  225. package/src/parser.ts +11 -1
  226. package/src/parserConsumedSequenceParser.ts +2 -4
  227. package/src/parserContext.ts +26 -11
  228. package/src/parserError.ts +17 -3
  229. package/src/regexpParser.test.ts +264 -0
  230. package/src/regexpParser.ts +126 -0
  231. package/src/regularExpression.ts +24 -0
  232. package/src/regularExpressionParser.test.ts +102 -0
  233. package/src/regularExpressionParser.ts +920 -0
  234. package/src/separatedArrayParser.ts +1 -3
  235. package/src/separatedNonEmptyArrayParser.ts +1 -3
  236. package/src/sliceBoundedParser.test.ts +2 -2
  237. package/src/sliceBoundedParser.ts +15 -19
  238. package/src/smaliParser.test.ts +64 -0
  239. package/src/smaliParser.test.ts.md +12 -12
  240. package/src/smaliParser.test.ts.snap +0 -0
  241. package/src/smaliParser.ts +246 -534
  242. package/src/stringEscapes.ts +253 -0
  243. package/src/symbolicExpression.ts +17 -0
  244. package/src/symbolicExpressionParser.test.ts +466 -0
  245. package/src/symbolicExpressionParser.ts +190 -0
  246. package/src/terminatedArrayParser.test.ts +9 -6
  247. package/src/terminatedArrayParser.ts +25 -29
  248. package/src/tupleParser.ts +21 -18
  249. package/src/unionParser.test-d.ts +105 -0
  250. package/src/unionParser.test.ts +18 -17
  251. package/src/unionParser.ts +28 -16
  252. package/src/zig.ts +411 -0
  253. package/src/zigParser.test.ts +1693 -0
  254. package/src/zigParser.ts +1745 -0
  255. package/src/zigUnparser.test.ts +37 -0
  256. package/src/zigUnparser.ts +615 -0
  257. package/src/zipParser.ts +20 -56
  258. package/src/zipUnparser.test.ts +1 -1
  259. package/src/zipUnparser.ts +22 -7
  260. package/tsconfig.json +2 -2
  261. package/build/exactElementSwitchParser.d.ts +0 -3
  262. package/src/exactElementSwitchParser.ts +0 -41
@@ -0,0 +1,35 @@
1
+ import type * as estree from 'estree';
2
+ import { type StripMeta } from './javaScriptParser.js';
3
+ export type JavaScriptProgram = StripMeta<estree.Program>;
4
+ export type JavaScriptStatement = StripMeta<estree.Statement>;
5
+ export type JavaScriptExpression = StripMeta<estree.Expression>;
6
+ export type JavaScriptIdentifier = StripMeta<estree.Identifier>;
7
+ export type JavaScriptLiteral = StripMeta<estree.Literal>;
8
+ export type JavaScriptBlockStatement = StripMeta<estree.BlockStatement>;
9
+ export type JavaScriptExpressionStatement = StripMeta<estree.ExpressionStatement>;
10
+ export type JavaScriptVariableDeclaration = StripMeta<estree.VariableDeclaration>;
11
+ export type JavaScriptVariableDeclarator = StripMeta<estree.VariableDeclarator>;
12
+ export type JavaScriptIfStatement = StripMeta<estree.IfStatement>;
13
+ export type JavaScriptWhileStatement = StripMeta<estree.WhileStatement>;
14
+ export type JavaScriptForStatement = StripMeta<estree.ForStatement>;
15
+ export type JavaScriptReturnStatement = StripMeta<estree.ReturnStatement>;
16
+ export type JavaScriptThrowStatement = StripMeta<estree.ThrowStatement>;
17
+ export type JavaScriptTryStatement = StripMeta<estree.TryStatement>;
18
+ export type JavaScriptCatchClause = StripMeta<estree.CatchClause>;
19
+ export type JavaScriptEmptyStatement = StripMeta<estree.EmptyStatement>;
20
+ export type JavaScriptFunctionDeclaration = StripMeta<estree.FunctionDeclaration>;
21
+ export type JavaScriptFunctionExpression = StripMeta<estree.FunctionExpression>;
22
+ export type JavaScriptArrowFunctionExpression = StripMeta<estree.ArrowFunctionExpression>;
23
+ export type JavaScriptBinaryExpression = StripMeta<estree.BinaryExpression>;
24
+ export type JavaScriptLogicalExpression = StripMeta<estree.LogicalExpression>;
25
+ export type JavaScriptUnaryExpression = StripMeta<estree.UnaryExpression>;
26
+ export type JavaScriptUpdateExpression = StripMeta<estree.UpdateExpression>;
27
+ export type JavaScriptAssignmentExpression = StripMeta<estree.AssignmentExpression>;
28
+ export type JavaScriptConditionalExpression = StripMeta<estree.ConditionalExpression>;
29
+ export type JavaScriptCallExpression = StripMeta<estree.SimpleCallExpression>;
30
+ export type JavaScriptNewExpression = StripMeta<estree.NewExpression>;
31
+ export type JavaScriptMemberExpression = StripMeta<estree.MemberExpression>;
32
+ export type JavaScriptArrayExpression = StripMeta<estree.ArrayExpression>;
33
+ export type JavaScriptObjectExpression = StripMeta<estree.ObjectExpression>;
34
+ export type JavaScriptProperty = StripMeta<estree.Property>;
35
+ export type JavaScriptThisExpression = StripMeta<estree.ThisExpression>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type * as estree from 'estree';
2
+ import { type Parser } from './parser.js';
3
+ type PositionalFields = 'loc' | 'range' | 'start' | 'end' | 'leadingComments' | 'trailingComments' | 'comments' | 'innerComments';
4
+ export type StripMeta<T> = T extends Array<infer U> ? Array<StripMeta<U>> : T extends object ? {
5
+ [K in Exclude<keyof T, PositionalFields>]: StripMeta<T[K]>;
6
+ } : T;
7
+ export type JavaScriptProgram = StripMeta<estree.Program>;
8
+ export declare const javaScriptProgramParser: Parser<JavaScriptProgram, string>;
9
+ export {};
@@ -0,0 +1,34 @@
1
+ import * as acorn from 'acorn';
2
+ import { promiseCompose } from './promiseCompose.js';
3
+ import { createRegExpParser } from './regexpParser.js';
4
+ function stripMeta(node) {
5
+ if (node === null || node === undefined) {
6
+ return node;
7
+ }
8
+ if (typeof node !== 'object') {
9
+ return node;
10
+ }
11
+ if (Array.isArray(node)) {
12
+ return node.map(element => stripMeta(element));
13
+ }
14
+ const result = {};
15
+ for (const [key, value] of Object.entries(node)) {
16
+ if (key === 'loc'
17
+ || key === 'range'
18
+ || key === 'start'
19
+ || key === 'end'
20
+ || key === 'raw'
21
+ || key === 'leadingComments'
22
+ || key === 'trailingComments'
23
+ || key === 'comments'
24
+ || key === 'innerComments') {
25
+ continue;
26
+ }
27
+ result[key] = stripMeta(value);
28
+ }
29
+ return result;
30
+ }
31
+ export const javaScriptProgramParser = promiseCompose(createRegExpParser(/[\s\S]*/), match => {
32
+ const ast = acorn.parse(match[0], { ecmaVersion: 'latest', sourceType: 'script' });
33
+ return stripMeta(ast);
34
+ });
@@ -0,0 +1,3 @@
1
+ import { type Unparser } from './unparser.js';
2
+ import { type JavaScriptProgram } from './javaScriptParser.js';
3
+ export declare const javaScriptProgramUnparser: Unparser<JavaScriptProgram, string>;
@@ -0,0 +1,4 @@
1
+ import { generate } from 'astring';
2
+ export const javaScriptProgramUnparser = async function* (program) {
3
+ yield generate(program);
4
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { testProp } from '@fast-check/ava';
2
+ import { arbitraryJavaScriptProgram } from './arbitraryJavaScript.js';
3
+ import { javaScriptProgramUnparser } from './javaScriptUnparser.js';
4
+ import { javaScriptProgramParser } from './javaScriptParser.js';
5
+ import { runParser } from './parser.js';
6
+ import { runUnparser } from './unparser.js';
7
+ import { stringParserInputCompanion } from './parserInputCompanion.js';
8
+ import { stringUnparserOutputCompanion } from './unparserOutputCompanion.js';
9
+ const seed = process.env.SEED ? Number(process.env.SEED) : undefined;
10
+ async function collectString(asyncIterable) {
11
+ let result = '';
12
+ for await (const chunk of asyncIterable) {
13
+ result += chunk;
14
+ }
15
+ return result;
16
+ }
17
+ testProp('javaScript roundtrip', [arbitraryJavaScriptProgram], async (t, program) => {
18
+ const source = await collectString(runUnparser(javaScriptProgramUnparser, program, stringUnparserOutputCompanion));
19
+ const reparsed = await runParser(javaScriptProgramParser, source, stringParserInputCompanion);
20
+ t.deepEqual(reparsed, program);
21
+ }, {
22
+ verbose: true,
23
+ seed,
24
+ });
@@ -0,0 +1,2 @@
1
+ import { type Unparser } from './unparser.js';
2
+ export declare const javaCompilationUnitUnparser: Unparser<unknown, string>;
@@ -0,0 +1,519 @@
1
+ import { escapeJavaString } from './stringEscapes.js';
2
+ const binaryOperatorMap = {
3
+ PLUS: '+',
4
+ MINUS: '-',
5
+ MULTIPLY: '*',
6
+ DIVIDE: '/',
7
+ REMAINDER: '%',
8
+ LESS: '<',
9
+ GREATER: '>',
10
+ LESS_EQUALS: '<=',
11
+ GREATER_EQUALS: '>=',
12
+ EQUALS: '==',
13
+ NOT_EQUALS: '!=',
14
+ AND: '&&',
15
+ OR: '||',
16
+ };
17
+ const assignOperatorMap = {
18
+ ASSIGN: '=',
19
+ PLUS: '+=',
20
+ MINUS: '-=',
21
+ MULTIPLY: '*=',
22
+ DIVIDE: '/=',
23
+ };
24
+ const prefixUnaryOperatorMap = {
25
+ PREFIX_INCREMENT: '++',
26
+ PREFIX_DECREMENT: '--',
27
+ MINUS: '-',
28
+ PLUS: '+',
29
+ LOGICAL_COMPLEMENT: '!',
30
+ };
31
+ const postfixUnaryOperatorMap = {
32
+ POSTFIX_INCREMENT: '++',
33
+ POSTFIX_DECREMENT: '--',
34
+ };
35
+ const primitiveTypeMap = {
36
+ BOOLEAN: 'boolean',
37
+ BYTE: 'byte',
38
+ CHAR: 'char',
39
+ DOUBLE: 'double',
40
+ FLOAT: 'float',
41
+ INT: 'int',
42
+ LONG: 'long',
43
+ SHORT: 'short',
44
+ };
45
+ const modifierKeywordMap = {
46
+ PUBLIC: 'public',
47
+ PROTECTED: 'protected',
48
+ PRIVATE: 'private',
49
+ STATIC: 'static',
50
+ FINAL: 'final',
51
+ ABSTRACT: 'abstract',
52
+ SYNCHRONIZED: 'synchronized',
53
+ NATIVE: 'native',
54
+ TRANSIENT: 'transient',
55
+ VOLATILE: 'volatile',
56
+ STRICTFP: 'strictfp',
57
+ DEFAULT: 'default',
58
+ SEALED: 'sealed',
59
+ NON_SEALED: 'non-sealed',
60
+ };
61
+ function flattenName(name) {
62
+ if (name.qualifier) {
63
+ return flattenName(name.qualifier) + '.' + name.identifier;
64
+ }
65
+ return name.identifier;
66
+ }
67
+ function unparseType(node) {
68
+ switch (node.type) {
69
+ case 'PrimitiveType':
70
+ return primitiveTypeMap[node.type_];
71
+ case 'VoidType':
72
+ return 'void';
73
+ case 'ClassOrInterfaceType': {
74
+ let result = '';
75
+ if (node.scope) {
76
+ result = unparseType(node.scope) + '.';
77
+ }
78
+ result += node.name.identifier;
79
+ if (node.typeArguments) {
80
+ const typeArgs = node.typeArguments;
81
+ if (typeArgs.length === 0) {
82
+ // Diamond is handled at the ObjectCreationExpr level
83
+ }
84
+ else {
85
+ result += '<' + typeArgs.map(t => unparseType(t)).join(', ') + '>';
86
+ }
87
+ }
88
+ return result;
89
+ }
90
+ case 'ArrayType': {
91
+ // Unwind to base type + count brackets
92
+ let base = node;
93
+ let brackets = 0;
94
+ while (base.type === 'ArrayType') {
95
+ brackets++;
96
+ base = base.componentType;
97
+ }
98
+ return unparseType(base) + '[]'.repeat(brackets);
99
+ }
100
+ case 'WildcardType': {
101
+ let result = '?';
102
+ if (node.extendedType) {
103
+ result += ' extends ' + unparseType(node.extendedType);
104
+ }
105
+ if (node.superType) {
106
+ result += ' super ' + unparseType(node.superType);
107
+ }
108
+ return result;
109
+ }
110
+ case 'UnknownType':
111
+ return '';
112
+ default:
113
+ throw new Error(`Unknown type: ${node.type}`);
114
+ }
115
+ }
116
+ function unparseExpression(node) {
117
+ switch (node.type) {
118
+ case 'NameExpr':
119
+ return node.name.identifier;
120
+ case 'StringLiteralExpr':
121
+ return `"${escapeJavaString(node.value)}"`;
122
+ case 'IntegerLiteralExpr':
123
+ return node.value;
124
+ case 'NullLiteralExpr':
125
+ return 'null';
126
+ case 'BooleanLiteralExpr':
127
+ return node.value ? 'true' : 'false';
128
+ case 'ThisExpr':
129
+ return 'this';
130
+ case 'FieldAccessExpr':
131
+ return unparseExpression(node.scope) + '.' + node.name.identifier;
132
+ case 'ArrayAccessExpr':
133
+ return unparseExpression(node.name) + '[' + unparseExpression(node.index) + ']';
134
+ case 'MethodCallExpr': {
135
+ let result = '';
136
+ if (node.scope) {
137
+ result = unparseExpression(node.scope) + '.';
138
+ }
139
+ result += node.name.identifier;
140
+ result += '(' + node.arguments.map(a => unparseExpression(a)).join(', ') + ')';
141
+ return result;
142
+ }
143
+ case 'ObjectCreationExpr': {
144
+ const type_ = node.type_;
145
+ let result = 'new ' + unparseType(type_);
146
+ // Diamond operator
147
+ if (type_.typeArguments) {
148
+ const typeArgs = type_.typeArguments;
149
+ if (typeArgs.length === 0) {
150
+ result += '<>';
151
+ }
152
+ }
153
+ result += '(' + node.arguments.map(a => unparseExpression(a)).join(', ') + ')';
154
+ return result;
155
+ }
156
+ case 'BinaryExpr':
157
+ return unparseExpression(node.left)
158
+ + ' ' + binaryOperatorMap[node.operator]
159
+ + ' ' + unparseExpression(node.right);
160
+ case 'UnaryExpr': {
161
+ const operator = node.operator;
162
+ if (prefixUnaryOperatorMap[operator]) {
163
+ return prefixUnaryOperatorMap[operator] + unparseExpression(node.expression);
164
+ }
165
+ if (postfixUnaryOperatorMap[operator]) {
166
+ return unparseExpression(node.expression) + postfixUnaryOperatorMap[operator];
167
+ }
168
+ throw new Error(`Unknown unary operator: ${operator}`);
169
+ }
170
+ case 'AssignExpr':
171
+ return unparseExpression(node.target)
172
+ + ' ' + assignOperatorMap[node.operator]
173
+ + ' ' + unparseExpression(node.value);
174
+ case 'ConditionalExpr':
175
+ return unparseExpression(node.condition)
176
+ + ' ? ' + unparseExpression(node.thenExpr)
177
+ + ' : ' + unparseExpression(node.elseExpr);
178
+ case 'CastExpr':
179
+ return '(' + unparseType(node.type_) + ') ' + unparseExpression(node.expression);
180
+ case 'EnclosedExpr':
181
+ return '(' + unparseExpression(node.inner) + ')';
182
+ case 'InstanceOfExpr':
183
+ return unparseExpression(node.expression)
184
+ + ' instanceof ' + unparseType(node.type_);
185
+ case 'LambdaExpr': {
186
+ const params = node.parameters;
187
+ const isEnclosing = node.isEnclosingParameters;
188
+ const body = node.body;
189
+ let paramStr;
190
+ if (isEnclosing) {
191
+ const paramParts = params.map(p => {
192
+ const paramType = p.type_;
193
+ const paramName = p.name.identifier;
194
+ if (paramType.type === 'UnknownType') {
195
+ return paramName;
196
+ }
197
+ return unparseType(paramType) + ' ' + paramName;
198
+ });
199
+ paramStr = '(' + paramParts.join(', ') + ')';
200
+ }
201
+ else {
202
+ paramStr = params[0].name.identifier;
203
+ }
204
+ let bodyStr;
205
+ if (body.type === 'BlockStmt') {
206
+ bodyStr = unparseBlockStmt(body);
207
+ }
208
+ else if (body.type === 'ExpressionStmt') {
209
+ bodyStr = unparseExpression(body.expression);
210
+ }
211
+ else {
212
+ bodyStr = unparseExpression(body);
213
+ }
214
+ return paramStr + ' -> ' + bodyStr;
215
+ }
216
+ case 'VariableDeclarationExpr':
217
+ return unparseVariableDeclarationExpr(node);
218
+ case 'MarkerAnnotationExpr':
219
+ return '@' + flattenName(node.name);
220
+ default:
221
+ throw new Error(`Unknown expression type: ${node.type}`);
222
+ }
223
+ }
224
+ function unparseVariableDeclarationExpr(node) {
225
+ const modifiers = node.modifiers;
226
+ const annotations = node.annotations;
227
+ const variables = node.variables;
228
+ let result = '';
229
+ for (const ann of annotations) {
230
+ result += unparseExpression(ann) + ' ';
231
+ }
232
+ for (const mod of modifiers) {
233
+ result += modifierKeywordMap[mod.keyword] + ' ';
234
+ }
235
+ // Type comes from first variable
236
+ const type_ = variables[0].type_;
237
+ result += unparseType(type_);
238
+ const varParts = variables.map(v => {
239
+ let varStr = ' ' + v.name.identifier;
240
+ if (v.initializer) {
241
+ varStr += ' = ' + unparseExpression(v.initializer);
242
+ }
243
+ return varStr;
244
+ });
245
+ result += varParts.join(',');
246
+ return result;
247
+ }
248
+ function unparseBlockStmt(node) {
249
+ const statements = node.statements;
250
+ if (statements.length === 0) {
251
+ return '{}';
252
+ }
253
+ return '{ ' + statements.map(s => unparseStatement(s)).join(' ') + ' }';
254
+ }
255
+ function unparseStatement(node) {
256
+ switch (node.type) {
257
+ case 'BlockStmt':
258
+ return unparseBlockStmt(node);
259
+ case 'ExpressionStmt':
260
+ return unparseExpression(node.expression) + ';';
261
+ case 'ReturnStmt': {
262
+ if (node.expression) {
263
+ return 'return ' + unparseExpression(node.expression) + ';';
264
+ }
265
+ return 'return;';
266
+ }
267
+ case 'ThrowStmt':
268
+ return 'throw ' + unparseExpression(node.expression) + ';';
269
+ case 'IfStmt': {
270
+ let result = 'if (' + unparseExpression(node.condition) + ') '
271
+ + unparseStatement(node.thenStmt);
272
+ if (node.elseStmt) {
273
+ result += ' else ' + unparseStatement(node.elseStmt);
274
+ }
275
+ return result;
276
+ }
277
+ case 'ForStmt': {
278
+ const init = node.initialization;
279
+ let initStr = '';
280
+ if (init.length > 0) {
281
+ initStr = init.map(i => unparseExpression(i)).join(', ');
282
+ }
283
+ let compareStr = '';
284
+ if (node.compare) {
285
+ compareStr = unparseExpression(node.compare);
286
+ }
287
+ const update = node.update;
288
+ const updateStr = update.map(u => unparseExpression(u)).join(', ');
289
+ return 'for (' + initStr + '; ' + compareStr + '; ' + updateStr + ') '
290
+ + unparseStatement(node.body);
291
+ }
292
+ case 'ForEachStmt':
293
+ return 'for (' + unparseVariableDeclarationExpr(node.variable) + ' : '
294
+ + unparseExpression(node.iterable) + ') '
295
+ + unparseStatement(node.body);
296
+ case 'TryStmt': {
297
+ const resources = node.resources;
298
+ let result = 'try';
299
+ if (resources.length > 0) {
300
+ result += ' (' + resources.map(r => unparseVariableDeclarationExpr(r)).join('; ') + ')';
301
+ }
302
+ result += ' ' + unparseBlockStmt(node.tryBlock);
303
+ const catchClauses = node.catchClauses;
304
+ for (const clause of catchClauses) {
305
+ const param = clause.parameter;
306
+ const paramType = param.type_;
307
+ const paramName = param.name.identifier;
308
+ result += ' catch (' + unparseType(paramType) + ' ' + paramName + ') '
309
+ + unparseBlockStmt(clause.body);
310
+ }
311
+ if (node.finallyBlock) {
312
+ result += ' finally ' + unparseBlockStmt(node.finallyBlock);
313
+ }
314
+ return result;
315
+ }
316
+ case 'SwitchStmt': {
317
+ const entries = node.entries;
318
+ let result = 'switch (' + unparseExpression(node.selector) + ') {';
319
+ for (const entry of entries) {
320
+ const isDefault = entry.isDefault;
321
+ const labels = entry.labels;
322
+ const statements = entry.statements;
323
+ if (isDefault) {
324
+ result += ' default:';
325
+ }
326
+ else {
327
+ for (const label of labels) {
328
+ result += ' case ' + unparseExpression(label) + ':';
329
+ }
330
+ }
331
+ for (const stmt of statements) {
332
+ result += ' ' + unparseStatement(stmt);
333
+ }
334
+ }
335
+ result += '}';
336
+ return result;
337
+ }
338
+ case 'ExplicitConstructorInvocationStmt': {
339
+ const keyword = node.isThis ? 'this' : 'super';
340
+ return keyword + '(' + node.arguments.map(a => unparseExpression(a)).join(', ') + ');';
341
+ }
342
+ default:
343
+ throw new Error(`Unknown statement type: ${node.type}`);
344
+ }
345
+ }
346
+ function unparseAnnotations(annotations) {
347
+ if (annotations.length === 0) {
348
+ return '';
349
+ }
350
+ return annotations.map(a => unparseExpression(a)).join(' ') + ' ';
351
+ }
352
+ function unparseModifiers(modifiers) {
353
+ if (modifiers.length === 0) {
354
+ return '';
355
+ }
356
+ return modifiers.map(m => modifierKeywordMap[m.keyword]).join(' ') + ' ';
357
+ }
358
+ function unparseParameter(param) {
359
+ let result = '';
360
+ result += unparseAnnotations(param.annotations);
361
+ result += unparseModifiers(param.modifiers);
362
+ const typeStr = unparseType(param.type_);
363
+ if (typeStr) {
364
+ result += typeStr;
365
+ if (param.isVarArgs) {
366
+ result += '...';
367
+ }
368
+ result += ' ';
369
+ }
370
+ result += param.name.identifier;
371
+ return result;
372
+ }
373
+ function unparseBodyDeclaration(node) {
374
+ switch (node.type) {
375
+ case 'FieldDeclaration': {
376
+ const variables = node.variables;
377
+ let result = unparseAnnotations(node.annotations);
378
+ result += unparseModifiers(node.modifiers);
379
+ result += unparseType(variables[0].type_);
380
+ const varParts = variables.map(v => {
381
+ let varStr = ' ' + v.name.identifier;
382
+ if (v.initializer) {
383
+ varStr += ' = ' + unparseExpression(v.initializer);
384
+ }
385
+ return varStr;
386
+ });
387
+ result += varParts.join(',') + ';';
388
+ return result;
389
+ }
390
+ case 'MethodDeclaration': {
391
+ let result = unparseAnnotations(node.annotations);
392
+ result += unparseModifiers(node.modifiers);
393
+ const typeParams = node.typeParameters;
394
+ if (typeParams.length > 0) {
395
+ result += '<' + typeParams.map(tp => {
396
+ let tpStr = tp.name.identifier;
397
+ const bounds = tp.typeBound;
398
+ if (bounds.length > 0) {
399
+ tpStr += ' extends ' + bounds.map(b => unparseType(b)).join(' & ');
400
+ }
401
+ return tpStr;
402
+ }).join(', ') + '> ';
403
+ }
404
+ result += unparseType(node.type_) + ' ';
405
+ result += node.name.identifier;
406
+ result += '(' + node.parameters.map(p => unparseParameter(p)).join(', ') + ')';
407
+ const thrownExceptions = node.thrownExceptions;
408
+ if (thrownExceptions.length > 0) {
409
+ result += ' throws ' + thrownExceptions.map(e => unparseType(e)).join(', ');
410
+ }
411
+ if (node.body) {
412
+ result += ' ' + unparseBlockStmt(node.body);
413
+ }
414
+ else {
415
+ result += ';';
416
+ }
417
+ return result;
418
+ }
419
+ case 'ConstructorDeclaration': {
420
+ let result = unparseAnnotations(node.annotations);
421
+ result += unparseModifiers(node.modifiers);
422
+ result += node.name.identifier;
423
+ result += '(' + node.parameters.map(p => unparseParameter(p)).join(', ') + ')';
424
+ const thrownExceptions = node.thrownExceptions;
425
+ if (thrownExceptions.length > 0) {
426
+ result += ' throws ' + thrownExceptions.map(e => unparseType(e)).join(', ');
427
+ }
428
+ result += ' ' + unparseBlockStmt(node.body);
429
+ return result;
430
+ }
431
+ case 'ClassOrInterfaceDeclaration':
432
+ case 'EnumDeclaration':
433
+ return unparseTypeDeclaration(node);
434
+ default:
435
+ throw new Error(`Unknown body declaration type: ${node.type}`);
436
+ }
437
+ }
438
+ function unparseTypeDeclaration(node) {
439
+ switch (node.type) {
440
+ case 'ClassOrInterfaceDeclaration': {
441
+ let result = unparseAnnotations(node.annotations);
442
+ result += unparseModifiers(node.modifiers);
443
+ result += (node.isInterface ? 'interface' : 'class') + ' ';
444
+ result += node.name.identifier;
445
+ const typeParams = node.typeParameters;
446
+ if (typeParams.length > 0) {
447
+ result += '<' + typeParams.map(tp => {
448
+ let tpStr = tp.name.identifier;
449
+ const bounds = tp.typeBound;
450
+ if (bounds.length > 0) {
451
+ tpStr += ' extends ' + bounds.map(b => unparseType(b)).join(' & ');
452
+ }
453
+ return tpStr;
454
+ }).join(', ') + '>';
455
+ }
456
+ const extendedTypes = node.extendedTypes;
457
+ if (extendedTypes.length > 0) {
458
+ result += ' extends ' + extendedTypes.map(t => unparseType(t)).join(', ');
459
+ }
460
+ const implementedTypes = node.implementedTypes;
461
+ if (implementedTypes.length > 0) {
462
+ result += ' implements ' + implementedTypes.map(t => unparseType(t)).join(', ');
463
+ }
464
+ const members = node.members;
465
+ if (members.length === 0) {
466
+ result += ' {}';
467
+ }
468
+ else {
469
+ result += ' { ' + members.map(m => unparseBodyDeclaration(m)).join('\n') + ' }';
470
+ }
471
+ return result;
472
+ }
473
+ case 'EnumDeclaration': {
474
+ let result = unparseAnnotations(node.annotations);
475
+ result += unparseModifiers(node.modifiers);
476
+ result += 'enum ';
477
+ result += node.name.identifier;
478
+ result += ' {}';
479
+ return result;
480
+ }
481
+ default:
482
+ throw new Error(`Unknown type declaration type: ${node.type}`);
483
+ }
484
+ }
485
+ export const javaCompilationUnitUnparser = async function* (input) {
486
+ const cu = input;
487
+ let result = '';
488
+ // Package declaration
489
+ if (cu.packageDeclaration) {
490
+ const pkg = cu.packageDeclaration;
491
+ result += unparseAnnotations(pkg.annotations);
492
+ result += 'package ' + flattenName(pkg.name) + ';';
493
+ }
494
+ // Imports
495
+ const imports = cu.imports;
496
+ for (const imp of imports) {
497
+ if (result.length > 0) {
498
+ result += '\n';
499
+ }
500
+ result += 'import ';
501
+ if (imp.isStatic) {
502
+ result += 'static ';
503
+ }
504
+ result += flattenName(imp.name);
505
+ if (imp.isAsterisk) {
506
+ result += '.*';
507
+ }
508
+ result += ';';
509
+ }
510
+ // Types
511
+ const types = cu.types;
512
+ for (const type of types) {
513
+ if (result.length > 0) {
514
+ result += '\n';
515
+ }
516
+ result += unparseTypeDeclaration(type);
517
+ }
518
+ yield result;
519
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { testProp } from '@fast-check/ava';
2
+ import { arbitraryJavaCompilationUnit } from './arbitraryJava.js';
3
+ import { javaCompilationUnitUnparser } from './javaUnparser.js';
4
+ import { javaCompilationUnitParser } from './javaParser.js';
5
+ import { runParser } from './parser.js';
6
+ import { runUnparser } from './unparser.js';
7
+ import { stringParserInputCompanion } from './parserInputCompanion.js';
8
+ import { stringUnparserOutputCompanion } from './unparserOutputCompanion.js';
9
+ const seed = process.env.SEED ? Number(process.env.SEED) : undefined;
10
+ async function collectString(asyncIterable) {
11
+ let result = '';
12
+ for await (const chunk of asyncIterable) {
13
+ result += chunk;
14
+ }
15
+ return result;
16
+ }
17
+ testProp('javaUnparser roundtrip', [arbitraryJavaCompilationUnit], async (t, compilationUnit) => {
18
+ const source = await collectString(runUnparser(javaCompilationUnitUnparser, compilationUnit, stringUnparserOutputCompanion));
19
+ const reparsed = await runParser(javaCompilationUnitParser, source, stringParserInputCompanion);
20
+ t.deepEqual(reparsed, compilationUnit);
21
+ }, {
22
+ verbose: true,
23
+ seed,
24
+ });