| OLD | NEW |
| (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 } |
| OLD | NEW |