OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'package:front_end/src/fasta/errors.dart'; | |
6 import 'package:front_end/src/fasta/parser/identifier_context.dart'; | |
7 import 'package:front_end/src/fasta/parser/parser.dart'; | |
8 import 'package:front_end/src/fasta/scanner/token.dart'; | |
9 import 'package:front_end/src/fasta/source/stack_listener.dart'; | |
10 | |
11 /// "Mini AST" representation of a declaration which can accept annotations. | |
12 class AnnotatedNode { | |
13 final Comment documentationComment; | |
14 | |
15 final List<Annotation> metadata; | |
16 | |
17 AnnotatedNode(this.documentationComment, List<Annotation> metadata) | |
18 : metadata = metadata ?? const []; | |
19 } | |
20 | |
21 /// "Mini AST" representation of an annotation. | |
22 class Annotation { | |
23 final String name; | |
24 | |
25 final String constructorName; | |
26 | |
27 final List<Expression> arguments; | |
28 | |
29 Annotation(this.name, this.constructorName, this.arguments); | |
30 } | |
31 | |
32 /// "Mini AST" representation of a class declaration. | |
33 class ClassDeclaration extends CompilationUnitMember { | |
34 final String name; | |
35 | |
36 final TypeName superclass; | |
37 | |
38 final List<ClassMember> members; | |
39 | |
40 ClassDeclaration(Comment documentationComment, List<Annotation> metadata, | |
41 this.name, this.superclass, this.members) | |
42 : super(documentationComment, metadata); | |
43 } | |
44 | |
45 /// "Mini AST" representation of a class member. | |
46 class ClassMember extends AnnotatedNode { | |
47 ClassMember(Comment documentationComment, List<Annotation> metadata) | |
48 : super(documentationComment, metadata); | |
49 } | |
50 | |
51 /// "Mini AST" representation of a comment. | |
52 class Comment { | |
53 final bool isDocumentation; | |
54 | |
55 final List<Token> tokens; | |
56 | |
57 factory Comment(Token commentToken) { | |
58 var tokens = <Token>[]; | |
59 bool isDocumentation = false; | |
60 while (commentToken != null) { | |
61 if (commentToken.lexeme.startsWith('/**') || | |
62 commentToken.lexeme.startsWith('///')) { | |
63 isDocumentation = true; | |
64 } | |
65 tokens.add(commentToken); | |
66 commentToken = commentToken.next; | |
67 } | |
68 return new Comment._(isDocumentation, tokens); | |
69 } | |
70 | |
71 Comment._(this.isDocumentation, this.tokens); | |
72 } | |
73 | |
74 /// "Mini AST" representation of a CompilationUnit. | |
75 class CompilationUnit { | |
76 final declarations = <CompilationUnitMember>[]; | |
77 } | |
78 | |
79 /// "Mini AST" representation of a top level member of a compilation unit. | |
80 class CompilationUnitMember extends AnnotatedNode { | |
81 CompilationUnitMember(Comment documentationComment, List<Annotation> metadata) | |
82 : super(documentationComment, metadata); | |
83 } | |
84 | |
85 /// "Mini AST" representation of a constructor declaration. | |
86 class ConstructorDeclaration extends ClassMember { | |
87 final ConstructorReference name; | |
88 | |
89 ConstructorDeclaration( | |
90 Comment documentationComment, List<Annotation> metadata, this.name) | |
91 : super(documentationComment, metadata); | |
92 } | |
93 | |
94 /// "Mini AST" representation of a constructor reference. | |
95 class ConstructorReference { | |
96 final String name; | |
97 | |
98 final String constructorName; | |
99 | |
100 ConstructorReference(this.name, this.constructorName); | |
101 } | |
102 | |
103 /// "Mini AST" representation of an individual enum constant in an enum | |
104 /// declaration. | |
105 class EnumConstantDeclaration extends AnnotatedNode { | |
106 final String name; | |
107 | |
108 EnumConstantDeclaration( | |
109 Comment documentationComment, List<Annotation> metadata, this.name) | |
110 : super(documentationComment, metadata); | |
111 } | |
112 | |
113 /// "Mini AST" representation of an enum declaration. | |
114 class EnumDeclaration extends CompilationUnitMember { | |
115 final String name; | |
116 | |
117 final List<EnumConstantDeclaration> constants; | |
118 | |
119 EnumDeclaration(Comment documentationComment, List<Annotation> metadata, | |
120 this.name, this.constants) | |
121 : super(documentationComment, metadata); | |
122 } | |
123 | |
124 /// "Mini AST" representation of an expression. | |
125 class Expression {} | |
126 | |
127 /// "Mini AST" representation of an integer literal. | |
128 class IntegerLiteral extends Expression { | |
129 final int value; | |
130 | |
131 IntegerLiteral(this.value); | |
132 } | |
133 | |
134 /// "Mini AST" representation of a method declaration. | |
135 class MethodDeclaration extends ClassMember { | |
136 final bool isGetter; | |
137 | |
138 final String name; | |
139 | |
140 final TypeName returnType; | |
141 | |
142 MethodDeclaration(Comment documentationComment, List<Annotation> metadata, | |
143 this.isGetter, this.name, this.returnType) | |
144 : super(documentationComment, metadata); | |
145 } | |
146 | |
147 /// Parser listener which generates a "mini AST" representation of the source | |
148 /// code. This representation is just sufficient for summary code generation. | |
149 class MiniAstBuilder extends StackListener { | |
150 bool inMetadata = false; | |
151 | |
152 final compilationUnit = new CompilationUnit(); | |
153 | |
154 @override | |
155 Uri get uri => null; | |
156 | |
157 @override | |
158 void beginMetadata(Token token) { | |
159 inMetadata = true; | |
160 } | |
161 | |
162 @override | |
163 void beginMetadataStar(Token token) { | |
164 debugEvent("beginMetadataStar"); | |
165 if (token.precedingComments != null) { | |
166 push(new Comment(token.precedingComments)); | |
167 } else { | |
168 push(NullValue.Comments); | |
169 } | |
170 } | |
171 | |
172 @override | |
173 void endArguments(int count, Token beginToken, Token endToken) { | |
174 debugEvent("Arguments"); | |
175 push(popList(count)); | |
176 } | |
177 | |
178 @override | |
179 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
180 debugEvent("ClassBody"); | |
181 push(popList(memberCount)); | |
182 } | |
183 | |
184 void endClassDeclaration( | |
185 int interfacesCount, | |
186 Token beginToken, | |
187 Token classKeyword, | |
188 Token extendsKeyword, | |
189 Token implementsKeyword, | |
190 Token endToken) { | |
191 debugEvent("ClassDeclaration"); | |
192 // ignore: strong_mode_down_cast_composite | |
193 List<ClassMember> members = pop(); | |
scheglov
2017/03/14 17:22:40
Would this be better?
var members = pop() as List<
Paul Berry
2017/03/14 17:31:36
Personally, I like it better. But IIRC, Peter has
scheglov
2017/03/14 17:35:37
OK
Probably performance is not a concern for gener
| |
194 TypeName superclass = pop(); | |
195 pop(); // Type variables | |
196 String name = pop(); | |
197 // ignore: strong_mode_down_cast_composite | |
198 List<Annotation> metadata = pop(); | |
199 Comment comment = pop(); | |
200 compilationUnit.declarations.add( | |
201 new ClassDeclaration(comment, metadata, name, superclass, members)); | |
202 } | |
203 | |
204 @override | |
205 void endCombinators(int count) { | |
206 debugEvent("Combinators"); | |
207 } | |
208 | |
209 @override | |
210 void endConditionalUris(int count) { | |
211 debugEvent("ConditionalUris"); | |
212 if (count != 0) { | |
213 internalError('Conditional URIs are not supported by summary codegen'); | |
214 } | |
215 } | |
216 | |
217 @override | |
218 void endConstructorReference( | |
219 Token start, Token periodBeforeName, Token endToken) { | |
220 debugEvent("ConstructorReference"); | |
221 String constructorName = popIfNotNull(periodBeforeName); | |
222 pop(); // Type arguments | |
223 String name = pop(); | |
224 push(new ConstructorReference(name, constructorName)); | |
225 } | |
226 | |
227 void endEnum(Token enumKeyword, Token endBrace, int count) { | |
228 debugEvent("Enum"); | |
229 // ignore: strong_mode_down_cast_composite | |
230 List<EnumConstantDeclaration> constants = popList(count); | |
231 String name = pop(); | |
232 // ignore: strong_mode_down_cast_composite | |
233 List<Annotation> metadata = pop(); | |
234 Comment comment = pop(); | |
235 compilationUnit.declarations | |
236 .add(new EnumDeclaration(comment, metadata, name, constants)); | |
237 } | |
238 | |
239 @override | |
240 void endFactoryMethod( | |
241 Token beginToken, Token factoryKeyword, Token endToken) { | |
242 debugEvent("FactoryMethod"); | |
243 pop(); // Body | |
244 ConstructorReference name = pop(); | |
245 // ignore: strong_mode_down_cast_composite | |
246 List<Annotation> metadata = pop(); | |
247 Comment comment = pop(); | |
248 push(new ConstructorDeclaration(comment, metadata, name)); | |
249 } | |
250 | |
251 @override | |
252 void endFieldInitializer(Token assignment) { | |
253 debugEvent("FieldInitializer"); | |
254 pop(); // Expression | |
255 } | |
256 | |
257 @override | |
258 void endFormalParameter( | |
259 Token covariantKeyword, Token thisKeyword, FormalParameterType kind) { | |
260 debugEvent("FormalParameter"); | |
261 pop(); // Name | |
262 pop(); // Type | |
263 pop(); // Metadata | |
264 pop(); // Comment | |
265 } | |
266 | |
267 @override | |
268 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
269 debugEvent("FormalParameters"); | |
270 } | |
271 | |
272 @override | |
273 void endIdentifierList(int count) { | |
274 debugEvent("IdentifierList"); | |
275 push(popList(count)); | |
276 } | |
277 | |
278 @override | |
279 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, | |
280 Token semicolon) { | |
281 debugEvent("Import"); | |
282 popIfNotNull(asKeyword); // Prefix identifier | |
283 pop(); // URI | |
284 pop(); // Metadata | |
285 pop(); // Comment | |
286 } | |
287 | |
288 @override | |
289 void endLibraryName(Token libraryKeyword, Token semicolon) { | |
290 debugEvent("LibraryName"); | |
291 pop(); // Library name | |
292 pop(); // Metadata | |
293 pop(); // Comment | |
294 } | |
295 | |
296 @override | |
297 void endLiteralString(int interpolationCount, Token endToken) { | |
298 super.endLiteralString(interpolationCount, endToken); | |
299 String value = pop(); | |
300 push(new StringLiteral(value)); | |
301 } | |
302 | |
303 @override | |
304 void endMember() { | |
305 debugEvent("Member"); | |
306 } | |
307 | |
308 @override | |
309 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | |
310 debugEvent("Metadata"); | |
311 inMetadata = false; | |
312 // ignore: strong_mode_down_cast_composite | |
313 List<Expression> arguments = pop(); | |
314 String constructorName = popIfNotNull(periodBeforeName); | |
315 pop(); // Type arguments | |
316 String name = pop(); | |
317 push(new Annotation(name, constructorName, arguments)); | |
318 } | |
319 | |
320 @override | |
321 void endMetadataStar(int count, bool forParameter) { | |
322 debugEvent("MetadataStar"); | |
323 push(popList(count) ?? NullValue.Metadata); | |
324 } | |
325 | |
326 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
327 debugEvent("Method"); | |
328 pop(); // Body | |
329 pop(); // Initializers | |
330 pop(); // Formal parameters | |
331 pop(); // Type variables | |
332 String name = pop(); | |
333 TypeName returnType = pop(); | |
334 // ignore: strong_mode_down_cast_composite | |
335 List<Annotation> metadata = pop(); | |
336 Comment comment = pop(); | |
337 push(new MethodDeclaration( | |
338 comment, metadata, getOrSet?.lexeme == 'get', name, returnType)); | |
339 } | |
340 | |
341 @override | |
342 void endSend(Token beginToken, Token endToken) { | |
343 debugEvent("Send"); | |
344 // ignore: strong_mode_down_cast_composite | |
345 pop(); // Arguments | |
346 pop(); // Type arguments | |
347 pop(); // Receiver | |
348 push(new UnknownExpression()); | |
349 } | |
350 | |
351 @override | |
352 void endShow(Token showKeyword) { | |
353 debugEvent("Show"); | |
354 pop(); // Shown names | |
355 } | |
356 | |
357 @override | |
358 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
359 // We ignore top level variable declarations; they are present just to make | |
360 // the IDL analyze without warnings. | |
361 debugEvent("TopLevelFields"); | |
362 popList(count); // Fields | |
363 pop(); // Type | |
364 pop(); // Metadata | |
365 pop(); // Comment | |
366 } | |
367 | |
368 @override | |
369 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
370 debugEvent("TypeArguments"); | |
371 push(popList(count)); | |
372 } | |
373 | |
374 @override | |
375 void handleAsyncModifier(Token asyncToken, Token starToken) { | |
376 debugEvent("AsyncModifier"); | |
377 } | |
378 | |
379 @override | |
380 void handleBinaryExpression(Token token) { | |
381 debugEvent("BinaryExpression"); | |
382 pop(); // RHS | |
383 pop(); // LHS | |
384 push(new UnknownExpression()); | |
385 } | |
386 | |
387 @override | |
388 void handleFormalParameterWithoutValue(Token token) { | |
389 debugEvent("FormalParameterWithoutValue"); | |
390 } | |
391 | |
392 @override | |
393 void handleFunctionBodySkipped(Token token, bool isExpressionBody) { | |
394 if (isExpressionBody) pop(); | |
395 push(NullValue.FunctionBody); | |
396 } | |
397 | |
398 void handleIdentifier(Token token, IdentifierContext context) { | |
399 if (context == IdentifierContext.enumValueDeclaration) { | |
400 var comment = new Comment(token.precedingComments); | |
401 push(new EnumConstantDeclaration(comment, null, token.lexeme)); | |
402 } else { | |
403 push(token.lexeme); | |
404 } | |
405 } | |
406 | |
407 void handleLiteralInt(Token token) { | |
408 debugEvent("LiteralInt"); | |
409 push(new IntegerLiteral(int.parse(token.lexeme))); | |
410 } | |
411 | |
412 void handleLiteralNull(Token token) { | |
413 debugEvent("LiteralNull"); | |
414 push(new UnknownExpression()); | |
415 } | |
416 | |
417 @override | |
418 void handleModifier(Token token) { | |
419 debugEvent("Modifier"); | |
420 } | |
421 | |
422 @override | |
423 void handleModifiers(int count) { | |
424 debugEvent("Modifiers"); | |
425 } | |
426 | |
427 @override | |
428 void handleQualified(Token period) { | |
429 debugEvent("Qualified"); | |
430 String suffix = pop(); | |
431 String prefix = pop(); | |
432 push('$prefix.$suffix'); | |
433 } | |
434 | |
435 @override | |
436 void handleType(Token beginToken, Token endToken) { | |
437 debugEvent("Type"); | |
438 // ignore: strong_mode_down_cast_composite | |
439 List<TypeName> typeArguments = pop(); | |
440 String name = pop(); | |
441 push(new TypeName(name, typeArguments)); | |
442 } | |
443 } | |
444 | |
445 /// Parser intended for use with [MiniAstBuilder]. | |
446 class MiniAstParser extends Parser { | |
447 MiniAstParser(MiniAstBuilder listener) : super(listener); | |
448 | |
449 Token parseArgumentsOpt(Token token) { | |
450 MiniAstBuilder listener = this.listener; | |
451 if (listener.inMetadata) { | |
452 return super.parseArgumentsOpt(token); | |
453 } else { | |
454 return skipArgumentsOpt(token); | |
455 } | |
456 } | |
457 | |
458 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | |
459 return skipFunctionBody(token, isExpression, allowAbstract); | |
460 } | |
461 } | |
462 | |
463 /// "Mini AST" representation of a string literal. | |
464 class StringLiteral extends Expression { | |
465 final String stringValue; | |
466 | |
467 StringLiteral(this.stringValue); | |
468 } | |
469 | |
470 /// "Mini AST" representation of a type name. | |
471 class TypeName { | |
472 final String name; | |
473 | |
474 final List<TypeName> typeArguments; | |
475 | |
476 TypeName(this.name, this.typeArguments); | |
477 } | |
478 | |
479 /// "Mini AST" representation of an expression which summary code generation | |
480 /// need not be concerned about. | |
481 class UnknownExpression extends Expression {} | |
OLD | NEW |