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/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 * Indicates whether the summary should be resynthesized assuming strong mode | 55 * Indicates whether the summary should be resynthesized assuming strong mode |
| 56 * semantics. | 56 * semantics. |
| 57 */ | 57 */ |
| 58 final bool strongMode; | 58 final bool strongMode; |
| 59 | 59 |
| 60 /** | 60 /** |
| 61 * Map of compilation units resynthesized from summaries. The two map keys | 61 * Map of compilation units resynthesized from summaries. The two map keys |
| 62 * are the first two elements of the element's location (the library URI and | 62 * are the first two elements of the element's location (the library URI and |
| 63 * the compilation unit URI). | 63 * the compilation unit URI). |
| 64 */ | 64 */ |
| 65 final Map<String, Map<String, CompilationUnitElement>> _resynthesizedUnits = | 65 final Map<String, Map<String, CompilationUnitElementImpl>> |
| 66 <String, Map<String, CompilationUnitElement>>{}; | 66 _resynthesizedUnits = <String, Map<String, CompilationUnitElementImpl>>{}; |
| 67 | 67 |
| 68 /** | 68 /** |
| 69 * Map of top level elements resynthesized from summaries. The three map | 69 * Map of top level elements resynthesized from summaries. The three map |
| 70 * keys are the first three elements of the element's location (the library | 70 * keys are the first three elements of the element's location (the library |
| 71 * URI, the compilation unit URI, and the name of the top level declaration). | 71 * URI, the compilation unit URI, and the name of the top level declaration). |
| 72 */ | 72 */ |
| 73 final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements = | 73 final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements = |
| 74 <String, Map<String, Map<String, Element>>>{}; | 74 <String, Map<String, Map<String, Element>>>{}; |
| 75 | 75 |
| 76 /** | 76 /** |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 libraryMap = _resynthesizedUnits[libraryUri]; | 118 libraryMap = _resynthesizedUnits[libraryUri]; |
| 119 assert(libraryMap != null); | 119 assert(libraryMap != null); |
| 120 } | 120 } |
| 121 String unitUri = components[1]; | 121 String unitUri = components[1]; |
| 122 CompilationUnitElement element = libraryMap[unitUri]; | 122 CompilationUnitElement element = libraryMap[unitUri]; |
| 123 if (element == null) { | 123 if (element == null) { |
| 124 throw new Exception('Unit element not found in summary: $location'); | 124 throw new Exception('Unit element not found in summary: $location'); |
| 125 } | 125 } |
| 126 return element; | 126 return element; |
| 127 } else if (components.length == 3 || components.length == 4) { | 127 } else if (components.length == 3 || components.length == 4) { |
| 128 Map<String, Map<String, Element>> libraryMap = | 128 Map<String, CompilationUnitElement> libraryMap = |
| 129 _resynthesizedElements[libraryUri]; | 129 _resynthesizedUnits[libraryUri]; |
| 130 if (libraryMap == null) { | 130 if (libraryMap == null) { |
| 131 getLibraryElement(libraryUri); | 131 getLibraryElement(libraryUri); |
| 132 libraryMap = _resynthesizedElements[libraryUri]; | 132 libraryMap = _resynthesizedUnits[libraryUri]; |
| 133 assert(libraryMap != null); | 133 assert(libraryMap != null); |
| 134 } | 134 } |
| 135 Map<String, Element> compilationUnitElements = libraryMap[components[1]]; | 135 CompilationUnitElementImpl unitElement = libraryMap[components[1]]; |
| 136 Element element; | 136 Element element = unitElement?.getChildNotImpl(components[2]); |
|
Paul Berry
2016/05/19 11:27:30
I have an efficiency concern here. You're replaci
scheglov
2016/05/19 16:54:57
That's fair.
I think that the approach with `getCh
| |
| 137 if (compilationUnitElements != null) { | |
| 138 element = compilationUnitElements[components[2]]; | |
| 139 } | |
| 140 if (element != null && components.length == 4) { | 137 if (element != null && components.length == 4) { |
| 141 String name = components[3]; | 138 String name = components[3]; |
| 142 Element parentElement = element; | 139 Element parentElement = element; |
| 143 if (parentElement is ClassElement) { | 140 if (parentElement is ClassElement) { |
| 144 if (name.endsWith('?')) { | 141 if (name.endsWith('?')) { |
| 145 element = | 142 element = |
| 146 parentElement.getGetter(name.substring(0, name.length - 1)); | 143 parentElement.getGetter(name.substring(0, name.length - 1)); |
| 147 } else if (name.endsWith('=')) { | 144 } else if (name.endsWith('=')) { |
| 148 element = | 145 element = |
| 149 parentElement.getSetter(name.substring(0, name.length - 1)); | 146 parentElement.getSetter(name.substring(0, name.length - 1)); |
| (...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1018 /** | 1015 /** |
| 1019 * Classes which should have their supertype set to "object" once | 1016 * Classes which should have their supertype set to "object" once |
| 1020 * resynthesis is complete. Only used if [isCoreLibrary] is `true`. | 1017 * resynthesis is complete. Only used if [isCoreLibrary] is `true`. |
| 1021 */ | 1018 */ |
| 1022 List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[]; | 1019 List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[]; |
| 1023 | 1020 |
| 1024 /** | 1021 /** |
| 1025 * Map of compilation unit elements that have been resynthesized so far. The | 1022 * Map of compilation unit elements that have been resynthesized so far. The |
| 1026 * key is the URI of the compilation unit. | 1023 * key is the URI of the compilation unit. |
| 1027 */ | 1024 */ |
| 1028 final Map<String, CompilationUnitElement> resynthesizedUnits = | 1025 final Map<String, CompilationUnitElementImpl> resynthesizedUnits = |
| 1029 <String, CompilationUnitElement>{}; | 1026 <String, CompilationUnitElementImpl>{}; |
| 1030 | 1027 |
| 1031 /** | 1028 /** |
| 1032 * Map of top level elements that have been resynthesized so far. The first | 1029 * Map of top level elements that have been resynthesized so far. The first |
| 1033 * key is the URI of the compilation unit; the second is the name of the top | 1030 * key is the URI of the compilation unit; the second is the name of the top |
| 1034 * level element. | 1031 * level element. |
| 1035 */ | 1032 */ |
| 1036 final Map<String, Map<String, Element>> resynthesizedElements = | 1033 final Map<String, Map<String, Element>> resynthesizedElements = |
| 1037 <String, Map<String, Element>>{}; | 1034 <String, Map<String, Element>>{}; |
| 1038 | 1035 |
| 1039 /** | 1036 /** |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1195 serializedImport.combinators.map(buildCombinator).toList(); | 1192 serializedImport.combinators.map(buildCombinator).toList(); |
| 1196 return importElement; | 1193 return importElement; |
| 1197 } | 1194 } |
| 1198 | 1195 |
| 1199 /** | 1196 /** |
| 1200 * Main entry point. Resynthesize the [LibraryElement] and return it. | 1197 * Main entry point. Resynthesize the [LibraryElement] and return it. |
| 1201 */ | 1198 */ |
| 1202 LibraryElement buildLibrary() { | 1199 LibraryElement buildLibrary() { |
| 1203 // Create LibraryElementImpl. | 1200 // Create LibraryElementImpl. |
| 1204 bool hasName = unlinkedUnits[0].libraryName.isNotEmpty; | 1201 bool hasName = unlinkedUnits[0].libraryName.isNotEmpty; |
| 1205 library = new LibraryElementImpl( | 1202 library = new LibraryElementImpl.forSerialized( |
| 1206 summaryResynthesizer.context, | 1203 summaryResynthesizer.context, |
| 1207 unlinkedUnits[0].libraryName, | 1204 unlinkedUnits[0].libraryName, |
| 1208 hasName ? unlinkedUnits[0].libraryNameOffset : -1, | 1205 hasName ? unlinkedUnits[0].libraryNameOffset : -1, |
| 1209 unlinkedUnits[0].libraryNameLength); | 1206 unlinkedUnits[0].libraryNameLength, |
| 1207 new _LibraryResynthesizerContext(this), | |
| 1208 unlinkedUnits[0]); | |
| 1210 // Create the defining unit. | 1209 // Create the defining unit. |
| 1211 _UnitResynthesizer definingUnitResynthesizer = | 1210 _UnitResynthesizer definingUnitResynthesizer = |
| 1212 createUnitResynthesizer(0, librarySource, null); | 1211 createUnitResynthesizer(0, librarySource, null); |
| 1213 CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit; | 1212 CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit; |
| 1214 definingUnitResynthesizer.buildDocumentation( | |
| 1215 library, unlinkedUnits[0].libraryDocumentationComment); | |
| 1216 definingUnitResynthesizer.buildAnnotations( | |
| 1217 library, unlinkedUnits[0].libraryAnnotations); | |
| 1218 library.definingCompilationUnit = definingUnit; | 1213 library.definingCompilationUnit = definingUnit; |
| 1219 definingUnit.source = librarySource; | 1214 definingUnit.source = librarySource; |
| 1220 definingUnit.librarySource = librarySource; | 1215 definingUnit.librarySource = librarySource; |
| 1221 // Create parts. | 1216 // Create parts. |
| 1222 List<_UnitResynthesizer> partResynthesizers = <_UnitResynthesizer>[]; | 1217 List<_UnitResynthesizer> partResynthesizers = <_UnitResynthesizer>[]; |
| 1223 UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0]; | 1218 UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0]; |
| 1224 assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 == | 1219 assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 == |
| 1225 linkedLibrary.units.length); | 1220 linkedLibrary.units.length); |
| 1226 for (int i = 1; i < linkedLibrary.units.length; i++) { | 1221 for (int i = 1; i < linkedLibrary.units.length; i++) { |
| 1227 _UnitResynthesizer partResynthesizer = buildPart( | 1222 _UnitResynthesizer partResynthesizer = buildPart( |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1251 definingUnitResynthesizer, | 1246 definingUnitResynthesizer, |
| 1252 unlinkedDefiningUnit.publicNamespace.exports[i], | 1247 unlinkedDefiningUnit.publicNamespace.exports[i], |
| 1253 unlinkedDefiningUnit.exports[i])); | 1248 unlinkedDefiningUnit.exports[i])); |
| 1254 } | 1249 } |
| 1255 library.exports = exports; | 1250 library.exports = exports; |
| 1256 // Populate units. | 1251 // Populate units. |
| 1257 populateUnit(definingUnitResynthesizer); | 1252 populateUnit(definingUnitResynthesizer); |
| 1258 for (_UnitResynthesizer partResynthesizer in partResynthesizers) { | 1253 for (_UnitResynthesizer partResynthesizer in partResynthesizers) { |
| 1259 populateUnit(partResynthesizer); | 1254 populateUnit(partResynthesizer); |
| 1260 } | 1255 } |
| 1261 BuildLibraryElementUtils.patchTopLevelAccessors(library); | |
| 1262 // Update delayed Object class references. | 1256 // Update delayed Object class references. |
| 1263 if (isCoreLibrary) { | 1257 if (isCoreLibrary) { |
| 1264 ClassElement objectElement = library.getType('Object'); | 1258 ClassElement objectElement = library.getType('Object'); |
| 1265 assert(objectElement != null); | 1259 assert(objectElement != null); |
| 1266 for (ClassElementImpl classElement in delayedObjectSubclasses) { | 1260 for (ClassElementImpl classElement in delayedObjectSubclasses) { |
| 1267 classElement.supertype = objectElement.type; | 1261 classElement.supertype = objectElement.type; |
| 1268 } | 1262 } |
| 1269 } | 1263 } |
| 1270 // Compute namespaces. | |
| 1271 library.publicNamespace = | |
| 1272 new NamespaceBuilder().createPublicNamespaceForLibrary(library); | |
| 1273 library.exportNamespace = buildExportNamespace( | |
| 1274 library.publicNamespace, linkedLibrary.exportNames); | |
| 1275 // Find the entry point. Note: we can't use element.isEntryPoint because | |
| 1276 // that will trigger resynthesis of exported libraries. | |
| 1277 Element entryPoint = | |
| 1278 library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME); | |
| 1279 if (entryPoint is FunctionElement) { | |
| 1280 library.entryPoint = entryPoint; | |
| 1281 } | |
| 1282 // Create the synthetic element for `loadLibrary`. | 1264 // Create the synthetic element for `loadLibrary`. |
| 1283 // Until the client received dart:core and dart:async, we cannot do this, | 1265 // Until the client received dart:core and dart:async, we cannot do this, |
| 1284 // because the TypeProvider is not fully initialized. So, it is up to the | 1266 // because the TypeProvider is not fully initialized. So, it is up to the |
| 1285 // Dart SDK client to initialize TypeProvider and finish the dart:core and | 1267 // Dart SDK client to initialize TypeProvider and finish the dart:core and |
| 1286 // dart:async libraries creation. | 1268 // dart:async libraries creation. |
| 1287 if (library.name != 'dart.core' && library.name != 'dart.async') { | 1269 if (library.name != 'dart.core' && library.name != 'dart.async') { |
| 1288 library.createLoadLibraryFunction(summaryResynthesizer.typeProvider); | 1270 library.createLoadLibraryFunction(summaryResynthesizer.typeProvider); |
| 1289 } | 1271 } |
| 1290 // Done. | 1272 // Done. |
| 1291 return library; | 1273 return library; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1363 */ | 1345 */ |
| 1364 void populateUnit(_UnitResynthesizer unitResynthesized) { | 1346 void populateUnit(_UnitResynthesizer unitResynthesized) { |
| 1365 // TODO(scheglov) | 1347 // TODO(scheglov) |
| 1366 unitResynthesized.populateUnit(); | 1348 unitResynthesized.populateUnit(); |
| 1367 String absoluteUri = unitResynthesized.unit.source.uri.toString(); | 1349 String absoluteUri = unitResynthesized.unit.source.uri.toString(); |
| 1368 resynthesizedUnits[absoluteUri] = unitResynthesized.unit; | 1350 resynthesizedUnits[absoluteUri] = unitResynthesized.unit; |
| 1369 resynthesizedElements[absoluteUri] = unitResynthesized.elementMap; | 1351 resynthesizedElements[absoluteUri] = unitResynthesized.elementMap; |
| 1370 } | 1352 } |
| 1371 } | 1353 } |
| 1372 | 1354 |
| 1355 class _LibraryResynthesizerContext implements LibraryResynthesizerContext { | |
|
Paul Berry
2016/05/19 11:27:30
Nit: a doc comment would be helpful here.
scheglov
2016/05/19 16:54:57
Done.
| |
| 1356 final _LibraryResynthesizer resynthesizer; | |
| 1357 | |
| 1358 _LibraryResynthesizerContext(this.resynthesizer); | |
| 1359 | |
| 1360 @override | |
| 1361 Namespace buildExportNamespace() { | |
| 1362 LibraryElementImpl library = resynthesizer.library; | |
| 1363 return resynthesizer.buildExportNamespace( | |
| 1364 library.publicNamespace, resynthesizer.linkedLibrary.exportNames); | |
| 1365 } | |
| 1366 | |
| 1367 @override | |
| 1368 Namespace buildPublicNamespace() { | |
| 1369 LibraryElementImpl library = resynthesizer.library; | |
| 1370 return new NamespaceBuilder().createPublicNamespaceForLibrary(library); | |
| 1371 } | |
| 1372 | |
| 1373 @override | |
| 1374 FunctionElement findEntryPoint() { | |
| 1375 LibraryElementImpl library = resynthesizer.library; | |
| 1376 Element entryPoint = | |
| 1377 library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME); | |
| 1378 if (entryPoint is FunctionElement) { | |
| 1379 return entryPoint; | |
| 1380 } | |
| 1381 return null; | |
| 1382 } | |
| 1383 | |
| 1384 @override | |
| 1385 void patchTopLevelAccessors() { | |
| 1386 LibraryElementImpl library = resynthesizer.library; | |
| 1387 BuildLibraryElementUtils.patchTopLevelAccessors(library); | |
| 1388 } | |
| 1389 } | |
| 1390 | |
| 1373 /** | 1391 /** |
| 1374 * Data structure used during resynthesis to record all the information that is | 1392 * Data structure used during resynthesis to record all the information that is |
| 1375 * known about how to resynthesize a single entry in [LinkedUnit.references] | 1393 * known about how to resynthesize a single entry in [LinkedUnit.references] |
| 1376 * (and its associated entry in [UnlinkedUnit.references], if it exists). | 1394 * (and its associated entry in [UnlinkedUnit.references], if it exists). |
| 1377 */ | 1395 */ |
| 1378 class _ReferenceInfo { | 1396 class _ReferenceInfo { |
| 1379 /** | 1397 /** |
| 1380 * The [_LibraryResynthesizer] which is being used to obtain summaries. | 1398 * The [_LibraryResynthesizer] which is being used to obtain summaries. |
| 1381 */ | 1399 */ |
| 1382 final _LibraryResynthesizer libraryResynthesizer; | 1400 final _LibraryResynthesizer libraryResynthesizer; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1561 ElementAnnotationImpl buildAnnotation(UnlinkedConst uc) { | 1579 ElementAnnotationImpl buildAnnotation(UnlinkedConst uc) { |
| 1562 return _unitResynthesizer.buildAnnotation(uc); | 1580 return _unitResynthesizer.buildAnnotation(uc); |
| 1563 } | 1581 } |
| 1564 | 1582 |
| 1565 @override | 1583 @override |
| 1566 Expression buildExpression(UnlinkedConst uc) { | 1584 Expression buildExpression(UnlinkedConst uc) { |
| 1567 return _unitResynthesizer._buildConstExpression(uc); | 1585 return _unitResynthesizer._buildConstExpression(uc); |
| 1568 } | 1586 } |
| 1569 | 1587 |
| 1570 @override | 1588 @override |
| 1589 UnitExplicitTopLevelAccessors buildTopLevelAccessors() { | |
| 1590 return _unitResynthesizer.buildUnitExplicitTopLevelAccessors(); | |
| 1591 } | |
| 1592 | |
| 1593 @override | |
| 1594 UnitExplicitTopLevelVariables buildTopLevelVariables() { | |
| 1595 return _unitResynthesizer.buildUnitExplicitTopLevelVariables(); | |
| 1596 } | |
| 1597 | |
| 1598 @override | |
| 1571 DartType resolveTypeRef( | 1599 DartType resolveTypeRef( |
| 1572 EntityRef type, TypeParameterizedElementMixin typeParameterContext, | 1600 EntityRef type, TypeParameterizedElementMixin typeParameterContext, |
| 1573 {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) { | 1601 {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) { |
| 1574 return _unitResynthesizer.buildType(type, typeParameterContext, | 1602 return _unitResynthesizer.buildType(type, typeParameterContext, |
| 1575 defaultVoid: defaultVoid, | 1603 defaultVoid: defaultVoid, |
| 1576 instantiateToBoundsAllowed: instantiateToBoundsAllowed); | 1604 instantiateToBoundsAllowed: instantiateToBoundsAllowed); |
| 1577 } | 1605 } |
| 1578 } | 1606 } |
| 1579 | 1607 |
| 1580 /** | 1608 /** |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2067 } else { | 2095 } else { |
| 2068 MethodElementImpl executableElement = | 2096 MethodElementImpl executableElement = |
| 2069 new MethodElementImpl.forSerialized( | 2097 new MethodElementImpl.forSerialized( |
| 2070 serializedExecutable, enclosingElement); | 2098 serializedExecutable, enclosingElement); |
| 2071 buildExecutableCommonParts(executableElement, serializedExecutable); | 2099 buildExecutableCommonParts(executableElement, serializedExecutable); |
| 2072 holder.addMethod(executableElement); | 2100 holder.addMethod(executableElement); |
| 2073 } | 2101 } |
| 2074 break; | 2102 break; |
| 2075 case UnlinkedExecutableKind.getter: | 2103 case UnlinkedExecutableKind.getter: |
| 2076 case UnlinkedExecutableKind.setter: | 2104 case UnlinkedExecutableKind.setter: |
| 2105 // Top-level accessors are created lazily. | |
| 2106 if (isTopLevel) { | |
| 2107 break; | |
| 2108 } | |
| 2109 // Class member accessors. | |
| 2077 PropertyAccessorElementImpl executableElement = | 2110 PropertyAccessorElementImpl executableElement = |
| 2078 new PropertyAccessorElementImpl.forSerialized( | 2111 new PropertyAccessorElementImpl.forSerialized( |
| 2079 serializedExecutable, enclosingElement); | 2112 serializedExecutable, enclosingElement); |
| 2080 buildExecutableCommonParts(executableElement, serializedExecutable); | 2113 buildExecutableCommonParts(executableElement, serializedExecutable); |
| 2081 DartType type; | 2114 DartType type; |
| 2082 if (kind == UnlinkedExecutableKind.getter) { | 2115 if (kind == UnlinkedExecutableKind.getter) { |
| 2083 type = executableElement.returnType; | 2116 type = executableElement.returnType; |
| 2084 } else { | 2117 } else { |
| 2085 type = executableElement.parameters[0].type; | 2118 type = executableElement.parameters[0].type; |
| 2086 } | 2119 } |
| 2087 holder.addAccessor(executableElement); | 2120 holder.addAccessor(executableElement); |
| 2088 PropertyInducingElementImpl implicitVariable; | 2121 FieldElementImpl field = buildImplicitField(name, type, kind, holder); |
| 2089 if (isTopLevel) { | 2122 field.static = serializedExecutable.isStatic; |
| 2090 implicitVariable = buildImplicitTopLevelVariable(name, kind, holder); | 2123 executableElement.variable = field; |
| 2124 if (kind == UnlinkedExecutableKind.getter) { | |
| 2125 field.getter = executableElement; | |
| 2091 } else { | 2126 } else { |
| 2092 FieldElementImpl field = buildImplicitField(name, type, kind, holder); | 2127 field.setter = executableElement; |
| 2093 field.static = serializedExecutable.isStatic; | |
| 2094 implicitVariable = field; | |
| 2095 } | |
| 2096 executableElement.variable = implicitVariable; | |
| 2097 if (kind == UnlinkedExecutableKind.getter) { | |
| 2098 implicitVariable.getter = executableElement; | |
| 2099 } else { | |
| 2100 implicitVariable.setter = executableElement; | |
| 2101 } | 2128 } |
| 2102 break; | 2129 break; |
| 2103 default: | 2130 default: |
| 2104 // The only other executable type is a constructor, and that is handled | 2131 // The only other executable type is a constructor, and that is handled |
| 2105 // separately (in [buildConstructor]. So this code should be | 2132 // separately (in [buildConstructor]. So this code should be |
| 2106 // unreachable. | 2133 // unreachable. |
| 2107 assert(false); | 2134 assert(false); |
| 2108 } | 2135 } |
| 2109 } | 2136 } |
| 2110 | 2137 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2147 | 2174 |
| 2148 /** | 2175 /** |
| 2149 * Build the implicit getter and setter associated with [element], and place | 2176 * Build the implicit getter and setter associated with [element], and place |
| 2150 * them in [holder]. | 2177 * them in [holder]. |
| 2151 */ | 2178 */ |
| 2152 void buildImplicitAccessors( | 2179 void buildImplicitAccessors( |
| 2153 PropertyInducingElementImpl element, ElementHolder holder) { | 2180 PropertyInducingElementImpl element, ElementHolder holder) { |
| 2154 String name = element.name; | 2181 String name = element.name; |
| 2155 DartType type = element.type; | 2182 DartType type = element.type; |
| 2156 PropertyAccessorElementImpl getter = | 2183 PropertyAccessorElementImpl getter = |
| 2157 new PropertyAccessorElementImpl(name, element.nameOffset); | 2184 buildImplicitGetter(element, name, type); |
| 2158 getter.getter = true; | 2185 holder?.addAccessor(getter); |
| 2159 getter.static = element.isStatic; | |
| 2160 getter.synthetic = true; | |
| 2161 getter.returnType = type; | |
| 2162 getter.type = new FunctionTypeImpl(getter); | |
| 2163 getter.variable = element; | |
| 2164 getter.hasImplicitReturnType = element.hasImplicitType; | |
| 2165 holder.addAccessor(getter); | |
| 2166 element.getter = getter; | |
| 2167 if (!(element.isConst || element.isFinal)) { | 2186 if (!(element.isConst || element.isFinal)) { |
| 2168 PropertyAccessorElementImpl setter = | 2187 PropertyAccessorElementImpl setter = |
| 2169 new PropertyAccessorElementImpl(name, element.nameOffset); | 2188 buildImplicitSetter(element, name, type); |
| 2170 setter.setter = true; | 2189 holder?.addAccessor(setter); |
| 2171 setter.static = element.isStatic; | |
| 2172 setter.synthetic = true; | |
| 2173 setter.parameters = <ParameterElement>[ | |
| 2174 new ParameterElementImpl('_$name', element.nameOffset) | |
| 2175 ..synthetic = true | |
| 2176 ..type = type | |
| 2177 ..parameterKind = ParameterKind.REQUIRED | |
| 2178 ]; | |
| 2179 setter.returnType = VoidTypeImpl.instance; | |
| 2180 setter.type = new FunctionTypeImpl(setter); | |
| 2181 setter.variable = element; | |
| 2182 holder.addAccessor(setter); | |
| 2183 element.setter = setter; | |
| 2184 } | 2190 } |
| 2185 } | 2191 } |
| 2186 | 2192 |
| 2187 /** | 2193 /** |
| 2188 * Build the implicit field associated with a getter or setter, and place it | 2194 * Build the implicit field associated with a getter or setter, and place it |
| 2189 * in [holder]. | 2195 * in [holder]. |
| 2190 */ | 2196 */ |
| 2191 FieldElementImpl buildImplicitField(String name, DartType type, | 2197 FieldElementImpl buildImplicitField(String name, DartType type, |
| 2192 UnlinkedExecutableKind kind, ElementHolder holder) { | 2198 UnlinkedExecutableKind kind, ElementHolder holder) { |
| 2193 FieldElementImpl field = holder.getField(name); | 2199 FieldElementImpl field = holder.getField(name); |
| 2194 if (field == null) { | 2200 if (field == null) { |
| 2195 field = new FieldElementImpl(name, -1); | 2201 field = new FieldElementImpl(name, -1); |
| 2196 field.synthetic = true; | 2202 field.synthetic = true; |
| 2197 field.final2 = kind == UnlinkedExecutableKind.getter; | 2203 field.final2 = kind == UnlinkedExecutableKind.getter; |
| 2198 field.type = type; | 2204 field.type = type; |
| 2199 holder.addField(field); | 2205 holder.addField(field); |
| 2200 return field; | 2206 return field; |
| 2201 } else { | 2207 } else { |
| 2202 // TODO(paulberry): what if the getter and setter have a type mismatch? | 2208 // TODO(paulberry): what if the getter and setter have a type mismatch? |
| 2203 field.final2 = false; | 2209 field.final2 = false; |
| 2204 return field; | 2210 return field; |
| 2205 } | 2211 } |
| 2206 } | 2212 } |
| 2207 | 2213 |
| 2208 /** | 2214 PropertyAccessorElementImpl buildImplicitGetter( |
|
Paul Berry
2016/05/19 11:27:30
Please add a doc comment here.
scheglov
2016/05/19 16:54:57
Done.
| |
| 2209 * Build the implicit top level variable associated with a getter or setter, | 2215 PropertyInducingElementImpl element, String name, DartType type) { |
| 2210 * and place it in [holder]. | 2216 PropertyAccessorElementImpl getter = |
| 2211 */ | 2217 new PropertyAccessorElementImpl(name, element.nameOffset); |
| 2212 PropertyInducingElementImpl buildImplicitTopLevelVariable( | 2218 getter.getter = true; |
| 2213 String name, UnlinkedExecutableKind kind, ElementHolder holder) { | 2219 getter.static = element.isStatic; |
| 2214 TopLevelVariableElementImpl variable = holder.getTopLevelVariable(name); | 2220 getter.synthetic = true; |
| 2215 if (variable == null) { | 2221 getter.returnType = type; |
| 2216 variable = new TopLevelVariableElementImpl(name, -1); | 2222 getter.type = new FunctionTypeImpl(getter); |
| 2217 variable.synthetic = true; | 2223 getter.variable = element; |
| 2218 variable.final2 = kind == UnlinkedExecutableKind.getter; | 2224 getter.hasImplicitReturnType = element.hasImplicitType; |
| 2219 holder.addTopLevelVariable(variable); | 2225 element.getter = getter; |
| 2220 return variable; | 2226 return getter; |
| 2221 } else { | 2227 } |
| 2222 // TODO(paulberry): what if the getter and setter have a type mismatch? | 2228 |
| 2223 variable.final2 = false; | 2229 PropertyAccessorElementImpl buildImplicitSetter( |
|
Paul Berry
2016/05/19 11:27:30
Ditto.
scheglov
2016/05/19 16:54:57
Done.
| |
| 2224 return variable; | 2230 PropertyInducingElementImpl element, String name, DartType type) { |
| 2225 } | 2231 PropertyAccessorElementImpl setter = |
| 2232 new PropertyAccessorElementImpl(name, element.nameOffset); | |
| 2233 setter.setter = true; | |
| 2234 setter.static = element.isStatic; | |
| 2235 setter.synthetic = true; | |
| 2236 setter.parameters = <ParameterElement>[ | |
| 2237 new ParameterElementImpl('_$name', element.nameOffset) | |
| 2238 ..synthetic = true | |
| 2239 ..type = type | |
| 2240 ..parameterKind = ParameterKind.REQUIRED | |
| 2241 ]; | |
| 2242 setter.returnType = VoidTypeImpl.instance; | |
| 2243 setter.type = new FunctionTypeImpl(setter); | |
| 2244 setter.variable = element; | |
| 2245 element.setter = setter; | |
| 2246 return setter; | |
| 2226 } | 2247 } |
| 2227 | 2248 |
| 2228 /** | 2249 /** |
| 2229 * Build the appropriate [DartType] object corresponding to a slot id in the | 2250 * Build the appropriate [DartType] object corresponding to a slot id in the |
| 2230 * [LinkedUnit.types] table. | 2251 * [LinkedUnit.types] table. |
| 2231 */ | 2252 */ |
| 2232 DartType buildLinkedType( | 2253 DartType buildLinkedType( |
| 2233 int slot, TypeParameterizedElementMixin typeParameterContext) { | 2254 int slot, TypeParameterizedElementMixin typeParameterContext) { |
| 2234 if (slot == 0) { | 2255 if (slot == 0) { |
| 2235 // A slot id of 0 means there is no [DartType] object to build. | 2256 // A slot id of 0 means there is no [DartType] object to build. |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2397 serializedParameter.visibleLength); | 2418 serializedParameter.visibleLength); |
| 2398 } | 2419 } |
| 2399 } | 2420 } |
| 2400 return parameterElement; | 2421 return parameterElement; |
| 2401 } | 2422 } |
| 2402 | 2423 |
| 2403 /** | 2424 /** |
| 2404 * Handle the parts that are common to top level variables and fields. | 2425 * Handle the parts that are common to top level variables and fields. |
| 2405 */ | 2426 */ |
| 2406 void buildPropertyIntroducingElementCommonParts( | 2427 void buildPropertyIntroducingElementCommonParts( |
| 2407 PropertyInducingElementImpl element, | 2428 PropertyInducingElementImpl element, UnlinkedVariable serializedVariable, |
| 2408 UnlinkedVariable serializedVariable) { | 2429 {bool isLazilyResynthesized: false}) { |
| 2409 buildVariableCommonParts(element, serializedVariable); | 2430 buildVariableCommonParts(element, serializedVariable, |
| 2431 isLazilyResynthesized: isLazilyResynthesized); | |
| 2410 element.propagatedType = buildLinkedType( | 2432 element.propagatedType = buildLinkedType( |
| 2411 serializedVariable.propagatedTypeSlot, | 2433 serializedVariable.propagatedTypeSlot, |
| 2412 _currentTypeParameterizedElement); | 2434 _currentTypeParameterizedElement); |
| 2413 } | 2435 } |
| 2414 | 2436 |
| 2415 /** | 2437 /** |
| 2416 * Build a [DartType] object based on a [EntityRef]. This [DartType] | 2438 * Build a [DartType] object based on a [EntityRef]. This [DartType] |
| 2417 * may refer to elements in other libraries than the library being | 2439 * may refer to elements in other libraries than the library being |
| 2418 * deserialized, so handles are used to avoid having to deserialize other | 2440 * deserialized, so handles are used to avoid having to deserialize other |
| 2419 * libraries in the process. | 2441 * libraries in the process. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2510 List<UnlinkedTypeParam> serializedTypeParameters) { | 2532 List<UnlinkedTypeParam> serializedTypeParameters) { |
| 2511 List<TypeParameterElement> typeParameters = | 2533 List<TypeParameterElement> typeParameters = |
| 2512 serializedTypeParameters.map(buildTypeParameter).toList(); | 2534 serializedTypeParameters.map(buildTypeParameter).toList(); |
| 2513 currentTypeParameters.add(typeParameters); | 2535 currentTypeParameters.add(typeParameters); |
| 2514 for (int i = 0; i < serializedTypeParameters.length; i++) { | 2536 for (int i = 0; i < serializedTypeParameters.length; i++) { |
| 2515 finishTypeParameter(serializedTypeParameters[i], typeParameters[i]); | 2537 finishTypeParameter(serializedTypeParameters[i], typeParameters[i]); |
| 2516 } | 2538 } |
| 2517 return typeParameters; | 2539 return typeParameters; |
| 2518 } | 2540 } |
| 2519 | 2541 |
| 2542 UnitExplicitTopLevelAccessors buildUnitExplicitTopLevelAccessors() { | |
| 2543 HashMap<String, TopLevelVariableElementImpl> implicitVariables = | |
| 2544 new HashMap<String, TopLevelVariableElementImpl>(); | |
| 2545 UnitExplicitTopLevelAccessors accessorsData = | |
| 2546 new UnitExplicitTopLevelAccessors(); | |
| 2547 for (UnlinkedExecutable unlinkedExecutable in unlinkedUnit.executables) { | |
| 2548 UnlinkedExecutableKind kind = unlinkedExecutable.kind; | |
| 2549 if (kind == UnlinkedExecutableKind.getter || | |
| 2550 kind == UnlinkedExecutableKind.setter) { | |
| 2551 // name | |
| 2552 String name = unlinkedExecutable.name; | |
| 2553 if (kind == UnlinkedExecutableKind.setter) { | |
| 2554 assert(name.endsWith('=')); | |
| 2555 name = name.substring(0, name.length - 1); | |
| 2556 } | |
| 2557 // create | |
| 2558 PropertyAccessorElementImpl accessor = | |
| 2559 new PropertyAccessorElementImpl.forSerialized( | |
| 2560 unlinkedExecutable, unit); | |
| 2561 accessorsData.accessors.add(accessor); | |
| 2562 buildExecutableCommonParts(accessor, unlinkedExecutable); | |
| 2563 // implicit variable | |
| 2564 TopLevelVariableElementImpl variable = implicitVariables[name]; | |
| 2565 if (variable == null) { | |
| 2566 variable = new TopLevelVariableElementImpl(name, -1); | |
| 2567 implicitVariables[name] = variable; | |
| 2568 accessorsData.implicitVariables.add(variable); | |
| 2569 variable.synthetic = true; | |
| 2570 variable.final2 = kind == UnlinkedExecutableKind.getter; | |
| 2571 } else { | |
| 2572 variable.final2 = false; | |
| 2573 } | |
| 2574 accessor.variable = variable; | |
| 2575 // link | |
| 2576 if (kind == UnlinkedExecutableKind.getter) { | |
| 2577 variable.getter = accessor; | |
| 2578 } else { | |
| 2579 variable.setter = accessor; | |
| 2580 } | |
| 2581 } | |
| 2582 } | |
| 2583 return accessorsData; | |
| 2584 } | |
| 2585 | |
| 2586 UnitExplicitTopLevelVariables buildUnitExplicitTopLevelVariables() { | |
| 2587 UnitExplicitTopLevelVariables variablesData = | |
| 2588 new UnitExplicitTopLevelVariables(); | |
| 2589 for (UnlinkedVariable unlinkedVariable in unlinkedUnit.variables) { | |
| 2590 TopLevelVariableElementImpl element; | |
| 2591 if (unlinkedVariable.constExpr != null && unlinkedVariable.isConst) { | |
| 2592 ConstTopLevelVariableElementImpl constElement = | |
| 2593 new ConstTopLevelVariableElementImpl.forSerialized( | |
| 2594 unlinkedVariable, unit); | |
| 2595 element = constElement; | |
| 2596 constElement.constantInitializer = | |
| 2597 _buildConstExpression(unlinkedVariable.constExpr); | |
| 2598 } else { | |
| 2599 element = new TopLevelVariableElementImpl.forSerialized( | |
| 2600 unlinkedVariable, unit); | |
| 2601 } | |
| 2602 buildPropertyIntroducingElementCommonParts(element, unlinkedVariable, | |
| 2603 isLazilyResynthesized: true); | |
| 2604 variablesData.variables.add(element); | |
| 2605 // implicit accessors | |
| 2606 String name = element.name; | |
| 2607 DartType type = element.type; | |
| 2608 variablesData.implicitAccessors | |
| 2609 .add(buildImplicitGetter(element, name, type)); | |
| 2610 if (!(element.isConst || element.isFinal)) { | |
| 2611 variablesData.implicitAccessors | |
| 2612 .add(buildImplicitSetter(element, name, type)); | |
| 2613 } | |
| 2614 } | |
| 2615 return variablesData; | |
| 2616 } | |
| 2617 | |
| 2520 /** | 2618 /** |
| 2521 * Resynthesize a [TopLevelVariableElement] or [FieldElement]. | 2619 * Resynthesize a [TopLevelVariableElement] or [FieldElement]. |
| 2522 */ | 2620 */ |
| 2523 void buildVariable(UnlinkedVariable serializedVariable, | 2621 void buildVariable(UnlinkedVariable serializedVariable, |
| 2524 [ElementHolder holder]) { | 2622 [ElementHolder holder]) { |
| 2525 if (holder == null) { | 2623 if (holder == null) { |
| 2526 TopLevelVariableElementImpl element; | 2624 throw new UnimplementedError('Must be lazy'); |
| 2527 if (serializedVariable.constExpr != null && serializedVariable.isConst) { | |
| 2528 ConstTopLevelVariableElementImpl constElement = | |
| 2529 new ConstTopLevelVariableElementImpl( | |
| 2530 serializedVariable.name, serializedVariable.nameOffset); | |
| 2531 element = constElement; | |
| 2532 constElement.constantInitializer = | |
| 2533 _buildConstExpression(serializedVariable.constExpr); | |
| 2534 } else { | |
| 2535 element = new TopLevelVariableElementImpl( | |
| 2536 serializedVariable.name, serializedVariable.nameOffset); | |
| 2537 } | |
| 2538 buildPropertyIntroducingElementCommonParts(element, serializedVariable); | |
| 2539 unitHolder.addTopLevelVariable(element); | |
| 2540 buildImplicitAccessors(element, unitHolder); | |
| 2541 } else { | 2625 } else { |
| 2542 FieldElementImpl element; | 2626 FieldElementImpl element; |
| 2543 if (serializedVariable.constExpr != null && | 2627 if (serializedVariable.constExpr != null && |
| 2544 (serializedVariable.isConst || | 2628 (serializedVariable.isConst || |
| 2545 serializedVariable.isFinal && !serializedVariable.isStatic)) { | 2629 serializedVariable.isFinal && !serializedVariable.isStatic)) { |
| 2546 ConstFieldElementImpl constElement = new ConstFieldElementImpl( | 2630 ConstFieldElementImpl constElement = new ConstFieldElementImpl( |
| 2547 serializedVariable.name, serializedVariable.nameOffset); | 2631 serializedVariable.name, serializedVariable.nameOffset); |
| 2548 element = constElement; | 2632 element = constElement; |
| 2549 constElement.constantInitializer = | 2633 constElement.constantInitializer = |
| 2550 _buildConstExpression(serializedVariable.constExpr); | 2634 _buildConstExpression(serializedVariable.constExpr); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2762 | 2846 |
| 2763 /** | 2847 /** |
| 2764 * Populate a [CompilationUnitElement] by deserializing all the elements | 2848 * Populate a [CompilationUnitElement] by deserializing all the elements |
| 2765 * contained in it. | 2849 * contained in it. |
| 2766 */ | 2850 */ |
| 2767 void populateUnit() { | 2851 void populateUnit() { |
| 2768 unlinkedUnit.classes.forEach(buildClass); | 2852 unlinkedUnit.classes.forEach(buildClass); |
| 2769 unlinkedUnit.enums.forEach(buildEnum); | 2853 unlinkedUnit.enums.forEach(buildEnum); |
| 2770 unlinkedUnit.executables.forEach((e) => buildExecutable(e, unit)); | 2854 unlinkedUnit.executables.forEach((e) => buildExecutable(e, unit)); |
| 2771 unlinkedUnit.typedefs.forEach(buildTypedef); | 2855 unlinkedUnit.typedefs.forEach(buildTypedef); |
| 2772 unlinkedUnit.variables.forEach(buildVariable); | |
| 2773 unit.accessors = unitHolder.accessors; | |
| 2774 unit.enums = unitHolder.enums; | 2856 unit.enums = unitHolder.enums; |
| 2775 unit.functions = unitHolder.functions; | 2857 unit.functions = unitHolder.functions; |
| 2776 List<FunctionTypeAliasElement> typeAliases = unitHolder.typeAliases; | 2858 List<FunctionTypeAliasElement> typeAliases = unitHolder.typeAliases; |
| 2777 for (FunctionTypeAliasElementImpl typeAlias in typeAliases) { | 2859 for (FunctionTypeAliasElementImpl typeAlias in typeAliases) { |
| 2778 if (typeAlias.isSynthetic) { | 2860 if (typeAlias.isSynthetic) { |
| 2779 typeAlias.enclosingElement = unit; | 2861 typeAlias.enclosingElement = unit; |
| 2780 } | 2862 } |
| 2781 } | 2863 } |
| 2782 unit.typeAliases = typeAliases.where((e) => !e.isSynthetic).toList(); | 2864 unit.typeAliases = typeAliases.where((e) => !e.isSynthetic).toList(); |
| 2783 unit.types = unitHolder.types; | 2865 unit.types = unitHolder.types; |
| 2784 unit.topLevelVariables = unitHolder.topLevelVariables; | |
| 2785 for (ClassElement cls in unit.types) { | 2866 for (ClassElement cls in unit.types) { |
| 2786 elementMap[cls.name] = cls; | 2867 elementMap[cls.name] = cls; |
| 2787 } | 2868 } |
| 2788 for (ClassElement cls in unit.enums) { | 2869 for (ClassElement cls in unit.enums) { |
| 2789 elementMap[cls.name] = cls; | 2870 elementMap[cls.name] = cls; |
| 2790 } | 2871 } |
| 2791 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { | 2872 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { |
| 2792 elementMap[typeAlias.name] = typeAlias; | 2873 elementMap[typeAlias.name] = typeAlias; |
| 2793 } | 2874 } |
| 2794 for (FunctionElement function in unit.functions) { | 2875 for (FunctionElement function in unit.functions) { |
| 2795 elementMap[function.name] = function; | 2876 elementMap[function.name] = function; |
| 2796 } | 2877 } |
| 2797 for (PropertyAccessorElementImpl accessor in unit.accessors) { | |
| 2798 elementMap[accessor.identifier] = accessor; | |
| 2799 } | |
| 2800 assert(currentTypeParameters.isEmpty); | 2878 assert(currentTypeParameters.isEmpty); |
| 2801 } | 2879 } |
| 2802 | 2880 |
| 2803 /** | 2881 /** |
| 2804 * Constructor initializers can reference fields and other constructors of | 2882 * Constructor initializers can reference fields and other constructors of |
| 2805 * the same class, including forward references. So, we need to delay | 2883 * the same class, including forward references. So, we need to delay |
| 2806 * resolution until after class elements are built. | 2884 * resolution until after class elements are built. |
| 2807 */ | 2885 */ |
| 2808 void resolveConstructorInitializers(ClassElementImpl classElement) { | 2886 void resolveConstructorInitializers(ClassElementImpl classElement) { |
| 2809 for (ConstructorElementImpl constructor in constructors.values) { | 2887 for (ConstructorElementImpl constructor in constructors.values) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2879 static String _getElementIdentifier(String name, ReferenceKind kind) { | 2957 static String _getElementIdentifier(String name, ReferenceKind kind) { |
| 2880 if (kind == ReferenceKind.topLevelPropertyAccessor || | 2958 if (kind == ReferenceKind.topLevelPropertyAccessor || |
| 2881 kind == ReferenceKind.propertyAccessor) { | 2959 kind == ReferenceKind.propertyAccessor) { |
| 2882 if (!name.endsWith('=')) { | 2960 if (!name.endsWith('=')) { |
| 2883 return name + '?'; | 2961 return name + '?'; |
| 2884 } | 2962 } |
| 2885 } | 2963 } |
| 2886 return name; | 2964 return name; |
| 2887 } | 2965 } |
| 2888 } | 2966 } |
| OLD | NEW |