Skip to content

Commit 21b026d

Browse files
jensjohacommit-bot@chromium.org
authored andcommitted
[CFE] Issue error when langauge version is specified too high
Specifying a language version higher than the highest supported version (aka the default version) is an error. Specifying a language verison in code that is higher than the one specified in .packages is an error. Change-Id: I44e1c8c45cef715038786dbf248925b73bd6cd7c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112240 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
1 parent 43eb2f7 commit 21b026d

File tree

20 files changed

+219
-14
lines changed

20 files changed

+219
-14
lines changed

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,19 @@ abstract class LibraryBuilder extends ModifierBuilder {
6464
/// Set the langauge version to a specific non-null major and minor version.
6565
///
6666
/// If the language version has previously been explicitly set set (i.e. with
67-
/// [explicit] set to true(), any subsequent call )(explicit or not) should be
67+
/// [explicit] set to true), any subsequent call (explicit or not) should be
6868
/// ignored.
6969
/// Multiple calls with [explicit] set to false should be allowed though.
7070
///
7171
/// The main idea is that the .packages file specifies a default language
72-
/// version, but that the library can have source code that speicies another
72+
/// version, but that the library can have source code that specifies another
7373
/// one which should be supported, but specifying several in code should not
7474
/// change anything.
75-
void setLanguageVersion(int major, int minor, {bool explicit});
75+
///
76+
/// [offset] and [length] refers to the offset and length of the source code
77+
/// specifying the language version.
78+
void setLanguageVersion(int major, int minor,
79+
{int offset: 0, int length, bool explicit});
7680

7781
@override
7882
Declaration get parent => null;

pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ class DillLibraryBuilder extends LibraryBuilder {
124124
bool get isSynthetic => library.isSynthetic;
125125

126126
@override
127-
void setLanguageVersion(int major, int minor, {bool explicit}) {}
127+
void setLanguageVersion(int major, int minor,
128+
{int offset: 0, int length, bool explicit}) {}
128129

129130
Uri get uri => library.importUri;
130131

pkg/front_end/lib/src/fasta/fasta_codes_generated.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6570,6 +6570,34 @@ Message _withArgumentsLabelNotFound(String name) {
65706570
arguments: {'name': name});
65716571
}
65726572

6573+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6574+
const Template<
6575+
Message Function(
6576+
int count,
6577+
int
6578+
count2)> templateLanguageVersionTooHigh = const Template<
6579+
Message Function(int count, int count2)>(
6580+
messageTemplate:
6581+
r"""The specified language version is too high. The highest supported language version is #count.#count2.""",
6582+
withArguments: _withArgumentsLanguageVersionTooHigh);
6583+
6584+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6585+
const Code<Message Function(int count, int count2)> codeLanguageVersionTooHigh =
6586+
const Code<Message Function(int count, int count2)>(
6587+
"LanguageVersionTooHigh",
6588+
templateLanguageVersionTooHigh,
6589+
);
6590+
6591+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6592+
Message _withArgumentsLanguageVersionTooHigh(int count, int count2) {
6593+
if (count == null) throw 'No count provided';
6594+
if (count2 == null) throw 'No count provided';
6595+
return new Message(codeLanguageVersionTooHigh,
6596+
message:
6597+
"""The specified language version is too high. The highest supported language version is ${count}.${count2}.""",
6598+
arguments: {'count': count, 'count2': count2});
6599+
}
6600+
65736601
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
65746602
const Code<Null> codeLibraryDirectiveNotFirst = messageLibraryDirectiveNotFirst;
65756603

pkg/front_end/lib/src/fasta/source/source_library_builder.dart

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ import '../fasta_codes.dart'
129129
templateIncorrectTypeArgumentQualified,
130130
templateIncorrectTypeArgumentQualifiedInferred,
131131
templateIntersectionTypeAsTypeArgument,
132+
templateLanguageVersionTooHigh,
132133
templateLoadLibraryHidesMember,
133134
templateLocalDefinitionHidesExport,
134135
templateLocalDefinitionHidesImport,
@@ -312,6 +313,9 @@ class SourceLibraryBuilder extends LibraryBuilder {
312313

313314
bool languageVersionExplicitlySet = false;
314315

316+
bool postponedProblemsIssued = false;
317+
List<PostponedProblem> postponedProblems;
318+
315319
SourceLibraryBuilder.internal(SourceLoader loader, Uri fileUri, Scope scope,
316320
SourceLibraryBuilder actualOrigin, Library library, Library nameOrigin)
317321
: this.fromScopes(loader, fileUri, new DeclarationBuilder.library(),
@@ -356,10 +360,26 @@ class SourceLibraryBuilder extends LibraryBuilder {
356360
}
357361

358362
@override
359-
void setLanguageVersion(int major, int minor, {bool explicit}) {
363+
void setLanguageVersion(int major, int minor,
364+
{int offset: 0, int length: noLength, bool explicit}) {
360365
if (languageVersionExplicitlySet) return;
361-
library.setLanguageVersion(major, minor);
362366
if (explicit) languageVersionExplicitlySet = true;
367+
368+
// If no language version has been set, the default is used.
369+
// If trying to set a langauge version that is higher than the "already-set"
370+
// version it's an error.
371+
if (major > library.languageVersionMajor ||
372+
(major == library.languageVersionMajor &&
373+
minor > library.languageVersionMinor)) {
374+
addPostponedProblem(
375+
templateLanguageVersionTooHigh.withArguments(
376+
library.languageVersionMajor, library.languageVersionMinor),
377+
offset,
378+
length,
379+
fileUri);
380+
return;
381+
}
382+
library.setLanguageVersion(major, minor);
363383
}
364384

365385
ConstructorReferenceBuilder addConstructorReference(Object name,
@@ -1105,6 +1125,33 @@ class SourceLibraryBuilder extends LibraryBuilder {
11051125
..bind(new VoidTypeBuilder(const VoidType(), this, charOffset));
11061126
}
11071127

1128+
/// Add a problem that might not be reported immediately.
1129+
///
1130+
/// Problems will be issued after source information has been added.
1131+
/// Once the problems has been issued, adding a new "postponed" problem will
1132+
/// be issued immediately.
1133+
void addPostponedProblem(
1134+
Message message, int charOffset, int length, Uri fileUri) {
1135+
if (postponedProblemsIssued) {
1136+
addProblem(message, charOffset, length, fileUri);
1137+
} else {
1138+
postponedProblems ??= <PostponedProblem>[];
1139+
postponedProblems
1140+
.add(new PostponedProblem(message, charOffset, length, fileUri));
1141+
}
1142+
}
1143+
1144+
void issuePostponedProblems() {
1145+
postponedProblemsIssued = true;
1146+
if (postponedProblems == null) return;
1147+
for (int i = 0; i < postponedProblems.length; ++i) {
1148+
PostponedProblem postponedProblem = postponedProblems[i];
1149+
addProblem(postponedProblem.message, postponedProblem.charOffset,
1150+
postponedProblem.length, postponedProblem.fileUri);
1151+
}
1152+
postponedProblems = null;
1153+
}
1154+
11081155
@override
11091156
FormattedMessage addProblem(
11101157
Message message, int charOffset, int length, Uri fileUri,
@@ -3026,3 +3073,12 @@ Uri computeLibraryUri(Declaration declaration) {
30263073
}
30273074

30283075
String extractName(name) => name is QualifiedName ? name.name : name;
3076+
3077+
class PostponedProblem {
3078+
final Message message;
3079+
final int charOffset;
3080+
final int length;
3081+
final Uri fileUri;
3082+
3083+
PostponedProblem(this.message, this.charOffset, this.length, this.fileUri);
3084+
}

pkg/front_end/lib/src/fasta/source/source_loader.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ class SourceLoader extends Loader {
214214
// TODO(jensj): What if we have several? What if it is unsupported?
215215
// What if the language version was already set via packages and this is
216216
// higher? Etc
217-
library.setLanguageVersion(version.major, version.minor, explicit: true);
217+
library.setLanguageVersion(version.major, version.minor,
218+
offset: version.offset, length: version.length, explicit: true);
218219
});
219220
Token token = result.tokens;
220221
if (!suppressLexicalErrors) {
@@ -236,6 +237,7 @@ class SourceLoader extends Loader {
236237
target.addSourceInformation(
237238
importUri, library.fileUri, result.lineStarts, source);
238239
}
240+
library.issuePostponedProblems();
239241
while (token is ErrorToken) {
240242
if (!suppressLexicalErrors) {
241243
ErrorToken error = token;

pkg/front_end/messages.status

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ InvalidVoid/part_wrapped_script1: Fail
334334
InvalidVoid/part_wrapped_script2: Fail
335335
InvalidVoid/script1: Fail
336336
InvalidVoid/script2: Fail
337+
LanguageVersionTooHigh/analyzerCode: Fail
338+
LanguageVersionTooHigh/part_wrapped_script: Fail # Content comes after "part of [...]" meaning it's not actually a language version specification.
337339
LibraryDirectiveNotFirst/part_wrapped_script1: Fail # Defining library name in the (now) part.
338340
LibraryDirectiveNotFirst/part_wrapped_script2: Fail
339341
LibraryDirectiveNotFirst/part_wrapped_script3: Fail

pkg/front_end/messages.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3613,3 +3613,8 @@ CombinedMemberSignatureFailed:
36133613
}
36143614
36153615
abstract class C implements I2, I1 {}
3616+
3617+
LanguageVersionTooHigh:
3618+
template: "The specified language version is too high. The highest supported language version is #count.#count2."
3619+
script: >
3620+
// @dart = 100.200
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
/*error: LanguageVersionTooHigh*/
6+
// @dart = 3.5
7+
8+
// If no valid language version is specified, we default to the most reason one.
9+
// In the tests this is hard-coded to 2.8.
10+
11+
/*library: languageVersion=2.8*/
12+
13+
main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
/*error: LanguageVersionTooHigh*/
6+
// @dart = 3.5
7+
8+
// @dart = 2.5
9+
10+
// If the first language version specified is not a valid language version,
11+
// we default to the most reason one. In the tests this is hard-coded to 2.8.
12+
13+
/*library: languageVersion=2.8*/
14+
15+
main() {}

pkg/front_end/test/language_versioning/data/library_with_no_version.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
// If no language version is specified, and none if given in a .packages file,
6-
// we default to the most reason one. In the tests this is hard-coded to 2.4.
6+
// we default to the most reason one. In the tests this is hard-coded to 2.8.
77

8-
/*library: languageVersion=2.4*/
8+
/*library: languageVersion=2.8*/
99

1010
main() {}

0 commit comments

Comments
 (0)