Files
sdk/pkg/analyzer/test/generated/invalid_code_test.dart
T
Konstantin Shcheglov 2ec47ad273 Use ElementKind.ENUM for enums.
There was a crash internally, caused by the fact that when we have
duplicate name for class and enum, during linking we put them into
different Reference bucket - @class and @enum, and also inside
the class, the reference to its name is the class.

But when we resolve, we check equality of elements using not
references, but locations. So, we need to make sure that their
kinds are also different, so go into different bucket, and so
not equal.

When they are InterfaceType and equal, we would try to match
type arguments against the wrong number of type parameters and crash.

Change-Id: Iee3f8691adac65d4b0395ceec7fc7250f96afa88
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152404
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
2020-06-25 00:20:31 +00:00

365 lines
8.4 KiB
Dart

// 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.
import 'dart:async';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../src/dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InvalidCodeTest);
defineReflectiveTests(InvalidCodeWithNullSafetyTest);
});
}
/// Tests for various end-to-end cases when invalid code caused exceptions
/// in one or another Analyzer subsystem. We are not interested not in specific
/// errors generated, but we want to make sure that there is at least one,
/// and analysis finishes without exceptions.
@reflectiveTest
class InvalidCodeTest extends DriverResolutionTest {
/// This code results in a method with the empty name, and the default
/// constructor, which also has the empty name. The `Map` in `f` initializer
/// references the empty name.
test_constructorAndMethodNameCollision() async {
await _assertCanBeAnalyzed('''
class C {
var f = { : };
@ ();
}
''');
}
test_constructorDeclaration_named_missingName() async {
await _assertCanBeAnalyzed('''
class C {
C.();
}
''');
}
test_constructorDeclaration_named_missingName_factory() async {
await _assertCanBeAnalyzed('''
class C {
factory C.();
}
''');
}
test_duplicateName_class_enum() async {
await _assertCanBeAnalyzed('''
class A<T> {
void foo(B b) {
b.bar(this);
}
}
class B {
void bar(A a) {}
}
enum A {
a, b, c
}
''');
}
test_extensionOverrideInAnnotationContext() async {
await _assertCanBeAnalyzed('''
class R {
const R(int x);
}
@R(E(null).f())
extension E on Object {
int f() => 0;
}
''');
}
test_extensionOverrideInConstContext() async {
await _assertCanBeAnalyzed('''
extension E on Object {
int f() => 0;
}
const e = E(null).f();
''');
}
test_fieldFormalParameter_annotation_localFunction() async {
await _assertCanBeAnalyzed(r'''
void main() {
void foo(@deprecated this.bar) {}
}
''');
}
test_fuzz_01() async {
await _assertCanBeAnalyzed(r'''
typedef F = void Function(bool, int a(double b));
''');
var alias = findElement.functionTypeAlias('F');
assertType(
alias.instantiate(
typeArguments: const [],
nullabilitySuffix: NullabilitySuffix.star,
),
'void Function(bool, int Function(double))');
}
test_fuzz_02() async {
await _assertCanBeAnalyzed(r'''
class G<class G{d
''');
}
test_fuzz_03() async {
await _assertCanBeAnalyzed('''
class{const():super.{n
''');
}
test_fuzz_04() async {
await _assertCanBeAnalyzed('''
f({a: ({b = 0}) {}}) {}
''');
}
test_fuzz_05() async {
// Here 'v' is used as both the local variable name, and its type.
// This triggers "reference before declaration" diagnostics.
// It attempts to ask the enclosing unit element for "v".
// Every (not library or unit) element must have the enclosing unit.
await _assertCanBeAnalyzed('''
f({a = [for (v v in [])]}) {}
''');
}
test_fuzz_06() async {
await _assertCanBeAnalyzed(r'''
class C {
int f;
set f() {}
}
''');
}
test_fuzz_07() async {
// typedef v(<T extends T>(e
await _assertCanBeAnalyzed(r'''
typedef F(a<TT extends TT>(e));
''');
}
test_fuzz_08() async {
// class{const v
// v=((){try catch
// When we resolve initializers of typed constant variables,
// we should build locale elements.
await _assertCanBeAnalyzed(r'''
class C {
const Object v = () { var a = 0; };
}
''');
}
test_fuzz_09() async {
await _assertCanBeAnalyzed(r'''
typedef void F(int a, this.b);
''');
var alias = findElement.functionTypeAlias('F');
assertType(
alias.instantiate(
typeArguments: const [],
nullabilitySuffix: NullabilitySuffix.star,
),
'void Function(int, dynamic)');
}
test_fuzz_10() async {
await _assertCanBeAnalyzed(r'''
void f<@A(() { Function() v; }) T>() {}
''');
}
test_fuzz_11() async {
// Here `F` is a generic function, so it cannot be used as a bound for
// a type parameter. The reason it crashed was that we did not build
// the bound for `Y` (not `T`), because of the order in which types
// for `T extends F` and `typedef F` were built.
await _assertCanBeAnalyzed(r'''
typedef F<X> = void Function<Y extends num>();
class A<T extends F> {}
''');
}
@failingTest
test_fuzz_12() async {
// This code crashed with summary2 because usually AST reader is lazy,
// so we did not read metadata `@b` for `c`. But default values must be
// read fully.
await _assertCanBeAnalyzed(r'''
void f({a = [for (@b c = 0;;)]}) {}
''');
}
test_fuzz_13() async {
// `x is int` promotes the type of `x` to `S extends int`, and the
// underlying element is `TypeParameterMember`, which by itself is
// questionable. But this is not a valid constant anyway, so we should
// not even try to serialize it.
await _assertCanBeAnalyzed(r'''
const v = [<S extends num>(S x) => x is int ? x : 0];
''');
}
test_fuzz_14() async {
// This crashed because parser produces `ConstructorDeclaration`.
// So, we try to create `ConstructorElement` for it, and it wants
// `ClassElement` as the enclosing element. But we have `ExtensionElement`.
await _assertCanBeAnalyzed(r'''
extension E {
factory S() {}
}
''');
}
test_fuzz_15() async {
// `@A` is not a valid annotation, it is missing arguments.
// There was a bug that we did not check for arguments being missing.
await _assertCanBeAnalyzed(r'''
class A<T> {}
@A
class B {}
''');
}
test_fuzz_16() async {
// The default constructor of `A` does not have formal parameters.
// But we give it arguments.
// There was a bug that we did not check for this mismatch.
await _assertCanBeAnalyzed(r'''
class A<T> {}
@A(0)
class B {}
''');
}
test_fuzz_38091() async {
// https://github.com/dart-lang/sdk/issues/38091
// this caused an infinite loop in parser recovery
await _assertCanBeAnalyzed(r'c(=k(<)>');
}
test_fuzz_38506() async {
// https://github.com/dart-lang/sdk/issues/38506
// We have only one LibraryElement to get resolved annotations.
// Leave annotations node of other LibraryDirective(s) unresolved.
await _assertCanBeAnalyzed(r'''
library c;
@foo
library c;
''');
}
test_fuzz_38878() async {
// We should not attempt to resolve `super` in annotations.
await _assertCanBeAnalyzed(r'''
class C {
@A(super.f())
f(int x) {}
}
''');
}
test_fuzz_38953() async {
// When we enter a directive, we should stop using the element walker
// of the unit, just like when we enter a method body. Even though using
// interpolation is not allowed in any directives.
await _assertCanBeAnalyzed(r'''
import '${[for(var v = 0;;) v]}';
export '${[for(var v = 0;;) v]}';
part '${[for(var v = 0;;) v]}';
''');
}
test_genericFunction_asTypeArgument_ofUnresolvedClass() async {
await _assertCanBeAnalyzed(r'''
C<int Function()> c;
''');
}
test_keywordInConstructorInitializer_assert() async {
await _assertCanBeAnalyzed('''
class C {
C() : assert = 0;
}
''');
}
test_keywordInConstructorInitializer_null() async {
await _assertCanBeAnalyzed('''
class C {
C() : null = 0;
}
''');
}
test_keywordInConstructorInitializer_super() async {
await _assertCanBeAnalyzed('''
class C {
C() : super = 0;
}
''');
}
test_keywordInConstructorInitializer_this() async {
await _assertCanBeAnalyzed('''
class C {
C() : this = 0;
}
''');
}
Future<void> _assertCanBeAnalyzed(String text) async {
await resolveTestCode(text);
assertHasTestErrors();
}
}
@reflectiveTest
class InvalidCodeWithNullSafetyTest extends DriverResolutionTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = FeatureSet.forTesting(
sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
@override
bool get typeToStringWithNullability => true;
test_issue_40837() async {
await _assertCanBeAnalyzed('''
class A {
const A(_);
}
@A(() => 0)
class B {}
''');
}
Future<void> _assertCanBeAnalyzed(String text) async {
await resolveTestCode(text);
assertHasTestErrors();
}
}