Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5357056

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Report errors when extension declarations are used as types
Change-Id: Iad0c7df54fac476c2f23af2fe4ba30ee5bf49167 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/110222 Reviewed-by: Dan Rubel <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent f771a1f commit 5357056

File tree

10 files changed

+136
-53
lines changed

10 files changed

+136
-53
lines changed

pkg/front_end/lib/src/fasta/builder/named_type_builder.dart

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,24 +103,26 @@ class NamedTypeBuilder extends TypeBuilder {
103103
return;
104104
} else if (member is TypeDeclarationBuilder) {
105105
declaration = member.origin;
106-
if (arguments == null && declaration.typeVariablesCount != 0) {
107-
String typeName;
108-
int typeNameOffset;
109-
if (name is Identifier) {
110-
typeName = name.name;
111-
typeNameOffset = name.charOffset;
112-
} else {
113-
typeName = name;
114-
typeNameOffset = charOffset;
106+
if (!declaration.isExtension) {
107+
if (arguments == null && declaration.typeVariablesCount != 0) {
108+
String typeName;
109+
int typeNameOffset;
110+
if (name is Identifier) {
111+
typeName = name.name;
112+
typeNameOffset = name.charOffset;
113+
} else {
114+
typeName = name;
115+
typeNameOffset = charOffset;
116+
}
117+
library.addProblem(
118+
templateMissingExplicitTypeArguments
119+
.withArguments(declaration.typeVariablesCount),
120+
typeNameOffset,
121+
typeName.length,
122+
fileUri);
115123
}
116-
library.addProblem(
117-
templateMissingExplicitTypeArguments
118-
.withArguments(declaration.typeVariablesCount),
119-
typeNameOffset,
120-
typeName.length,
121-
fileUri);
124+
return;
122125
}
123-
return;
124126
}
125127
Template<Message Function(String name)> template =
126128
member == null ? templateTypeNotFound : templateNotAType;

pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ abstract class TypeAliasBuilder<T extends TypeBuilder, R>
2525
this.type,
2626
LibraryBuilder<T, Object> parent,
2727
int charOffset)
28-
: super(metadata, null, name, parent, charOffset);
28+
: super(metadata, 0, name, parent, charOffset);
2929

3030
String get debugName => "TypeAliasBuilder";
3131

pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ abstract class TypeDeclarationBuilder<T extends TypeBuilder, R>
2525
TypeDeclarationBuilder(
2626
this.metadata, this.modifiers, this.name, this.parent, int charOffset,
2727
[Uri fileUri])
28-
: super(parent, charOffset, fileUri);
28+
: assert(modifiers != null),
29+
super(parent, charOffset, fileUri);
2930

3031
bool get isTypeDeclaration => true;
3132

pkg/front_end/lib/src/fasta/kernel/expression_generator.dart

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ abstract class Generator {
169169

170170
/// Builds a [Expression] representing a read from the generator.
171171
///
172-
/// The read of the this subexpression does _not_ need to support a
173-
/// simultaneous write of the same subexpression.
172+
/// The read of this subexpression does _not_ need to support a simultaneous
173+
/// write of the same subexpression.
174174
Expression buildSimpleRead() {
175175
return _finish(_makeSimpleRead(), null);
176176
}
@@ -181,7 +181,7 @@ abstract class Generator {
181181
/// simultaneous write of the same subexpression.
182182
///
183183
/// This is in contrast to [_makeRead] which is used for instance in compound
184-
/// assignments like `a.b = c` where both a read and a write of the
184+
/// assignments like `a.b += c` where both a read and a write of the
185185
/// subexpression `a.b` occurs.
186186
///
187187
/// Subclasses that can benefit from this distinction should override this
@@ -440,6 +440,11 @@ abstract class Generator {
440440
}
441441
}
442442

443+
/// Returns a [TypeBuilder] for this subexpression instantiated with the
444+
/// type [arguments]. If no type arguments are provided [arguments] is `null`.
445+
///
446+
/// The type arguments have not been resolved and should be resolved to
447+
/// create a [TypeBuilder] for a valid type.
443448
TypeBuilder buildTypeWithResolvedArguments(
444449
List<UnresolvedType<TypeBuilder>> arguments) {
445450
NamedTypeBuilder result = new NamedTypeBuilder(token.lexeme, null);
@@ -1647,8 +1652,8 @@ class DeferredAccessGenerator extends Generator {
16471652
@override
16481653
TypeBuilder buildTypeWithResolvedArguments(
16491654
List<UnresolvedType<TypeBuilder>> arguments) {
1650-
String name =
1651-
"${prefixGenerator._plainNameForRead}.${suffixGenerator._plainNameForRead}";
1655+
String name = "${prefixGenerator._plainNameForRead}."
1656+
"${suffixGenerator._plainNameForRead}";
16521657
TypeBuilder type =
16531658
suffixGenerator.buildTypeWithResolvedArguments(arguments);
16541659
LocatedMessage message;
@@ -1705,6 +1710,25 @@ class DeferredAccessGenerator extends Generator {
17051710
}
17061711
}
17071712

1713+
/// [TypeUseGenerator] represents the subexpression whose prefix is the name of
1714+
/// a class, enum, type variable, typedef, mixin declaration, extension
1715+
/// declaration or built-in type, like dynamic and void.
1716+
///
1717+
/// For instance:
1718+
///
1719+
/// class A<T> {}
1720+
/// typedef B = Function();
1721+
/// mixin C<T> on A<T> {}
1722+
/// extension D<T> on A<T> {}
1723+
///
1724+
/// method<T>() {
1725+
/// C<B> // a TypeUseGenerator is created for `C` and `B`.
1726+
/// B b; // a TypeUseGenerator is created for `B`.
1727+
/// D.foo(); // a TypeUseGenerator is created for `D`.
1728+
/// new A<T>(); // a TypeUseGenerator is created for `A` and `T`.
1729+
/// T(); // a TypeUseGenerator is created for `T`.
1730+
/// }
1731+
///
17081732
class TypeUseGenerator extends ReadOnlyAccessGenerator {
17091733
final TypeDeclarationBuilder declaration;
17101734

@@ -1718,6 +1742,10 @@ class TypeUseGenerator extends ReadOnlyAccessGenerator {
17181742
@override
17191743
TypeBuilder buildTypeWithResolvedArguments(
17201744
List<UnresolvedType<TypeBuilder>> arguments) {
1745+
if (declaration.isExtension) {
1746+
// Extension declarations cannot be used as types.
1747+
return super.buildTypeWithResolvedArguments(arguments);
1748+
}
17211749
if (arguments != null) {
17221750
int expected = declaration.typeVariablesCount;
17231751
if (arguments.length != expected) {

pkg/front_end/lib/src/testing/id_testing_helper.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:front_end/src/api_prototype/compiler_options.dart'
5+
import 'package:kernel/ast.dart';
6+
import '../api_prototype/compiler_options.dart'
67
show CompilerOptions, DiagnosticMessage;
7-
import 'package:front_end/src/api_prototype/experimental_flags.dart'
8-
show ExperimentalFlag;
9-
import 'package:front_end/src/api_prototype/terminal_color_support.dart'
8+
import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
9+
import '../api_prototype/terminal_color_support.dart'
1010
show printDiagnosticMessage;
11-
import 'package:front_end/src/fasta/messages.dart' show FormattedMessage;
12-
import 'package:front_end/src/fasta/severity.dart' show Severity;
13-
import 'package:kernel/ast.dart';
11+
import '../fasta/messages.dart' show FormattedMessage;
12+
import '../fasta/severity.dart' show Severity;
1413
import '../kernel_generator_impl.dart' show CompilerResult;
1514
import 'compiler_common.dart' show compileScript, toTestUri;
1615
import 'id.dart'
@@ -29,6 +28,7 @@ import 'id_testing_utils.dart';
2928

3029
export '../fasta/compiler_context.dart' show CompilerContext;
3130
export '../kernel_generator_impl.dart' show CompilerResult;
31+
export '../fasta/messages.dart' show FormattedMessage;
3232

3333
/// Test configuration used for testing CFE in its default state.
3434
const TestConfig defaultCfeConfig = const TestConfig(cfeMarker, 'cfe');

pkg/front_end/lib/src/testing/id_testing_utils.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:front_end/src/fasta/builder/builder.dart';
6-
import 'package:front_end/src/fasta/kernel/kernel_builder.dart';
7-
import 'package:front_end/src/fasta/source/source_library_builder.dart';
8-
import 'package:front_end/src/fasta/source/source_loader.dart';
9-
import 'package:front_end/src/kernel_generator_impl.dart';
105
import 'package:kernel/ast.dart';
6+
import '../fasta/builder/builder.dart';
7+
import '../fasta/kernel/kernel_builder.dart';
8+
import '../fasta/messages.dart';
9+
import '../fasta/source/source_library_builder.dart';
10+
import '../fasta/source/source_loader.dart';
11+
import '../kernel_generator_impl.dart';
1112

1213
/// Helper methods to use in annotated tests.
1314
@@ -424,3 +425,8 @@ String typeVariableBuilderToText(TypeVariableBuilder typeVariable) {
424425
}
425426
return name;
426427
}
428+
429+
/// Returns a textual representation of [errors] to be used in testing.
430+
String errorsToText(List<FormattedMessage> errors) {
431+
return errors.map((m) => m.message).join(',');
432+
}

pkg/front_end/test/extensions/data/instance_members.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ extension B2<T> on B1<T> {
5454
builder-name=method1,
5555
member-name=method1
5656
*/
57-
B2<T> method1() {
57+
B1<T> method1() {
5858
// TODO(johnniwinther): Use `this` here instead.
5959
return null;
6060
}
@@ -67,7 +67,7 @@ extension B2<T> on B1<T> {
6767
member-params=[o],
6868
member-type-params=[S]
6969
*/
70-
B2<T> method2<S>(S o) {
70+
B1<T> method2<S>(S o) {
7171
print(o);
7272
// TODO(johnniwinther): Use `this` here instead.
7373
return null;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
class A1 {}
6+
7+
/*class: A2:
8+
builder-name=A2,
9+
builder-onTypes=[A1],
10+
builder-supertype=Object,
11+
cls-name=A2,
12+
cls-supertype=Object
13+
*/
14+
extension A2 on A1 {}
15+
16+
class B1<T> {}
17+
18+
/*class: B2:
19+
builder-name=B2,
20+
builder-onTypes=[B1<T>],
21+
builder-supertype=Object,
22+
builder-type-params=[T],
23+
cls-name=B2,
24+
cls-supertype=Object,
25+
cls-type-params=[T]
26+
*/
27+
extension B2<T> on B1<T> {}
28+
29+
main() {
30+
/*error: errors=['A2' isn't a type.]*/
31+
A2 var1;
32+
/*error: errors=['B2' isn't a type.]*/
33+
B2<A1> var2;
34+
B1</*error: errors=['A2' isn't a type.]*/A2> var3;
35+
}
36+
37+
/*error: errors=['A2' isn't a type.]*/
38+
A2 method1() => null;
39+
40+
// TODO(johnniwinther): We should report an error on the number of type
41+
// arguments here.
42+
/*error: errors=['B2' isn't a type.,Expected 0 type arguments.]*/
43+
B2<A1> method2() => null;
44+
45+
B1</*error: errors=['A2' isn't a type.]*/A2> method3() => null;

pkg/front_end/test/extensions/extensions_test.dart

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,8 @@ import 'package:front_end/src/testing/features.dart';
1010
import 'package:front_end/src/testing/id_testing.dart'
1111
show DataInterpreter, runTests;
1212
import 'package:front_end/src/testing/id_testing.dart';
13-
import 'package:front_end/src/testing/id_testing_helper.dart'
14-
show
15-
CfeDataExtractor,
16-
CompilerResult,
17-
DataComputer,
18-
cfeExtensionMethodsConfig,
19-
createUriForFileName,
20-
onFailure,
21-
runTestFor;
13+
import 'package:front_end/src/testing/id_testing_helper.dart';
2214
import 'package:front_end/src/testing/id_testing_utils.dart';
23-
import 'package:kernel/ast.dart' show Class, Member, TreeNode;
2415
import 'package:kernel/ast.dart';
2516

2617
main(List<String> args) async {
@@ -51,6 +42,19 @@ class ExtensionsDataComputer extends DataComputer<Features> {
5142
new ExtensionsDataExtractor(compilerResult, actualMap).computeForClass(cls);
5243
}
5344

45+
@override
46+
bool get supportsErrors => true;
47+
48+
@override
49+
Features computeErrorData(
50+
CompilerResult compiler, Id id, List<FormattedMessage> errors) {
51+
Features features = new Features();
52+
for (FormattedMessage error in errors) {
53+
features.addElement(Tags.errors, error.message);
54+
}
55+
return features;
56+
}
57+
5458
@override
5559
DataInterpreter<Features> get dataValidator =>
5660
const FeaturesDataInterpreter();
@@ -72,6 +76,8 @@ class Tags {
7276
static const String memberName = 'member-name';
7377
static const String memberTypeParameters = 'member-type-params';
7478
static const String memberParameters = 'member-params';
79+
80+
static const String errors = 'errors';
7581
}
7682

7783
class ExtensionsDataExtractor extends CfeDataExtractor<Features> {
@@ -118,11 +124,6 @@ class ExtensionsDataExtractor extends CfeDataExtractor<Features> {
118124
return features;
119125
}
120126

121-
@override
122-
Features computeNodeValue(Id id, TreeNode node) {
123-
return null;
124-
}
125-
126127
@override
127128
Features computeMemberValue(Id id, Member member) {
128129
if (member.enclosingClass == null) {

pkg/front_end/test/id_testing/id_testing_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class IdTestingDataComputer extends DataComputer<String> {
6666

6767
String computeErrorData(
6868
CompilerResult compiler, Id id, List<FormattedMessage> errors) {
69-
return errors.map((m) => m.message).join(',');
69+
return errorsToText(errors);
7070
}
7171

7272
@override

0 commit comments

Comments
 (0)