11import * as ts from "typescript" ;
2- import { JavaType } from "../java" ;
2+ import { JavaType } from "../java" ;
33
44export 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