Skip to content
This repository was archived by the owner on May 12, 2025. It is now read-only.

Commit bfc57d6

Browse files
authored
add type mapping tests and improve boolean mapping (#199)
* add type mapping tests and improve boolean mapping * add more test and bigint mapping
1 parent 2cea88f commit bfc57d6

File tree

3 files changed

+338
-84
lines changed

3 files changed

+338
-84
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ bin/
1010
.vscode/*
1111
/rewrite-javascript-remote-server/src/main/resources/node-server/node_modules/
1212
/rewrite-javascript-remote-server/src/main/resources/node-server/package-lock.json
13+
.DS_Store
Lines changed: 122 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,142 @@
11
import * as ts from "typescript";
2-
import {JavaType} from "../java";
2+
import { JavaType } from "../java";
33

44
export class JavaScriptTypeMapping {
5+
private readonly typeCache: Map<string, JavaType> = new Map();
6+
private readonly regExpSymbol: ts.Symbol | undefined;
57

6-
private readonly typeCache: Map<string, JavaType> = new Map();
7-
private readonly regExpSymbol: ts.Symbol | undefined;
8+
constructor(private readonly checker: ts.TypeChecker) {
9+
this.regExpSymbol = checker.resolveName(
10+
"RegExp",
11+
undefined,
12+
ts.SymbolFlags.Type,
13+
false
14+
);
15+
}
816

9-
constructor(private readonly checker: ts.TypeChecker) {
10-
this.regExpSymbol = checker.resolveName('RegExp', undefined, ts.SymbolFlags.Type, false);
17+
type(node: ts.Node): JavaType | null {
18+
let type: ts.Type | undefined;
19+
if (ts.isExpression(node)) {
20+
type = this.checker.getTypeAtLocation(node);
21+
} else if (ts.isTypeNode(node)) {
22+
type = this.checker.getTypeFromTypeNode(node);
1123
}
1224

13-
type(node: ts.Node): JavaType | null {
14-
let type: ts.Type | undefined;
15-
if (ts.isExpression(node)) {
16-
type = this.checker.getTypeAtLocation(node);
17-
} else if (ts.isTypeNode(node)) {
18-
type = this.checker.getTypeFromTypeNode(node);
19-
}
25+
return type ? this.getType(type) : null;
26+
}
2027

21-
return type ? this.getType(type) : null;
28+
private getType(type: ts.Type) {
29+
const signature = this.getSignature(type);
30+
const existing = this.typeCache.get(signature);
31+
if (existing) {
32+
return existing;
2233
}
34+
const result = this.createType(type, signature);
35+
this.typeCache.set(signature, result);
36+
return result;
37+
}
2338

24-
private getType(type: ts.Type) {
25-
const signature = this.getSignature(type);
26-
const existing = this.typeCache.get(signature);
27-
if (existing) {
28-
return existing;
29-
}
30-
const result = this.createType(type, signature);
31-
this.typeCache.set(signature, result);
32-
return result;
33-
}
39+
private getSignature(type: ts.Type) {
40+
// FIXME for classes we need to include the containing module / package in the signature and probably include in the qualified name
41+
return this.checker.typeToString(type);
42+
}
43+
44+
primitiveType(node: ts.Node): JavaType.Primitive {
45+
const type = this.type(node);
46+
return type instanceof JavaType.Primitive
47+
? type
48+
: JavaType.Primitive.of(JavaType.PrimitiveKind.None);
49+
}
3450

35-
private getSignature(type: ts.Type) {
36-
// FIXME for classes we need to include the containing module / package in the signature and probably include in the qualified name
37-
return this.checker.typeToString(type);
51+
variableType(node: ts.NamedDeclaration): JavaType.Variable | null {
52+
if (ts.isVariableDeclaration(node)) {
53+
const symbol = this.checker.getSymbolAtLocation(node.name);
54+
if (symbol) {
55+
const type = this.checker.getTypeOfSymbolAtLocation(symbol, node);
56+
}
3857
}
58+
return null;
59+
}
60+
61+
methodType(node: ts.Node): JavaType.Method | null {
62+
return null;
63+
}
3964

40-
primitiveType(node: ts.Node): JavaType.Primitive {
41-
const type = this.type(node);
42-
return type instanceof JavaType.Primitive ? type : JavaType.Primitive.of(JavaType.PrimitiveKind.None);
65+
private createType(type: ts.Type, signature: string): JavaType {
66+
if (type.isLiteral()) {
67+
if (type.isNumberLiteral()) {
68+
return JavaType.Primitive.of(JavaType.PrimitiveKind.Double);
69+
} else if (type.isStringLiteral()) {
70+
return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
71+
}
4372
}
4473

45-
variableType(node: ts.NamedDeclaration): JavaType.Variable | null {
46-
if (ts.isVariableDeclaration(node)) {
47-
const symbol = this.checker.getSymbolAtLocation(node.name);
48-
if (symbol) {
49-
const type = this.checker.getTypeOfSymbolAtLocation(symbol, node);
50-
}
51-
}
52-
return null;
74+
if (type.flags === ts.TypeFlags.Null) {
75+
return JavaType.Primitive.of(JavaType.PrimitiveKind.Null);
76+
} else if (type.flags === ts.TypeFlags.Undefined) {
77+
return JavaType.Primitive.of(JavaType.PrimitiveKind.None);
78+
} else if (
79+
type.flags === ts.TypeFlags.Number ||
80+
type.flags === ts.TypeFlags.NumberLiteral ||
81+
type.flags === ts.TypeFlags.NumberLike
82+
) {
83+
return JavaType.Primitive.of(JavaType.PrimitiveKind.Double);
84+
} else if (
85+
type.flags === ts.TypeFlags.String ||
86+
type.flags === ts.TypeFlags.StringLiteral ||
87+
type.flags === ts.TypeFlags.StringLike
88+
) {
89+
return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
90+
} else if (type.flags === ts.TypeFlags.Void) {
91+
return JavaType.Primitive.of(JavaType.PrimitiveKind.Void);
92+
} else if (
93+
type.flags === ts.TypeFlags.BigInt ||
94+
type.flags === ts.TypeFlags.BigIntLiteral ||
95+
type.flags === ts.TypeFlags.BigIntLike
96+
) {
97+
return JavaType.Primitive.of(JavaType.PrimitiveKind.Long);
98+
} else if (
99+
(type.symbol !== undefined && type.symbol === this.regExpSymbol) ||
100+
this.checker.typeToString(type) === "RegExp"
101+
) {
102+
return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
53103
}
54104

55-
methodType(node: ts.Node): JavaType.Method | null {
56-
return null;
105+
/**
106+
* TypeScript may assign multiple flags to a single type (e.g., Boolean + Union).
107+
* Using a bitwise check ensures we detect Boolean even if other flags are set.
108+
*/
109+
if (
110+
type.flags & ts.TypeFlags.Boolean ||
111+
type.flags & ts.TypeFlags.BooleanLiteral ||
112+
type.flags & ts.TypeFlags.BooleanLike
113+
) {
114+
return JavaType.Primitive.of(JavaType.PrimitiveKind.Boolean);
57115
}
58116

59-
private createType(type: ts.Type, signature: string): JavaType {
60-
if (type.isLiteral()) {
61-
if (type.isNumberLiteral()) {
62-
return JavaType.Primitive.of(JavaType.PrimitiveKind.Double);
63-
} else if (type.isStringLiteral()) {
64-
return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
65-
}
66-
}
67-
68-
if (type.flags === ts.TypeFlags.Null) {
69-
return JavaType.Primitive.of(JavaType.PrimitiveKind.Null);
70-
} else if (type.flags === ts.TypeFlags.Undefined) {
71-
return JavaType.Primitive.of(JavaType.PrimitiveKind.None);
72-
} else if (type.flags === ts.TypeFlags.Number) {
73-
return JavaType.Primitive.of(JavaType.PrimitiveKind.Double);
74-
} else if (type.flags === ts.TypeFlags.String) {
75-
return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
76-
} else if (type.flags === ts.TypeFlags.BooleanLiteral) {
77-
return JavaType.Primitive.of(JavaType.PrimitiveKind.Boolean);
78-
} else if (type.flags === ts.TypeFlags.Void) {
79-
return JavaType.Primitive.of(JavaType.PrimitiveKind.Void);
80-
} else if (type.symbol === this.regExpSymbol) {
81-
return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
82-
}
83-
84-
if (type.isUnion()) {
85-
let result = new JavaType.Union();
86-
this.typeCache.set(signature, result);
87-
88-
const types = type.types.map(t => this.getType(t));
89-
result.unsafeSet(types);
90-
return result;
91-
} else if (type.isClass()) {
92-
// FIXME flags
93-
let result = new JavaType.Class(0, type.symbol.name, JavaType.Class.Kind.Class);
94-
this.typeCache.set(signature, result);
95-
// FIXME unsafeSet
96-
return result;
97-
}
98-
99-
// if (ts.isRegularExpressionLiteral(node)) {
100-
// return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
101-
// }
102-
return JavaType.Unknown.INSTANCE;
117+
if (type.isUnion()) {
118+
let result = new JavaType.Union();
119+
this.typeCache.set(signature, result);
120+
121+
const types = type.types.map((t) => this.getType(t));
122+
result.unsafeSet(types);
123+
return result;
124+
} else if (type.isClass()) {
125+
// FIXME flags
126+
let result = new JavaType.Class(
127+
0,
128+
type.symbol.name,
129+
JavaType.Class.Kind.Class
130+
);
131+
this.typeCache.set(signature, result);
132+
// FIXME unsafeSet
133+
return result;
103134
}
104-
}
135+
136+
// if (ts.isRegularExpressionLiteral(node)) {
137+
// return JavaType.Primitive.of(JavaType.PrimitiveKind.String);
138+
// }
139+
140+
return JavaType.Unknown.INSTANCE;
141+
}
142+
}

0 commit comments

Comments
 (0)