Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,35 @@
* Deprecated `builder.dart`: import `source_gen.dart` instead.
* Added `TypeChecker`, a high-level API for performing static type checks:

```dart
import 'package:analyzer/dart/element/type.dart';
import 'package:source_gen/source_gen.dart';

void checkType(DartType dartType) {
// Checks compared to runtime type `SomeClass`.
print(const TypeChecker.forRuntime(SomeClass).isExactlyType(dartType));
```dart
import 'package:analyzer/dart/element/type.dart';
import 'package:source_gen/source_gen.dart';

void checkType(DartType dartType) {
// Checks compared to runtime type `SomeClass`.
print(const TypeChecker.forRuntime(SomeClass).isExactlyType(dartType));

// Checks compared to a known Url/Symbol:
const TypeChecker.forUrl('package:foo/foo.dart#SomeClass');

// Checks compared to another resolved `DartType`:
const TypeChecker.forStatic(anotherDartType);
}
```

* Failing to add a `library` directive to a library that is being used as a
generator target that generates partial files (`part of`) is now an explicit
error that gives a hint on how to name and fix your library:

// Checks compared to a known Url/Symbol:
const TypeChecker.forUrl('package:foo/foo.dart#SomeClass');
```bash
> Could not find library identifier so a "part of" cannot be built.
>
> Consider adding the following to your source file:
>
> "library foo.bar;"
```

// Checks compared to another resolved `DartType`:
const TypeChecker.forStatic(anotherDartType);
}
```
In Dart SDK `>=1.25.0` this can be relaxed as `part of` can refer to a path.

## 0.5.8

Expand Down
18 changes: 14 additions & 4 deletions lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,26 @@ class GeneratorBuilder extends Builder {
var generatedOutputs =
await _generate(library, generators, buildStep).toList();

// Don't outputs useless files.
if (generatedOutputs.isEmpty) return;

var contentBuffer = new StringBuffer();

if (!isStandalone) {
contentBuffer.writeln('part of ${library.name};');
var asset = buildStep.inputId;
var name = nameOfPartial(library, asset);
if (name == null) {
var suggest = suggestLibraryName(asset);
throw new InvalidGenerationSourceError(
'Could not find library identifier so a "part of" cannot be built.',
todo: ''
'Consider adding the following to your source file:\n\n'
'library $suggest;');
}
contentBuffer.writeln('part of $name;');
contentBuffer.writeln();
}

// Don't output useless files.
if (generatedOutputs.isEmpty) return;

for (GeneratedOutput output in generatedOutputs) {
contentBuffer.writeln('');
contentBuffer.writeln(_headerLine);
Expand Down
35 changes: 35 additions & 0 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';

String friendlyNameForElement(Element element) {
var friendlyName = element.displayName;
Expand Down Expand Up @@ -39,6 +40,40 @@ String friendlyNameForElement(Element element) {
return names.join(' ');
}

/// Returns a name suitable for `part of "..."` when pointing to [element].
///
/// Returns `null` if [element] is missing identifier.
///
/// Starting in `1.25.0`, setting [allowUnnamedPartials] will fallback
/// (actually, preferred) to `'part of "package:foo/path.dart'`, and null will
/// never be returned.
String nameOfPartial(
LibraryElement element,
AssetId source, {
bool allowUnnamedPartials: false,
}) {
if (element.name != null && element.name.isNotEmpty) {
return element.name;
}
if (allowUnnamedPartials) {
return '\'package:${source.package}/${source.path}\'';
}
return null;
}

/// Returns a suggested library identifier based on [source] path and package.
String suggestLibraryName(AssetId source) {
// lib/test.dart --> [lib/test.dart]
var parts = source.path.split('/');
// [lib/test.dart] --> [lib/test]
parts[parts.length - 1] = parts.last.split('.').first;
// [lib/test] --> [test]
if (parts.first == 'lib') {
parts = parts.skip(1);
}
return '${source.package}.${parts.join('.')}';
}

/// Returns all of the declarations in [unit], including [unit] as the first
/// item.
Iterable<Element> getElementsFromLibraryElement(LibraryElement unit) sync* {
Expand Down
9 changes: 9 additions & 0 deletions test/builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ void main() {
returnsNormally);
});

test('Throws an exception when no library identifier is found', () async {
var sources = _createPackageStub(pkgName, testLibContent: 'class A {}');
var builder = new GeneratorBuilder([const CommentGenerator()]);
expect(
testBuilder(builder, sources,
outputs: {'$pkgName|lib/test_lib.g.dart': ''}),
throwsA(const isInstanceOf<InvalidGenerationSourceError>()));
});

test(
'Simple Generator test for library',
() => _generateTest(
Expand Down