Version 2.14.0-14.0.dev

Merge commit '5168b3eb96e03e23542653494917f1f21a3537a8' into 'dev'
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 406ded7..398e956 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -9,6 +9,8 @@
   Use `AnalysisSession.getResolvedLibraryByElement2()` instead.
 * Deprecated `AnalysisSession.getLibraryByUri()`.
   Use `AnalysisSession.getLibraryByUri2()` instead.
+* Deprecated `AnalysisSession.getErrors()`.
+  Use `AnalysisSession.getErrors2()` instead.
 
 ## 1.4.0
 * Deprecated `TypeProvider.nonSubtypableClasses`.
diff --git a/pkg/analyzer/example/analyze.dart b/pkg/analyzer/example/analyze.dart
index 7442e33..a94f27e 100644
--- a/pkg/analyzer/example/analyze.dart
+++ b/pkg/analyzer/example/analyze.dart
@@ -5,6 +5,7 @@
 import 'dart:io';
 
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 
@@ -31,12 +32,14 @@
         continue;
       }
 
-      final errorsResult = await context.currentSession.getErrors(filePath);
-      for (final error in errorsResult.errors) {
-        if (error.errorCode.type != ErrorType.TODO) {
-          print(
-              '  \u001b[1m${error.source.shortName}\u001b[0m ${error.message}');
-          issueCount++;
+      final errorsResult = await context.currentSession.getErrors2(filePath);
+      if (errorsResult is ErrorsResult) {
+        for (final error in errorsResult.errors) {
+          if (error.errorCode.type != ErrorType.TODO) {
+            print(
+                '  \u001b[1m${error.source.shortName}\u001b[0m ${error.message}');
+            issueCount++;
+          }
         }
       }
     }
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index e60f786..762a44f 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -74,7 +74,8 @@
 /// syntactic and semantic.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class ErrorsResult implements AnalysisResultWithErrors {}
+abstract class ErrorsResult
+    implements SomeErrorsResult, AnalysisResultWithErrors {}
 
 /// The result of computing some cheap information for a single file, when full
 /// parsed file is not required, so [ParsedUnitResult] is not necessary.
@@ -97,6 +98,7 @@
 class InvalidPathResult
     implements
         InvalidResult,
+        SomeErrorsResult,
         SomeResolvedLibraryResult,
         SomeResolvedUnitResult,
         SomeUnitElementResult {}
@@ -142,6 +144,7 @@
 class NotPathOfUriResult
     implements
         InvalidResult,
+        SomeErrorsResult,
         SomeResolvedLibraryResult,
         SomeResolvedUnitResult,
         SomeUnitElementResult {}
@@ -262,6 +265,15 @@
   VALID
 }
 
+/// The result of computing all of the errors contained in a single file, both
+/// syntactic and semantic.
+///
+/// Clients may not extend, implement or mix-in this class.
+///
+/// There are existing implementations of this class.
+/// [ErrorsResult] represents a valid result.
+abstract class SomeErrorsResult {}
+
 /// The result of building the element model for a library.
 ///
 /// Clients may not extend, implement or mix-in this class.
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 21c2c01..5e4b6fa 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -36,8 +36,16 @@
   ///
   /// If the file cannot be analyzed by this session, then the result will have
   /// a result state indicating the nature of the problem.
+  @Deprecated('Use getErrors2() instead')
   Future<ErrorsResult> getErrors(String path);
 
+  /// Return a future that will complete with information about the errors
+  /// contained in the file with the given absolute, normalized [path].
+  ///
+  /// If the file cannot be analyzed by this session, then the result will have
+  /// a result state indicating the nature of the problem.
+  Future<SomeErrorsResult> getErrors2(String path);
+
   /// Return information about the file at the given absolute, normalized
   /// [path].
   FileResult getFile(String path);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index ed6805c..33182f1 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -171,7 +171,7 @@
   final _referencingNameTasks = <_FilesReferencingNameTask>[];
 
   /// The mapping from the files for which errors were requested using
-  /// [getErrors] to the [Completer]s to report the result.
+  /// [getErrors2] to the [Completer]s to report the result.
   final _errorsRequestedFiles = <String, List<Completer<ErrorsResult>>>{};
 
   /// The requests from [_errorsRequestedFiles] for files which were found to
@@ -549,12 +549,39 @@
   ///
   /// This method does not use analysis priorities, and must not be used in
   /// interactive analysis, such as Analysis Server or its plugins.
