Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: lib/base.ts

Issue 2225953002: Strip more unused features. (Closed) Base URL: git@github.com:dart-lang/js_facade_gen.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 import * as ts from 'typescript'; 1 import * as ts from 'typescript';
2 import {Transpiler} from './main'; 2
3 import {OutputContext, Transpiler} from './main';
3 4
4 export type ClassLike = ts.ClassDeclaration | ts.InterfaceDeclaration; 5 export type ClassLike = ts.ClassDeclaration | ts.InterfaceDeclaration;
6 export type NamedDeclaration = ClassLike | ts.PropertyDeclaration | ts.VariableD eclaration |
7 ts.MethodDeclaration | ts.ModuleDeclaration | ts.FunctionDeclaration;
8
9 export type Set = {
10 [s: string]: boolean
11 };
5 12
6 export function ident(n: ts.Node): string { 13 export function ident(n: ts.Node): string {
7 if (n.kind === ts.SyntaxKind.Identifier) return (<ts.Identifier>n).text; 14 if (n.kind === ts.SyntaxKind.Identifier) return (<ts.Identifier>n).text;
8 if (n.kind === ts.SyntaxKind.QualifiedName) { 15 if (n.kind === ts.SyntaxKind.QualifiedName) {
9 let qname = (<ts.QualifiedName>n); 16 let qname = (<ts.QualifiedName>n);
10 let leftName = ident(qname.left); 17 let leftName = ident(qname.left);
11 if (leftName) return leftName + '.' + ident(qname.right); 18 if (leftName) return leftName + '.' + ident(qname.right);
12 } 19 }
13 return null; 20 return null;
14 } 21 }
15 22
23 export function isFunctionTypedefLikeInterface(ifDecl: ts.InterfaceDeclaration): boolean {
24 return ifDecl.members && ifDecl.members.length === 1 &&
25 ifDecl.members[0].kind === ts.SyntaxKind.CallSignature;
26 }
27
28 export function getDeclaration(type: ts.Type): ts.Declaration {
29 let symbol = type.getSymbol();
30 if (!symbol) return null;
31 if (symbol.valueDeclaration) return symbol.valueDeclaration;
32 return symbol.declarations && symbol.declarations.length > 0 ? symbol.declarat ions[0] : null;
33 }
34
35 export function isExtendsClause(heritageClause: ts.HeritageClause) {
36 return heritageClause.token === ts.SyntaxKind.ExtendsKeyword &&
37 heritageClause.parent.kind !== ts.SyntaxKind.InterfaceDeclaration;
38 }
39 export function isConstructor(n: ts.Node): boolean {
40 return n.kind === ts.SyntaxKind.Constructor || n.kind === ts.SyntaxKind.Constr uctSignature;
41 }
42
43 export function isStatic(n: ts.Node): boolean {
44 let hasStatic = false;
45 ts.forEachChild(n, (child) => {
46 if (child.kind === ts.SyntaxKind.StaticKeyword) {
47 hasStatic = true;
48 }
49 });
50 return hasStatic;
51 }
52
53 export function isCallableType(type: ts.TypeNode, tc: ts.TypeChecker): boolean {
54 if (isFunctionType(type, tc)) return true;
55 if (type.kind === ts.SyntaxKind.TypeReference) {
56 if (tc.getSignaturesOfType(tc.getTypeAtLocation(type), ts.SignatureKind.Call ).length > 0)
57 return true;
58 }
59 return false;
60 }
61
62 export function isFunctionType(type: ts.TypeNode, tc: ts.TypeChecker): boolean {
63 let kind = type.kind;
64 if (kind === ts.SyntaxKind.FunctionType) return true;
65 if (kind === ts.SyntaxKind.TypeReference) {
66 let t = tc.getTypeAtLocation(type);
67 if (t.symbol && t.symbol.flags & ts.SymbolFlags.Function) return true;
68 }
69
70 if (kind === ts.SyntaxKind.UnionType) {
71 let types = (<ts.UnionTypeNode>type).types;
72 for (let i = 0; i < types.length; ++i) {
73 if (!isFunctionType(types[i], tc)) {
74 return false;
75 }
76 }
77 return true;
78 }
79 // Warning: if the kind is a reference type and the reference is to an
80 // interface that only has a call member we will not return that it is a
81 // function type.
82 if (kind === ts.SyntaxKind.TypeLiteral) {
83 let members = (<ts.TypeLiteralNode>type).members;
84 for (let i = 0; i < members.length; ++i) {
85 if (members[i].kind !== ts.SyntaxKind.CallSignature) {
86 return false;
87 }
88 }
89 return true;
90 }
91 return false;
92 }
93
94 export function isTypeNode(node: ts.Node): boolean {
95 switch (node.kind) {
96 case ts.SyntaxKind.UnionType:
97 case ts.SyntaxKind.TypeReference:
98 case ts.SyntaxKind.TypeLiteral:
99 case ts.SyntaxKind.LastTypeNode:
100 case ts.SyntaxKind.ArrayType:
101 case ts.SyntaxKind.TypePredicate:
102 case ts.SyntaxKind.TypeQuery:
103 case ts.SyntaxKind.TupleType:
104 case ts.SyntaxKind.NumberKeyword:
105 case ts.SyntaxKind.StringKeyword:
106 case ts.SyntaxKind.VoidKeyword:
107 case ts.SyntaxKind.BooleanKeyword:
108 case ts.SyntaxKind.AnyKeyword:
109 case ts.SyntaxKind.FunctionType:
110 return true;
111 default:
112 return false;
113 }
114 }
115
116 export function isCallable(decl: ClassLike): boolean {
117 let members = decl.members as Array<ts.ClassElement>;
118 return members.some((member) => { return member.kind === ts.SyntaxKind.CallSig nature; });
119 }
120
121 export function copyLocation(src: ts.TextRange, dest: ts.TextRange) {
122 dest.pos = src.pos;
123 dest.end = src.end;
124 }
125
126 // Polyfill for ES6 Array.find.
127 export function arrayFindPolyfill<T>(
128 nodeArray: ts.NodeArray<T>, predicate: (node: T) => boolean): T {
129 for (let i = 0; i < nodeArray.length; ++i) {
130 if (predicate(nodeArray[i])) return nodeArray[i];
131 }
132 return null;
133 }
134
135 export function getAncestor(n: ts.Node, kind: ts.SyntaxKind): ts.Node {
136 for (let parent = n; parent; parent = parent.parent) {
137 if (parent.kind === kind) return parent;
138 }
139 return null;
140 }
141
142 export function getEnclosingClass(n: ts.Node): ClassLike {
143 for (let parent = n.parent; parent; parent = parent.parent) {
144 if (parent.kind === ts.SyntaxKind.ClassDeclaration ||
145 parent.kind === ts.SyntaxKind.InterfaceDeclaration) {
146 return <ClassLike>parent;
147 }
148 }
149 return null;
150 }
151
152 export function isConstCall(node: ts.CallExpression): boolean {
153 return node && ident(node.expression) === 'CONST_EXPR';
154 }
155
156 export function isInsideConstExpr(node: ts.Node): boolean {
157 return isConstCall(<ts.CallExpression>getAncestor(node, ts.SyntaxKind.CallExpr ession));
158 }
159
160
16 export class TranspilerBase { 161 export class TranspilerBase {
17 private idCounter: number = 0; 162 private idCounter: number = 0;
18 constructor(private transpiler: Transpiler) {} 163 constructor(protected transpiler: Transpiler) {}
19 164
20 visit(n: ts.Node) { this.transpiler.visit(n); } 165 visit(n: ts.Node) { this.transpiler.visit(n); }
166 pushContext(context: OutputContext) { this.transpiler.pushContext(context); }
167 popContext() { this.transpiler.popContext(); }
21 emit(s: string) { this.transpiler.emit(s); } 168 emit(s: string) { this.transpiler.emit(s); }
22 emitNoSpace(s: string) { this.transpiler.emitNoSpace(s); } 169 emitNoSpace(s: string) { this.transpiler.emitNoSpace(s); }
170 enterCodeComment() { return this.transpiler.enterCodeComment(); }
171 exitCodeComment() { return this.transpiler.exitCodeComment(); }
172
173 emitImport(toEmit: string) {
174 if (!this.transpiler.importsEmitted[toEmit]) {
175 this.pushContext(OutputContext.Import);
176 this.emit(`import "${toEmit}";`);
177 this.transpiler.importsEmitted[toEmit] = true;
178 this.popContext();
179 }
180 }
181
23 reportError(n: ts.Node, message: string) { this.transpiler.reportError(n, mess age); } 182 reportError(n: ts.Node, message: string) { this.transpiler.reportError(n, mess age); }
24 183
25 visitNode(n: ts.Node): boolean { throw new Error('not implemented'); } 184 visitNode(n: ts.Node): boolean { throw new Error('not implemented'); }
26 185
27 visitEach(nodes: ts.Node[]) { nodes.forEach((n) => this.visit(n)); } 186 visitEach(nodes: ts.Node[]) { nodes.forEach((n) => this.visit(n)); }
28 187
29 visitEachIfPresent(nodes?: ts.Node[]) { 188 visitEachIfPresent(nodes?: ts.Node[]) {
30 if (nodes) this.visitEach(nodes); 189 if (nodes) this.visitEach(nodes);
31 } 190 }
32 191
33 visitList(nodes: ts.Node[], separator = ',') { 192 visitList(nodes: ts.Node[], separator = ',') {
34 for (let i = 0; i < nodes.length; i++) { 193 for (let i = 0; i < nodes.length; i++) {
35 this.visit(nodes[i]); 194 this.visit(nodes[i]);
36 if (i < nodes.length - 1) this.emit(separator); 195 if (i < nodes.length - 1) this.emit(separator);
37 } 196 }
38 } 197 }
39 198
40 uniqueId(name: string): string { 199 uniqueId(name: string): string {
41 const id = this.idCounter++; 200 const id = this.idCounter++;
42 return `_${name}\$\$ts2dart\$${id}`; 201 return `_${name}\$\$js_facade_gen\$${id}`;
43 } 202 }
44 203
45 assert(c: ts.Node, condition: boolean, reason: string): void { 204 assert(c: ts.Node, condition: boolean, reason: string): void {
46 if (!condition) { 205 if (!condition) {
47 this.reportError(c, reason); 206 this.reportError(c, reason);
48 throw new Error(reason); 207 throw new Error(reason);
49 } 208 }
50 } 209 }
51 210
52 getAncestor(n: ts.Node, kind: ts.SyntaxKind): ts.Node { 211 getAncestor(n: ts.Node, kind: ts.SyntaxKind): ts.Node {
53 for (let parent = n; parent; parent = parent.parent) { 212 for (let parent = n; parent; parent = parent.parent) {
54 if (parent.kind === kind) return parent; 213 if (parent.kind === kind) return parent;
55 } 214 }
56 return null; 215 return null;
57 } 216 }
58 217
59 hasAncestor(n: ts.Node, kind: ts.SyntaxKind): boolean { return !!this.getAnces tor(n, kind); } 218 hasAncestor(n: ts.Node, kind: ts.SyntaxKind): boolean { return !!getAncestor(n , kind); }
60 219
61 hasAnnotation(decorators: ts.NodeArray<ts.Decorator>, name: string): boolean { 220 hasAnnotation(decorators: ts.NodeArray<ts.Decorator>, name: string): boolean {
62 if (!decorators) return false; 221 if (!decorators) return false;
63 return decorators.some((d) => { 222 return decorators.some((d) => {
64 let decName = ident(d.expression); 223 let decName = ident(d.expression);
65 if (decName === name) return true; 224 if (decName === name) return true;
66 if (d.expression.kind !== ts.SyntaxKind.CallExpression) return false; 225 if (d.expression.kind !== ts.SyntaxKind.CallExpression) return false;
67 let callExpr = (<ts.CallExpression>d.expression); 226 let callExpr = (<ts.CallExpression>d.expression);
68 decName = ident(callExpr.expression); 227 decName = ident(callExpr.expression);
69 return decName === name; 228 return decName === name;
70 }); 229 });
71 } 230 }
72 231
73 hasFlag(n: {flags: number}, flag: ts.NodeFlags): boolean { 232 hasFlag(n: {flags: number}, flag: ts.NodeFlags): boolean {
74 return n && (n.flags & flag) !== 0 || false; 233 return n && (n.flags & flag) !== 0 || false;
75 } 234 }
76 235
77 isConst(decl: ClassLike) {
78 return this.hasAnnotation(decl.decorators, 'CONST') ||
79 (<ts.NodeArray<ts.Declaration>>decl.members).some((m) => {
80 if (m.kind !== ts.SyntaxKind.Constructor) return false;
81 return this.hasAnnotation(m.decorators, 'CONST');
82 });
83 }
84
85 maybeDestructureIndexType(node: ts.TypeLiteralNode): [ts.TypeNode, ts.TypeNode ] {
86 let members = node.members;
87 if (members.length !== 1 || members[0].kind !== ts.SyntaxKind.IndexSignature ) {
88 return null;
89 }
90 let indexSig = <ts.IndexSignatureDeclaration>(members[0]);
91 if (indexSig.parameters.length > 1) {
92 this.reportError(indexSig, 'Expected an index signature to have a single p arameter');
93 }
94 return [indexSig.parameters[0].type, indexSig.type];
95 }
96
97
98 getRelativeFileName(fileName: string): string { 236 getRelativeFileName(fileName: string): string {
99 return this.transpiler.getRelativeFileName(fileName); 237 return this.transpiler.getRelativeFileName(fileName);
100 } 238 }
101 239
102 maybeVisitTypeArguments(n: {typeArguments?: ts.NodeArray<ts.TypeNode>}) { 240 maybeVisitTypeArguments(n: {typeArguments?: ts.NodeArray<ts.TypeNode>}) {
103 if (n.typeArguments) { 241 if (n.typeArguments) {
104 // If it's a single type argument `<void>`, ignore it and emit nothing. 242 // If it's a single type argument `<void>`, ignore it and emit nothing.
105 // This is particularly useful for `Promise<void>`, see 243 // This is particularly useful for `Promise<void>`, see
106 // https://github.com/dart-lang/sdk/issues/2231#issuecomment-108313639 244 // https://github.com/dart-lang/sdk/issues/2231#issuecomment-108313639
107 if (n.typeArguments.length === 1 && n.typeArguments[0].kind === ts.SyntaxK ind.VoidKeyword) { 245 if (n.typeArguments.length === 1 && n.typeArguments[0].kind === ts.SyntaxK ind.VoidKeyword) {
108 return; 246 return;
109 } 247 }
110 this.emitNoSpace('<'); 248 this.emitNoSpace('<');
111 this.visitList(n.typeArguments); 249 this.visitList(n.typeArguments);
112 this.emit('>'); 250 this.emit('>');
113 } 251 }
114 } 252 }
253
254 visitParameters(parameters: ts.ParameterDeclaration[]) {
255 this.emit('(');
256 let firstInitParamIdx = 0;
257 for (; firstInitParamIdx < parameters.length; firstInitParamIdx++) {
258 // ObjectBindingPatterns are handled within the parameter visit.
259 let isOpt = parameters[firstInitParamIdx].initializer ||
260 parameters[firstInitParamIdx].questionToken ||
261 parameters[firstInitParamIdx].dotDotDotToken;
262 if (isOpt && parameters[firstInitParamIdx].name.kind !== ts.SyntaxKind.Obj ectBindingPattern) {
263 break;
264 }
265 }
266
267 if (firstInitParamIdx !== 0) {
268 let requiredParams = parameters.slice(0, firstInitParamIdx);
269 this.visitList(requiredParams);
270 }
271
272 if (firstInitParamIdx !== parameters.length) {
273 if (firstInitParamIdx !== 0) this.emit(',');
274 let positionalOptional = parameters.slice(firstInitParamIdx, parameters.le ngth);
275 this.emit('[');
276 this.visitList(positionalOptional);
277 this.emit(']');
278 }
279
280 this.emit(')');
281 }
115 } 282 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698