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

Unified Diff: pkg/analyzer/lib/src/summary/resynthesize.dart

Issue 1679923002: Resynthesize constructor initializers. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/summary/resynthesize.dart
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 085136b6d95bd4041a3976cac80a744b476c025f..7a0d5a91924ee14a8779726c02b5db78718f5ac9 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -435,8 +435,13 @@ class _ConstExprBuilder {
_push(AstFactory.propertyAccess(target, property));
break;
case UnlinkedConstOperation.pushConstructorParameter:
- // TODO(scheglov) implement
- throw new UnimplementedError('$operation');
+ String name = uc.strings[stringPtr++];
+ SimpleIdentifier identifier = AstFactory.identifier3(name);
+ identifier.staticElement = resynthesizer.currentConstructor.parameters
+ .firstWhere((parameter) => parameter.name == name,
+ orElse: () => throw new StateError(
+ 'Unable to resolve constructor parameter: $name'));
+ _push(identifier);
break;
}
}
@@ -693,6 +698,12 @@ class _LibraryResynthesizer {
CompilationUnitElementImpl currentCompilationUnit;
/**
+ * The [ConstructorElementImpl] for the constructor currently being
+ * resynthesized.
+ */
+ ConstructorElementImpl currentConstructor;
+
+ /**
* Map of top level elements that have been resynthesized so far. The first
* key is the URI of the compilation unit; the second is the name of the top
* level element.
@@ -719,6 +730,13 @@ class _LibraryResynthesizer {
Map<String, FieldElementImpl> fields;
/**
+ * If a class is currently being resynthesized, map from constructor name to
+ * the corresponding constructor element. This is used when resynthesizing
+ * constructor initializers.
+ */
+ Map<String, ConstructorElementImpl> constructors;
+
+ /**
* List of [_ReferenceInfo] objects describing the references in the current
* compilation unit.
*/
@@ -805,6 +823,7 @@ class _LibraryResynthesizer {
buildVariable(serializedVariable, memberHolder);
}
bool constructorFound = false;
+ constructors = <String, ConstructorElementImpl>{};
for (UnlinkedExecutable serializedExecutable
in serializedClass.executables) {
switch (serializedExecutable.kind) {
@@ -829,6 +848,7 @@ class _LibraryResynthesizer {
constructor.returnType = correspondingType;
constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
constructor, null, currentTypeArguments, false);
+// constructor.constantInitializers = <ConstructorInitializer>[];
Paul Berry 2016/02/08 20:40:55 Accidental debug code?
memberHolder.addConstructor(constructor);
}
classElement.constructors = memberHolder.constructors;
@@ -840,10 +860,12 @@ class _LibraryResynthesizer {
classElement.type = correspondingType;
buildDocumentation(classElement, serializedClass.documentationComment);
buildAnnotations(classElement, serializedClass.annotations);
+ resolveConstructorInitializers(classElement);
unitHolder.addType(classElement);
} finally {
currentTypeParameters = <TypeParameterElement>[];
fields = null;
+ constructors = null;
}
}
@@ -867,6 +889,29 @@ class _LibraryResynthesizer {
}
/**
+ * Resynthesize the [ConstructorInitializer] in context of
+ * [currentConstructor], which is used to resolve constructor parameter names.
+ */
+ ConstructorInitializer buildConstantInitializer(
+ UnlinkedConstructorInitializer serialized) {
+ UnlinkedConstructorInitializerKind kind = serialized.kind;
+ String name = serialized.name;
+ List<Expression> arguments =
+ serialized.arguments.map(_buildConstExpression).toList();
+ switch (kind) {
+ case UnlinkedConstructorInitializerKind.field:
+ return AstFactory.constructorFieldInitializer(
+ false, name, _buildConstExpression(serialized.expression));
+ case UnlinkedConstructorInitializerKind.superInvocation:
+ return AstFactory.superConstructorInvocation2(
+ name.isNotEmpty ? name : null, arguments);
+ case UnlinkedConstructorInitializerKind.thisInvocation:
+ return AstFactory.redirectingConstructorInvocation2(
+ name.isNotEmpty ? name : null, arguments);
+ }
+ }
+
+ /**
* Resynthesize a [ConstructorElement] and place it in the given [holder].
* [classType] is the type of the class for which this element is a
* constructor.
@@ -874,13 +919,19 @@ class _LibraryResynthesizer {
void buildConstructor(UnlinkedExecutable serializedExecutable,
ElementHolder holder, InterfaceType classType) {
assert(serializedExecutable.kind == UnlinkedExecutableKind.constructor);
- ConstructorElementImpl constructorElement = new ConstructorElementImpl(
+ currentConstructor = new ConstructorElementImpl(
serializedExecutable.name, serializedExecutable.nameOffset);
- constructorElement.returnType = classType;
- buildExecutableCommonParts(constructorElement, serializedExecutable);
- constructorElement.factory = serializedExecutable.isFactory;
- constructorElement.const2 = serializedExecutable.isConst;
- holder.addConstructor(constructorElement);
+ constructors[serializedExecutable.name] = currentConstructor;
+ currentConstructor.returnType = classType;
+ buildExecutableCommonParts(currentConstructor, serializedExecutable);
+ currentConstructor.factory = serializedExecutable.isFactory;
+ currentConstructor.const2 = serializedExecutable.isConst;
+ currentConstructor.constantInitializers = serializedExecutable
+ .constantInitializers
+ .map(buildConstantInitializer)
+ .toList();
+ holder.addConstructor(currentConstructor);
+ currentConstructor = null;
}
/**
@@ -1789,6 +1840,34 @@ class _LibraryResynthesizer {
unitHolder = new ElementHolder();
}
+ /**
+ * Constructor initializers can reference fields and other constructors of
+ * the same class, including forward references. So, we need to delay
+ * resolution until after class elements are built.
+ */
+ void resolveConstructorInitializers(ClassElementImpl classElement) {
+ for (ConstructorElementImpl constructor in constructors.values) {
+ for (ConstructorInitializer initializer
+ in constructor.constantInitializers) {
+ if (initializer is ConstructorFieldInitializer) {
+ SimpleIdentifier nameNode = initializer.fieldName;
+ nameNode.staticElement = fields[nameNode.name];
+ } else if (initializer is SuperConstructorInvocation) {
+ SimpleIdentifier nameNode = initializer.constructorName;
+ ConstructorElement element = new _DeferredConstructorElement(
+ classElement.supertype, nameNode?.name ?? '');
+ initializer.staticElement = element;
+ nameNode?.staticElement = element;
+ } else if (initializer is RedirectingConstructorInvocation) {
+ SimpleIdentifier nameNode = initializer.constructorName;
+ ConstructorElement element = constructors[nameNode?.name ?? ''];
+ initializer.staticElement = element;
+ nameNode?.staticElement = element;
+ }
+ }
+ }
+ }
+
Expression _buildConstExpression(UnlinkedConst uc) {
return new _ConstExprBuilder(this, uc).build();
}
« no previous file with comments | « pkg/analyzer/lib/src/generated/testing/test_type_provider.dart ('k') | pkg/analyzer/test/src/summary/resynthesize_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698