Skip to content

Commit b347ce4

Browse files
authored
skip files with only known annotation names (#765)
Previously we would bail out early for files with no top level annotations, this also skips well known annotations (although it isn't perfect, and assumes people aren't shadowing these names).
1 parent a086f2b commit b347ce4

File tree

5 files changed

+65
-34
lines changed

5 files changed

+65
-34
lines changed

source_gen/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.0.0-wip
2+
3+
- Update the GeneratorForAnnotation optimization to skip files with well known
4+
annotation names such as `override`, `Deprecated`, and `pragma`.
5+
16
## 3.0.0-dev
27

38
- **Breaking Change**: use the new `element2` APIs in `analyzer`. Builders that

source_gen/lib/src/builder.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class _Builder extends Builder {
9393
if (!await resolver.isLibrary(buildStep.inputId)) return;
9494

9595
if (_generators.every((g) => g is GeneratorForAnnotation) &&
96-
!(await _hasAnyTopLevelAnnotations(
96+
!(await _hasInterestingTopLevelAnnotations(
9797
buildStep.inputId,
9898
resolver,
9999
buildStep,
@@ -382,7 +382,7 @@ Stream<GeneratedOutput> _generate(
382382
}
383383
}
384384

385-
Future<bool> _hasAnyTopLevelAnnotations(
385+
Future<bool> _hasInterestingTopLevelAnnotations(
386386
AssetId input,
387387
Resolver resolver,
388388
BuildStep buildStep,
@@ -399,16 +399,30 @@ Future<bool> _hasAnyTopLevelAnnotations(
399399
}
400400
}
401401
for (var declaration in parsed.declarations) {
402-
if (declaration.metadata.isNotEmpty) return true;
402+
if (declaration.metadata.any(_isUnknownAnnotation)) {
403+
return true;
404+
}
403405
}
404406
for (var partId in partIds) {
405-
if (await _hasAnyTopLevelAnnotations(partId, resolver, buildStep)) {
407+
if (await _hasInterestingTopLevelAnnotations(partId, resolver, buildStep)) {
406408
return true;
407409
}
408410
}
409411
return false;
410412
}
411413

414+
bool _isUnknownAnnotation(Annotation annotation) {
415+
const knownAnnotationNames = {
416+
// Annotations from dart:core, there is an assumption that people are not
417+
// overriding these.
418+
'deprecated',
419+
'Deprecated',
420+
'override',
421+
'pragma',
422+
};
423+
return !knownAnnotationNames.contains(annotation.name.name);
424+
}
425+
412426
const defaultFileHeader = '// GENERATED CODE - DO NOT MODIFY BY HAND';
413427

414428
String _defaultFormatOutput(String code, Version version) =>

source_gen/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: source_gen
2-
version: 3.0.0-dev
2+
version: 3.0.0-wip
33
description: >-
44
Source code generation builders and utilities for the Dart build system
55
repository: https://github.com/dart-lang/source_gen/tree/master/source_gen

source_gen/test/builder_test.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,11 @@ foo generated content
889889
''',
890890
testLibPartContent: '''
891891
part of 'test_lib.dart';
892-
@deprecated
892+
893+
// Use this to avoid the short circuit.
894+
const deprecated2 = deprecated;
895+
896+
@deprecated2
893897
int x;
894898
''',
895899
);

source_gen/test/generator_for_annotation_test.dart

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -99,32 +99,37 @@ $dartFormatWidth
9999
}
100100
});
101101

102-
test(
103-
'Does not resolve the library if there are no top level annotations',
104-
() async {
105-
final builder = LibraryBuilder(
106-
_StubGenerator<Deprecated>('Deprecated', elementBehavior: (_) => null),
107-
);
108-
final input = AssetId('a', 'lib/a.dart');
109-
final assets = {input: 'main() {}'};
110-
111-
final readerWriter =
112-
TestReaderWriter()..testing.writeString(input, assets[input]!);
113-
114-
final resolver = _TestingResolver(assets);
115-
116-
await runBuilder(
117-
builder,
118-
[input],
119-
readerWriter,
120-
readerWriter,
121-
_FixedResolvers(resolver),
122-
);
102+
test('Does not resolve the library if there are no interesting top level '
103+
'annotations', () async {
104+
final builder = LibraryBuilder(
105+
_StubGenerator<Deprecated>('Deprecated', elementBehavior: (_) => null),
106+
);
107+
final input = AssetId('a', 'lib/a.dart');
108+
final assets = {
109+
input: '''
110+
@Deprecated()
111+
@deprecated
112+
@override
113+
@pragma('')
114+
main() {}''',
115+
};
116+
117+
final readerWriter =
118+
TestReaderWriter()..testing.writeString(input, assets[input]!);
119+
120+
final resolver = _TestingResolver(assets);
121+
122+
await runBuilder(
123+
builder,
124+
[input],
125+
readerWriter,
126+
readerWriter,
127+
_FixedResolvers(resolver),
128+
);
123129

124-
expect(resolver.parsedUnits, {input});
125-
expect(resolver.resolvedLibs, isEmpty);
126-
},
127-
);
130+
expect(resolver.parsedUnits, {input});
131+
expect(resolver.resolvedLibs, isEmpty);
132+
});
128133

129134
test('applies to annotated libraries', () async {
130135
final builder = LibraryBuilder(
@@ -289,13 +294,16 @@ class _StubGenerator<T> extends GeneratorForAnnotation<T> {
289294

290295
const _inputMap = {
291296
'a|lib/file.dart': '''
292-
@deprecated
297+
// Use this to avoid the short circuit.
298+
const deprecated2 = deprecated;
299+
300+
@deprecated2
293301
final foo = 'foo';
294302
295-
@deprecated
303+
@deprecated2
296304
final bar = 'bar';
297305
298-
@deprecated
306+
@deprecated2
299307
final baz = 'baz';
300308
''',
301309
};

0 commit comments

Comments
 (0)