44
55import 'dart:async' ;
66
7- // ignore: implementation_imports
8- import 'package:_fe_analyzer_shared/src/base/syntactic_entity.dart' ;
97import 'package:analyzer/dart/analysis/analysis_context.dart' ;
108import 'package:analyzer/dart/analysis/analysis_context_collection.dart' ;
119import 'package:analyzer/dart/analysis/results.dart' ;
1210import 'package:analyzer/dart/ast/ast.dart' ;
11+ import 'package:analyzer/dart/ast/token.dart' ;
1312import 'package:analyzer/file_system/physical_file_system.dart' ;
1413import 'package:watcher/watcher.dart' ;
1514
@@ -28,6 +27,27 @@ typedef PreviewPath = ({String path, Uri uri});
2827/// Represents a set of previews for a given file.
2928typedef PreviewMapping = Map <PreviewPath , List <String >>;
3029
30+ extension on Token {
31+ /// Convenience getter to identify tokens for private fields and functions.
32+ bool get isPrivate => toString ().startsWith ('_' );
33+ }
34+
35+ extension on Annotation {
36+ /// Convenience getter to identify `@Preview` annotations
37+ bool get isPreview => name.name == 'Preview' ;
38+ }
39+
40+ /// Convenience getters for examining [String] paths.
41+ extension on String {
42+ bool get isDartFile => endsWith ('.dart' );
43+ bool get isGeneratedPreviewFile => endsWith (PreviewCodeGenerator .generatedPreviewFilePath);
44+ }
45+
46+ extension on ParsedUnitResult {
47+ /// Convenience method to package [path] and [uri] into a [PreviewPath]
48+ PreviewPath toPreviewPath () => (path: path, uri: uri);
49+ }
50+
3151class PreviewDetector {
3252 PreviewDetector ({required this .fs, required this .logger, required this .onChangeDetected});
3353
@@ -49,8 +69,7 @@ class PreviewDetector {
4969 final String eventPath = event.path;
5070 // Only trigger a reload when changes to Dart sources are detected. We
5171 // ignore the generated preview file to avoid getting stuck in a loop.
52- if (! eventPath.endsWith ('.dart' ) ||
53- eventPath.endsWith (PreviewCodeGenerator .generatedPreviewFilePath)) {
72+ if (! eventPath.isDartFile || eventPath.isGeneratedPreviewFile) {
5473 return ;
5574 }
5675 logger.printStatus ('Detected change in $eventPath .' );
@@ -110,36 +129,35 @@ class PreviewDetector {
110129
111130 for (final String filePath in context.contextRoot.analyzedFiles ()) {
112131 logger.printTrace ('Checking file: $filePath ' );
113- if (! filePath.endsWith ( '.dart' ) ) {
132+ if (! filePath.isDartFile ) {
114133 continue ;
115134 }
116135
117136 final SomeParsedLibraryResult lib = context.currentSession.getParsedLibrary (filePath);
118137 if (lib is ParsedLibraryResult ) {
119- for (final ParsedUnitResult unit in lib.units) {
120- final List <String > previewEntries =
121- previews[(path: unit.path, uri: unit.uri)] ?? < String > [];
122- for (final SyntacticEntity entity in unit.unit.childEntities) {
123- if (entity is FunctionDeclaration && ! entity.name.toString ().startsWith ('_' )) {
138+ for (final ParsedUnitResult libUnit in lib.units) {
139+ final List <String > previewEntries = previews[libUnit.toPreviewPath ()] ?? < String > [];
140+ for (final CompilationUnitMember entity in libUnit.unit.declarations) {
141+ if (entity is FunctionDeclaration && ! entity.name.isPrivate) {
124142 bool foundPreview = false ;
125143 for (final Annotation annotation in entity.metadata) {
126- if (annotation.name.name == 'Preview' ) {
144+ if (annotation.isPreview ) {
127145 // What happens if the annotation is applied multiple times?
128146 foundPreview = true ;
129147 break ;
130148 }
131149 }
132150 if (foundPreview) {
133151 logger.printStatus ('Found preview at:' );
134- logger.printStatus ('File path: ${unit .uri }' );
152+ logger.printStatus ('File path: ${libUnit .uri }' );
135153 logger.printStatus ('Preview function: ${entity .name }' );
136154 logger.printStatus ('' );
137155 previewEntries.add (entity.name.toString ());
138156 }
139157 }
140158 }
141159 if (previewEntries.isNotEmpty) {
142- previews[(path : unit.path, uri : unit.uri )] = previewEntries;
160+ previews[libUnit. toPreviewPath ( )] = previewEntries;
143161 }
144162 }
145163 } else {
0 commit comments