@@ -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
30283075String 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+ }
0 commit comments