| 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 serialization.elements; | 5 library serialization.elements; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 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 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 .add(serializeTypeRef(typeArguments[i], context)); | 1064 .add(serializeTypeRef(typeArguments[i], context)); |
| 1065 } | 1065 } |
| 1066 b.typeArguments = serializedArguments; | 1066 b.typeArguments = serializedArguments; |
| 1067 } | 1067 } |
| 1068 } | 1068 } |
| 1069 } | 1069 } |
| 1070 return b; | 1070 return b; |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 /** | 1073 /** |
| 1074 * Create a new entry in the references table ([UnlinkedLibrary.references] | 1074 * Create a new entry in the references table ([UnlinkedUnit.references] |
| 1075 * and [LinkedLibrary.references]) representing an entity having the given | 1075 * and [LinkedUnit.references]) representing an entity having the given |
| 1076 * [name] and [kind]. If [unit] is given, it is the index of the compilation | 1076 * [name] and [kind]. If [unit] is given, it is the index of the compilation |
| 1077 * unit containing the entity being referred to. If [prefixReference] is | 1077 * unit containing the entity being referred to. If [prefixReference] is |
| 1078 * given, it indicates the entry in the references table for the prefix. | 1078 * given, it indicates the entry in the references table for the prefix. |
| 1079 */ | 1079 */ |
| 1080 int serializeUnlinkedReference(String name, ReferenceKind kind, | 1080 int serializeUnlinkedReference(String name, ReferenceKind kind, |
| 1081 {int unit: 0, int prefixReference: 0}) { | 1081 {int unit: 0, int prefixReference: 0}) { |
| 1082 assert(unlinkedReferences.length == linkedReferences.length); | 1082 assert(unlinkedReferences.length == linkedReferences.length); |
| 1083 int index = unlinkedReferences.length; | 1083 int index = unlinkedReferences.length; |
| 1084 unlinkedReferences.add(new UnlinkedReferenceBuilder( | 1084 unlinkedReferences.add(new UnlinkedReferenceBuilder( |
| 1085 name: name, prefixReference: prefixReference)); | 1085 name: name, prefixReference: prefixReference)); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 linkedReference = linkedReferences[index]; | 1268 linkedReference = linkedReferences[index]; |
| 1269 } | 1269 } |
| 1270 linkedReference.dependency = | 1270 linkedReference.dependency = |
| 1271 librarySerializer.serializeDependency(dependentLibrary); | 1271 librarySerializer.serializeDependency(dependentLibrary); |
| 1272 if (element is TypeParameterizedElement) { | 1272 if (element is TypeParameterizedElement) { |
| 1273 linkedReference.numTypeParameters += element.typeParameters.length; | 1273 linkedReference.numTypeParameters += element.typeParameters.length; |
| 1274 } | 1274 } |
| 1275 return index; | 1275 return index; |
| 1276 }); | 1276 }); |
| 1277 } | 1277 } |
| 1278 | |
| 1279 int _getLengthPropertyReference(int prefix) { | |
| 1280 return serializeUnlinkedReference('length', ReferenceKind.length, | |
| 1281 prefixReference: prefix); | |
| 1282 } | |
| 1283 } | 1278 } |
| 1284 | 1279 |
| 1285 /** | 1280 /** |
| 1286 * Instances of this class keep track of intermediate state during | 1281 * Instances of this class keep track of intermediate state during |
| 1287 * serialization of a single constant [Expression]. | 1282 * serialization of a single constant [Expression]. |
| 1288 */ | 1283 */ |
| 1289 class _ConstExprSerializer extends AbstractConstExprSerializer { | 1284 class _ConstExprSerializer extends AbstractConstExprSerializer { |
| 1290 final _CompilationUnitSerializer serializer; | 1285 final _CompilationUnitSerializer serializer; |
| 1291 final Element context; | 1286 final Element context; |
| 1292 | 1287 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 : ReferenceKind.unresolved, | 1341 : ReferenceKind.unresolved, |
| 1347 prefixReference: typeRef.reference, | 1342 prefixReference: typeRef.reference, |
| 1348 unit: typeLinkedRef.unit); | 1343 unit: typeLinkedRef.unit); |
| 1349 return new EntityRefBuilder( | 1344 return new EntityRefBuilder( |
| 1350 reference: refId, typeArguments: typeRef.typeArguments); | 1345 reference: refId, typeArguments: typeRef.typeArguments); |
| 1351 } | 1346 } |
| 1352 } | 1347 } |
| 1353 | 1348 |
| 1354 EntityRefBuilder serializeIdentifier(Identifier identifier, | 1349 EntityRefBuilder serializeIdentifier(Identifier identifier, |
| 1355 {int prefixReference: 0}) { | 1350 {int prefixReference: 0}) { |
| 1356 Element element = identifier.staticElement; | 1351 if (identifier is SimpleIdentifier) { |
| 1357 // Unresolved identifier. | 1352 Element element = identifier.staticElement; |
| 1358 if (element == null) { | 1353 if (element is TypeParameterElement) { |
| 1359 int reference; | 1354 throw new StateError('Constants may not refer to type parameters.'); |
| 1360 if (identifier is PrefixedIdentifier) { | 1355 } |
| 1361 int prefix = serializeIdentifier(identifier.prefix).reference; | 1356 if (_isPrelinkResolvableElement(element)) { |
| 1362 reference = serializer.serializeUnlinkedReference( | 1357 int ref = serializer._getElementReferenceId(element); |
| 1358 return new EntityRefBuilder(reference: ref); |
| 1359 } else { |
| 1360 int ref = serializer.serializeUnlinkedReference( |
| 1361 identifier.name, ReferenceKind.unresolved); |
| 1362 return new EntityRefBuilder(reference: ref); |
| 1363 } |
| 1364 } else if (identifier is PrefixedIdentifier) { |
| 1365 Element element = identifier.staticElement; |
| 1366 if (_isPrelinkResolvableElement(element)) { |
| 1367 int ref = serializer._getElementReferenceId(element); |
| 1368 return new EntityRefBuilder(reference: ref); |
| 1369 } else { |
| 1370 int prefixRef = serializeIdentifier(identifier.prefix).reference; |
| 1371 int ref = serializer.serializeUnlinkedReference( |
| 1363 identifier.identifier.name, ReferenceKind.unresolved, | 1372 identifier.identifier.name, ReferenceKind.unresolved, |
| 1364 prefixReference: prefix); | 1373 prefixReference: prefixRef); |
| 1365 } else { | 1374 return new EntityRefBuilder(reference: ref); |
| 1366 reference = serializer.serializeUnlinkedReference( | |
| 1367 identifier.name, ReferenceKind.unresolved, | |
| 1368 prefixReference: prefixReference); | |
| 1369 } | 1375 } |
| 1370 return new EntityRefBuilder(reference: reference); | 1376 } else { |
| 1377 throw new StateError( |
| 1378 'Unexpected identifier type: ${identifier.runtimeType}'); |
| 1371 } | 1379 } |
| 1372 // The only supported instance property accessor - `length`. | |
| 1373 if (identifier is PrefixedIdentifier && | |
| 1374 element is PropertyAccessorElement && | |
| 1375 !element.isStatic) { | |
| 1376 if (element.name != 'length') { | |
| 1377 throw new StateError('Only "length" property is allowed in constants.'); | |
| 1378 } | |
| 1379 Element prefixElement = identifier.prefix.staticElement; | |
| 1380 int prefixRef = serializer._getElementReferenceId(prefixElement); | |
| 1381 int lengthRef = serializer._getLengthPropertyReference(prefixRef); | |
| 1382 return new EntityRefBuilder(reference: lengthRef); | |
| 1383 } | |
| 1384 if (element is TypeParameterElement) { | |
| 1385 throw new StateError('Constants may not refer to type parameters.'); | |
| 1386 } | |
| 1387 return new EntityRefBuilder( | |
| 1388 reference: serializer._getElementReferenceId(element)); | |
| 1389 } | 1380 } |
| 1390 | 1381 |
| 1391 @override | 1382 @override |
| 1392 EntityRefBuilder serializePropertyAccess(PropertyAccess access) { | 1383 EntityRefBuilder serializeIdentifierSequence(Expression expr) { |
| 1393 Element element = access.propertyName.staticElement; | 1384 if (expr is Identifier) { |
| 1394 // Unresolved property access. | 1385 return serializeIdentifier(expr); |
| 1395 if (element == null) { | 1386 } |
| 1396 Expression target = access.target; | 1387 if (expr is PropertyAccess) { |
| 1397 if (target is Identifier) { | 1388 Element element = expr.propertyName.staticElement; |
| 1398 EntityRefBuilder targetRef = serializeIdentifier(target); | 1389 if (_isPrelinkResolvableElement(element)) { |
| 1399 EntityRefBuilder propertyRef = serializeIdentifier(access.propertyName, | 1390 int ref = serializer._getElementReferenceId(element); |
| 1400 prefixReference: targetRef.reference); | 1391 return new EntityRefBuilder(reference: ref); |
| 1401 return new EntityRefBuilder(reference: propertyRef.reference); | |
| 1402 } else { | 1392 } else { |
| 1403 // TODO(scheglov) should we handle other targets in malformed constants? | 1393 int targetRef = serializeIdentifierSequence(expr.target).reference; |
| 1404 throw new StateError('Unexpected target type: ${target.runtimeType}'); | 1394 int ref = serializer.serializeUnlinkedReference( |
| 1395 expr.propertyName.name, ReferenceKind.unresolved, |
| 1396 prefixReference: targetRef); |
| 1397 return new EntityRefBuilder(reference: ref); |
| 1405 } | 1398 } |
| 1399 } else { |
| 1400 throw new StateError('Unexpected node type: ${expr.runtimeType}'); |
| 1406 } | 1401 } |
| 1407 // The only supported instance property accessor - `length`. | |
| 1408 Expression target = access.target; | |
| 1409 if (target is Identifier && | |
| 1410 element is PropertyAccessorElement && | |
| 1411 !element.isStatic) { | |
| 1412 assert(element.name == 'length'); | |
| 1413 Element prefixElement = target.staticElement; | |
| 1414 int prefixRef = serializer._getElementReferenceId(prefixElement); | |
| 1415 int lengthRef = serializer._getLengthPropertyReference(prefixRef); | |
| 1416 return new EntityRefBuilder(reference: lengthRef); | |
| 1417 } | |
| 1418 return new EntityRefBuilder( | |
| 1419 reference: serializer._getElementReferenceId(element)); | |
| 1420 } | 1402 } |
| 1421 | 1403 |
| 1422 @override | 1404 @override |
| 1423 EntityRefBuilder serializeType(TypeName typeName) { | 1405 EntityRefBuilder serializeType(TypeName typeName) { |
| 1424 if (typeName != null) { | 1406 if (typeName != null) { |
| 1425 DartType type = typeName.type; | 1407 DartType type = typeName.type; |
| 1426 if (type == null || type.isUndefined) { | 1408 if (type == null || type.isUndefined) { |
| 1427 return serializeIdentifier(typeName.name); | 1409 return serializeIdentifier(typeName.name); |
| 1428 } | 1410 } |
| 1429 } | 1411 } |
| 1430 DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance; | 1412 DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance; |
| 1431 return serializer.serializeTypeRef(type, context); | 1413 return serializer.serializeTypeRef(type, context); |
| 1432 } | 1414 } |
| 1415 |
| 1416 /** |
| 1417 * Return `true` if the given [element] can be resolved at prelink step. |
| 1418 */ |
| 1419 static bool _isPrelinkResolvableElement(Element element) { |
| 1420 if (element == null) { |
| 1421 return false; |
| 1422 } |
| 1423 if (element == DynamicTypeImpl.instance.element) { |
| 1424 return true; |
| 1425 } |
| 1426 if (element is PrefixElement) { |
| 1427 return true; |
| 1428 } |
| 1429 Element enclosingElement = element.enclosingElement; |
| 1430 if (enclosingElement is CompilationUnitElement) { |
| 1431 return true; |
| 1432 } |
| 1433 if (enclosingElement is ClassElement) { |
| 1434 return element is ConstructorElement || |
| 1435 element is ClassMemberElement && element.isStatic || |
| 1436 element is PropertyAccessorElement && element.isStatic; |
| 1437 } |
| 1438 return false; |
| 1439 } |
| 1433 } | 1440 } |
| 1434 | 1441 |
| 1435 /** | 1442 /** |
| 1436 * Instances of this class keep track of intermediate state during | 1443 * Instances of this class keep track of intermediate state during |
| 1437 * serialization of a single library. | 1444 * serialization of a single library. |
| 1438 */ | 1445 */ |
| 1439 class _LibrarySerializer { | 1446 class _LibrarySerializer { |
| 1440 /** | 1447 /** |
| 1441 * The library to be serialized. | 1448 * The library to be serialized. |
| 1442 */ | 1449 */ |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1622 exportNames.add(new LinkedExportNameBuilder( | 1629 exportNames.add(new LinkedExportNameBuilder( |
| 1623 name: name, | 1630 name: name, |
| 1624 dependency: serializeDependency(dependentLibrary), | 1631 dependency: serializeDependency(dependentLibrary), |
| 1625 unit: unit, | 1632 unit: unit, |
| 1626 kind: kind)); | 1633 kind: kind)); |
| 1627 } | 1634 } |
| 1628 pb.exportNames = exportNames; | 1635 pb.exportNames = exportNames; |
| 1629 return pb; | 1636 return pb; |
| 1630 } | 1637 } |
| 1631 } | 1638 } |
| OLD | NEW |