Index: pkg/compiler/lib/src/resolution/constructors.dart |
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart |
index 7a4dbc68af735d296d314058213cbcc0a99162b1..e30cfdcd7e496a70befa528d5db98275db08b9fc 100644 |
--- a/pkg/compiler/lib/src/resolution/constructors.dart |
+++ b/pkg/compiler/lib/src/resolution/constructors.dart |
@@ -32,6 +32,7 @@ import 'members.dart' show lookupInScope, ResolverVisitor; |
import 'registry.dart' show ResolutionRegistry; |
import 'resolution_common.dart' show CommonResolverVisitor; |
import 'resolution_result.dart'; |
+import 'scope.dart' show Scope, ExtensionScope; |
class InitializerResolver { |
final ResolverVisitor visitor; |
@@ -294,14 +295,30 @@ class InitializerResolver { |
* Resolve all initializers of this constructor. In the case of a redirecting |
* constructor, the resolved constructor's function element is returned. |
*/ |
- ConstructorElement resolveInitializers() { |
+ ConstructorElement resolveInitializers( |
+ {bool enableInitializingFormalAccess: false}) { |
Map<dynamic /*String|int*/, ConstantExpression> defaultValues = |
<dynamic /*String|int*/, ConstantExpression>{}; |
ConstructedConstantExpression constructorInvocation; |
// Keep track of all "this.param" parameters specified for constructor so |
// that we can ensure that fields are initialized only once. |
FunctionSignature functionParameters = constructor.functionSignature; |
+ Scope oldScope = visitor.scope; |
+ if (enableInitializingFormalAccess) { |
+ // In order to get the correct detection of name clashes between all |
+ // parameters (regular ones and initializing formals) we must extend |
+ // the parameter scope rather than adding a new nested scope. |
+ visitor.scope = new ExtensionScope(visitor.scope); |
+ } |
+ Link<Node> parameterNodes = (functionNode.parameters == null) |
+ ? const Link<Node>() |
+ : functionNode.parameters.nodes; |
functionParameters.forEachParameter((ParameterElementX element) { |
+ List<Element> optionals = functionParameters.optionalParameters; |
+ if (!optionals.isEmpty && element == optionals.first) { |
+ NodeList nodes = parameterNodes.head; |
+ parameterNodes = nodes.nodes; |
+ } |
if (isConst) { |
if (element.isOptional) { |
if (element.constantCache == null) { |
@@ -325,9 +342,15 @@ class InitializerResolver { |
} |
} |
if (element.isInitializingFormal) { |
+ VariableDefinitions variableDefinitions = parameterNodes.head; |
+ Node parameterNode = variableDefinitions.definitions.nodes.head; |
InitializingFormalElementX initializingFormal = element; |
FieldElement field = initializingFormal.fieldElement; |
checkForDuplicateInitializers(field, element.initializer); |
+ if (enableInitializingFormalAccess) { |
+ visitor.defineLocalVariable(parameterNode, initializingFormal); |
+ visitor.addToScope(initializingFormal); |
+ } |
if (isConst) { |
if (element.isNamed) { |
fieldInitializers[field] = new NamedArgumentReference(element.name); |
@@ -339,6 +362,7 @@ class InitializerResolver { |
isValidAsConstant = false; |
} |
} |
+ parameterNodes = parameterNodes.tail; |
}); |
if (functionNode.initializers == null) { |
@@ -430,6 +454,7 @@ class InitializerResolver { |
fieldInitializers, |
constructorInvocation); |
} |
+ visitor.scope = oldScope; |
return null; // If there was no redirection always return null. |
} |
} |