Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library summary_resynthesizer; | 5 library summary_resynthesizer; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 * corresponding field element. This is used when resynthesizing | 411 * corresponding field element. This is used when resynthesizing |
| 412 * initializing formal parameters. | 412 * initializing formal parameters. |
| 413 */ | 413 */ |
| 414 Map<String, FieldElementImpl> fields; | 414 Map<String, FieldElementImpl> fields; |
| 415 | 415 |
| 416 /** | 416 /** |
| 417 * List of constant variables to compute values for. | 417 * List of constant variables to compute values for. |
| 418 */ | 418 */ |
| 419 List<_ConstVariable> constVariables = <_ConstVariable>[]; | 419 List<_ConstVariable> constVariables = <_ConstVariable>[]; |
| 420 | 420 |
| 421 /** | |
| 422 * List of [_ReferenceInfo] objects describing the references in the current | |
| 423 * compilation unit. | |
| 424 */ | |
| 425 List<_ReferenceInfo> referenceInfos; | |
| 426 | |
| 421 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, | 427 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, |
| 422 this.unlinkedUnits, this.librarySource) { | 428 this.unlinkedUnits, this.librarySource) { |
| 423 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; | 429 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; |
| 424 } | 430 } |
| 425 | 431 |
| 426 /** | 432 /** |
| 427 * Return a list of type arguments corresponding to [currentTypeParameters]. | 433 * Return a list of type arguments corresponding to [currentTypeParameters]. |
| 428 */ | 434 */ |
| 429 List<TypeParameterType> get currentTypeArguments => currentTypeParameters | 435 List<TypeParameterType> get currentTypeArguments => currentTypeParameters |
| 430 ?.map((TypeParameterElement param) => param.type) | 436 ?.map((TypeParameterElement param) => param.type) |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1106 } else { | 1112 } else { |
| 1107 return summaryResynthesizer.typeProvider.dynamicType; | 1113 return summaryResynthesizer.typeProvider.dynamicType; |
| 1108 } | 1114 } |
| 1109 } | 1115 } |
| 1110 if (type.paramReference != 0) { | 1116 if (type.paramReference != 0) { |
| 1111 // TODO(paulberry): make this work for generic methods. | 1117 // TODO(paulberry): make this work for generic methods. |
| 1112 return currentTypeParameters[ | 1118 return currentTypeParameters[ |
| 1113 currentTypeParameters.length - type.paramReference] | 1119 currentTypeParameters.length - type.paramReference] |
| 1114 .type; | 1120 .type; |
| 1115 } else { | 1121 } else { |
| 1116 LinkedReference referenceResolution = | 1122 DartType getTypeParameter(int i) { |
| 1117 linkedUnit.references[type.reference]; | 1123 if (i < type.typeArguments.length) { |
| 1118 String name; | 1124 return buildType(type.typeArguments[i]); |
| 1119 if (type.reference < unlinkedUnit.references.length) { | |
| 1120 name = unlinkedUnit.references[type.reference].name; | |
| 1121 } else { | |
| 1122 name = referenceResolution.name; | |
| 1123 } | |
| 1124 ElementLocationImpl location; | |
| 1125 if (referenceResolution.dependency != 0) { | |
| 1126 location = getReferencedLocation( | |
| 1127 linkedLibrary.dependencies[referenceResolution.dependency], | |
| 1128 referenceResolution.unit, | |
| 1129 name); | |
| 1130 } else if (referenceResolution.kind == ReferenceKind.unresolved) { | |
| 1131 return summaryResynthesizer.typeProvider.undefinedType; | |
| 1132 } else if (name == 'dynamic') { | |
| 1133 return summaryResynthesizer.typeProvider.dynamicType; | |
| 1134 } else if (name == 'void') { | |
| 1135 return VoidTypeImpl.instance; | |
| 1136 } else { | |
| 1137 String referencedLibraryUri = librarySource.uri.toString(); | |
| 1138 String partUri; | |
| 1139 if (referenceResolution.unit != 0) { | |
| 1140 String uri = unlinkedUnits[0].publicNamespace.parts[ | |
| 1141 referenceResolution.unit - 1]; | |
| 1142 Source partSource = | |
| 1143 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri); | |
| 1144 partUri = partSource.uri.toString(); | |
| 1145 } else { | 1125 } else { |
| 1146 partUri = referencedLibraryUri; | 1126 return summaryResynthesizer.typeProvider.dynamicType; |
| 1147 } | |
| 1148 location = new ElementLocationImpl.con3( | |
| 1149 <String>[referencedLibraryUri, partUri, name]); | |
| 1150 } | |
| 1151 List<DartType> typeArguments = const <DartType>[]; | |
| 1152 if (referenceResolution.numTypeParameters != 0) { | |
| 1153 typeArguments = <DartType>[]; | |
| 1154 for (int i = 0; i < referenceResolution.numTypeParameters; i++) { | |
| 1155 if (i < type.typeArguments.length) { | |
| 1156 typeArguments.add(buildType(type.typeArguments[i])); | |
| 1157 } else { | |
| 1158 typeArguments.add(summaryResynthesizer.typeProvider.dynamicType); | |
| 1159 } | |
| 1160 } | 1127 } |
| 1161 } | 1128 } |
| 1162 switch (referenceResolution.kind) { | 1129 _ReferenceInfo referenceInfo = referenceInfos[type.reference]; |
| 1163 case ReferenceKind.classOrEnum: | 1130 return referenceInfo.buildType(getTypeParameter); |
| 1164 return new InterfaceTypeImpl.elementWithNameAndArgs( | |
| 1165 new ClassElementHandle(summaryResynthesizer, location), | |
| 1166 name, | |
| 1167 typeArguments); | |
| 1168 case ReferenceKind.typedef: | |
| 1169 return new FunctionTypeImpl.elementWithNameAndArgs( | |
| 1170 new FunctionTypeAliasElementHandle( | |
| 1171 summaryResynthesizer, location), | |
| 1172 name, | |
| 1173 typeArguments, | |
| 1174 typeArguments.isNotEmpty); | |
| 1175 default: | |
| 1176 // TODO(paulberry): figure out how to handle this case (which should | |
| 1177 // only occur in the event of erroneous code). | |
| 1178 throw new UnimplementedError(); | |
| 1179 } | |
| 1180 } | 1131 } |
| 1181 } | 1132 } |
| 1182 | 1133 |
| 1183 /** | 1134 /** |
| 1184 * Resynthesize a [FunctionTypeAliasElement] and place it in the | 1135 * Resynthesize a [FunctionTypeAliasElement] and place it in the |
| 1185 * [unitHolder]. | 1136 * [unitHolder]. |
| 1186 */ | 1137 */ |
| 1187 void buildTypedef(UnlinkedTypedef serializedTypedef) { | 1138 void buildTypedef(UnlinkedTypedef serializedTypedef) { |
| 1188 try { | 1139 try { |
| 1189 currentTypeParameters = | 1140 currentTypeParameters = |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1309 .resolveUri(referencedLibrarySource, uri); | 1260 .resolveUri(referencedLibrarySource, uri); |
| 1310 partUri = partSource.uri.toString(); | 1261 partUri = partSource.uri.toString(); |
| 1311 } else { | 1262 } else { |
| 1312 partUri = referencedLibraryUri; | 1263 partUri = referencedLibraryUri; |
| 1313 } | 1264 } |
| 1314 return new ElementLocationImpl.con3( | 1265 return new ElementLocationImpl.con3( |
| 1315 <String>[referencedLibraryUri, partUri, name]); | 1266 <String>[referencedLibraryUri, partUri, name]); |
| 1316 } | 1267 } |
| 1317 | 1268 |
| 1318 /** | 1269 /** |
| 1270 * Populate [referenceInfos] with the correct information for the current | |
| 1271 * compilation unit. | |
| 1272 */ | |
| 1273 void populateReferenceInfos() { | |
| 1274 int numLinkedReferences = linkedUnit.references.length; | |
| 1275 int numUnlinkedReferences = unlinkedUnit.references.length; | |
| 1276 referenceInfos = new List<_ReferenceInfo>(numLinkedReferences); | |
| 1277 for (int i = 0; i < numLinkedReferences; i++) { | |
| 1278 LinkedReference linkedReference = linkedUnit.references[i]; | |
| 1279 String name; | |
| 1280 if (i < numUnlinkedReferences) { | |
| 1281 name = unlinkedUnit.references[i].name; | |
| 1282 } else { | |
| 1283 name = linkedUnit.references[i].name; | |
| 1284 } | |
| 1285 ElementHandle element; | |
| 1286 DartType type; | |
| 1287 if (linkedReference.kind == ReferenceKind.unresolved) { | |
| 1288 type = summaryResynthesizer.typeProvider.undefinedType; | |
| 1289 } else if (name == 'dynamic') { | |
| 1290 type = summaryResynthesizer.typeProvider.dynamicType; | |
| 1291 } else if (name == 'void') { | |
| 1292 type = VoidTypeImpl.instance; | |
| 1293 } else { | |
| 1294 ElementLocation location; | |
| 1295 if (linkedReference.dependency != 0) { | |
| 1296 location = getReferencedLocation( | |
| 1297 linkedLibrary.dependencies[linkedReference.dependency], | |
| 1298 linkedReference.unit, | |
| 1299 name); | |
| 1300 } else { | |
| 1301 String referencedLibraryUri = librarySource.uri.toString(); | |
| 1302 String partUri; | |
| 1303 if (linkedReference.unit != 0) { | |
| 1304 String uri = unlinkedUnits[0].publicNamespace.parts[ | |
| 1305 linkedReference.unit - 1]; | |
| 1306 Source partSource = summaryResynthesizer.sourceFactory | |
| 1307 .resolveUri(librarySource, uri); | |
| 1308 partUri = partSource.uri.toString(); | |
| 1309 } else { | |
| 1310 partUri = referencedLibraryUri; | |
| 1311 } | |
| 1312 location = new ElementLocationImpl.con3( | |
| 1313 <String>[referencedLibraryUri, partUri, name]); | |
| 1314 } | |
| 1315 switch (linkedReference.kind) { | |
| 1316 case ReferenceKind.classOrEnum: | |
| 1317 element = new ClassElementHandle(summaryResynthesizer, location); | |
| 1318 break; | |
| 1319 case ReferenceKind.typedef: | |
| 1320 element = new FunctionTypeAliasElementHandle( | |
| 1321 summaryResynthesizer, location); | |
| 1322 break; | |
| 1323 default: | |
| 1324 // This is an element that doesn't (yet) need to be referred to | |
| 1325 // directly, so don't bother populating an element for it. | |
| 1326 // TODO(paulberry): add support for more kinds, as needed. | |
| 1327 break; | |
| 1328 } | |
| 1329 } | |
| 1330 referenceInfos[i] = new _ReferenceInfo( | |
| 1331 name, element, type, linkedReference.numTypeParameters); | |
| 1332 } | |
| 1333 } | |
| 1334 | |
| 1335 /** | |
| 1319 * Populate a [CompilationUnitElement] by deserializing all the elements | 1336 * Populate a [CompilationUnitElement] by deserializing all the elements |
| 1320 * contained in it. | 1337 * contained in it. |
| 1321 */ | 1338 */ |
| 1322 void populateUnit(CompilationUnitElementImpl unit, int unitNum) { | 1339 void populateUnit(CompilationUnitElementImpl unit, int unitNum) { |
| 1323 linkedUnit = linkedLibrary.units[unitNum]; | 1340 linkedUnit = linkedLibrary.units[unitNum]; |
| 1324 unlinkedUnit = unlinkedUnits[unitNum]; | 1341 unlinkedUnit = unlinkedUnits[unitNum]; |
| 1325 linkedTypeMap = <int, EntityRef>{}; | 1342 linkedTypeMap = <int, EntityRef>{}; |
| 1326 for (EntityRef t in linkedUnit.types) { | 1343 for (EntityRef t in linkedUnit.types) { |
| 1327 linkedTypeMap[t.slot] = t; | 1344 linkedTypeMap[t.slot] = t; |
| 1328 } | 1345 } |
| 1346 populateReferenceInfos(); | |
| 1329 unitHolder = new ElementHolder(); | 1347 unitHolder = new ElementHolder(); |
| 1330 unlinkedUnit.classes.forEach(buildClass); | 1348 unlinkedUnit.classes.forEach(buildClass); |
| 1331 unlinkedUnit.enums.forEach(buildEnum); | 1349 unlinkedUnit.enums.forEach(buildEnum); |
| 1332 unlinkedUnit.executables.forEach(buildExecutable); | 1350 unlinkedUnit.executables.forEach(buildExecutable); |
| 1333 unlinkedUnit.typedefs.forEach(buildTypedef); | 1351 unlinkedUnit.typedefs.forEach(buildTypedef); |
| 1334 unlinkedUnit.variables.forEach(buildVariable); | 1352 unlinkedUnit.variables.forEach(buildVariable); |
| 1335 String absoluteUri = unit.source.uri.toString(); | 1353 String absoluteUri = unit.source.uri.toString(); |
| 1336 unit.accessors = unitHolder.accessors; | 1354 unit.accessors = unitHolder.accessors; |
| 1337 unit.enums = unitHolder.enums; | 1355 unit.enums = unitHolder.enums; |
| 1338 unit.functions = unitHolder.functions; | 1356 unit.functions = unitHolder.functions; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1359 elementMap[function.name] = function; | 1377 elementMap[function.name] = function; |
| 1360 } | 1378 } |
| 1361 for (PropertyAccessorElementImpl accessor in unit.accessors) { | 1379 for (PropertyAccessorElementImpl accessor in unit.accessors) { |
| 1362 elementMap[accessor.identifier] = accessor; | 1380 elementMap[accessor.identifier] = accessor; |
| 1363 } | 1381 } |
| 1364 resummarizedElements[absoluteUri] = elementMap; | 1382 resummarizedElements[absoluteUri] = elementMap; |
| 1365 unitHolder = null; | 1383 unitHolder = null; |
| 1366 linkedUnit = null; | 1384 linkedUnit = null; |
| 1367 unlinkedUnit = null; | 1385 unlinkedUnit = null; |
| 1368 linkedTypeMap = null; | 1386 linkedTypeMap = null; |
| 1387 referenceInfos = null; | |
| 1369 } | 1388 } |
| 1370 } | 1389 } |
| 1390 | |
| 1391 /** | |
| 1392 * Data structure used during resynthesis to record all the information that is | |
| 1393 * known about how to reserialize a single entry in [LinkedUnit.references] | |
| 1394 * (and its associated entry in [UnlinkedUnit.references], if it exists). | |
| 1395 */ | |
| 1396 class _ReferenceInfo { | |
| 1397 /** | |
| 1398 * The name of the entity referred to by this reference. | |
| 1399 */ | |
| 1400 final String name; | |
| 1401 | |
| 1402 /** | |
| 1403 * The element referred to by this reference, or `null` if there is no | |
| 1404 * associated element (e.g. because it is a reference to an undefined | |
| 1405 * entity). | |
| 1406 */ | |
| 1407 final ElementHandle element; | |
| 1408 | |
| 1409 /** | |
| 1410 * If this reference refers to a non-generic type, the type it refers to. | |
| 1411 * Otherwise `null`. | |
| 1412 */ | |
| 1413 DartType type; | |
| 1414 | |
| 1415 /** | |
| 1416 * The number of type parameters accepted by the entity referred to by this | |
| 1417 * reference, or zero if it doesn't accept any type parameters. | |
| 1418 */ | |
| 1419 final int numTypeParameters; | |
| 1420 | |
| 1421 /** | |
| 1422 * Create a new [_ReferenceInfo] object referring to an element called [name] | |
| 1423 * via the element handle [elementHandle], and having [numTypeParameters] | |
| 1424 * type parameters. | |
| 1425 * | |
| 1426 * For the special types `dynamic` and `void`, [specialType] should point to | |
| 1427 * the type itself. Otherwise, pass `null` and the type will be computed | |
| 1428 * when appropriate. | |
| 1429 */ | |
| 1430 _ReferenceInfo( | |
| 1431 this.name, this.element, DartType specialType, this.numTypeParameters) { | |
| 1432 if (specialType != null) { | |
| 1433 type = specialType; | |
| 1434 } else if (numTypeParameters == 0) { | |
| 1435 // We can precompute the type because it doesn't depend on type | |
| 1436 // parameters. | |
| 1437 type = _buildType(null); | |
| 1438 } | |
| 1439 } | |
| 1440 | |
| 1441 /** | |
| 1442 * Build a [DartType] corresponding to the result of applying the entity | |
| 1443 * referred to by this [_ReferenceInfo] to some type parameters. The type | |
|
scheglov
2016/01/28 22:52:51
I guess the "apply" operation is commutative, but
Paul Berry
2016/01/28 23:05:56
Done.
| |
| 1444 * parameters are retrieved by calling [getTypeParameter]. | |
| 1445 * | |
| 1446 * If the entity referred to by this [_ReferenceInfo] is not a type, `null` | |
| 1447 * is returned. | |
| 1448 */ | |
| 1449 DartType buildType(DartType getTypeParameter(int i)) { | |
| 1450 DartType result = | |
| 1451 numTypeParameters == 0 ? type : _buildType(getTypeParameter); | |
| 1452 if (result == null) { | |
| 1453 // TODO(paulberry): figure out how to handle this case (which should | |
| 1454 // only occur in the event of erroneous code). | |
| 1455 throw new UnimplementedError(); | |
| 1456 } | |
| 1457 return result; | |
| 1458 } | |
| 1459 | |
| 1460 /** | |
| 1461 * If this reference refers to a type, build a [DartType] which instantiates | |
| 1462 * it with type arguments returned by [getTypeParameter]. Otherwise return | |
| 1463 * `null`. | |
| 1464 */ | |
| 1465 DartType _buildType(DartType getTypeParameter(int i)) { | |
|
scheglov
2016/01/28 22:52:51
Would it be better to name this function "getTypeA
Paul Berry
2016/01/28 23:05:56
Done.
| |
| 1466 List<DartType> typeArguments = const <DartType>[]; | |
| 1467 if (numTypeParameters != 0) { | |
| 1468 typeArguments = <DartType>[]; | |
| 1469 for (int i = 0; i < numTypeParameters; i++) { | |
| 1470 typeArguments.add(getTypeParameter(i)); | |
| 1471 } | |
| 1472 } | |
| 1473 ElementHandle element = this.element; // To allow type promotion | |
| 1474 if (element is ClassElementHandle) { | |
| 1475 return new InterfaceTypeImpl.elementWithNameAndArgs( | |
| 1476 element, name, typeArguments); | |
| 1477 } else if (element is FunctionTypeAliasElementHandle) { | |
| 1478 return new FunctionTypeImpl.elementWithNameAndArgs( | |
| 1479 element, name, typeArguments, typeArguments.isNotEmpty); | |
| 1480 } else { | |
| 1481 return null; | |
| 1482 } | |
| 1483 } | |
| 1484 } | |
| OLD | NEW |