replace parser language version comment processing

This CL removes duplicate language version processing from parser
now that the scanner does this work.

In addition...
- update parser tests to listen for languageVersion scanner event
- remove languageVersion field from CompilationUnitImpl and AstBuilder
- add Scanner.buildConfig for translating a FeatureSet into a ScannerConfiguration
- remove old language version parser tests
- cleanup parser nnbd tests

Change-Id: I6ead6a3ab6d5d424e9a7dfbf69da110e43c63982
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100990
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 47135ed..bbc3d44 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -28,7 +28,6 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:pub_semver/src/version.dart';
 
 /// Two or more string literals that are implicitly concatenated because of
 /// being adjacent (separated only by whitespace).
@@ -2045,8 +2044,6 @@
   @override
   CompilationUnitElement declaredElement;
 
-  Version languageVersion;
-
   /// The line information for this compilation unit.
   @override
   LineInfo lineInfo;
@@ -2061,7 +2058,7 @@
   LocalVariableInfo localVariableInfo = new LocalVariableInfo();
 
   /// Is `true` if this unit has been parsed as non-nullable.
-  bool isNonNullable = false;
+  final bool isNonNullable;
 
   @override
   final FeatureSet featureSet;
@@ -2077,7 +2074,9 @@
       List<Directive> directives,
       List<CompilationUnitMember> declarations,
       this.endToken,
-      this.featureSet) {
+      this.featureSet)
+      : this.isNonNullable =
+            featureSet?.isEnabled(Feature.non_nullable) ?? false {
     _scriptTag = _becomeParentOf(scriptTag);
     _directives = new NodeListImpl<Directive>(this, directives);
     _declarations = new NodeListImpl<CompilationUnitMember>(this, declarations);
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index 717805d..566caf2 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -151,4 +151,13 @@
     }
     return firstToken;
   }
+
+  /// Return a ScannerConfiguration based upon the specified feature set.
+  static fasta.ScannerConfiguration buildConfig(FeatureSet featureSet) =>
+      featureSet == null
+          ? fasta.ScannerConfiguration()
+          : fasta.ScannerConfiguration(
+              enableGtGtGt: featureSet.isEnabled(Feature.triple_shift),
+              enableGtGtGtEq: featureSet.isEnabled(Feature.triple_shift),
+              enableNonNullable: featureSet.isEnabled(Feature.non_nullable));
 }
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 5e22b47..ccc46ca 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -57,9 +57,8 @@
     show NullValue, StackListener;
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/token.dart'
-    show CommentToken, SyntheticStringToken, SyntheticToken;
+    show SyntheticStringToken, SyntheticToken;
 import 'package:kernel/ast.dart' show AsyncMarker;
-import 'package:pub_semver/pub_semver.dart';
 
 const _invalidCollectionElement = const _InvalidCollectionElement._();
 
@@ -70,7 +69,6 @@
   final FastaErrorReporter errorReporter;
   final Uri fileUri;
   ScriptTag scriptTag;
-  Version languageVersion;
   final List<Directive> directives = <Directive>[];
   final List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
   final localDeclarations = <int, AstNode>{};
@@ -513,8 +511,6 @@
         declarations: declarations,
         endToken: endToken,
         featureSet: _featureSet) as CompilationUnitImpl;
-    unit.languageVersion = languageVersion;
-    unit.isNonNullable = enableNonNullable;
     push(unit);
   }
 
@@ -2522,16 +2518,6 @@
     push(ast.label(name, colon));
   }
 
-  @override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    debugEvent('LanguageVersion');
-    assert(commentToken is CommentToken);
-    assert(major != null);
-    assert(minor != null);
-
-    languageVersion = Version(major, minor, 0);
-  }
-
   void handleLiteralBool(Token token) {
     bool value = identical(token.stringValue, "true");
     assert(value || identical(token.stringValue, "false"));
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 78b62e4..f002898 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -19,11 +19,13 @@
 import 'package:front_end/src/fasta/parser/async_modifier.dart';
 import 'package:front_end/src/fasta/parser/forwarding_listener.dart' as fasta;
 import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
+import 'package:front_end/src/fasta/scanner.dart' as fasta;
 import 'package:front_end/src/fasta/scanner.dart'
-    show ScannerConfiguration, ScannerResult, scanString;
+    show LanguageVersionToken, ScannerConfiguration, ScannerResult, scanString;
 import 'package:front_end/src/fasta/scanner/error_token.dart' show ErrorToken;
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
+import 'package:pub_semver/src/version.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -1640,17 +1642,22 @@
           .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
     }
 
