[ DAS ] Update widget preview detection to report both file and library URIs

Change-Id: I138a8eb52ee38356f4cf710a7e530bfa7aa9daf4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/490361
Auto-Submit: Ben Konyi <bkonyi@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Ben Konyi
2026-03-26 09:21:56 -07:00
committed by Commit Queue
parent 907087a744
commit 93ecced96f
5 changed files with 49 additions and 16 deletions
@@ -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,
),
@@ -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<void> {
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<void> {
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<void> {
required bool isWidgetBuilder,
}) {
return FlutterWidgetPreviewDetails(
scriptUri: _currentScriptUri,
scriptUri: _scriptUri,
libraryUri: _libraryUri,
position: Position(character: column, line: line),
packageName: packageName,
functionName: functionName,
@@ -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<void> test_pubWorkspace() async {
@@ -382,6 +382,13 @@ List<LspEntity> 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',
@@ -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,