Skip to content

Commit 3c84f42

Browse files
authored
Add a warning when 'part' is missing. (#209)
* Add a warning when 'part' is missing. * Dartfmt. * Manually fix travis.
1 parent 43244b9 commit 3c84f42

File tree

5 files changed

+49
-11
lines changed

5 files changed

+49
-11
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
* Added `spanForElement`; returns a `SourceSpan` for an analyzer `Element`.
44

5+
* Logs a _warning_ to the console when a `GeneratorBuilder` outputs a part file
6+
for a given input, but that input does not define `part 'name.g.dart';`.
7+
58
## 0.6.0
69

710
* **Breaking change**: `TypeChecker#annotationsOf|firstAnnotationOf` now

lib/src/builder.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class GeneratorBuilder extends Builder {
9898
// library/part definitions because users expect some files to be skipped
9999
// therefore they do not have "library".
100100
if (generatedOutputs.isEmpty) return;
101+
final outputId = _generatedFile(buildStep.inputId);
101102

102103
var contentBuffer = new StringBuffer();
103104
if (!isStandalone) {
@@ -115,6 +116,11 @@ class GeneratorBuilder extends Builder {
115116
'Consider adding the following to your source file:\n\n'
116117
'library $suggest;');
117118
}
119+
final part = computePartUrl(buildStep.inputId, outputId);
120+
if (!library.parts.map((c) => c.uri).contains(part)) {
121+
// TODO: Upgrade to error in a future breaking change?
122+
log.warning('Missing "part \'$part\';".');
123+
}
118124
contentBuffer.writeln('part of $name;');
119125
contentBuffer.writeln();
120126
}
@@ -138,7 +144,7 @@ class GeneratorBuilder extends Builder {
138144
} catch (e, stack) {
139145
log.severe(
140146
'Error formatting generated source code for ${library.identifier}'
141-
'which was output to ${_generatedFile(buildStep.inputId).path}.\n'
147+
'which was output to ${outputId.path}.\n'
142148
'This may indicate an issue in the generated code or in the '
143149
'formatter.\n'
144150
'Please check the generated code and file an issue on source_gen if '
@@ -147,8 +153,7 @@ class GeneratorBuilder extends Builder {
147153
stack);
148154
}
149155

150-
buildStep.writeAsString(
151-
_generatedFile(buildStep.inputId), '$_topHeader$genPartContent');
156+
buildStep.writeAsString(outputId, '$_topHeader$genPartContent');
152157
}
153158

154159
@override

lib/src/utils.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ String suggestLibraryName(AssetId source) {
7676
return '${source.package}.${parts.join('.')}';
7777
}
7878

79+
/// Returns what 'part "..."' URL is needed to import [output] from [input].
80+
///
81+
/// For example, will return `test_lib.g.dart` for `test_lib.dart`.
82+
String computePartUrl(AssetId input, AssetId output) =>
83+
p.joinAll(p.split(p.relative(output.path, from: input.path)).skip(1));
84+
7985
/// Returns a URL representing [element].
8086
String urlOfElement(Element element) => element.kind == ElementKind.DYNAMIC
8187
? 'dart:core#dynmaic'

test/builder_test.dart

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ void main() {
119119
});
120120
});
121121

122+
test('warns when a non-standalone builder does not see "part"', () async {
123+
var srcs =
124+
_createPackageStub(pkgName, testLibContent: _testLibContentNoPart);
125+
var builder = new GeneratorBuilder([const CommentGenerator()]);
126+
var logs = <String>[];
127+
await testBuilder(
128+
builder,
129+
srcs,
130+
onLog: (log) {
131+
logs.add(log.message);
132+
},
133+
);
134+
expect(logs, ['Missing "part \'test_lib.g.dart\';".']);
135+
});
136+
122137
test('defaults to formatting generated code with the DartFormatter',
123138
() async {
124139
await testBuilder(new GeneratorBuilder([new UnformattedCodeGenerator()]),
@@ -167,16 +182,16 @@ Future _generateTest(CommentGenerator gen, String expectedContent) async {
167182
generateFor: new Set.from(['$pkgName|lib/test_lib.dart']),
168183
outputs: {
169184
'$pkgName|lib/test_lib.g.dart': expectedContent,
170-
});
185+
},
186+
onLog: (log) => fail('Unexpected log message: ${log.message}'));
171187
}
172188

173189
/// Creates a package using [pkgName].
174190
Map<String, String> _createPackageStub(String pkgName,
175191
{String testLibContent, String testLibPartContent}) {
176192
return {
177193
'$pkgName|lib/test_lib.dart': testLibContent ?? _testLibContent,
178-
'$pkgName|lib/test_lib_part.dart':
179-
testLibPartContent ?? _testLibPartContent,
194+
'$pkgName|lib/test_lib.g.dart': testLibPartContent ?? _testLibPartContent,
180195
};
181196
}
182197

@@ -200,14 +215,20 @@ const pkgName = 'pkg';
200215

201216
const _testLibContent = r'''
202217
library test_lib;
203-
part 'test_lib_part.dart';
218+
part 'test_lib.g.dart';
219+
final int foo = 42;
220+
class Person { }
221+
''';
222+
223+
const _testLibContentNoPart = r'''
224+
library test_lib;
204225
final int foo = 42;
205226
class Person { }
206227
''';
207228

208229
const _testLibContentWithError = r'''
209230
library test_lib;
210-
part 'test_lib_part.dart';
231+
part 'test_lib.g.dart';
211232
class MyError { }
212233
class MyGoodError { }
213234
''';

test/span_for_element_test.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ void main() {
1212
LibraryElement library;
1313

1414
setUpAll(() async {
15-
final resolver = await resolveSource(r'''
15+
final resolver = await resolveSource(
16+
r'''
1617
library test_lib;
17-
18+
1819
abstract class Example implements List {}
19-
''', inputId: new AssetId('test_lib', 'lib/test_lib.dart'));
20+
''',
21+
inputId: new AssetId('test_lib', 'lib/test_lib.dart'),
22+
);
2023
library = resolver.getLibraryByName('test_lib');
2124
});
2225

0 commit comments

Comments
 (0)