Re-apply "Add AnalysisDriver.resetUriResolution() and use it for analysis.reanalyze request."

Original change's description:
> Add AnalysisDriver.resetUriResolution() and use it for analysis.reanalyze request.
>
> This CL changes "analysis.reanalyze" API. We decided to repurpose it. It was not
> used for some time now in IntelliJ, and AFAIK has never been used in VS Code.
>
> R=​brianwilkerson@google.com, paulberry@google.com
>
> Change-Id: I7510b0189197c9f3f848b0fc59a7b2bd22889ac7
> Reviewed-on: https://dart-review.googlesource.com/c/85523
> Reviewed-by: Paul Berry <paulberry@google.com>
> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>

Change-Id: I828c9a77f1e28d44c00bfcf39527514e39cccc42
Reviewed-on: https://dart-review.googlesource.com/c/86221
Commit-Queue: Paul Berry <paulberry@google.com>
Auto-Submit: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 5af3aa0..713507e 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -810,33 +810,16 @@
       </dd></dl></dd><dt class="request"><a name="request_analysis.reanalyze">analysis.reanalyze</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "analysis.reanalyze"
-  "params": {
-    "<b>roots</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_FilePath">FilePath</a>&gt;
-  }
 }</pre><br><pre>response: {
   "id": String
   "error": <span style="color:#999999">optional</span> <a href="#type_RequestError">RequestError</a>
 }</pre></div>
     <p>
-      Force the re-analysis of everything contained in the specified
-      analysis roots. This will cause all previously computed analysis
-      results to be discarded and recomputed, and will cause all subscribed
-      notifications to be re-sent.
+      Force re-reading of all potentially changed files, re-resolving of all
+      referenced URIs, and corresponding re-analysis of everything affected in
+      the current analysis roots.
     </p>