+    // Adjust the feature set based on language version comment.
+    void languageVersionChanged(
+        fasta.Scanner scanner, LanguageVersionToken languageVersion) {
+      // TODO(danrubel): Move this to a central location
+      // and base this on the feature set being downgraded.
+
+      featureSet = featureSet.restrictToVersion(
+          Version(languageVersion.major, languageVersion.minor, 0));
+      scanner.configuration = Scanner.buildConfig(featureSet);
+    }
+
     // Scan tokens
-    bool enableTripleShift =
-        featureSet != null && featureSet.isEnabled(Feature.triple_shift);
-    bool enableNonNullable =
-        featureSet != null && featureSet.isEnabled(Feature.non_nullable);
     ScannerResult result = scanString(content,
         includeComments: true,
-        configuration: ScannerConfiguration(
-            enableGtGtGt: enableTripleShift,
-            enableGtGtGtEq: enableTripleShift,
-            enableNonNullable: enableNonNullable));
+        configuration: Scanner.buildConfig(featureSet),
+        languageVersionChanged: languageVersionChanged);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -2151,24 +2158,19 @@
  */
 @reflectiveTest
 class NNBDParserTest_Fasta extends FastaParserTestCase {
-  CompilationUnit parseNNBDCompilationUnit(String code,
-      {List<ExpectedError> errors}) {
-    createParser(code, featureSet: nonNullable);
-    CompilationUnit unit = _parserProxy.parseCompilationUnit2();
-    assertErrors(errors: errors);
-    return unit;
-  }
-
   void test_assignment_complex() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }',
+        featureSet: nonNullable);
   }
 
   void test_assignment_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }',
+        featureSet: nonNullable);
   }
 
   void test_binary_expression_statement() {
-    final unit = parseNNBDCompilationUnit('D? foo(X? x) { X ?? x2; }');
+    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }',
+        featureSet: nonNullable);
     FunctionDeclaration funct = unit.declarations[0];
     BlockFunctionBody body = funct.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -2181,24 +2183,28 @@
   }
 
   void test_conditional() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }',
+        featureSet: nonNullable);
   }
 
   void test_conditional_complex() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }',
+        featureSet: nonNullable);
   }
 
   void test_conditional_error() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
+    parseCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
         errors: [
           expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
           expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
           expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
-        ]);
+        ],
+        featureSet: nonNullable);
   }
 
   void test_conditional_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }',
+        featureSet: nonNullable);
   }
 
   void test_enableNonNullable_false() {
@@ -2207,49 +2213,59 @@
   }
 
   void test_for() {
-    parseNNBDCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
+    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }',
+        featureSet: nonNullable);
   }
 
   void test_for_conditional() {
-    parseNNBDCompilationUnit(
-        'main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
+    parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }',
+        featureSet: nonNullable);
   }
 
   void test_for_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
+    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }',
+        featureSet: nonNullable);
   }
 
   void test_foreach() {
-    parseNNBDCompilationUnit('main() { for(int x in [7]) { } }');
+    parseCompilationUnit('main() { for(int x in [7]) { } }',
+        featureSet: nonNullable);
   }
 
   void test_foreach_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x in [7, null]) { } }');
