Implement type inference for asserts in constructor initializers.

R=scheglov@google.com

Review-Url: https://codereview.chromium.org/2995553002 .
This commit is contained in:
Paul Berry 2017-08-04 17:55:07 -07:00
parent 4cb87e6f1e
commit 1b9ba53fb6
10 changed files with 117 additions and 6 deletions

View file

@ -92,13 +92,15 @@ class BaseAnalysisDriverTest {
}),
new ResourceUriResolver(provider)
], null, provider),
new AnalysisOptionsImpl()
..strongMode = true
..enableUriInPartOf = true,
createAnalysisOptions(),
disableChangesAndCacheAllResults: disableChangesAndCacheAllResults,
externalSummaries: externalSummaries);
}
AnalysisOptionsImpl createAnalysisOptions() => new AnalysisOptionsImpl()
..strongMode = true
..enableUriInPartOf = true;
int findOffset(String search) {
int offset = testCode.indexOf(search);
if (offset < 0) {

View file

@ -12,6 +12,7 @@ import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
@ -133,6 +134,10 @@ class _ElementNamer {
}
class _FrontEndInferenceTest extends BaseAnalysisDriverTest {
@override
AnalysisOptionsImpl createAnalysisOptions() =>
super.createAnalysisOptions()..enableAssertInitializer = true;
Future<String> runTest(String path, String code) {
return fasta.CompilerContext.runWithDefaultOptions((_) async {
Uri uri = provider.pathContext.toUri(path);

View file

@ -2763,14 +2763,15 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
// So we produce an initializer like this:
//
// var #t0 = (() { statement; }) ()
return new LocalInitializer(new VariableDeclaration.forValue(
buildMethodInvocation(
return new KernelAssertInitializer(
new VariableDeclaration.forValue(buildMethodInvocation(
new FunctionExpression(new FunctionNode(statement)),
callName,
new Arguments.empty(),
statement.fileOffset,
isConstantExpression: true,
isImplicitCall: true)));
isImplicitCall: true)),
statement);
}
@override

View file

@ -90,6 +90,23 @@ class KernelAsExpression extends AsExpression implements KernelExpression {
}
}
/// Concrete shadow object representing an assert initializer in kernel form.
class KernelAssertInitializer extends LocalInitializer
implements KernelInitializer {
/// The assert statement performing the check
AssertStatement _statement;
KernelAssertInitializer(VariableDeclaration variable, this._statement)
: super(variable);
@override
void _inferInitializer(KernelTypeInferrer inferrer) {
inferrer.listener.assertInitializerEnter(this);
inferrer.inferStatement(_statement);
inferrer.listener.assertInitializerExit(this);
}
}
/// Concrete shadow object representing an assertion statement in kernel form.
class KernelAssertStatement extends AssertStatement implements KernelStatement {
KernelAssertStatement(Expression condition,

View file

@ -90,6 +90,12 @@ class TypeInferenceListener
void asExpressionExit(AsExpression expression, DartType inferredType) =>
genericExpressionExit("asExpression", expression, inferredType);
void assertInitializerEnter(LocalInitializer initializer) =>
genericInitializerEnter("assertInitializer", initializer);
void assertInitializerExit(LocalInitializer initializer) =>
genericInitializerExit("assertInitializer", initializer);
void assertStatementEnter(AssertStatement statement) =>
genericStatementEnter('assertStatement', statement);

View file

@ -26,6 +26,7 @@ functions: Crash
implicit_scope_test: Crash
implicit_this: Crash
inference/abstract_class_instantiation: Crash
inference/assert_initializer: Crash
inference/assign_local: Crash
inference/block_bodied_lambdas_basic: Crash
inference/block_bodied_lambdas_basic_void: Crash

View file

@ -0,0 +1,21 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
T f<T>() => null;
class C {
C.expressionOnly() : assert(/*@typeArgs=dynamic*/ f());
C.expressionAndMessage()
: assert(/*@typeArgs=dynamic*/ f(), /*@typeArgs=dynamic*/ f());
}
main() {
// Test type inference of assert statements just to verify that the behavior
// is the same.
assert(/*@typeArgs=dynamic*/ f());
assert(/*@typeArgs=dynamic*/ f(), /*@typeArgs=dynamic*/ f());
}

View file

@ -0,0 +1,22 @@
library test;
import self as self;
import "dart:core" as core;
class C extends core::Object {
constructor expressionOnly() → void
: final dynamic #t1 = () → dynamic
assert(self::f<dynamic>());
.call(), super core::Object::•()
;
constructor expressionAndMessage() → void
: final dynamic #t2 = () → dynamic
assert(self::f<dynamic>(), self::f<dynamic>());
.call(), super core::Object::•()
;
}
static method f<T extends core::Object>() → self::f::T
return null;
static method main() → dynamic {
assert(self::f<dynamic>());
assert(self::f<dynamic>(), self::f<dynamic>());
}

View file

@ -0,0 +1,14 @@
library test;
import self as self;
import "dart:core" as core;
class C extends core::Object {
constructor expressionOnly() → void
;
constructor expressionAndMessage() → void
;
}
static method f<T extends core::Object>() → self::f::T
;
static method main() → dynamic
;

View file

@ -0,0 +1,22 @@
library test;
import self as self;
import "dart:core" as core;
class C extends core::Object {
constructor expressionOnly() → void
: final dynamic #t1 = () → dynamic
assert(self::f<dynamic>());
.call(), super core::Object::•()
;
constructor expressionAndMessage() → void
: final dynamic #t2 = () → dynamic
assert(self::f<dynamic>(), self::f<dynamic>());
.call(), super core::Object::•()
;
}
static method f<T extends core::Object>() → self::f::T
return null;
static method main() → dynamic {
assert(self::f<dynamic>());
assert(self::f<dynamic>(), self::f<dynamic>());
}