mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:19:49 +00:00
New tests for initializing formal access.
This CL adds tests for previously uncovered elements of the semantics and includes fixes such that the desired behavior is obtained. In particular, an `isInitializingFormal` element may now occur in contexts where it wasn't expected until now, and changes were made to handle it. It is also checked that a capture of an initializing formal (in a function literal) captures the parameter, not the field. R=johnniwinther@google.com Review URL: https://codereview.chromium.org/2039833002 .
This commit is contained in:
parent
2d310f1e67
commit
543a51ff3e
|
@ -3859,7 +3859,7 @@ class TryBoxedVariables extends ast.Visitor {
|
|||
if (Elements.isLocal(element)) {
|
||||
LocalElement local = element;
|
||||
if (insideInitializer &&
|
||||
local.isParameter &&
|
||||
(local.isParameter || local.isInitializingFormal) &&
|
||||
local.enclosingElement == currentFunction) {
|
||||
assert(local.enclosingElement.isConstructor);
|
||||
// Initializers in an initializer-list can communicate via parameters.
|
||||
|
@ -3871,7 +3871,9 @@ class TryBoxedVariables extends ast.Visitor {
|
|||
// outlive the activation of the function).
|
||||
markAsCaptured(local);
|
||||
} else if (inTryStatement) {
|
||||
assert(local.isParameter || local.isVariable);
|
||||
assert(local.isParameter ||
|
||||
local.isVariable ||
|
||||
local.isInitializingFormal);
|
||||
// Search for the position of the try block containing the variable
|
||||
// declaration, or -1 if it is declared outside the outermost try.
|
||||
int i = tryNestingStack.length - 1;
|
||||
|
|
|
@ -2573,6 +2573,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
} else {
|
||||
semantics = new StaticAccess.parameter(element);
|
||||
}
|
||||
} else if (element.isInitializingFormal &&
|
||||
compiler.options.enableInitializingFormalAccess) {
|
||||
error = reportAndCreateErroneousElement(node.selector, name.text,
|
||||
MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER, {'name': name});
|
||||
semantics = new StaticAccess.finalParameter(element);
|
||||
} else if (element.isVariable) {
|
||||
if (element.isFinal || element.isConst) {
|
||||
error = reportAndCreateErroneousElement(node.selector, name.text,
|
||||
|
|
|
@ -681,7 +681,12 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|||
assert(invariant(node, element != null,
|
||||
message: 'Missing element for identifier'));
|
||||
assert(invariant(
|
||||
node, element.isVariable || element.isParameter || element.isField,
|
||||
node,
|
||||
element.isVariable ||
|
||||
element.isParameter ||
|
||||
element.isField ||
|
||||
(element.isInitializingFormal &&
|
||||
compiler.options.enableInitializingFormalAccess),
|
||||
message: 'Unexpected context element ${element}'));
|
||||
return element.computeType(resolution);
|
||||
}
|
||||
|
@ -762,7 +767,9 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|||
return access;
|
||||
}
|
||||
if (receiverElement != null &&
|
||||
(receiverElement.isVariable || receiverElement.isParameter)) {
|
||||
(receiverElement.isVariable || receiverElement.isParameter ||
|
||||
(receiverElement.isInitializingFormal &&
|
||||
compiler.options.enableInitializingFormalAccess))) {
|
||||
Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
|
||||
if (typePromotions != null) {
|
||||
while (!typePromotions.isEmpty) {
|
||||
|
@ -1078,7 +1085,9 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|||
}
|
||||
|
||||
ElementAccess createPromotedAccess(Element element) {
|
||||
if (element.isVariable || element.isParameter) {
|
||||
if (element.isVariable || element.isParameter ||
|
||||
(element.isInitializingFormal &&
|
||||
compiler.options.enableInitializingFormalAccess)) {
|
||||
TypePromotion typePromotion = getKnownTypePromotion(element);
|
||||
if (typePromotion != null) {
|
||||
return new PromotedAccess(element, typePromotion.type);
|
||||
|
@ -1213,7 +1222,11 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|||
}
|
||||
}
|
||||
|
||||
if (variable != null && (variable.isVariable || variable.isParameter)) {
|
||||
if (variable != null &&
|
||||
(variable.isVariable ||
|
||||
variable.isParameter ||
|
||||
(variable.isInitializingFormal &&
|
||||
compiler.options.enableInitializingFormalAccess))) {
|
||||
DartType knownType = getKnownType(variable);
|
||||
if (!knownType.isDynamic) {
|
||||
DartType shownType = elements.getType(node.arguments.head);
|
||||
|
|
|
@ -682,6 +682,8 @@ final Map<String, Message> MESSAGES = {
|
|||
template: "The setter '#{memberName}' is not defined for the "
|
||||
"class '#{className}'.",
|
||||
usedBy: [dart2js, analyzer],
|
||||
// TODO(eernst): When this.x access is available, add examples here,
|
||||
// e.g., "class A { var x; A(this.x) : x = 3; } main() => new A(2);"
|
||||
examples: const ["class A {} main() { new A().x = 499; }",]),
|
||||
|
||||
'NO_SUCH_SUPER_MEMBER': new Message(
|
||||
|
|
19
tests/language/initializing_formal_capture_test.dart
Normal file
19
tests/language/initializing_formal_capture_test.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// DartOptions=--initializing-formal-access
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A {
|
||||
var x, y;
|
||||
A(this.x) : y = (() => x);
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A(2);
|
||||
a.x = 3;
|
||||
Expect.equals(a.x, 3);
|
||||
Expect.equals(a.y(), 2);
|
||||
}
|
20
tests/language/initializing_formal_final_test.dart
Normal file
20
tests/language/initializing_formal_final_test.dart
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// DartOptions=--initializing-formal-access
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A {
|
||||
var x, y;
|
||||
// This should cause a warning because `x` is final when
|
||||
// accessed as an initializing formal.
|
||||
A(this.x) : y = (() { x = 3; });
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A(2);
|
||||
Expect.equals(a.x, 2);
|
||||
Expect.throws(() => a.y(), (e) => e is NoSuchMethodError);
|
||||
}
|
30
tests/language/initializing_formal_promotion_test.dart
Normal file
30
tests/language/initializing_formal_promotion_test.dart
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// DartOptions=--initializing-formal-access
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class B {}
|
||||
|
||||
class A {
|
||||
B x, y;
|
||||
A(this.x) {
|
||||
// Promote to subtype.
|
||||
if (x is C) y = x.x;
|
||||
// Promotion fails, not a subtype.
|
||||
if (x is A) y = x;
|
||||
}
|
||||
}
|
||||
|
||||
class C extends A implements B {
|
||||
C(B x) : super(x);
|
||||
}
|
||||
|
||||
main() {
|
||||
C c2 = new C(null);
|
||||
C cc = new C(c2);
|
||||
Expect.equals(c2.y, null);
|
||||
Expect.equals(cc.y, c2);
|
||||
}
|
19
tests/language/initializing_formal_type_test.dart
Normal file
19
tests/language/initializing_formal_type_test.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// DartOptions=--initializing-formal-access
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A {
|
||||
int x;
|
||||
String y;
|
||||
A(this.x) : y = x { y = x; }
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A(null);
|
||||
Expect.equals(a.x, null);
|
||||
Expect.equals(a.y, null);
|
||||
}
|
Loading…
Reference in a new issue