+    parseCompilationUnit('main() { for(int? x in [7, null]) { } }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable() {
-    parseNNBDCompilationUnit('main() { C? Function() x = 7; }');
+    parseCompilationUnit('main() { C? Function() x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_1() {
-    parseNNBDCompilationUnit('main() { C Function()? x = 7; }');
+    parseCompilationUnit('main() { C Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_2() {
-    parseNNBDCompilationUnit('main() { C? Function()? x = 7; }');
+    parseCompilationUnit('main() { C? Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_3() {
-    parseNNBDCompilationUnit('main() { C? Function()? Function()? x = 7; }');
+    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_prefixed() {
-    parseNNBDCompilationUnit('main() { C.a? Function()? x = 7; }');
+    parseCompilationUnit('main() { C.a? Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_is_nullable() {
-    CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { x is String? ? (x + y) : z; }');
+    CompilationUnit unit = parseCompilationUnit(
+        'main() { x is String? ? (x + y) : z; }',
+        featureSet: nonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -2264,8 +2280,9 @@
   }
 
   void test_is_nullable_parenthesis() {
-    CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
+    CompilationUnit unit = parseCompilationUnit(
+        'main() { (x is String?) ? (x + y) : z; }',
+        featureSet: nonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -2280,6 +2297,15 @@
     expect(elseExpression, isSimpleIdentifier);
   }
 
+  void test_is_nullable_parenthesis_optOut() {
+    parseCompilationUnit('''
+// @dart = 2.2
+main() { (x is String?) ? (x + y) : z; }
+''',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)],
+        featureSet: nonNullable);
+  }
+
   void test_late_as_identifier() {
     parseCompilationUnit('''
 class C {
@@ -2296,7 +2322,7 @@
 ''', featureSet: preNonNullable);
   }
 
-  void test_late_as_identifier_opt_out() {
+  void test_late_as_identifier_optOut() {
     parseCompilationUnit('''
 // @dart = 2.2
 class C {
@@ -2314,7 +2340,8 @@
   }
 
   void test_nullCheck() {
-    var unit = parseNNBDCompilationUnit('f(int? y) { var x = y!; }');
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
+        featureSet: nonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     VariableDeclarationStatement statement = body.block.statements[0];
@@ -2339,19 +2366,22 @@
   }
 
   void test_nullCheckFunctionResult() {
-    parseNNBDCompilationUnit('f() { var x = g()! + 7; }');
+    parseCompilationUnit('f() { var x = g()! + 7; }', featureSet: nonNullable);
   }
 
   void test_nullCheckIndexedValue() {
-    parseNNBDCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckIndexedValue2() {
-    parseNNBDCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckInExpression() {
-    parseNNBDCompilationUnit('f(int? y) { var x = y! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckInExpression_disabled() {
@@ -2364,23 +2394,28 @@
   }
 
   void test_nullCheckMethodResult() {
-    parseNNBDCompilationUnit('f() { var x = g.m()! + 7; }');
+    parseCompilationUnit('f() { var x = g.m()! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckMethodResult2() {
-    parseNNBDCompilationUnit('f() { var x = g?.m()! + 7; }');
+    parseCompilationUnit('f() { var x = g?.m()! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckMethodResult3() {
-    parseNNBDCompilationUnit('f() { var x = super.m()! + 7; }');
+    parseCompilationUnit('f() { var x = super.m()! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckOnConstConstructor() {
-    parseNNBDCompilationUnit('f() { var x = const Foo()!; }');
+    parseCompilationUnit('f() { var x = const Foo()!; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckOnConstructor() {
-    parseNNBDCompilationUnit('f() { var x = new Foo()!; }');
+    parseCompilationUnit('f() { var x = new Foo()!; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteral_disabled() {
@@ -2391,46 +2426,47 @@
 
   void test_nullCheckOnLiteralDouble() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = 1.2!; }');
+    parseCompilationUnit('f() { var x = 1.2!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralInt() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = 0!; }');
+    parseCompilationUnit('f() { var x = 0!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralList() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = [1,2]!; }');
+    parseCompilationUnit('f() { var x = [1,2]!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralMap() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = {1:2}!; }');
+    parseCompilationUnit('f() { var x = {1:2}!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralSet() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = {1,2}!; }');
+    parseCompilationUnit('f() { var x = {1,2}!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralString() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = "seven"!; }');
+    parseCompilationUnit('f() { var x = "seven"!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnNull() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = null!; }');
+    parseCompilationUnit('f() { var x = null!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnSymbol() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = #seven!; }');
+    parseCompilationUnit('f() { var x = #seven!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnValue() {
-    parseNNBDCompilationUnit('f(Point p) { var x = p.y! + 7; }');
+    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckOnValue_disabled() {
@@ -2440,24 +2476,27 @@
   }
 
   void test_nullCheckParenthesizedExpression() {
-    parseNNBDCompilationUnit('f(int? y) { var x = (y)! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = (y)! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckPropertyAccess() {
-    parseNNBDCompilationUnit('f() { var x = g.p! + 7; }');
+    parseCompilationUnit('f() { var x = g.p! + 7; }', featureSet: nonNullable);
   }
 
   void test_nullCheckPropertyAccess2() {
-    parseNNBDCompilationUnit('f() { var x = g?.p! + 7; }');
+    parseCompilationUnit('f() { var x = g?.p! + 7; }', featureSet: nonNullable);
   }
 
   void test_nullCheckPropertyAccess3() {
-    parseNNBDCompilationUnit('f() { var x = super.p! + 7; }');
+    parseCompilationUnit('f() { var x = super.p! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
     // -x! is parsed as -(x!).
-    var unit = parseNNBDCompilationUnit('void main() { -x!; }');
+    var unit =
+        parseCompilationUnit('void main() { -x!; }', featureSet: nonNullable);
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -2469,7 +2508,8 @@
 
   void test_postfix_null_assertion_of_postfix_expression() {
     // x++! is parsed as (x++)!.
-    var unit = parseNNBDCompilationUnit('void main() { x++!; }');
+    var unit =
+        parseCompilationUnit('void main() { x++!; }', featureSet: nonNullable);
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -3238,101 +3278,6 @@
 @reflectiveTest
 class TopLevelParserTest_Fasta extends FastaParserTestCase
     with TopLevelParserTestMixin {
-  void test_languageVersion_afterImport() {
-    var unit = parseCompilationUnit('''
-import 'foo.dart';
-// @dart = 2.3
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_beforeComment() {
-    var unit = parseCompilationUnit('''
-// some other comment
-// @dart = 2.3
-// yet another comment
-import 'foo.dart';
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeFunction() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.3
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeImport() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.3
-import 'foo.dart';
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeImport_afterScript() {
-    var unit = parseCompilationUnit('''
-#!/bin/dart
-// @dart = 2.3
-import 'foo.dart';
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeLibrary() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.3
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_incomplete_version() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_invalid_identifier() {
-    var unit = parseCompilationUnit('''
-// @dart = blat
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_invalid_version() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.x
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_unspecified() {
-    var unit = parseCompilationUnit('''
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
   void test_parseClassDeclaration_native_allowed() {
     allowNativeClause = true;
     test_parseClassDeclaration_native();
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 433dec9..bb60229 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -1149,11 +1149,6 @@
   }
 
   @override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    listener?.handleLanguageVersion(commentToken, major, minor);
-  }
-
-  @override
   void handleLiteralBool(Token token) {
     listener?.handleLiteralBool(token);
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index a975c63..5239ab9 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -1423,15 +1423,6 @@
     logEvent("Script");
   }
 
-  /// A language version comment was parsed of the form
-  /// // @dart = <major>.<minor>
-  ///
-  /// For more information, see
-  /// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/language-versioning.md#individual-library-language-version-override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    // TODO(danrubel): Update listeners to handle this
-  }
-
   /// A type has been just parsed, and the parser noticed that the next token
   /// has a type substitution comment /*=T*. So, the type that has been just
   /// parsed should be discarded, and a new type should be parsed instead.
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 2894e06..51b32e6 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -10,14 +10,11 @@
 
 import '../scanner.dart' show ErrorToken, Token;
 
-import '../scanner/characters.dart' show $0, $9, $SPACE;
-
 import '../../scanner/token.dart'
     show
         ASSIGNMENT_PRECEDENCE,
         BeginToken,
         CASCADE_PRECEDENCE,
-        CommentToken,
         EQUALITY_PRECEDENCE,
         Keyword,
         POSTFIX_PRECEDENCE,
@@ -341,7 +338,6 @@
       directiveState?.checkScriptTag(this, token.next);
       token = parseScript(token);
     }
-    parseLanguageVersionOpt(token);
     while (!token.next.isEof) {
       final Token start = token.next;
       token = parseTopLevelDeclarationImpl(token, directiveState);
@@ -368,74 +364,6 @@
     return token;
   }
 
-  /// Parse the optional language version comment as specified in
-  /// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/language-versioning.md#individual-library-language-version-override
-  void parseLanguageVersionOpt(Token token) {
-    // TODO(danrubel): Handle @dart version multi-line comments and dartdoc
-    // or update the spec to exclude them.
-    token = token.next.precedingComments;
-    while (token is CommentToken) {
-      if (parseLanguageVersionText(token)) {
-        break;
-      }
-      token = token.next;
-    }
-  }
-
-  bool parseLanguageVersionText(CommentToken token) {
-    String text = token.lexeme;
-    if (text == null || !text.startsWith('//')) {
-      return false;
-    }
-    int index = _skipSpaces(text, 2);
-    if (!text.startsWith('@dart', index)) {
-      return false;
-    }
-    index = _skipSpaces(text, index + 5);
-    if (!text.startsWith('=', index)) {
-      return false;
-    }
-    int start = index = _skipSpaces(text, index + 1);
-    index = _skipDigits(text, start);
-    if (start == index) {
-      return false;
-    }
-    int major = int.parse(text.substring(start, index));
-    if (!text.startsWith('.', index)) {
-      return false;
-    }
-    start = index + 1;
-    index = _skipDigits(text, start);
-    if (start == index) {
-      return false;
-    }
-    int minor = int.parse(text.substring(start, index));
-    index = _skipSpaces(text, index);
-    if (index != text.length) {
-      return false;
-    }
-    listener.handleLanguageVersion(token, major, minor);
-    return true;
-  }
-
-  int _skipSpaces(String text, int index) {
-    while (index < text.length && text.codeUnitAt(index) == $SPACE) {
-      ++index;
-    }
-    return index;
-  }
-
-  int _skipDigits(String text, int index) {
-    while (index < text.length) {
-      int code = text.codeUnitAt(index);
-      if (code < $0 || code > $9) {
-        break;
-      }
-      ++index;
-    }
-    return index;
-  }
-
   /// This method exists for analyzer compatibility only
   /// and will be removed once analyzer/fasta integration is complete.
   ///