+  @Deprecated('Use getErrors2() instead')
   Future<ErrorsResult> getErrors(String path) async {
     _throwIfNotAbsolutePath(path);
-    if (!_fsState.hasUri(path)) {
+
+    var result = await getErrors2(path);
+
+    if (result is NotPathOfUriResult) {
       return NotValidErrorsResultImpl(ResultState.NOT_FILE_OF_URI);
     }
 
+    return result as ErrorsResult;
+  }
+
+  /// Return a [Future] that completes with the [ErrorsResult] for the Dart
+  /// file with the given [path].
+  ///
+  /// The [path] must be absolute and normalized.
+  ///
+  /// This method does not use analysis priorities, and must not be used in
+  /// interactive analysis, such as Analysis Server or its plugins.
+  Future<SomeErrorsResult> getErrors2(String path) async {
+    if (!_isAbsolutePath(path)) {
+      return Future.value(
+        InvalidPathResult(),
+      );
+    }
+
+    if (!_fsState.hasUri(path)) {
+      return Future.value(
+        NotPathOfUriResult(),
+      );
+    }
+
     var completer = Completer<ErrorsResult>();
     _errorsRequestedFiles
         .putIfAbsent(path, () => <Completer<ErrorsResult>>[])
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 108b6cd..fe0a088 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -58,6 +58,7 @@
   @deprecated
   driver.AnalysisDriver getDriver() => _driver;
 
+  @Deprecated('Use getErrors2() instead')
   @override
   Future<ErrorsResult> getErrors(String path) {
     _checkConsistency();
@@ -65,6 +66,12 @@
   }
 
   @override
+  Future<SomeErrorsResult> getErrors2(String path) {
+    _checkConsistency();
+    return _driver.getErrors2(path);
+  }
+
+  @override
   FileResult getFile(String path) {
     _checkConsistency();
     return _driver.getFileSync(path);
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 6869458..dceca73 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -6,6 +6,7 @@
 import 'dart:io' as io;
 
 import 'package:analyzer/dart/analysis/context_locator.dart' as api;
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart'
     show File, Folder, ResourceProvider, ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart';
@@ -201,10 +202,16 @@
 
     List<AnalysisErrorInfo> errors = [];
     for (Source source in sources) {
-      var errorsResult = await analysisDriver.getErrors(source.fullName);
-      errors.add(
-          AnalysisErrorInfoImpl(errorsResult.errors, errorsResult.lineInfo));
-      _sourcesAnalyzed.add(source);
+      var errorsResult = await analysisDriver.getErrors2(source.fullName);
+      if (errorsResult is ErrorsResult) {
+        errors.add(
+          AnalysisErrorInfoImpl(
+            errorsResult.errors,
+            errorsResult.lineInfo,
+          ),
+        );
+        _sourcesAnalyzed.add(source);
+      }
     }
 
     return errors;
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 6f951ad..793b2a6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1220,6 +1220,7 @@
     expect(driver.getCachedResult(a), same(result));
   }
 
+  @deprecated
   test_getErrors() async {
     String content = 'int f() => 42 + bar();';
     addTestFile(content, priority: true);
@@ -1230,6 +1231,22 @@
     expect(result.errors, hasLength(1));
   }
 
+  test_getErrors2() async {
+    String content = 'int f() => 42 + bar();';
+    addTestFile(content, priority: true);
+
+    var result = await driver.getErrors2(testFile) as ErrorsResult;
+    expect(result.path, testFile);
+    expect(result.uri.toString(), 'package:test/test.dart');
+    expect(result.errors, hasLength(1));
+  }
+
+  test_getErrors2_notAbsolutePath() async {
+    var result = await driver.getErrors2('not_absolute.dart');
+    expect(result, isA<InvalidPathResult>());
+  }
+
+  @deprecated
   test_getErrors_notAbsolutePath() async {
     expect(() async {
       await driver.getErrors('not_absolute.dart');
@@ -2444,7 +2461,7 @@
     getFile(asyncPath).delete();
     addTestFile('class C {}');
 
-    ErrorsResult result = await driver.getErrors(testFile);
+    var result = await driver.getErrors2(testFile) as ErrorsResult;
     expect(result.errors, hasLength(1));
 
     AnalysisError error = result.errors[0];
@@ -2456,7 +2473,7 @@
     getFile(corePath).delete();
     addTestFile('class C {}');
 
-    ErrorsResult result = await driver.getErrors(testFile);
+    var result = await driver.getErrors2(testFile) as ErrorsResult;
     expect(result.errors, hasLength(1));
 
     AnalysisError error = result.errors[0];
@@ -2684,13 +2701,13 @@
 
     // Process a.dart so that we know that it's a library for c.dart later.
     {
-      ErrorsResult result = await driver.getErrors(a);
+      var result = await driver.getErrors2(a) as ErrorsResult;
       expect(result.errors, isEmpty);
     }
 
     // c.dart does not have errors in the context of a.dart
     {
-      ErrorsResult result = await driver.getErrors(c);
+      var result = await driver.getErrors2(c) as ErrorsResult;
       expect(result.errors, isEmpty);
     }
   }
@@ -2720,7 +2737,7 @@
 
     // c.dart is resolve in the context of a.dart, so have no errors
     {
-      ErrorsResult result = await driver.getErrors(c);
+      var result = await driver.getErrors2(c) as ErrorsResult;
       expect(result.errors, isEmpty);
     }
   }
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 6a74188..e75afcd 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -28,6 +28,31 @@
 @reflectiveTest
 class AnalysisSessionImpl_BazelWorkspaceTest
     extends BazelWorkspaceResolutionTest {
+  void test_getErrors2_notFileOfUri() async {
+    var relPath = 'dart/my/lib/a.dart';
+    newFile('$workspaceRootPath/bazel-bin/$relPath');
+
+    var path = convertPath('$workspaceRootPath/$relPath');
+    var session = contextFor(path).currentSession;
+    var result = await session.getErrors2(path);
+    expect(result, isA<NotPathOfUriResult>());
+  }
+
+  void test_getErrors2_valid() async {
+    var file = newFile(
+      '$workspaceRootPath/dart/my/lib/a.dart',
+      content: 'var x = 0',
+    );
+
+    var session = contextFor(file.path).currentSession;
+    var result = await session.getErrorsValid(file.path);
+    expect(result.state, ResultState.VALID);
+    expect(result.path, file.path);
+    expect(result.errors, hasLength(1));
+    expect(result.uri.toString(), 'package:dart.my/a.dart');
+  }
+
+  @deprecated
   void test_getErrors_notFileOfUri() async {
     var relPath = 'dart/my/lib/a.dart';
     newFile('$workspaceRootPath/bazel-bin/$relPath');
@@ -39,6 +64,7 @@
     expect(() => result.errors, throwsStateError);
   }
 
+  @deprecated
   void test_getErrors_valid() async {
     var file = newFile(
       '$workspaceRootPath/dart/my/lib/a.dart',
@@ -212,6 +238,7 @@
     testPath = convertPath('/home/test/lib/test.dart');
   }
 
+  @deprecated
   test_getErrors() async {
     newFile(testPath, content: 'class C {');
     var errorsResult = await session.getErrors(testPath);
@@ -220,6 +247,19 @@
     expect(errorsResult.errors, isNotEmpty);
   }
 
+  test_getErrors2() async {
+    newFile(testPath, content: 'class C {');
+    var errorsResult = await session.getErrorsValid(testPath);
+    expect(errorsResult.session, session);
+    expect(errorsResult.path, testPath);
+    expect(errorsResult.errors, isNotEmpty);
+  }
+
+  test_getErrors2_invalidPath_notAbsolute() async {
+    var errorsResult = await session.getErrors2('not_absolute.dart');
+    expect(errorsResult, isA<InvalidPathResult>());
+  }
+
   @deprecated
   test_getLibraryByUri() async {
     newFile(testPath, content: r'''
@@ -818,4 +858,8 @@
       LibraryElement element) async {
     return await getResolvedLibraryByElement2(element) as ResolvedLibraryResult;
   }
+
+  Future<ErrorsResult> getErrorsValid(String path) async {
+    return await getErrors2(path) as ErrorsResult;
+  }
 }
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
index 841fe15..8ffc750 100644
--- a/pkg/analyzer/test/verify_docs_test.dart
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -118,26 +118,27 @@
       if (contexts.length != 1) {
         fail('The snippets directory contains multiple analysis contexts.');
       }
-      ErrorsResult results =
-          await contexts[0].currentSession.getErrors(snippetPath);
-      Iterable<AnalysisError> errors = results.errors.where((error) {
-        ErrorCode errorCode = error.errorCode;
-        return errorCode != HintCode.UNUSED_IMPORT &&
-            errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
-      });
-      if (errors.isNotEmpty) {
-        String filePath =
-            provider.pathContext.relative(file.path, from: docFolder.path);
-        if (output.isNotEmpty) {
+      var results = await contexts[0].currentSession.getErrors2(snippetPath);
+      if (results is ErrorsResult) {
+        Iterable<AnalysisError> errors = results.errors.where((error) {
+          ErrorCode errorCode = error.errorCode;
+          return errorCode != HintCode.UNUSED_IMPORT &&
+              errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
+        });
+        if (errors.isNotEmpty) {
+          String filePath =
+              provider.pathContext.relative(file.path, from: docFolder.path);
+          if (output.isNotEmpty) {
+            output.writeln();
+          }
+          output.writeln('Errors in snippet in "$filePath":');
           output.writeln();
-        }
-        output.writeln('Errors in snippet in "$filePath":');
-        output.writeln();
-        output.writeln(snippet);
-        output.writeln();
-        int importsLength = imports.length + 1; // account for the '\n'.
-        for (var error in errors) {
-          writeError(error, importsLength);
+          output.writeln(snippet);
+          output.writeln();
+          int importsLength = imports.length + 1; // account for the '\n'.
+          for (var error in errors) {
+            writeError(error, importsLength);
+          }
         }
       }
     } catch (exception, stackTrace) {
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index a3e1fd9..1b1e423 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -113,8 +113,10 @@
   /// Fills [errorsResults] using [files].
   Future<void> prepareErrors() async {
     for (var path in files) {
-      var errorsResult = await analysisDriver.getErrors(path);
-      errorsResults.add(errorsResult);
+      var errorsResult = await analysisDriver.getErrors2(path);
+      if (errorsResult is ErrorsResult) {
+        errorsResults.add(errorsResult);
+      }
     }
   }
 
diff --git a/tools/VERSION b/tools/VERSION
index 76de4d9..cde3d7a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 13
+PRERELEASE 14
 PRERELEASE_PATCH 0
\ No newline at end of file