mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:01:42 +00:00
Implement type inference for asserts in constructor initializers.
R=scheglov@google.com Review-Url: https://codereview.chromium.org/2995553002 .
This commit is contained in:
parent
4cb87e6f1e
commit
1b9ba53fb6
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
21
pkg/front_end/testcases/inference/assert_initializer.dart
Normal file
21
pkg/front_end/testcases/inference/assert_initializer.dart
Normal 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());
|
||||
}
|
|
@ -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>());
|
||||
}
|
|
@ -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
|
||||
;
|
|
@ -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>());
|
||||
}
|
Loading…
Reference in a new issue