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

Side by Side Diff: packages/analyzer/lib/src/summary/resynthesize.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 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
(Empty)
1 // Copyright (c) 2015, 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 library summary_resynthesizer;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart';
11 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/dart/element/type.dart';
13 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/element/handle.dart';
15 import 'package:analyzer/src/dart/element/member.dart';
16 import 'package:analyzer/src/dart/element/type.dart';
17 import 'package:analyzer/src/generated/engine.dart';
18 import 'package:analyzer/src/generated/resolver.dart';
19 import 'package:analyzer/src/generated/source_io.dart';
20 import 'package:analyzer/src/generated/testing/ast_factory.dart';
21 import 'package:analyzer/src/generated/testing/token_factory.dart';
22 import 'package:analyzer/src/generated/utilities_dart.dart';
23 import 'package:analyzer/src/summary/format.dart';
24 import 'package:analyzer/src/summary/idl.dart';
25 import 'package:analyzer/src/util/fast_uri.dart';
26
27 /**
28 * Implementation of [ElementResynthesizer] used when resynthesizing an element
29 * model from summaries.
30 */
31 abstract class SummaryResynthesizer extends ElementResynthesizer {
32 /**
33 * The parent [SummaryResynthesizer] which is asked to resynthesize elements
34 * and get summaries before this resynthesizer attempts to do this.
35 * Can be `null`.
36 */
37 final SummaryResynthesizer parent;
38
39 /**
40 * Source factory used to convert URIs to [Source] objects.
41 */
42 final SourceFactory sourceFactory;
43
44 /**
45 * Cache of [Source] objects that have already been converted from URIs.
46 */
47 final Map<String, Source> _sources = <String, Source>{};
48
49 /**
50 * The [TypeProvider] used to obtain core types (such as Object, int, List,
51 * and dynamic) during resynthesis.
52 */
53 final TypeProvider typeProvider;
54
55 /**
56 * Indicates whether the summary should be resynthesized assuming strong mode
57 * semantics.
58 */
59 final bool strongMode;
60
61 /**
62 * Map of compilation units resynthesized from summaries. The two map keys
63 * are the first two elements of the element's location (the library URI and
64 * the compilation unit URI).
65 */
66 final Map<String, Map<String, CompilationUnitElementImpl>>
67 _resynthesizedUnits = <String, Map<String, CompilationUnitElementImpl>>{};
68
69 /**
70 * Map of top level elements resynthesized from summaries. The three map
71 * keys are the first three elements of the element's location (the library
72 * URI, the compilation unit URI, and the name of the top level declaration).
73 */
74 final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements =
75 <String, Map<String, Map<String, Element>>>{};
76
77 /**
78 * Map of libraries which have been resynthesized from summaries. The map
79 * key is the library URI.
80 */
81 final Map<String, LibraryElement> _resynthesizedLibraries =
82 <String, LibraryElement>{};
83
84 SummaryResynthesizer(this.parent, AnalysisContext context, this.typeProvider,
85 this.sourceFactory, this.strongMode)
86 : super(context);
87
88 /**
89 * Number of libraries that have been resynthesized so far.
90 */
91 int get resynthesisCount => _resynthesizedLibraries.length;
92
93 /**
94 * Perform delayed finalization of the `dart:core` and `dart:async` libraries.
95 */
96 void finalizeCoreAsyncLibraries() {
97 (_resynthesizedLibraries['dart:core'] as LibraryElementImpl)
98 .createLoadLibraryFunction(typeProvider);
99 (_resynthesizedLibraries['dart:async'] as LibraryElementImpl)
100 .createLoadLibraryFunction(typeProvider);
101 }
102
103 @override
104 Element getElement(ElementLocation location) {
105 List<String> components = location.components;
106 String libraryUri = components[0];
107 // Ask the parent resynthesizer.
108 if (parent != null && parent._hasLibrarySummary(libraryUri)) {
109 return parent.getElement(location);
110 }
111 // Resynthesize locally.
112 if (components.length == 1) {
113 return getLibraryElement(libraryUri);
114 } else if (components.length == 2) {
115 Map<String, CompilationUnitElement> libraryMap =
116 _resynthesizedUnits[libraryUri];
117 if (libraryMap == null) {
118 getLibraryElement(libraryUri);
119 libraryMap = _resynthesizedUnits[libraryUri];
120 assert(libraryMap != null);
121 }
122 String unitUri = components[1];
123 CompilationUnitElement element = libraryMap[unitUri];
124 if (element == null) {
125 throw new Exception('Unit element not found in summary: $location');
126 }
127 return element;
128 } else if (components.length == 3 || components.length == 4) {
129 String unitUri = components[1];
130 // Prepare elements-in-units in the library.
131 Map<String, Map<String, Element>> unitsInLibrary =
132 _resynthesizedElements[libraryUri];
133 if (unitsInLibrary == null) {
134 unitsInLibrary = new HashMap<String, Map<String, Element>>();
135 _resynthesizedElements[libraryUri] = unitsInLibrary;
136 }
137 // Prepare elements in the unit.
138 Map<String, Element> elementsInUnit = unitsInLibrary[unitUri];
139 if (elementsInUnit == null) {
140 // Prepare the CompilationUnitElementImpl.
141 Map<String, CompilationUnitElementImpl> libraryMap =
142 _resynthesizedUnits[libraryUri];
143 if (libraryMap == null) {
144 getLibraryElement(libraryUri);
145 libraryMap = _resynthesizedUnits[libraryUri];
146 assert(libraryMap != null);
147 }
148 CompilationUnitElementImpl unitElement = libraryMap[unitUri];
149 // Fill elements in the unit map.
150 if (unitElement != null) {
151 elementsInUnit = new HashMap<String, Element>();
152 void putElement(Element e) {
153 String id =
154 e is PropertyAccessorElementImpl ? e.identifier : e.name;
155 elementsInUnit[id] = e;
156 }
157
158 unitElement.accessors.forEach(putElement);
159 unitElement.enums.forEach(putElement);
160 unitElement.functions.forEach(putElement);
161 unitElement.functionTypeAliases.forEach(putElement);
162 unitElement.topLevelVariables.forEach(putElement);
163 unitElement.types.forEach(putElement);
164 unitsInLibrary[unitUri] = elementsInUnit;
165 }
166 }
167 // Get the element.
168 Element element = elementsInUnit[components[2]];
169 if (element != null && components.length == 4) {
170 String name = components[3];
171 Element parentElement = element;
172 if (parentElement is ClassElement) {
173 if (name.endsWith('?')) {
174 element =
175 parentElement.getGetter(name.substring(0, name.length - 1));
176 } else if (name.endsWith('=')) {
177 element =
178 parentElement.getSetter(name.substring(0, name.length - 1));
179 } else if (name.isEmpty) {
180 element = parentElement.unnamedConstructor;
181 } else {
182 element = parentElement.getField(name) ??
183 parentElement.getMethod(name) ??
184 parentElement.getNamedConstructor(name);
185 }
186 } else {
187 // The only elements that are currently retrieved using 4-component
188 // locations are class members.
189 throw new StateError(
190 '4-element locations not supported for ${element.runtimeType}');
191 }
192 }
193 if (element == null) {
194 throw new Exception('Element not found in summary: $location');
195 }
196 return element;
197 } else {
198 throw new UnimplementedError(location.toString());
199 }
200 }
201
202 /**
203 * Get the [LibraryElement] for the given [uri], resynthesizing it if it
204 * hasn't been resynthesized already.
205 */
206 LibraryElement getLibraryElement(String uri) {
207 if (parent != null && parent._hasLibrarySummary(uri)) {
208 return parent.getLibraryElement(uri);
209 }
210 return _resynthesizedLibraries.putIfAbsent(uri, () {
211 LinkedLibrary serializedLibrary = _getLinkedSummaryOrNull(uri);
212 Source librarySource = _getSource(uri);
213 if (serializedLibrary == null) {
214 LibraryElementImpl libraryElement =
215 new LibraryElementImpl(context, '', -1, 0);
216 libraryElement.synthetic = true;
217 CompilationUnitElementImpl unitElement =
218 new CompilationUnitElementImpl(librarySource.shortName);
219 libraryElement.definingCompilationUnit = unitElement;
220 unitElement.source = librarySource;
221 unitElement.librarySource = librarySource;
222 return libraryElement..synthetic = true;
223 }
224 UnlinkedUnit unlinkedSummary = _getUnlinkedSummaryOrNull(uri);
225 if (unlinkedSummary == null) {
226 throw new StateError('Unable to find unlinked summary: $uri');
227 }
228 List<UnlinkedUnit> serializedUnits = <UnlinkedUnit>[unlinkedSummary];
229 for (String part in serializedUnits[0].publicNamespace.parts) {
230 Source partSource = sourceFactory.resolveUri(librarySource, part);
231 String partAbsUri = partSource.uri.toString();
232 serializedUnits.add(_getUnlinkedSummaryOrNull(partAbsUri) ??
233 new UnlinkedUnitBuilder(codeRange: new CodeRangeBuilder()));
234 }
235 _LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
236 this, serializedLibrary, serializedUnits, librarySource);
237 LibraryElement library = libraryResynthesizer.buildLibrary();
238 _resynthesizedUnits[uri] = libraryResynthesizer.resynthesizedUnits;
239 return library;
240 });
241 }
242
243 /**
244 * Return the [LinkedLibrary] for the given [uri] or `null` if it could not
245 * be found. Caller has already checked that `parent.hasLibrarySummary(uri)`
246 * returns `false`.
247 */
248 LinkedLibrary getLinkedSummary(String uri);
249
250 /**
251 * Return the [UnlinkedUnit] for the given [uri] or `null` if it could not
252 * be found. Caller has already checked that `parent.hasLibrarySummary(uri)`
253 * returns `false`.
254 */
255 UnlinkedUnit getUnlinkedSummary(String uri);
256
257 /**
258 * Return `true` if this resynthesizer can provide summaries of the libraries
259 * with the given [uri]. Caller has already checked that
260 * `parent.hasLibrarySummary(uri)` returns `false`.
261 */
262 bool hasLibrarySummary(String uri);
263
264 /**
265 * Return the [LinkedLibrary] for the given [uri] or return `null` if it
266 * could not be found.
267 */
268 LinkedLibrary _getLinkedSummaryOrNull(String uri) {
269 if (parent != null && parent._hasLibrarySummary(uri)) {
270 return parent._getLinkedSummaryOrNull(uri);
271 }
272 return getLinkedSummary(uri);
273 }
274
275 /**
276 * Get the [Source] object for the given [uri].
277 */
278 Source _getSource(String uri) {
279 return _sources.putIfAbsent(uri, () => sourceFactory.forUri(uri));
280 }
281
282 /**
283 * Return the [UnlinkedUnit] for the given [uri] or return `null` if it
284 * could not be found.
285 */
286 UnlinkedUnit _getUnlinkedSummaryOrNull(String uri) {
287 if (parent != null && parent._hasLibrarySummary(uri)) {
288 return parent._getUnlinkedSummaryOrNull(uri);
289 }
290 return getUnlinkedSummary(uri);
291 }
292
293 /**
294 * Return `true` if this resynthesizer can provide summaries of the libraries
295 * with the given [uri].
296 */
297 bool _hasLibrarySummary(String uri) {
298 if (parent != null && parent._hasLibrarySummary(uri)) {
299 return true;
300 }
301 return hasLibrarySummary(uri);
302 }
303 }
304
305 /**
306 * Builder of [Expression]s from [UnlinkedConst]s.
307 */
308 class _ConstExprBuilder {
309 final _UnitResynthesizer resynthesizer;
310 final ElementImpl context;
311 final UnlinkedConst uc;
312
313 int intPtr = 0;
314 int doublePtr = 0;
315 int stringPtr = 0;
316 int refPtr = 0;
317 final List<Expression> stack = <Expression>[];
318
319 _ConstExprBuilder(this.resynthesizer, this.context, this.uc);
320
321 /**
322 * Return the [ConstructorElement] enclosing [context].
323 */
324 ConstructorElement get _enclosingConstructor {
325 for (Element e = context; e != null; e = e.enclosingElement) {
326 if (e is ConstructorElement) {
327 return e;
328 }
329 }
330 throw new StateError(
331 'Unable to find the enclosing constructor of $context');
332 }
333
334 Expression build() {
335 if (!uc.isValidConst) {
336 return AstFactory.identifier3(r'$$invalidConstExpr$$');
337 }
338 for (UnlinkedConstOperation operation in uc.operations) {
339 switch (operation) {
340 case UnlinkedConstOperation.pushNull:
341 _push(AstFactory.nullLiteral());
342 break;
343 // bool
344 case UnlinkedConstOperation.pushFalse:
345 _push(AstFactory.booleanLiteral(false));
346 break;
347 case UnlinkedConstOperation.pushTrue:
348 _push(AstFactory.booleanLiteral(true));
349 break;
350 // literals
351 case UnlinkedConstOperation.pushInt:
352 int value = uc.ints[intPtr++];
353 _push(AstFactory.integer(value));
354 break;
355 case UnlinkedConstOperation.pushLongInt:
356 int value = 0;
357 int count = uc.ints[intPtr++];
358 for (int i = 0; i < count; i++) {
359 int next = uc.ints[intPtr++];
360 value = value << 32 | next;
361 }
362 _push(AstFactory.integer(value));
363 break;
364 case UnlinkedConstOperation.pushDouble:
365 double value = uc.doubles[doublePtr++];
366 _push(AstFactory.doubleLiteral(value));
367 break;
368 case UnlinkedConstOperation.makeSymbol:
369 String component = uc.strings[stringPtr++];
370 _push(AstFactory.symbolLiteral([component]));
371 break;
372 // String
373 case UnlinkedConstOperation.pushString:
374 String value = uc.strings[stringPtr++];
375 _push(AstFactory.string2(value));
376 break;
377 case UnlinkedConstOperation.concatenate:
378 int count = uc.ints[intPtr++];
379 List<InterpolationElement> elements = <InterpolationElement>[];
380 for (int i = 0; i < count; i++) {
381 Expression expr = _pop();
382 InterpolationElement element = _newInterpolationElement(expr);
383 elements.insert(0, element);
384 }
385 _push(AstFactory.string(elements));
386 break;
387 // binary
388 case UnlinkedConstOperation.equal:
389 _pushBinary(TokenType.EQ_EQ);
390 break;
391 case UnlinkedConstOperation.notEqual:
392 _pushBinary(TokenType.BANG_EQ);
393 break;
394 case UnlinkedConstOperation.and:
395 _pushBinary(TokenType.AMPERSAND_AMPERSAND);
396 break;
397 case UnlinkedConstOperation.or:
398 _pushBinary(TokenType.BAR_BAR);
399 break;
400 case UnlinkedConstOperation.bitXor:
401 _pushBinary(TokenType.CARET);
402 break;
403 case UnlinkedConstOperation.bitAnd:
404 _pushBinary(TokenType.AMPERSAND);
405 break;
406 case UnlinkedConstOperation.bitOr:
407 _pushBinary(TokenType.BAR);
408 break;
409 case UnlinkedConstOperation.bitShiftLeft:
410 _pushBinary(TokenType.LT_LT);
411 break;
412 case UnlinkedConstOperation.bitShiftRight:
413 _pushBinary(TokenType.GT_GT);
414 break;
415 case UnlinkedConstOperation.add:
416 _pushBinary(TokenType.PLUS);
417 break;
418 case UnlinkedConstOperation.subtract:
419 _pushBinary(TokenType.MINUS);
420 break;
421 case UnlinkedConstOperation.multiply:
422 _pushBinary(TokenType.STAR);
423 break;
424 case UnlinkedConstOperation.divide:
425 _pushBinary(TokenType.SLASH);
426 break;
427 case UnlinkedConstOperation.floorDivide:
428 _pushBinary(TokenType.TILDE_SLASH);
429 break;
430 case UnlinkedConstOperation.modulo:
431 _pushBinary(TokenType.PERCENT);
432 break;
433 case UnlinkedConstOperation.greater:
434 _pushBinary(TokenType.GT);
435 break;
436 case UnlinkedConstOperation.greaterEqual:
437 _pushBinary(TokenType.GT_EQ);
438 break;
439 case UnlinkedConstOperation.less:
440 _pushBinary(TokenType.LT);
441 break;
442 case UnlinkedConstOperation.lessEqual:
443 _pushBinary(TokenType.LT_EQ);
444 break;
445 // prefix
446 case UnlinkedConstOperation.complement:
447 _pushPrefix(TokenType.TILDE);
448 break;
449 case UnlinkedConstOperation.negate:
450 _pushPrefix(TokenType.MINUS);
451 break;
452 case UnlinkedConstOperation.not:
453 _pushPrefix(TokenType.BANG);
454 break;
455 // conditional
456 case UnlinkedConstOperation.conditional:
457 Expression elseExpr = _pop();
458 Expression thenExpr = _pop();
459 Expression condition = _pop();
460 _push(
461 AstFactory.conditionalExpression(condition, thenExpr, elseExpr));
462 break;
463 // invokeMethodRef
464 case UnlinkedConstOperation.invokeMethodRef:
465 _pushInvokeMethodRef();
466 break;
467 // containers
468 case UnlinkedConstOperation.makeUntypedList:
469 _pushList(null);
470 break;
471 case UnlinkedConstOperation.makeTypedList:
472 TypeName itemType = _newTypeName();
473 _pushList(AstFactory.typeArgumentList(<TypeName>[itemType]));
474 break;
475 case UnlinkedConstOperation.makeUntypedMap:
476 _pushMap(null);
477 break;
478 case UnlinkedConstOperation.makeTypedMap:
479 TypeName keyType = _newTypeName();
480 TypeName valueType = _newTypeName();
481 _pushMap(AstFactory.typeArgumentList(<TypeName>[keyType, valueType]));
482 break;
483 case UnlinkedConstOperation.pushReference:
484 _pushReference();
485 break;
486 case UnlinkedConstOperation.extractProperty:
487 _pushExtractProperty();
488 break;
489 case UnlinkedConstOperation.invokeConstructor:
490 _pushInstanceCreation();
491 break;
492 case UnlinkedConstOperation.pushParameter:
493 String name = uc.strings[stringPtr++];
494 SimpleIdentifier identifier = AstFactory.identifier3(name);
495 identifier.staticElement = _enclosingConstructor.parameters
496 .firstWhere((parameter) => parameter.name == name,
497 orElse: () => throw new StateError(
498 'Unable to resolve constructor parameter: $name'));
499 _push(identifier);
500 break;
501 case UnlinkedConstOperation.assignToRef:
502 case UnlinkedConstOperation.assignToProperty:
503 case UnlinkedConstOperation.assignToIndex:
504 case UnlinkedConstOperation.extractIndex:
505 case UnlinkedConstOperation.invokeMethod:
506 case UnlinkedConstOperation.cascadeSectionBegin:
507 case UnlinkedConstOperation.cascadeSectionEnd:
508 case UnlinkedConstOperation.typeCast:
509 case UnlinkedConstOperation.typeCheck:
510 case UnlinkedConstOperation.throwException:
511 case UnlinkedConstOperation.pushLocalFunctionReference:
512 throw new UnimplementedError(
513 'Unexpected $operation in a constant expression.');
514 }
515 }
516 return stack.single;
517 }
518
519 List<Expression> _buildArguments() {
520 List<Expression> arguments;
521 {
522 int numNamedArgs = uc.ints[intPtr++];
523 int numPositionalArgs = uc.ints[intPtr++];
524 int numArgs = numNamedArgs + numPositionalArgs;
525 arguments = _removeTopItems(numArgs);
526 // add names to the named arguments
527 for (int i = 0; i < numNamedArgs; i++) {
528 String name = uc.strings[stringPtr++];
529 int index = numPositionalArgs + i;
530 arguments[index] = AstFactory.namedExpression2(name, arguments[index]);
531 }
532 }
533 return arguments;
534 }
535
536 /**
537 * Build the identifier sequence (a single or prefixed identifier, or a
538 * property access) corresponding to the given reference [info].
539 */
540 Expression _buildIdentifierSequence(_ReferenceInfo info) {
541 Expression enclosing;
542 if (info.enclosing != null) {
543 enclosing = _buildIdentifierSequence(info.enclosing);
544 }
545 Element element = info.element;
546 if (element == null && info.name == 'length') {
547 element = _getStringLengthElement();
548 }
549 if (enclosing == null) {
550 return AstFactory.identifier3(info.name)..staticElement = element;
551 }
552 if (enclosing is SimpleIdentifier) {
553 SimpleIdentifier identifier = AstFactory.identifier3(info.name)
554 ..staticElement = element;
555 return AstFactory.identifier(enclosing, identifier);
556 }
557 SimpleIdentifier property = AstFactory.identifier3(info.name)
558 ..staticElement = element;
559 return AstFactory.propertyAccess(enclosing, property);
560 }
561
562 TypeName _buildTypeAst(DartType type) {
563 List<TypeName> argumentNodes;
564 if (type is ParameterizedType) {
565 if (!resynthesizer.libraryResynthesizer.typesWithImplicitTypeArguments
566 .contains(type)) {
567 List<DartType> typeArguments = type.typeArguments;
568 argumentNodes = typeArguments.every((a) => a.isDynamic)
569 ? null
570 : typeArguments.map(_buildTypeAst).toList();
571 }
572 }
573 TypeName node = AstFactory.typeName4(type.name, argumentNodes);
574 node.type = type;
575 (node.name as SimpleIdentifier).staticElement = type.element;
576 return node;
577 }
578
579 PropertyAccessorElement _getStringLengthElement() =>
580 resynthesizer.typeProvider.stringType.getGetter('length');
581
582 InterpolationElement _newInterpolationElement(Expression expr) {
583 if (expr is SimpleStringLiteral) {
584 return new InterpolationString(expr.literal, expr.value);
585 } else {
586 return new InterpolationExpression(
587 TokenFactory.tokenFromType(TokenType.STRING_INTERPOLATION_EXPRESSION),
588 expr,
589 TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
590 }
591 }
592
593 /**
594 * Convert the next reference to the [DartType] and return the AST
595 * corresponding to this type.
596 */
597 TypeName _newTypeName() {
598 EntityRef typeRef = uc.references[refPtr++];
599 DartType type =
600 resynthesizer.buildType(typeRef, context?.typeParameterContext);
601 return _buildTypeAst(type);
602 }
603
604 Expression _pop() => stack.removeLast();
605
606 void _push(Expression expr) {
607 stack.add(expr);
608 }
609
610 void _pushBinary(TokenType operator) {
611 Expression right = _pop();
612 Expression left = _pop();
613 _push(AstFactory.binaryExpression(left, operator, right));
614 }
615
616 void _pushExtractProperty() {
617 Expression target = _pop();
618 String name = uc.strings[stringPtr++];
619 SimpleIdentifier propertyNode = AstFactory.identifier3(name);
620 // Only String.length property access can be potentially resolved.
621 if (name == 'length') {
622 propertyNode.staticElement = _getStringLengthElement();
623 }
624 _push(AstFactory.propertyAccess(target, propertyNode));
625 }
626
627 void _pushInstanceCreation() {
628 EntityRef ref = uc.references[refPtr++];
629 _ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
630 // prepare ConstructorElement
631 TypeName typeNode;
632 String constructorName;
633 ConstructorElement constructorElement;
634 if (info.element != null) {
635 if (info.element is ConstructorElement) {
636 constructorName = info.name;
637 } else if (info.element is ClassElement) {
638 constructorName = null;
639 } else {
640 throw new StateError('Unsupported element for invokeConstructor '
641 '${info.element?.runtimeType}');
642 }
643 InterfaceType definingType = resynthesizer._createConstructorDefiningType(
644 context?.typeParameterContext, info, ref.typeArguments);
645 constructorElement =
646 resynthesizer._getConstructorForInfo(definingType, info);
647 typeNode = _buildTypeAst(definingType);
648 } else {
649 if (info.enclosing != null) {
650 if (info.enclosing.enclosing != null) {
651 PrefixedIdentifier typeName = AstFactory.identifier5(
652 info.enclosing.enclosing.name, info.enclosing.name);
653 typeName.prefix.staticElement = info.enclosing.enclosing.element;
654 typeName.identifier.staticElement = info.enclosing.element;
655 typeName.identifier.staticType = info.enclosing.type;
656 typeNode = AstFactory.typeName3(typeName);
657 typeNode.type = info.enclosing.type;
658 constructorName = info.name;
659 } else if (info.enclosing.element != null) {
660 SimpleIdentifier typeName =
661 AstFactory.identifier3(info.enclosing.name);
662 typeName.staticElement = info.enclosing.element;
663 typeName.staticType = info.enclosing.type;
664 typeNode = AstFactory.typeName3(typeName);
665 typeNode.type = info.enclosing.type;
666 constructorName = info.name;
667 } else {
668 typeNode = AstFactory.typeName3(
669 AstFactory.identifier5(info.enclosing.name, info.name));
670 constructorName = null;
671 }
672 } else {
673 typeNode = AstFactory.typeName4(info.name);
674 }
675 }
676 // prepare arguments
677 List<Expression> arguments = _buildArguments();
678 // create ConstructorName
679 ConstructorName constructorNode;
680 if (constructorName != null) {
681 constructorNode = AstFactory.constructorName(typeNode, constructorName);
682 constructorNode.name.staticElement = constructorElement;
683 } else {
684 constructorNode = AstFactory.constructorName(typeNode, null);
685 }
686 constructorNode.staticElement = constructorElement;
687 // create InstanceCreationExpression
688 InstanceCreationExpression instanceCreation = AstFactory
689 .instanceCreationExpression(Keyword.CONST, constructorNode, arguments);
690 instanceCreation.staticElement = constructorElement;
691 _push(instanceCreation);
692 }
693
694 void _pushInvokeMethodRef() {
695 List<Expression> arguments = _buildArguments();
696 EntityRef ref = uc.references[refPtr++];
697 _ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
698 Expression node = _buildIdentifierSequence(info);
699 TypeArgumentList typeArguments;
700 int numTypeArguments = uc.ints[intPtr++];
701 if (numTypeArguments > 0) {
702 List<TypeName> typeNames = new List<TypeName>(numTypeArguments);
703 for (int i = 0; i < numTypeArguments; i++) {
704 typeNames[i] = _newTypeName();
705 }
706 typeArguments = AstFactory.typeArgumentList(typeNames);
707 }
708 if (node is SimpleIdentifier) {
709 _push(new MethodInvocation(
710 null,
711 TokenFactory.tokenFromType(TokenType.PERIOD),
712 node,
713 typeArguments,
714 AstFactory.argumentList(arguments)));
715 } else {
716 throw new UnimplementedError('For ${node?.runtimeType}: $node');
717 }
718 }
719
720 void _pushList(TypeArgumentList typeArguments) {
721 int count = uc.ints[intPtr++];
722 List<Expression> elements = <Expression>[];
723 for (int i = 0; i < count; i++) {
724 elements.insert(0, _pop());
725 }
726 _push(AstFactory.listLiteral2(Keyword.CONST, typeArguments, elements));
727 }
728
729 void _pushMap(TypeArgumentList typeArguments) {
730 int count = uc.ints[intPtr++];
731 List<MapLiteralEntry> entries = <MapLiteralEntry>[];
732 for (int i = 0; i < count; i++) {
733 Expression value = _pop();
734 Expression key = _pop();
735 entries.insert(0, AstFactory.mapLiteralEntry2(key, value));
736 }
737 _push(AstFactory.mapLiteral(Keyword.CONST, typeArguments, entries));
738 }
739
740 void _pushPrefix(TokenType operator) {
741 Expression operand = _pop();
742 _push(AstFactory.prefixExpression(operator, operand));
743 }
744
745 void _pushReference() {
746 EntityRef ref = uc.references[refPtr++];
747 _ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
748 Expression node = _buildIdentifierSequence(info);
749 _push(node);
750 }
751
752 List<Expression> _removeTopItems(int count) {
753 int start = stack.length - count;
754 int end = stack.length;
755 List<Expression> items = stack.getRange(start, end).toList();
756 stack.removeRange(start, end);
757 return items;
758 }
759 }
760
761 /**
762 * Local function element representing the initializer for a variable that has
763 * been resynthesized from a summary. The actual element won't be constructed
764 * until it is requested. But properties [context] and [enclosingElement] can
765 * be used without creating the actual element.
766 */
767 class _DeferredInitializerElement extends FunctionElementHandle {
768 /**
769 * The variable element containing this element.
770 */
771 @override
772 final VariableElement enclosingElement;
773
774 _DeferredInitializerElement(this.enclosingElement) : super(null, null);
775
776 @override
777 FunctionElement get actualElement => enclosingElement.initializer;
778
779 @override
780 AnalysisContext get context => enclosingElement.context;
781
782 @override
783 ElementLocation get location => actualElement.location;
784 }
785
786 /**
787 * Local function element that has been resynthesized from a summary. The
788 * actual element won't be constructed until it is requested. But properties
789 * [context] and [enclosingElement] can be used without creating the actual
790 * element.
791 */
792 class _DeferredLocalFunctionElement extends FunctionElementHandle {
793 /**
794 * The executable element containing this element.
795 */
796 @override
797 final ExecutableElement enclosingElement;
798
799 /**
800 * The index of this function within [ExecutableElement.functions].
801 */
802 final int _localIndex;
803
804 _DeferredLocalFunctionElement(this.enclosingElement, this._localIndex)
805 : super(null, null);
806
807 @override
808 FunctionElement get actualElement {
809 ExecutableElement enclosingElement = this.enclosingElement;
810 if (enclosingElement is PropertyAccessorElement &&
811 enclosingElement.isSynthetic) {
812 return enclosingElement.variable.initializer;
813 } else {
814 return enclosingElement.functions[_localIndex];
815 }
816 }
817
818 @override
819 AnalysisContext get context => enclosingElement.context;
820
821 @override
822 ElementLocation get location => actualElement.location;
823 }
824
825 /**
826 * Local variable element that has been resynthesized from a summary. The
827 * actual element won't be constructed until it is requested. But properties
828 * [context] and [enclosingElement] can be used without creating the actual
829 * element.
830 */
831 class _DeferredLocalVariableElement extends LocalVariableElementHandle {
832 /**
833 * The executable element containing this element.
834 */
835 @override
836 final ExecutableElement enclosingElement;
837
838 /**
839 * The index of this variable within [ExecutableElement.localVariables].
840 */
841 final int _localIndex;
842
843 _DeferredLocalVariableElement(this.enclosingElement, this._localIndex)
844 : super(null, null);
845
846 @override
847 LocalVariableElement get actualElement =>
848 enclosingElement.localVariables[_localIndex];
849
850 @override
851 AnalysisContext get context => enclosingElement.context;
852
853 @override
854 ElementLocation get location => actualElement.location;
855 }
856
857 /**
858 * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the
859 * elements in a single library from that library's summary.
860 */
861 class _LibraryResynthesizer {
862 /**
863 * The [SummaryResynthesizer] which is being used to obtain summaries.
864 */
865 final SummaryResynthesizer summaryResynthesizer;
866
867 /**
868 * Linked summary of the library to be resynthesized.
869 */
870 final LinkedLibrary linkedLibrary;
871
872 /**
873 * Unlinked compilation units constituting the library to be resynthesized.
874 */
875 final List<UnlinkedUnit> unlinkedUnits;
876
877 /**
878 * [Source] object for the library to be resynthesized.
879 */
880 final Source librarySource;
881
882 /**
883 * The URI of [librarySource].
884 */
885 String libraryUri;
886
887 /**
888 * Indicates whether [librarySource] is the `dart:core` library.
889 */
890 bool isCoreLibrary;
891
892 /**
893 * The resynthesized library.
894 */
895 LibraryElementImpl library;
896
897 /**
898 * Map of compilation unit elements that have been resynthesized so far. The
899 * key is the URI of the compilation unit.
900 */
901 final Map<String, CompilationUnitElementImpl> resynthesizedUnits =
902 <String, CompilationUnitElementImpl>{};
903
904 /**
905 * Types with implicit type arguments, which are the same as type parameter
906 * bounds (in strong mode), or `dynamic` (in spec mode).
907 */
908 final Set<DartType> typesWithImplicitTypeArguments =
909 new Set<DartType>.identity();
910
911 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
912 this.unlinkedUnits, this.librarySource) {
913 libraryUri = librarySource.uri.toString();
914 isCoreLibrary = libraryUri == 'dart:core';
915 }
916
917 /**
918 * Resynthesize a [NamespaceCombinator].
919 */
920 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
921 if (serializedCombinator.shows.isNotEmpty) {
922 return new ShowElementCombinatorImpl.forSerialized(serializedCombinator);
923 } else {
924 return new HideElementCombinatorImpl.forSerialized(serializedCombinator);
925 }
926 }
927
928 /**
929 * Build an [ElementHandle] referring to the entity referred to by the given
930 * [exportName].
931 */
932 ElementHandle buildExportName(LinkedExportName exportName) {
933 String name = exportName.name;
934 if (exportName.kind == ReferenceKind.topLevelPropertyAccessor &&
935 !name.endsWith('=')) {
936 name += '?';
937 }
938 ElementLocationImpl location = new ElementLocationImpl.con3(
939 getReferencedLocationComponents(
940 exportName.dependency, exportName.unit, name));
941 switch (exportName.kind) {
942 case ReferenceKind.classOrEnum:
943 return new ClassElementHandle(summaryResynthesizer, location);
944 case ReferenceKind.typedef:
945 return new FunctionTypeAliasElementHandle(
946 summaryResynthesizer, location);
947 case ReferenceKind.topLevelFunction:
948 return new FunctionElementHandle(summaryResynthesizer, location);
949 case ReferenceKind.topLevelPropertyAccessor:
950 return new PropertyAccessorElementHandle(
951 summaryResynthesizer, location);
952 case ReferenceKind.constructor:
953 case ReferenceKind.function:
954 case ReferenceKind.propertyAccessor:
955 case ReferenceKind.method:
956 case ReferenceKind.prefix:
957 case ReferenceKind.unresolved:
958 case ReferenceKind.variable:
959 // Should never happen. Exported names never refer to import prefixes,
960 // and they always refer to defined top-level entities.
961 throw new StateError('Unexpected export name kind: ${exportName.kind}');
962 }
963 return null;
964 }
965
966 /**
967 * Build the export namespace for the library by aggregating together its
968 * [publicNamespace] and [exportNames].
969 */
970 Namespace buildExportNamespace(
971 Namespace publicNamespace, List<LinkedExportName> exportNames) {
972 HashMap<String, Element> definedNames = new HashMap<String, Element>();
973 // Start by populating all the public names from [publicNamespace].
974 publicNamespace.definedNames.forEach((String name, Element element) {
975 definedNames[name] = element;
976 });
977 // Add all the names from [exportNames].
978 for (LinkedExportName exportName in exportNames) {
979 definedNames.putIfAbsent(
980 exportName.name, () => buildExportName(exportName));
981 }
982 return new Namespace(definedNames);
983 }
984
985 /**
986 * Main entry point. Resynthesize the [LibraryElement] and return it.
987 */
988 LibraryElement buildLibrary() {
989 // Create LibraryElementImpl.
990 bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
991 library = new LibraryElementImpl.forSerialized(
992 summaryResynthesizer.context,
993 unlinkedUnits[0].libraryName,
994 hasName ? unlinkedUnits[0].libraryNameOffset : -1,
995 unlinkedUnits[0].libraryNameLength,
996 new _LibraryResynthesizerContext(this),
997 unlinkedUnits[0]);
998 // Create the defining unit.
999 _UnitResynthesizer definingUnitResynthesizer =
1000 createUnitResynthesizer(0, librarySource, null);
1001 CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit;
1002 library.definingCompilationUnit = definingUnit;
1003 definingUnit.source = librarySource;
1004 definingUnit.librarySource = librarySource;
1005 // Create parts.
1006 List<_UnitResynthesizer> partResynthesizers = <_UnitResynthesizer>[];
1007 UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
1008 assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
1009 linkedLibrary.units.length);
1010 for (int i = 1; i < linkedLibrary.units.length; i++) {
1011 _UnitResynthesizer partResynthesizer = buildPart(
1012 definingUnitResynthesizer,
1013 unlinkedDefiningUnit.publicNamespace.parts[i - 1],
1014 unlinkedDefiningUnit.parts[i - 1],
1015 i);
1016 partResynthesizers.add(partResynthesizer);
1017 }
1018 library.parts = partResynthesizers.map((r) => r.unit).toList();
1019 // Populate units.
1020 rememberUriToUnit(definingUnitResynthesizer);
1021 for (_UnitResynthesizer partResynthesizer in partResynthesizers) {
1022 rememberUriToUnit(partResynthesizer);
1023 }
1024 // Create the synthetic element for `loadLibrary`.
1025 // Until the client received dart:core and dart:async, we cannot do this,
1026 // because the TypeProvider is not fully initialized. So, it is up to the
1027 // Dart SDK client to initialize TypeProvider and finish the dart:core and
1028 // dart:async libraries creation.
1029 if (library.name != 'dart.core' && library.name != 'dart.async') {
1030 library.createLoadLibraryFunction(summaryResynthesizer.typeProvider);
1031 }
1032 // Done.
1033 return library;
1034 }
1035
1036 /**
1037 * Create, but do not populate, the [CompilationUnitElement] for a part other
1038 * than the defining compilation unit.
1039 */
1040 _UnitResynthesizer buildPart(_UnitResynthesizer definingUnitResynthesizer,
1041 String uri, UnlinkedPart partDecl, int unitNum) {
1042 Source unitSource =
1043 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
1044 _UnitResynthesizer partResynthesizer =
1045 createUnitResynthesizer(unitNum, unitSource, partDecl);
1046 CompilationUnitElementImpl partUnit = partResynthesizer.unit;
1047 partUnit.uriOffset = partDecl.uriOffset;
1048 partUnit.uriEnd = partDecl.uriEnd;
1049 partUnit.source = unitSource;
1050 partUnit.librarySource = librarySource;
1051 partUnit.uri = uri;
1052 return partResynthesizer;
1053 }
1054
1055 /**
1056 * Set up data structures for deserializing a compilation unit.
1057 */
1058 _UnitResynthesizer createUnitResynthesizer(
1059 int unitNum, Source unitSource, UnlinkedPart unlinkedPart) {
1060 LinkedUnit linkedUnit = linkedLibrary.units[unitNum];
1061 UnlinkedUnit unlinkedUnit = unlinkedUnits[unitNum];
1062 return new _UnitResynthesizer(
1063 this, unlinkedUnit, linkedUnit, unitSource, unlinkedPart);
1064 }
1065
1066 /**
1067 * Build the components of an [ElementLocationImpl] for the entity in the
1068 * given [unit] of the dependency located at [dependencyIndex], and having
1069 * the given [name].
1070 */
1071 List<String> getReferencedLocationComponents(
1072 int dependencyIndex, int unit, String name) {
1073 if (dependencyIndex == 0) {
1074 String referencedLibraryUri = libraryUri;
1075 String partUri;
1076 if (unit != 0) {
1077 String uri = unlinkedUnits[0].publicNamespace.parts[unit - 1];
1078 Source partSource =
1079 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
1080 partUri = partSource.uri.toString();
1081 } else {
1082 partUri = referencedLibraryUri;
1083 }
1084 return <String>[referencedLibraryUri, partUri, name];
1085 }
1086 LinkedDependency dependency = linkedLibrary.dependencies[dependencyIndex];
1087 Source referencedLibrarySource = summaryResynthesizer.sourceFactory
1088 .resolveUri(librarySource, dependency.uri);
1089 String referencedLibraryUri = referencedLibrarySource.uri.toString();
1090 String partUri;
1091 if (unit != 0) {
1092 String uri = dependency.parts[unit - 1];
1093 Source partSource =
1094 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
1095 partUri = partSource.uri.toString();
1096 } else {
1097 partUri = referencedLibraryUri;
1098 }
1099 return <String>[referencedLibraryUri, partUri, name];
1100 }
1101
1102 /**
1103 * Remember the absolute URI to the corresponding unit mapping.
1104 */
1105 void rememberUriToUnit(_UnitResynthesizer unitResynthesized) {
1106 CompilationUnitElementImpl unit = unitResynthesized.unit;
1107 String absoluteUri = unit.source.uri.toString();
1108 resynthesizedUnits[absoluteUri] = unit;
1109 }
1110 }
1111
1112 /**
1113 * Implementation of [LibraryResynthesizerContext] for [_LibraryResynthesizer].
1114 */
1115 class _LibraryResynthesizerContext implements LibraryResynthesizerContext {
1116 final _LibraryResynthesizer resynthesizer;
1117
1118 _LibraryResynthesizerContext(this.resynthesizer);
1119
1120 @override
1121 LinkedLibrary get linkedLibrary => resynthesizer.linkedLibrary;
1122
1123 @override
1124 LibraryElement buildExportedLibrary(String relativeUri) {
1125 return _getLibraryByRelativeUri(relativeUri);
1126 }
1127
1128 @override
1129 Namespace buildExportNamespace() {
1130 LibraryElementImpl library = resynthesizer.library;
1131 return resynthesizer.buildExportNamespace(
1132 library.publicNamespace, resynthesizer.linkedLibrary.exportNames);
1133 }
1134
1135 @override
1136 LibraryElement buildImportedLibrary(int dependency) {
1137 String depUri = resynthesizer.linkedLibrary.dependencies[dependency].uri;
1138 return _getLibraryByRelativeUri(depUri);
1139 }
1140
1141 @override
1142 Namespace buildPublicNamespace() {
1143 LibraryElementImpl library = resynthesizer.library;
1144 return new NamespaceBuilder().createPublicNamespaceForLibrary(library);
1145 }
1146
1147 @override
1148 FunctionElement findEntryPoint() {
1149 LibraryElementImpl library = resynthesizer.library;
1150 Element entryPoint =
1151 library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
1152 if (entryPoint is FunctionElement) {
1153 return entryPoint;
1154 }
1155 return null;
1156 }
1157
1158 @override
1159 void patchTopLevelAccessors() {
1160 LibraryElementImpl library = resynthesizer.library;
1161 BuildLibraryElementUtils.patchTopLevelAccessors(library);
1162 }
1163
1164 LibraryElementHandle _getLibraryByRelativeUri(String depUri) {
1165 String absoluteUri = resolveRelativeUri(
1166 resynthesizer.librarySource.uri, FastUri.parse(depUri))
1167 .toString();
1168 return new LibraryElementHandle(resynthesizer.summaryResynthesizer,
1169 new ElementLocationImpl.con3(<String>[absoluteUri]));
1170 }
1171 }
1172
1173 /**
1174 * Data structure used during resynthesis to record all the information that is
1175 * known about how to resynthesize a single entry in [LinkedUnit.references]
1176 * (and its associated entry in [UnlinkedUnit.references], if it exists).
1177 */
1178 class _ReferenceInfo {
1179 /**
1180 * The [_LibraryResynthesizer] which is being used to obtain summaries.
1181 */
1182 final _LibraryResynthesizer libraryResynthesizer;
1183
1184 /**
1185 * The enclosing [_ReferenceInfo], or `null` for top-level elements.
1186 */
1187 final _ReferenceInfo enclosing;
1188
1189 /**
1190 * The name of the entity referred to by this reference.
1191 */
1192 final String name;
1193
1194 /**
1195 * The element referred to by this reference, or `null` if there is no
1196 * associated element (e.g. because it is a reference to an undefined
1197 * entity).
1198 */
1199 final Element element;
1200
1201 /**
1202 * If this reference refers to a non-generic type, the type it refers to.
1203 * Otherwise `null`.
1204 */
1205 DartType type;
1206
1207 /**
1208 * The number of type parameters accepted by the entity referred to by this
1209 * reference, or zero if it doesn't accept any type parameters.
1210 */
1211 final int numTypeParameters;
1212
1213 /**
1214 * Create a new [_ReferenceInfo] object referring to an element called [name]
1215 * via the element handle [element], and having [numTypeParameters] type
1216 * parameters.
1217 *
1218 * For the special types `dynamic` and `void`, [specialType] should point to
1219 * the type itself. Otherwise, pass `null` and the type will be computed
1220 * when appropriate.
1221 */
1222 _ReferenceInfo(this.libraryResynthesizer, this.enclosing, this.name,
1223 this.element, DartType specialType, this.numTypeParameters) {
1224 if (specialType != null) {
1225 type = specialType;
1226 } else {
1227 type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
1228 }
1229 }
1230
1231 /**
1232 * Build a [DartType] corresponding to the result of applying some type
1233 * arguments to the entity referred to by this [_ReferenceInfo]. The type
1234 * arguments are retrieved by calling [getTypeArgument].
1235 *
1236 * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be
1237 * created which refers to a function type implicitly defined by one of the
1238 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
1239 * [EntityRef.implicitFunctionTypeIndices].
1240 *
1241 * If the entity referred to by this [_ReferenceInfo] is not a type, `null`
1242 * is returned.
1243 */
1244 DartType buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
1245 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
1246 DartType result =
1247 (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty)
1248 ? type
1249 : _buildType(instantiateToBoundsAllowed, numTypeArguments,
1250 getTypeArgument, implicitFunctionTypeIndices);
1251 if (result == null) {
1252 // TODO(paulberry): figure out how to handle this case (which should
1253 // only occur in the event of erroneous code).
1254 throw new UnimplementedError();
1255 }
1256 return result;
1257 }
1258
1259 /**
1260 * If this reference refers to a type, build a [DartType]. Otherwise return
1261 * `null`. If [numTypeArguments] is the same as the [numTypeParameters],
1262 * the type in instantiated with type arguments returned by [getTypeArgument],
1263 * otherwise it is instantiated with type parameter bounds (if strong mode),
1264 * or with `dynamic` type arguments.
1265 *
1266 * If [implicitFunctionTypeIndices] is not null, a [DartType] should be
1267 * created which refers to a function type implicitly defined by one of the
1268 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
1269 * [EntityRef.implicitFunctionTypeIndices].
1270 */
1271 DartType _buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
1272 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
1273 ElementHandle element = this.element; // To allow type promotion
1274 if (element is ClassElementHandle) {
1275 List<DartType> typeArguments = null;
1276 // If type arguments are specified, use them.
1277 // Otherwise, delay until they are requested.
1278 if (numTypeParameters == 0) {
1279 typeArguments = const <DartType>[];
1280 } else if (numTypeArguments == numTypeParameters) {
1281 typeArguments = new List<DartType>(numTypeParameters);
1282 for (int i = 0; i < numTypeParameters; i++) {
1283 typeArguments[i] = getTypeArgument(i);
1284 }
1285 }
1286 InterfaceTypeImpl type =
1287 new InterfaceTypeImpl.elementWithNameAndArgs(element, name, () {
1288 if (typeArguments == null) {
1289 typeArguments = element.typeParameters
1290 .map/*<DartType>*/((_) => DynamicTypeImpl.instance)
1291 .toList();
1292 if (libraryResynthesizer.summaryResynthesizer.strongMode &&
1293 instantiateToBoundsAllowed) {
1294 List<DartType> typeParameterTypes;
1295 for (int i = 0; i < typeArguments.length; i++) {
1296 DartType bound = element.typeParameters[i].bound;
1297 if (bound != null) {
1298 typeParameterTypes ??= element.typeParameters
1299 .map/*<DartType>*/((TypeParameterElement e) => e.type)
1300 .toList();
1301 typeArguments[i] =
1302 bound.substitute2(typeArguments, typeParameterTypes);
1303 }
1304 }
1305 }
1306 }
1307 return typeArguments;
1308 });
1309 // Mark the type as having implicit type arguments, so that we don't
1310 // attempt to request them during constant expression resynthesizing.
1311 if (typeArguments == null) {
1312 libraryResynthesizer.typesWithImplicitTypeArguments.add(type);
1313 }
1314 // Done.
1315 return type;
1316 } else if (element is FunctionTypedElement) {
1317 int numTypeArguments;
1318 FunctionTypedElementComputer computer;
1319 if (implicitFunctionTypeIndices.isNotEmpty) {
1320 numTypeArguments = numTypeParameters;
1321 computer = () {
1322 FunctionTypedElement element = this.element;
1323 for (int index in implicitFunctionTypeIndices) {
1324 element = element.parameters[index].type.element;
1325 }
1326 return element;
1327 };
1328 } else if (element is FunctionTypeAliasElementHandle) {
1329 return new FunctionTypeImpl.elementWithNameAndArgs(
1330 element,
1331 name,
1332 _buildTypeArguments(numTypeParameters, getTypeArgument),
1333 numTypeParameters != 0);
1334 } else {
1335 // For a type that refers to a generic executable, the type arguments ar e
1336 // not supposed to include the arguments to the executable itself.
1337 numTypeArguments = enclosing == null ? 0 : enclosing.numTypeParameters;
1338 computer = () => this.element as FunctionTypedElement;
1339 }
1340 // TODO(paulberry): Is it a bug that we have to pass `false` for
1341 // isInstantiated?
1342 return new DeferredFunctionTypeImpl(computer, null,
1343 _buildTypeArguments(numTypeArguments, getTypeArgument), false);
1344 } else {
1345 return null;
1346 }
1347 }
1348
1349 /**
1350 * Build a list of type arguments having length [numTypeArguments] where each
1351 * type argument is obtained by calling [getTypeArgument].
1352 */
1353 List<DartType> _buildTypeArguments(
1354 int numTypeArguments, DartType getTypeArgument(int i)) {
1355 List<DartType> typeArguments = const <DartType>[];
1356 if (numTypeArguments != 0) {
1357 typeArguments = <DartType>[];
1358 for (int i = 0; i < numTypeArguments; i++) {
1359 typeArguments.add(getTypeArgument(i));
1360 }
1361 }
1362 return typeArguments;
1363 }
1364 }
1365
1366 class _ResynthesizerContext implements ResynthesizerContext {
1367 final _UnitResynthesizer _unitResynthesizer;
1368
1369 _ResynthesizerContext(this._unitResynthesizer);
1370
1371 @override
1372 ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc) {
1373 return _unitResynthesizer.buildAnnotation(context, uc);
1374 }
1375
1376 @override
1377 Expression buildExpression(ElementImpl context, UnlinkedConst uc) {
1378 return _unitResynthesizer._buildConstExpression(context, uc);
1379 }
1380
1381 @override
1382 UnitExplicitTopLevelAccessors buildTopLevelAccessors() {
1383 return _unitResynthesizer.buildUnitExplicitTopLevelAccessors();
1384 }
1385
1386 @override
1387 UnitExplicitTopLevelVariables buildTopLevelVariables() {
1388 return _unitResynthesizer.buildUnitExplicitTopLevelVariables();
1389 }
1390
1391 @override
1392 bool inheritsCovariant(int slot) {
1393 return _unitResynthesizer.parametersInheritingCovariant.contains(slot);
1394 }
1395
1396 @override
1397 bool isInConstCycle(int slot) {
1398 return _unitResynthesizer.constCycles.contains(slot);
1399 }
1400
1401 @override
1402 ConstructorElement resolveConstructorRef(
1403 TypeParameterizedElementMixin typeParameterContext, EntityRef entry) {
1404 return _unitResynthesizer._getConstructorForEntry(
1405 typeParameterContext, entry);
1406 }
1407
1408 @override
1409 DartType resolveLinkedType(
1410 int slot, TypeParameterizedElementMixin typeParameterContext) {
1411 return _unitResynthesizer.buildLinkedType(slot, typeParameterContext);
1412 }
1413
1414 @override
1415 DartType resolveTypeRef(
1416 EntityRef type, TypeParameterizedElementMixin typeParameterContext,
1417 {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) {
1418 return _unitResynthesizer.buildType(type, typeParameterContext,
1419 defaultVoid: defaultVoid,
1420 instantiateToBoundsAllowed: instantiateToBoundsAllowed);
1421 }
1422 }
1423
1424 /**
1425 * An instance of [_UnitResynthesizer] is responsible for resynthesizing the
1426 * elements in a single unit from that unit's summary.
1427 */
1428 class _UnitResynthesizer {
1429 /**
1430 * The [_LibraryResynthesizer] which is being used to obtain summaries.
1431 */
1432 final _LibraryResynthesizer libraryResynthesizer;
1433
1434 /**
1435 * The [UnlinkedUnit] from which elements are currently being resynthesized.
1436 */
1437 final UnlinkedUnit unlinkedUnit;
1438
1439 /**
1440 * The [LinkedUnit] from which elements are currently being resynthesized.
1441 */
1442 final LinkedUnit linkedUnit;
1443
1444 /**
1445 * The [CompilationUnitElementImpl] for the compilation unit currently being
1446 * resynthesized.
1447 */
1448 CompilationUnitElementImpl unit;
1449
1450 /**
1451 * Map from slot id to the corresponding [EntityRef] object for linked types
1452 * (i.e. propagated and inferred types).
1453 */
1454 final Map<int, EntityRef> linkedTypeMap = <int, EntityRef>{};
1455
1456 /**
1457 * Set of slot ids corresponding to const constructors that are part of
1458 * cycles.
1459 */
1460 Set<int> constCycles;
1461
1462 /**
1463 * Set of slot ids corresponding to parameters that inherit `@covariant`
1464 * behavior.
1465 */
1466 Set<int> parametersInheritingCovariant;
1467
1468 int numLinkedReferences;
1469 int numUnlinkedReferences;
1470
1471 /**
1472 * List of [_ReferenceInfo] objects describing the references in the current
1473 * compilation unit. This list is works as a lazily filled cache, use
1474 * [getReferenceInfo] to get the [_ReferenceInfo] for an index.
1475 */
1476 List<_ReferenceInfo> referenceInfos;
1477
1478 /**
1479 * The [ResynthesizerContext] for this resynthesize session.
1480 */
1481 ResynthesizerContext _resynthesizerContext;
1482
1483 _UnitResynthesizer(this.libraryResynthesizer, this.unlinkedUnit,
1484 this.linkedUnit, Source unitSource, UnlinkedPart unlinkedPart) {
1485 _resynthesizerContext = new _ResynthesizerContext(this);
1486 unit = new CompilationUnitElementImpl.forSerialized(
1487 libraryResynthesizer.library,
1488 _resynthesizerContext,
1489 unlinkedUnit,
1490 unlinkedPart,
1491 unitSource.shortName);
1492 for (EntityRef t in linkedUnit.types) {
1493 linkedTypeMap[t.slot] = t;
1494 }
1495 constCycles = linkedUnit.constCycles.toSet();
1496 parametersInheritingCovariant =
1497 linkedUnit.parametersInheritingCovariant.toSet();
1498 numLinkedReferences = linkedUnit.references.length;
1499 numUnlinkedReferences = unlinkedUnit.references.length;
1500 referenceInfos = new List<_ReferenceInfo>(numLinkedReferences);
1501 }
1502
1503 SummaryResynthesizer get summaryResynthesizer =>
1504 libraryResynthesizer.summaryResynthesizer;
1505
1506 TypeProvider get typeProvider => summaryResynthesizer.typeProvider;
1507
1508 /**
1509 * Build [ElementAnnotationImpl] for the given [UnlinkedConst].
1510 */
1511 ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc) {
1512 ElementAnnotationImpl elementAnnotation = new ElementAnnotationImpl(unit);
1513 Expression constExpr = _buildConstExpression(context, uc);
1514 if (constExpr is Identifier) {
1515 elementAnnotation.element = constExpr.staticElement;
1516 elementAnnotation.annotationAst = AstFactory.annotation(constExpr);
1517 } else if (constExpr is InstanceCreationExpression) {
1518 elementAnnotation.element = constExpr.staticElement;
1519 Identifier typeName = constExpr.constructorName.type.name;
1520 SimpleIdentifier constructorName = constExpr.constructorName.name;
1521 if (typeName is SimpleIdentifier && constructorName != null) {
1522 // E.g. `@cls.ctor()`. Since `cls.ctor` would have been parsed as
1523 // a PrefixedIdentifier, we need to resynthesize it as one.
1524 typeName = AstFactory.identifier(typeName, constructorName);
1525 constructorName = null;
1526 }
1527 elementAnnotation.annotationAst = AstFactory.annotation2(
1528 typeName, constructorName, constExpr.argumentList)
1529 ..element = constExpr.staticElement;
1530 } else {
1531 throw new StateError(
1532 'Unexpected annotation type: ${constExpr.runtimeType}');
1533 }
1534 return elementAnnotation;
1535 }
1536
1537 /**
1538 * Build an implicit getter for the given [property] and bind it to the
1539 * [property] and to its enclosing element.
1540 */
1541 PropertyAccessorElementImpl buildImplicitGetter(
1542 PropertyInducingElementImpl property) {
1543 PropertyAccessorElementImpl_ImplicitGetter getter =
1544 new PropertyAccessorElementImpl_ImplicitGetter(property);
1545 getter.enclosingElement = property.enclosingElement;
1546 return getter;
1547 }
1548
1549 /**
1550 * Build an implicit setter for the given [property] and bind it to the
1551 * [property] and to its enclosing element.
1552 */
1553 PropertyAccessorElementImpl buildImplicitSetter(
1554 PropertyInducingElementImpl property) {
1555 PropertyAccessorElementImpl_ImplicitSetter setter =
1556 new PropertyAccessorElementImpl_ImplicitSetter(property);
1557 setter.enclosingElement = property.enclosingElement;
1558 return setter;
1559 }
1560
1561 /**
1562 * Build the appropriate [DartType] object corresponding to a slot id in the
1563 * [LinkedUnit.types] table.
1564 */
1565 DartType buildLinkedType(
1566 int slot, TypeParameterizedElementMixin typeParameterContext) {
1567 if (slot == 0) {
1568 // A slot id of 0 means there is no [DartType] object to build.
1569 return null;
1570 }
1571 EntityRef type = linkedTypeMap[slot];
1572 if (type == null) {
1573 // A missing entry in [LinkedUnit.types] means there is no [DartType]
1574 // stored in this slot.
1575 return null;
1576 }
1577 return buildType(type, typeParameterContext);
1578 }
1579
1580 /**
1581 * Build a [DartType] object based on a [EntityRef]. This [DartType]
1582 * may refer to elements in other libraries than the library being
1583 * deserialized, so handles are used to avoid having to deserialize other
1584 * libraries in the process.
1585 */
1586 DartType buildType(
1587 EntityRef type, TypeParameterizedElementMixin typeParameterContext,
1588 {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) {
1589 if (type == null) {
1590 if (defaultVoid) {
1591 return VoidTypeImpl.instance;
1592 } else {
1593 return DynamicTypeImpl.instance;
1594 }
1595 }
1596 if (type.paramReference != 0) {
1597 return typeParameterContext.getTypeParameterType(type.paramReference);
1598 } else if (type.syntheticReturnType != null) {
1599 FunctionElementImpl element =
1600 new FunctionElementImpl_forLUB(unit, typeParameterContext, type);
1601 return element.type;
1602 } else {
1603 DartType getTypeArgument(int i) {
1604 if (i < type.typeArguments.length) {
1605 return buildType(type.typeArguments[i], typeParameterContext);
1606 } else {
1607 return DynamicTypeImpl.instance;
1608 }
1609 }
1610
1611 _ReferenceInfo referenceInfo = getReferenceInfo(type.reference);
1612 return referenceInfo.buildType(
1613 instantiateToBoundsAllowed,
1614 type.typeArguments.length,
1615 getTypeArgument,
1616 type.implicitFunctionTypeIndices);
1617 }
1618 }
1619
1620 UnitExplicitTopLevelAccessors buildUnitExplicitTopLevelAccessors() {
1621 HashMap<String, TopLevelVariableElementImpl> implicitVariables =
1622 new HashMap<String, TopLevelVariableElementImpl>();
1623 UnitExplicitTopLevelAccessors accessorsData =
1624 new UnitExplicitTopLevelAccessors();
1625 for (UnlinkedExecutable unlinkedExecutable in unlinkedUnit.executables) {
1626 UnlinkedExecutableKind kind = unlinkedExecutable.kind;
1627 if (kind == UnlinkedExecutableKind.getter ||
1628 kind == UnlinkedExecutableKind.setter) {
1629 // name
1630 String name = unlinkedExecutable.name;
1631 if (kind == UnlinkedExecutableKind.setter) {
1632 assert(name.endsWith('='));
1633 name = name.substring(0, name.length - 1);
1634 }
1635 // create
1636 PropertyAccessorElementImpl accessor =
1637 new PropertyAccessorElementImpl.forSerialized(
1638 unlinkedExecutable, unit);
1639 accessorsData.accessors.add(accessor);
1640 // implicit variable
1641 TopLevelVariableElementImpl variable = implicitVariables[name];
1642 if (variable == null) {
1643 variable = new TopLevelVariableElementImpl(name, -1);
1644 variable.enclosingElement = unit;
1645 implicitVariables[name] = variable;
1646 accessorsData.implicitVariables.add(variable);
1647 variable.synthetic = true;
1648 variable.final2 = kind == UnlinkedExecutableKind.getter;
1649 } else {
1650 variable.final2 = false;
1651 }
1652 accessor.variable = variable;
1653 // link
1654 if (kind == UnlinkedExecutableKind.getter) {
1655 variable.getter = accessor;
1656 } else {
1657 variable.setter = accessor;
1658 }
1659 }
1660 }
1661 return accessorsData;
1662 }
1663
1664 UnitExplicitTopLevelVariables buildUnitExplicitTopLevelVariables() {
1665 List<UnlinkedVariable> unlinkedVariables = unlinkedUnit.variables;
1666 int numberOfVariables = unlinkedVariables.length;
1667 UnitExplicitTopLevelVariables variablesData =
1668 new UnitExplicitTopLevelVariables(numberOfVariables);
1669 for (int i = 0; i < numberOfVariables; i++) {
1670 UnlinkedVariable unlinkedVariable = unlinkedVariables[i];
1671 TopLevelVariableElementImpl element;
1672 if (unlinkedVariable.initializer?.bodyExpr != null &&
1673 unlinkedVariable.isConst) {
1674 element = new ConstTopLevelVariableElementImpl.forSerialized(
1675 unlinkedVariable, unit);
1676 } else {
1677 element = new TopLevelVariableElementImpl.forSerialized(
1678 unlinkedVariable, unit);
1679 }
1680 variablesData.variables[i] = element;
1681 // implicit accessors
1682 variablesData.implicitAccessors.add(buildImplicitGetter(element));
1683 if (!(element.isConst || element.isFinal)) {
1684 variablesData.implicitAccessors.add(buildImplicitSetter(element));
1685 }
1686 }
1687 return variablesData;
1688 }
1689
1690 /**
1691 * Return [_ReferenceInfo] with the given [index], lazily resolving it.
1692 */
1693 _ReferenceInfo getReferenceInfo(int index) {
1694 _ReferenceInfo result = referenceInfos[index];
1695 if (result == null) {
1696 LinkedReference linkedReference = linkedUnit.references[index];
1697 String name;
1698 int containingReference;
1699 if (index < numUnlinkedReferences) {
1700 name = unlinkedUnit.references[index].name;
1701 containingReference = unlinkedUnit.references[index].prefixReference;
1702 } else {
1703 name = linkedUnit.references[index].name;
1704 containingReference = linkedUnit.references[index].containingReference;
1705 }
1706 _ReferenceInfo enclosingInfo = containingReference != 0
1707 ? getReferenceInfo(containingReference)
1708 : null;
1709 Element element;
1710 DartType type;
1711 int numTypeParameters = linkedReference.numTypeParameters;
1712 if (linkedReference.kind == ReferenceKind.unresolved) {
1713 type = UndefinedTypeImpl.instance;
1714 element = null;
1715 } else if (name == 'dynamic') {
1716 type = DynamicTypeImpl.instance;
1717 element = type.element;
1718 } else if (name == 'void') {
1719 type = VoidTypeImpl.instance;
1720 element = type.element;
1721 } else if (name == '*bottom*') {
1722 type = BottomTypeImpl.instance;
1723 element = null;
1724 } else {
1725 List<String> locationComponents;
1726 if (enclosingInfo != null && enclosingInfo.element is ClassElement) {
1727 String identifier = _getElementIdentifier(name, linkedReference.kind);
1728 locationComponents =
1729 enclosingInfo.element.location.components.toList();
1730 locationComponents.add(identifier);
1731 } else {
1732 String identifier = _getElementIdentifier(name, linkedReference.kind);
1733 locationComponents =
1734 libraryResynthesizer.getReferencedLocationComponents(
1735 linkedReference.dependency, linkedReference.unit, identifier);
1736 }
1737 ElementLocation location =
1738 new ElementLocationImpl.con3(locationComponents);
1739 if (enclosingInfo != null) {
1740 numTypeParameters += enclosingInfo.numTypeParameters;
1741 }
1742 switch (linkedReference.kind) {
1743 case ReferenceKind.classOrEnum:
1744 element = new ClassElementHandle(summaryResynthesizer, location);
1745 break;
1746 case ReferenceKind.constructor:
1747 assert(location.components.length == 4);
1748 element =
1749 new ConstructorElementHandle(summaryResynthesizer, location);
1750 break;
1751 case ReferenceKind.method:
1752 assert(location.components.length == 4);
1753 element = new MethodElementHandle(summaryResynthesizer, location);
1754 break;
1755 case ReferenceKind.propertyAccessor:
1756 assert(location.components.length == 4);
1757 element = new PropertyAccessorElementHandle(
1758 summaryResynthesizer, location);
1759 break;
1760 case ReferenceKind.topLevelFunction:
1761 assert(location.components.length == 3);
1762 element = new FunctionElementHandle(summaryResynthesizer, location);
1763 break;
1764 case ReferenceKind.topLevelPropertyAccessor:
1765 element = new PropertyAccessorElementHandle(
1766 summaryResynthesizer, location);
1767 break;
1768 case ReferenceKind.typedef:
1769 element = new FunctionTypeAliasElementHandle(
1770 summaryResynthesizer, location);
1771 break;
1772 case ReferenceKind.variable:
1773 Element enclosingElement = enclosingInfo.element;
1774 if (enclosingElement is ExecutableElement) {
1775 element = new _DeferredLocalVariableElement(
1776 enclosingElement, linkedReference.localIndex);
1777 } else {
1778 throw new StateError('Unexpected element enclosing variable:'
1779 ' ${enclosingElement.runtimeType}');
1780 }
1781 break;
1782 case ReferenceKind.function:
1783 Element enclosingElement = enclosingInfo.element;
1784 if (enclosingElement is VariableElement) {
1785 element = new _DeferredInitializerElement(enclosingElement);
1786 } else if (enclosingElement is ExecutableElement) {
1787 element = new _DeferredLocalFunctionElement(
1788 enclosingElement, linkedReference.localIndex);
1789 } else {
1790 throw new StateError('Unexpected element enclosing function:'
1791 ' ${enclosingElement.runtimeType}');
1792 }
1793 break;
1794 case ReferenceKind.prefix:
1795 case ReferenceKind.unresolved:
1796 break;
1797 }
1798 }
1799 result = new _ReferenceInfo(libraryResynthesizer, enclosingInfo, name,
1800 element, type, numTypeParameters);
1801 referenceInfos[index] = result;
1802 }
1803 return result;
1804 }
1805
1806 Expression _buildConstExpression(ElementImpl context, UnlinkedConst uc) {
1807 return new _ConstExprBuilder(this, context, uc).build();
1808 }
1809
1810 /**
1811 * Return the defining type for a [ConstructorElement] by applying
1812 * [typeArgumentRefs] to the given linked [info].
1813 */
1814 DartType _createConstructorDefiningType(
1815 TypeParameterizedElementMixin typeParameterContext,
1816 _ReferenceInfo info,
1817 List<EntityRef> typeArgumentRefs) {
1818 bool isClass = info.element is ClassElement;
1819 _ReferenceInfo classInfo = isClass ? info : info.enclosing;
1820 List<DartType> typeArguments = typeArgumentRefs
1821 .map((t) => buildType(t, typeParameterContext))
1822 .toList();
1823 return classInfo.buildType(true, typeArguments.length, (i) {
1824 if (i < typeArguments.length) {
1825 return typeArguments[i];
1826 } else {
1827 return DynamicTypeImpl.instance;
1828 }
1829 }, const <int>[]);
1830 }
1831
1832 /**
1833 * Return the [ConstructorElement] corresponding to the given [entry].
1834 */
1835 ConstructorElement _getConstructorForEntry(
1836 TypeParameterizedElementMixin typeParameterContext, EntityRef entry) {
1837 _ReferenceInfo info = getReferenceInfo(entry.reference);
1838 DartType type = _createConstructorDefiningType(
1839 typeParameterContext, info, entry.typeArguments);
1840 if (type is InterfaceType) {
1841 return _getConstructorForInfo(type, info);
1842 }
1843 return null;
1844 }
1845
1846 /**
1847 * Return the [ConstructorElement] corresponding to the given linked [info],
1848 * using the [classType] which has already been computed (e.g. by
1849 * [_createConstructorDefiningType]). Both cases when [info] is a
1850 * [ClassElement] and [ConstructorElement] are supported.
1851 */
1852 ConstructorElement _getConstructorForInfo(
1853 InterfaceType classType, _ReferenceInfo info) {
1854 ConstructorElement element;
1855 Element infoElement = info.element;
1856 if (infoElement is ConstructorElement) {
1857 element = infoElement;
1858 } else if (infoElement is ClassElement) {
1859 element = infoElement.unnamedConstructor;
1860 }
1861 if (element != null && info.numTypeParameters != 0) {
1862 return new ConstructorMember(element, classType);
1863 }
1864 return element;
1865 }
1866
1867 /**
1868 * If the given [kind] is a top-level or class member property accessor, and
1869 * the given [name] does not end with `=`, i.e. does not denote a setter,
1870 * return the getter identifier by appending `?`.
1871 */
1872 static String _getElementIdentifier(String name, ReferenceKind kind) {
1873 if (kind == ReferenceKind.topLevelPropertyAccessor ||
1874 kind == ReferenceKind.propertyAccessor) {
1875 if (!name.endsWith('=')) {
1876 return name + '?';
1877 }
1878 }
1879 return name;
1880 }
1881 }
OLDNEW
« no previous file with comments | « packages/analyzer/lib/src/summary/public_namespace_computer.dart ('k') | packages/analyzer/lib/src/summary/summarize_ast.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698