Add a method to resolve a library

Change-Id: I0eba5b60bb46fa7dfbceb2b26e0d1d5ec3ae3ebf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194015
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Keerti Parthasarathy <keertip@google.com>
diff --git a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
index 97a397f..5e45d1e7 100644
--- a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
@@ -204,14 +204,7 @@
 
   @override
   Future<ResolvedLibraryResult> getResolvedLibrary(String path) async {
-    var resolvedUnit = await getResolvedUnit(path);
-    return ResolvedLibraryResultImpl(
-      this,
-      path,
-      resolvedUnit.uri,
-      resolvedUnit.libraryElement,
-      [resolvedUnit],
-    );
+    return analysisContext.fileResolver.resolveLibrary(path: path);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 219aadc..03b5275 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -86,7 +86,7 @@
   /// It is used to allow assists and fixes without resolving the same file
   /// multiple times, as we compute more than one assist, or fixes when there
   /// are more than one error on a line.
-  final Map<String, ResolvedUnitResult> _cachedResults = {};
+  final Map<String, ResolvedLibraryResult> _cachedResults = {};
 
   FileResolver(
     PerformanceLog logger,
@@ -373,6 +373,48 @@
 
     performance ??= OperationPerformanceImpl('<default>');
 
+    return logger.run('Resolve $path', () {
+      var fileContext = getFileContext(
+        path: path,
+        performance: performance!,
+      );
+      var file = fileContext.file;
+
+      // If we have a `part of` directive, we want to analyze this library.
+      // But the library must include the file, so have its element.
+      var libraryFile = file;
+      var partOfLibrary = file.partOfLibrary;
+      if (partOfLibrary != null) {
+        if (partOfLibrary.libraryFiles.contains(file)) {
+          libraryFile = partOfLibrary;
+        }
+      }
+
+      var libraryUnit = resolveLibrary(
+        completionLine: completionLine,
+        completionColumn: completionColumn,
+        path: libraryFile.path,
+        completionPath: path,
+        performance: performance,
+      );
+      var result =
+          libraryUnit.units!.firstWhere((element) => element.path == path);
+      return result;
+    });
+  }
+
+  /// The [completionLine] and [completionColumn] are zero based.
+  ResolvedLibraryResult resolveLibrary({
+    int? completionLine,
+    int? completionColumn,
+    String? completionPath,
+    required String path,
+    OperationPerformanceImpl? performance,
+  }) {
+    _throwIfNotAbsoluteNormalizedPath(path);
+
+    performance ??= OperationPerformanceImpl('<default>');
+
     var cachedResult = _cachedResults[path];
     if (cachedResult != null) {
       return cachedResult;
@@ -410,10 +452,6 @@
 
       testView?.addResolvedFile(path);
 
-      var content = _getFileContent(path);
-      var errorListener = RecordingErrorListener();
-      var unit = file.parse(errorListener, content);
-
       late Map<FileState, UnitAnalysisResult> results;
 
       logger.run('Compute analysis results', () {
@@ -432,7 +470,7 @@
         try {
           results = performance!.run('analyze', (performance) {
             return libraryAnalyzer.analyzeSync(
-              completionPath: completionOffset != null ? path : null,
+              completionPath: completionOffset != null ? completionPath : null,
               completionOffset: completionOffset,
               performance: performance,
             );
@@ -450,19 +488,28 @@
           );
         }
       });
-      UnitAnalysisResult fileResult = results[file]!;
 
-      var result = ResolvedUnitResultImpl(
-        contextObjects!.analysisSession,
-        path,
-        file.uri,
-        file.exists,
-        content,
-        unit.lineInfo!,
-        false, // isPart
-        fileResult.unit,
-        fileResult.errors,
-      );
+      results.forEach((key, value) {
+        print('$key: $value');
+      });
+      var resolvedUnits = results.values.map((fileResult) {
+        var file = fileResult.file;
+        return ResolvedUnitResultImpl(
+          contextObjects!.analysisSession,
+          file.path,
+          file.uri,
+          file.exists,
+          file.getContent(),
+          file.lineInfo,
+          file.unlinked2.hasPartOfDirective,
+          fileResult.unit,
+          fileResult.errors,
+        );
+      }).toList();
+
+      var libraryUnit = resolvedUnits.first;
+      var result = ResolvedLibraryResultImpl(contextObjects!.analysisSession,
+          path, libraryUnit.uri, libraryUnit.libraryElement, resolvedUnits);
       _cachedResults[path] = result;
       return result;
     });
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 15b8ebd..aa6dfb3 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -679,6 +679,30 @@
     expect(result, isNot(same(result1)));
   }
 
+  test_resolveLibrary() async {
+    var aPath = convertPath('/workspace/dart/test/lib/a.dart');
+    newFile(aPath, content: r'''
+part 'test.dart';
+
+class A {
+  int m;
+}
+''');
+
+    newFile('/workspace/dart/test/lib/test.dart', content: r'''
+part of 'a.dart';
+
+void func() {
+  var a = A();
+  print(a.m);
+}
+''');
+
+    var result = fileResolver.resolveLibrary(path: aPath);
+    expect(result.path, aPath);
+    expect(result.units?.length, 2);
+  }
+
   test_reuse_compatibleOptions() async {
     newFile('/workspace/dart/aaa/BUILD', content: '');
     newFile('/workspace/dart/bbb/BUILD', content: '');