diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_get_widget_previews.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_get_widget_previews.dart index 0863e3ef5b1..20f3cb831bd 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_get_widget_previews.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_get_widget_previews.dart @@ -87,7 +87,7 @@ class FlutterWidgetPreviewsHandler var node = graph[result.libraryElement.uri]!; return success( FlutterWidgetPreviews( - scriptUris: [result.uri], + scriptUris: node.previews.map((e) => e.scriptUri).toSet().toList(), previews: node.previews, namespaces: flutterWidgetPreviewDetector.namespaces, ), diff --git a/pkg/analysis_server/lib/src/services/flutter/widget_previews.dart b/pkg/analysis_server/lib/src/services/flutter/widget_previews.dart index e676ceb3126..a0eec4cac38 100644 --- a/pkg/analysis_server/lib/src/services/flutter/widget_previews.dart +++ b/pkg/analysis_server/lib/src/services/flutter/widget_previews.dart @@ -96,6 +96,7 @@ class FlutterWidgetPreviewDetector { preview.dependencyHasErrors != dependencyHasErrors) { node.previews[i] = FlutterWidgetPreviewDetails( scriptUri: preview.scriptUri, + libraryUri: preview.libraryUri, position: preview.position, packageName: preview.packageName, functionName: preview.functionName, @@ -149,7 +150,7 @@ final class LibraryPreviewNode { void addPreviews({required ResolvedUnitResult unit}) { // Iterate over the compilation unit's AST to find previews. var visitor = _PreviewVisitor( - lib: unit.libraryElement, + unit: unit, previewNode: this, namespaceAllocator: namespaceAllocator, ); @@ -243,21 +244,26 @@ class _PreviewVisitor extends RecursiveAstVisitor { ConstructorDeclaration? _currentConstructor; MethodDeclaration? _currentMethod; - late Uri _currentScriptUri; - late CompilationUnit _currentUnit; + late ResolvedUnitResult _currentUnit; + final LineInfo _lineInfo; + final Uri _scriptUri; + final Uri _libraryUri; + _PreviewVisitor({ - required LibraryElement lib, + required ResolvedUnitResult unit, required this.previewNode, required this.namespaceAllocator, - }) : packageName = lib.uri.scheme == 'package' - ? lib.uri.pathSegments.first - : null; + }) : packageName = unit.libraryElement.uri.scheme == 'package' + ? unit.libraryElement.uri.pathSegments.first + : null, + _lineInfo = unit.lineInfo, + _scriptUri = Uri.file(unit.path), + _libraryUri = unit.libraryElement.uri; void findPreviewsInResolvedUnitResult(ResolvedUnitResult unit) { - _currentScriptUri = unit.uri; - _currentUnit = unit.unit; - _currentUnit.visitChildren(this); + _currentUnit = unit; + _currentUnit.unit.visitChildren(this); } bool hasRequiredParams(FormalParameterList? params) { @@ -277,8 +283,7 @@ class _PreviewVisitor extends RecursiveAstVisitor { if (preview == null) { return; } - LineInfo lineInfo = _currentUnit.lineInfo; - CharacterLocation location = lineInfo.getLocation(node.offset); + CharacterLocation location = _lineInfo.getLocation(node.offset); int line = location.lineNumber; int column = location.columnNumber; var hasError = previewNode.hasErrors; @@ -289,7 +294,8 @@ class _PreviewVisitor extends RecursiveAstVisitor { required bool isWidgetBuilder, }) { return FlutterWidgetPreviewDetails( - scriptUri: _currentScriptUri, + scriptUri: _scriptUri, + libraryUri: _libraryUri, position: Position(character: column, line: line), packageName: packageName, functionName: functionName, diff --git a/pkg/analysis_server/test/lsp/exhaustive_flutter_widget_preview_test.dart b/pkg/analysis_server/test/lsp/exhaustive_flutter_widget_preview_test.dart index 57b631071cc..7e76e81c334 100644 --- a/pkg/analysis_server/test/lsp/exhaustive_flutter_widget_preview_test.dart +++ b/pkg/analysis_server/test/lsp/exhaustive_flutter_widget_preview_test.dart @@ -320,8 +320,13 @@ Widget partPreview() => Text('Part'); expect(result!.previews, hasLength(2)); expect(result.previews.any((p) => p.functionName == 'mainPreview'), isTrue); expect(result.previews.any((p) => p.functionName == 'partPreview'), isTrue); - // Use package: URI as observed in the Actual results. - expect(result.scriptUris.first.toString(), 'package:test/main.dart'); + expect(result.previews.map((p) => p.libraryUri.toString()).toSet(), { + 'package:test/main.dart', + }); + expect(result.scriptUris.map((e) => e.toString()), [ + 'file:///home/my_project/lib/main.dart', + 'file:///home/my_project/lib/part.dart', + ]); } Future test_pubWorkspace() async { diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart index 4be01212bc1..b7dcb0533fb 100644 --- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart +++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart @@ -382,6 +382,13 @@ List getCustomClasses() { 'The file:// URI pointing to the script in which the ' 'preview is defined.', ), + field( + 'libraryUri', + type: 'Uri', + comment: + 'The unresolved URI pointing to the library in which the ' + 'preview is defined. This is either a package: or dart: URI.', + ), field( 'position', type: 'Position', diff --git a/third_party/pkg/language_server_protocol/lib/protocol_custom_generated.dart b/third_party/pkg/language_server_protocol/lib/protocol_custom_generated.dart index b986b3028c8..24e6adb668f 100644 --- a/third_party/pkg/language_server_protocol/lib/protocol_custom_generated.dart +++ b/third_party/pkg/language_server_protocol/lib/protocol_custom_generated.dart @@ -2192,6 +2192,10 @@ class FlutterWidgetPreviewDetails implements ToJsonable { /// Set to true if `previewAnnotation` represents a `MultiPreview`. final bool isMultiPreview; + /// The unresolved URI pointing to the library in which the preview is + /// defined. This is either a package: or dart: URI. + final Uri libraryUri; + /// The name of the package in which this annotated preview function was /// defined. /// @@ -2219,6 +2223,7 @@ class FlutterWidgetPreviewDetails implements ToJsonable { required this.hasError, required this.isBuilder, required this.isMultiPreview, + required this.libraryUri, this.packageName, required this.position, required this.previewAnnotation, @@ -2231,6 +2236,7 @@ class FlutterWidgetPreviewDetails implements ToJsonable { hasError, isBuilder, isMultiPreview, + libraryUri, packageName, position, previewAnnotation, @@ -2246,6 +2252,7 @@ class FlutterWidgetPreviewDetails implements ToJsonable { hasError == other.hasError && isBuilder == other.isBuilder && isMultiPreview == other.isMultiPreview && + libraryUri == other.libraryUri && packageName == other.packageName && position == other.position && previewAnnotation == other.previewAnnotation && @@ -2260,6 +2267,7 @@ class FlutterWidgetPreviewDetails implements ToJsonable { result['hasError'] = hasError; result['isBuilder'] = isBuilder; result['isMultiPreview'] = isMultiPreview; + result['libraryUri'] = libraryUri.toString(); result['packageName'] = packageName; result['position'] = position.toJson(); result['previewAnnotation'] = previewAnnotation; @@ -2292,6 +2300,10 @@ class FlutterWidgetPreviewDetails implements ToJsonable { allowsUndefined: false, allowsNull: false)) { return false; } + if (!_canParseUri(obj, reporter, 'libraryUri', + allowsUndefined: false, allowsNull: false)) { + return false; + } if (!_canParseString(obj, reporter, 'packageName', allowsUndefined: false, allowsNull: true)) { return false; @@ -2323,6 +2335,8 @@ class FlutterWidgetPreviewDetails implements ToJsonable { final isBuilder = isBuilderJson as bool; final isMultiPreviewJson = json['isMultiPreview']; final isMultiPreview = isMultiPreviewJson as bool; + final libraryUriJson = json['libraryUri']; + final libraryUri = Uri.parse(libraryUriJson as String); final packageNameJson = json['packageName']; final packageName = packageNameJson as String?; final positionJson = json['position']; @@ -2337,6 +2351,7 @@ class FlutterWidgetPreviewDetails implements ToJsonable { hasError: hasError, isBuilder: isBuilder, isMultiPreview: isMultiPreview, + libraryUri: libraryUri, packageName: packageName, position: position, previewAnnotation: previewAnnotation,