-    <p>
-      If no analysis roots are provided, then all current analysis roots
-      will be re-analyzed. If an empty list of analysis roots is provided,
-      then nothing will be re-analyzed. If the list contains one or more
-      paths that are not currently analysis roots, then an error of type
-      <tt>INVALID_ANALYSIS_ROOT</tt> will be generated.
-    </p>
-    
-  <h4>parameters:</h4><dl><dt class="field"><b>roots: List&lt;<a href="#type_FilePath">FilePath</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
-        
-        <p>
-          A list of the analysis roots that are to be re-analyzed.
-        </p>
-      </dd></dl></dd><dt class="request"><a name="request_analysis.setAnalysisRoots">analysis.setAnalysisRoots</a></dt><dd><div class="box"><pre>request: {
+  </dd><dt class="request"><a name="request_analysis.setAnalysisRoots">analysis.setAnalysisRoots</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "analysis.setAnalysisRoots"
   "params": {
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 38d52a9..15c626a 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -72,7 +72,6 @@
 const String ANALYSIS_REQUEST_GET_SIGNATURE_FILE = 'file';
 const String ANALYSIS_REQUEST_GET_SIGNATURE_OFFSET = 'offset';
 const String ANALYSIS_REQUEST_REANALYZE = 'analysis.reanalyze';
-const String ANALYSIS_REQUEST_REANALYZE_ROOTS = 'roots';
 const String ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS = 'analysis.setAnalysisRoots';
 const String ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_EXCLUDED = 'excluded';
 const String ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_INCLUDED = 'included';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 3a0a480..5130033 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -3495,83 +3495,28 @@
 /**
  * analysis.reanalyze params
  *
- * {
- *   "roots": optional List<FilePath>
- * }
- *
  * Clients may not extend, implement or mix-in this class.
  */
 class AnalysisReanalyzeParams implements RequestParams {
-  List<String> _roots;
-
-  /**
-   * A list of the analysis roots that are to be re-analyzed.
-   */
-  List<String> get roots => _roots;
-
-  /**
-   * A list of the analysis roots that are to be re-analyzed.
-   */
-  void set roots(List<String> value) {
-    this._roots = value;
-  }
-
-  AnalysisReanalyzeParams({List<String> roots}) {
-    this.roots = roots;
-  }
-
-  factory AnalysisReanalyzeParams.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    if (json == null) {
-      json = {};
-    }
-    if (json is Map) {
-      List<String> roots;
-      if (json.containsKey("roots")) {
-        roots = jsonDecoder.decodeList(
-            jsonPath + ".roots", json["roots"], jsonDecoder.decodeString);
-      }
-      return new AnalysisReanalyzeParams(roots: roots);
-    } else {
-      throw jsonDecoder.mismatch(jsonPath, "analysis.reanalyze params", json);
-    }
-  }
-
-  factory AnalysisReanalyzeParams.fromRequest(Request request) {
-    return new AnalysisReanalyzeParams.fromJson(
-        new RequestDecoder(request), "params", request.params);
-  }
-
   @override
-  Map<String, dynamic> toJson() {
-    Map<String, dynamic> result = {};
-    if (roots != null) {
-      result["roots"] = roots;
-    }
-    return result;
-  }
+  Map<String, dynamic> toJson() => <String, dynamic>{};
 
   @override
   Request toRequest(String id) {
-    return new Request(id, "analysis.reanalyze", toJson());
+    return new Request(id, "analysis.reanalyze", null);
   }
 
   @override
-  String toString() => json.encode(toJson());
-
-  @override
   bool operator ==(other) {
     if (other is AnalysisReanalyzeParams) {
-      return listEqual(roots, other.roots, (String a, String b) => a == b);
+      return true;
     }
     return false;
   }
 
   @override
   int get hashCode {
-    int hash = 0;
-    hash = JenkinsSmiHash.combine(hash, roots.hashCode);
-    return JenkinsSmiHash.finish(hash);
+    return 613039876;
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ff16acf..3beccc1 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -396,12 +396,12 @@
         resourceProvider.pathContext.normalize(path) == path;
   }
 
-  /// Trigger reanalysis of all files in the given list of analysis [roots], or
-  /// everything if the analysis roots is `null`.
-  void reanalyze(List<Resource> roots) {
-    // Instruct the contextDirectoryManager to rebuild all contexts from
-    // scratch.
-    contextManager.refresh(roots);
+  /// Read all files, resolve all URIs, and perform required analysis in
+  /// all current analysis drivers.
+  void reanalyze() {
+    for (var driver in driverMap.values) {
+      driver.resetUriResolution();
+    }
   }
 
   /// Send the given [notification] to the client.
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index d9d7164..fd6e154 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -20,7 +20,6 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart' as engine;
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
@@ -320,23 +319,8 @@
   Response reanalyze(Request request) {
     server.options.analytics?.sendEvent('analysis', 'reanalyze');
 
-    AnalysisReanalyzeParams params =
-        new AnalysisReanalyzeParams.fromRequest(request);
-    List<String> roots = params.roots;
-    if (roots == null || roots.isNotEmpty) {
-      List<String> includedPaths = server.contextManager.includedPaths;
-      List<Resource> rootResources = null;
-      if (roots != null) {
-        rootResources = <Resource>[];
-        for (String rootPath in roots) {
-          if (!includedPaths.contains(rootPath)) {
-            return new Response.invalidAnalysisRoot(request, rootPath);
-          }
-          rootResources.add(server.resourceProvider.getResource(rootPath));
-        }
-      }
-      server.reanalyze(rootResources);
-    }
+    server.reanalyze();
+
     //
     // Restart all of the plugins. This is an async operation that will happen
     // in the background.
diff --git a/pkg/analysis_server/test/analysis/reanalyze_test.dart b/pkg/analysis_server/test/analysis/reanalyze_test.dart
index 886b200..1606a84 100644
--- a/pkg/analysis_server/test/analysis/reanalyze_test.dart
+++ b/pkg/analysis_server/test/analysis/reanalyze_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
@@ -23,53 +21,39 @@
 class ReanalyzeTest extends AbstractAnalysisTest {
   Map<String, List<AnalysisError>> filesErrors = {};
 
-  Completer _resultsAvailable = new Completer();
-
   @override
   void processNotification(Notification notification) {
     if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
       var decoded = new AnalysisErrorsParams.fromNotification(notification);
       filesErrors[decoded.file] = decoded.errors;
-      _resultsAvailable.complete(null);
     }
   }
 
-  test_reanalyze() {
-    createProject();
-    Map drivers = server.driverMap;
-    expect(drivers, hasLength(1));
-    Request request = new Request("0", ANALYSIS_REQUEST_REANALYZE);
-    handleSuccessfulRequest(request);
-    drivers = server.driverMap;
-    expect(drivers, hasLength(1));
-  }
+  test_reanalyze() async {
+    var b = convertPath('/other/b.dart');
 
-  test_reanalyze_with_overlay() async {
+    newFile(testFile, content: r'''
+import '../../other/b.dart';
+
+B b;
+''');
     createProject();
-    newFolder(testFolder);
-    newFile(testFile, content: 'main() {}');
-    // Update the content with an overlay that contains a syntax error.
-    server.updateContent('1', {testFile: new AddContentOverlay('main() {')});
-    await _resultsAvailable.future;
-    // Verify that the syntax error was detected.
-    {
-      List<AnalysisError> errors = filesErrors[testFile];
-      expect(errors, hasLength(1));
-    }
-    // Remove testFile from filesErrors so that we'll notice when the file is
-    // re-analyzed.
-    filesErrors.remove(testFile);
+
+    // b.dart does not exist, and `B` is unresolved.
+    await waitForTasksFinished();
+    expect(filesErrors[testFile], hasLength(2));
+
+    // Clear errors, so that we'll notice new results.
+    filesErrors.clear();
+
+    // Create b.dart, reanalyzing should fix the error.
+    newFile(b, content: 'class B {}');
+
     // Reanalyze.
-    _resultsAvailable = new Completer();
-    server.reanalyze(null);
-    await _resultsAvailable.future;
-    // The file should have been reanalyzed.
-    expect(filesErrors, contains(testFile));
-    // Verify that the syntax error is present (this indicates that the
-    // content introduced by the call to updateContent is still in effect).
-    {
-      List<AnalysisError> errors = filesErrors[testFile];
-      expect(errors, hasLength(1));
-    }
+    server.reanalyze();
+    await waitForTasksFinished();
+
+    // No errors.
+    expect(filesErrors[testFile], isEmpty);
   }
 }
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index c2566bf..16bcdd2 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -58,12 +58,12 @@
   void setUp() {
     super.setUp();
     registerLintRules();
-    createProject();
     libPath = resourceProvider.convertPath('/project/lib');
     testFile = resourceProvider.convertPath('/project/lib/fileToBeFixed.dart');
   }
 
   test_dartfix_convertClassToMixin() async {
+    createProject();
     addTestFile('''
 class A {}
 class B extends A {}
@@ -80,6 +80,7 @@
   }
 
   test_dartfix_convertToIntLiteral() async {
+    createProject();
     addTestFile('''
 const double myDouble = 42.0;
     ''');
@@ -92,6 +93,7 @@
   }
 
   test_dartfix_moveTypeArgumentToClass() async {
+    createProject();
     addTestFile('''
 class A<T> { A.from(Object obj) { } }
 main() {
@@ -110,34 +112,26 @@
   }
 
   test_dartfix_excludedSource() async {
-    addTestFile('''
-const double myDouble = 42.0;
-    ''');
-
-    // Assert dartfix suggestions
-    EditDartfixResult result = await performFix();
-    expect(result.suggestions, hasLength(1));
-    expectSuggestion(result.suggestions[0], 'int literal', 24, 4);
-    expectEdits(result.edits, '''
-const double myDouble = 42;
-    ''');
-
     // Add analysis options to exclude the lib directory then reanalyze
     newFile('/project/analysis_options.yaml', content: '''
 analyzer:
   exclude:
     - lib/**
 ''');
-    handleSuccessfulRequest(new Request(nextRequestId, 'analysis.reanalyze'),
-        handler: analysisHandler);
+
+    createProject();
+    addTestFile('''
+const double myDouble = 42.0;
+    ''');
 
     // Assert no suggestions now that source has been excluded
-    result = await performFix();
+    final result = await performFix();
     expect(result.suggestions, hasLength(0));
     expect(result.edits, hasLength(0));
   }
 
   test_dartfix_partFile() async {
+    createProject();
     newFile('/project/lib/lib.dart', content: '''
 library lib2;
 part 'fileToBeFixed.dart';
@@ -158,6 +152,7 @@
   }
 
   test_dartfix_partFile_loose() async {
+    createProject();
     addTestFile('''
 part of lib2;
 const double myDouble = 42.0;
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 401723d..65b4cec 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -460,26 +460,12 @@
   }
 
   /**
-   * Force the re-analysis of everything contained in the specified analysis
-   * roots. This will cause all previously computed analysis results to be
-   * discarded and recomputed, and will cause all subscribed notifications to
-   * be re-sent.
-   *
-   * If no analysis roots are provided, then all current analysis roots will be
-   * re-analyzed. If an empty list of analysis roots is provided, then nothing
-   * will be re-analyzed. If the list contains one or more paths that are not
-   * currently analysis roots, then an error of type INVALID_ANALYSIS_ROOT will
-   * be generated.
-   *
-   * Parameters
-   *
-   * roots: List<FilePath> (optional)
-   *
-   *   A list of the analysis roots that are to be re-analyzed.
+   * Force re-reading of all potentially changed files, re-resolving of all
+   * referenced URIs, and corresponding re-analysis of everything affected in
+   * the current analysis roots.
    */
-  Future sendAnalysisReanalyze({List<String> roots}) async {
-    var params = new AnalysisReanalyzeParams(roots: roots).toJson();
-    var result = await server.send("analysis.reanalyze", params);
+  Future sendAnalysisReanalyze() async {
+    var result = await server.send("analysis.reanalyze", null);
     outOfTestExpect(result, isNull);
     return null;
   }
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 13ba921..3e82faf 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1849,14 +1849,8 @@
 
 /**
  * analysis.reanalyze params
- *
- * {
- *   "roots": optional List<FilePath>
- * }
  */
-final Matcher isAnalysisReanalyzeParams = new LazyMatcher(() =>
-    new MatchesJsonObject("analysis.reanalyze params", null,
-        optionalFields: {"roots": isListOf(isFilePath)}));
+final Matcher isAnalysisReanalyzeParams = isNull;
 
 /**
  * analysis.reanalyze result
diff --git a/pkg/analysis_server/test/stress/utilities/server.dart b/pkg/analysis_server/test/stress/utilities/server.dart
index ccd2ac5..fc489ef 100644
--- a/pkg/analysis_server/test/stress/utilities/server.dart
+++ b/pkg/analysis_server/test/stress/utilities/server.dart
@@ -436,8 +436,8 @@
     return _send("analysis.getReachableSources", params);
   }
 
-  void sendAnalysisReanalyze({List<String> roots}) {
-    var params = new AnalysisReanalyzeParams(roots: roots).toJson();
+  void sendAnalysisReanalyze() {
+    var params = new AnalysisReanalyzeParams().toJson();
     _send("analysis.reanalyze", params);
   }
 
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index ae85d07..eeb2c58 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -167,18 +167,10 @@
   /**
    * {@code analysis.reanalyze}
    *
-   * Force the re-analysis of everything contained in the specified analysis roots. This will cause
-   * all previously computed analysis results to be discarded and recomputed, and will cause all
-   * subscribed notifications to be re-sent.
-   *
-   * If no analysis roots are provided, then all current analysis roots will be re-analyzed. If an
-   * empty list of analysis roots is provided, then nothing will be re-analyzed. If the list contains
-   * one or more paths that are not currently analysis roots, then an error of type
-   * INVALID_ANALYSIS_ROOT will be generated.
-   *
-   * @param roots A list of the analysis roots that are to be re-analyzed.
+   * Force re-reading of all potentially changed files, re-resolving of all referenced URIs, and
+   * corresponding re-analysis of everything affected in the current analysis roots.
    */
-  public void analysis_reanalyze(List<String> roots);
+  public void analysis_reanalyze();
 
   /**
    * {@code analysis.setAnalysisRoots}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 2f66a93..0266e7c 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -715,28 +715,10 @@
   </request>
   <request method="reanalyze">
     <p>
-      Force the re-analysis of everything contained in the specified
-      analysis roots. This will cause all previously computed analysis
-      results to be discarded and recomputed, and will cause all subscribed
-      notifications to be re-sent.
+      Force re-reading of all potentially changed files, re-resolving of all
+      referenced URIs, and corresponding re-analysis of everything affected in
+      the current analysis roots.
     </p>
-    <p>
-      If no analysis roots are provided, then all current analysis roots
-      will be re-analyzed. If an empty list of analysis roots is provided,
-      then nothing will be re-analyzed. If the list contains one or more
-      paths that are not currently analysis roots, then an error of type
-      <tt>INVALID_ANALYSIS_ROOT</tt> will be generated.
-    </p>
-    <params>
-      <field name="roots" optional="true">
-        <list>
-          <ref>FilePath</ref>
-        </list>
-        <p>
-          A list of the analysis roots that are to be re-analyzed.
-        </p>
-      </field>
-    </params>
   </request>
   <request method="setAnalysisRoots">
     <p>
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 38d52a9..15c626a 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -72,7 +72,6 @@
 const String ANALYSIS_REQUEST_GET_SIGNATURE_FILE = 'file';
 const String ANALYSIS_REQUEST_GET_SIGNATURE_OFFSET = 'offset';
 const String ANALYSIS_REQUEST_REANALYZE = 'analysis.reanalyze';
-const String ANALYSIS_REQUEST_REANALYZE_ROOTS = 'roots';
 const String ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS = 'analysis.setAnalysisRoots';
 const String ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_EXCLUDED = 'excluded';
 const String ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_INCLUDED = 'included';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 9fabb4c..bea5464 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -3495,83 +3495,28 @@
 /**
  * analysis.reanalyze params
  *
- * {
- *   "roots": optional List<FilePath>
- * }
- *
  * Clients may not extend, implement or mix-in this class.
  */
 class AnalysisReanalyzeParams implements RequestParams {
-  List<String> _roots;
-
-  /**
-   * A list of the analysis roots that are to be re-analyzed.
-   */
-  List<String> get roots => _roots;
-
-  /**
-   * A list of the analysis roots that are to be re-analyzed.
-   */
-  void set roots(List<String> value) {
-    this._roots = value;
-  }
-
-  AnalysisReanalyzeParams({List<String> roots}) {
-    this.roots = roots;
-  }
-
-  factory AnalysisReanalyzeParams.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    if (json == null) {
-      json = {};
-    }
-    if (json is Map) {
-      List<String> roots;
-      if (json.containsKey("roots")) {
-        roots = jsonDecoder.decodeList(
-            jsonPath + ".roots", json["roots"], jsonDecoder.decodeString);
-      }
-      return new AnalysisReanalyzeParams(roots: roots);
-    } else {
-      throw jsonDecoder.mismatch(jsonPath, "analysis.reanalyze params", json);
-    }
-  }
-
-  factory AnalysisReanalyzeParams.fromRequest(Request request) {
-    return new AnalysisReanalyzeParams.fromJson(
-        new RequestDecoder(request), "params", request.params);
-  }
-
   @override
-  Map<String, dynamic> toJson() {
-    Map<String, dynamic> result = {};
-    if (roots != null) {
-      result["roots"] = roots;
-    }
-    return result;
-  }
+  Map<String, dynamic> toJson() => <String, dynamic>{};
 
   @override
   Request toRequest(String id) {
-    return new Request(id, "analysis.reanalyze", toJson());
+    return new Request(id, "analysis.reanalyze", null);
   }
 
   @override
-  String toString() => json.encode(toJson());
-
-  @override
   bool operator ==(other) {
     if (other is AnalysisReanalyzeParams) {
-      return listEqual(roots, other.roots, (String a, String b) => a == b);
+      return true;
     }
     return false;
   }
 
   @override
   int get hashCode {
-    int hash = 0;
-    hash = JenkinsSmiHash.combine(hash, roots.hashCode);
-    return JenkinsSmiHash.finish(hash);
+    return 613039876;
   }
 }
 
diff --git a/pkg/analyzer/lib/source/embedder.dart b/pkg/analyzer/lib/source/embedder.dart
index fe2a5f4..dfd679f 100644
--- a/pkg/analyzer/lib/source/embedder.dart
+++ b/pkg/analyzer/lib/source/embedder.dart
@@ -171,6 +171,9 @@
   int get length => _embedderSdk?.urlMappings?.length ?? 0;
 
   @override
+  void clearCache() {}
+
+  @override
   Source resolveAbsolute(Uri uri, [Uri actualUri]) =>
       _dartUriResolver.resolveAbsolute(uri, actualUri);
 
diff --git a/pkg/analyzer/lib/src/context/source.dart b/pkg/analyzer/lib/src/context/source.dart
index 6c3b58e..70abd3dc 100644
--- a/pkg/analyzer/lib/src/context/source.dart
+++ b/pkg/analyzer/lib/src/context/source.dart
@@ -101,6 +101,14 @@
   }
 
   @override
+  void clearCache() {
+    _absoluteUriToSourceCache.clear();
+    for (var resolver in resolvers) {
+      resolver.clearCache();
+    }
+  }
+
+  @override
   SourceFactory clone() {
     SourceFactory factory =
         new SourceFactory(resolvers, _packages, _resourceProvider);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index a1cc939..0615c10 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -1317,6 +1317,16 @@
   }
 
   /**
+   * Reset URI resolution, read again all files, build files graph, and ensure
+   * that for all added files new results are reported.
+   */
+  void resetUriResolution() {
+    _fsState.resetUriResolution();
+    _fileTracker.scheduleAllAddedFiles();
+    _changeHook();
+  }
+
+  /**
    * Implementation for [changeFile].
    */
   void _changeFile(String path) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 2ea7c4c..8aa37cc 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -961,17 +961,22 @@
   }
 
   /**
+   * Reset URI resolution, and forget all files. So, the next time any file is
+   * requested, it will be read, and its whole (potentially different) graph
+   * will be built.
+   */
+  void resetUriResolution() {
+    _sourceFactory.clearCache();
+    _fileContentCache.clear();
+    _clearFiles();
+  }
+
+  /**
    * Remove the file with the given [path].
    */
   void removeFile(String path) {
     markFileForReading(path);
-    _uriToFile.clear();
-    knownFilePaths.clear();
-    knownFiles.clear();
-    _pathToFiles.clear();
-    _pathToCanonicalFile.clear();
-    _partToLibraries.clear();
-    _subtypedNameToFiles.clear();
+    _clearFiles();
   }
 
   void _addFileWithPath(String path, FileState file) {
@@ -985,6 +990,17 @@
     }
     files.add(file);
   }
+
+  /// Clear all [FileState] data - all maps from path or URI, etc.
+  void _clearFiles() {
+    _uriToFile.clear();
+    knownFilePaths.clear();
+    knownFiles.clear();
+    _pathToFiles.clear();
+    _pathToCanonicalFile.clear();
+    _partToLibraries.clear();
+    _subtypedNameToFiles.clear();
+  }
 }
 
 @visibleForTesting
@@ -1078,6 +1094,10 @@
     return file;
   }
 
+  void clear() {
+    _pathToFile.clear();
+  }
+
   /**
    * Remove the file with the given [path] from the cache.
    */
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart b/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
index c49cf71..f355cc9 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
@@ -211,6 +211,13 @@
   }
 
   /**
+   * Schedule all added files for analysis.
+   */
+  void scheduleAllAddedFiles() {
+    _pendingFiles.addAll(addedFiles);
+  }
+
+  /**
    * Verify the API signature for the file with the given [path], and decide
    * which linked libraries should be invalidated, and files reanalyzed.
    */
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 5c8b4c3..9b1d4e7 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -17,6 +17,11 @@
 export 'package:analyzer/source/line_info.dart' show LineInfo;
 export 'package:analyzer/source/source_range.dart';
 
+/**
+ * A function that is used to visit [ContentCache] entries.
+ */
+typedef void ContentCacheVisitor(String fullPath, int stamp, String contents);
+
 /// Base class providing implementations for the methods in [Source] that don't
 /// require filesystem access.
 abstract class BasicSource extends Source {
@@ -44,11 +49,6 @@
 }
 
 /**
- * A function that is used to visit [ContentCache] entries.
- */
-typedef void ContentCacheVisitor(String fullPath, int stamp, String contents);
-
-/**
  * A cache used to override the default content of a [Source].
  */
 class ContentCache {
@@ -565,6 +565,12 @@
   Map<String, List<Folder>> get packageMap;
 
   /**
+   * Clear any cached URI resolution information in the [SourceFactory] itself,
+   * and also ask each [UriResolver]s to clear its caches.
+   */
+  void clearCache();
+
+  /**
    * Return a source factory that will resolve URI's in the same way that this
    * source factory does.
    */
@@ -778,6 +784,11 @@
  */
 abstract class UriResolver {
   /**
+   * Clear any cached URI resolution information.
+   */
+  void clearCache() {}
+
+  /**
    * Resolve the given absolute URI. Return a [Source] representing the file to which
    * it was resolved, whether or not the resulting source exists, or `null` if it could not be
    * resolved because the URI is invalid.
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index c4e6c21..cc3a1fe 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -58,6 +58,11 @@
         _context = workspace.provider.pathContext;
 
   @override
+  void clearCache() {
+    _sourceCache.clear();
+  }
+
+  @override
   Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     return _sourceCache.putIfAbsent(uri, () {
       if (uri.scheme != 'package') {
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index 8f6daf9..a834e3d 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -172,6 +172,9 @@
   Uri Function(Source) restoreAbsoluteFunction;
 
   @override
+  void clearCache() {}
+
+  @override
   noSuchMethod(Invocation invocation) {
     throw new StateError('Unexpected invocation of ${invocation.memberName}');
   }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 50b6094..f197f46 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -3164,6 +3164,55 @@
     } on ArgumentError {}
   }
 
+  test_resetUriResolution() async {
+    var a = convertPath('/aaa/lib/a.dart');
+    var b = convertPath('/bbb/lib/b.dart');
+
+    newFile(a, content: '');
+    newFile(b, content: r'''
+import 'package:aaa/a.dart'; // ignore: unused_import
+A a;
+''');
+
+    // Subscribe for errors.
+    driver.addFile(b);
+
+    // `package:aaa/a.dart` does not define class `A`.
+    // So, there is an error in `b.dart`.
+    await waitForIdleWithoutExceptions();
+    expect(allResults, hasLength(1));
+    expect(allResults[0].path, b);
+    expect(allResults[0].errors, hasLength(1));
+
+    // Create generated file for `package:aaa/a.dart`.
+    var aUri = Uri.parse('package:aaa/a.dart');
+    var aGeneratedPath = convertPath('/generated/aaa/lib/a2.dart');
+    var aGeneratedFile = newFile(aGeneratedPath, content: 'class A {}');
+
+    // Configure UriResolver to provide this generated file.
+    generatedUriResolver.resolveAbsoluteFunction =
+        (uri, actualUri) => aGeneratedFile.createSource(actualUri);
+    generatedUriResolver.restoreAbsoluteFunction = (source) {
+      String path = source.fullName;
+      if (path == a || path == aGeneratedPath) {
+        return aUri;
+      } else {
+        return null;
+      }
+    };
+
+    // Reset URI resolution, and analyze.
+    allResults.clear();
+    driver.resetUriResolution();
+
+    // `package:aaa/a.dart` is resolved differently now, so the new list of
+    // errors for `b.dart` (the empty list) is reported.
+    await waitForIdleWithoutExceptions();
+    expect(allResults, hasLength(1));
+    expect(allResults[0].path, b);
+    expect(allResults[0].errors, isEmpty);
+  }
+
   test_results_order() async {
     var a = convertPath('/test/lib/a.dart');
     var b = convertPath('/test/lib/b.dart');