Update docs for Dart components in SQL

Scopes components are enabled by default, so the warning is no longer
necessary.
This commit is contained in:
Simon Binder 2023-01-22 22:53:45 +01:00
parent 48e7785491
commit 2c63c1a64e
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
10 changed files with 631 additions and 66 deletions

View File

@ -24,28 +24,57 @@ builders:
release: true release: true
targets: targets:
# We run drift and other builders first, syntax higlighting is more prepare:
# accurate if the generated classes exist. auto_apply_builders: false
source_gen: builders:
":versions":
enabled: true
drift_dev:preparing_builder:
enabled: true
sources:
- "$package$"
- "lib/versions.json"
- "lib/snippets/**"
- "tool/write_versions.dart"
- "tool/snippets.dart"
- "test/generated/**"
codegen:
dependencies: [":prepare"]
auto_apply_builders: false auto_apply_builders: false
builders: builders:
drift_dev:preparing_builder: drift_dev:preparing_builder:
enabled: false # Runs in prepare target
# Modular drift generation, suitable for standalone snippets that aren't part of a database
drift_dev:analyzer:
enabled: true enabled: true
options: &options
generate_connect_constructor: true
generate_for:
include: &modular
- "lib/snippets/modular/**"
drift_dev:modular:
enabled: true
options: *options
generate_for:
include: *modular
# Non-modular drift generation. Used for some "getting started" e2e examples.
drift_dev:drift_dev: drift_dev:drift_dev:
enabled: true enabled: true
options: options: *options
generate_connect_constructor: true generate_for:
exclude: *modular
json_serializable: json_serializable:
enabled: true enabled: true
sources: sources:
- lib/** - lib/**
- test/generated/** - test/generated/**
prepare: syntax_highlighting:
dependencies: [":source_gen"] dependencies: [":codegen"]
builders: builders:
":versions":
enabled: true
":code_snippets": ":code_snippets":
enabled: true enabled: true
generate_for: generate_for:
@ -58,13 +87,11 @@ targets:
auto_apply_builders: false auto_apply_builders: false
sources: sources:
- "$package$" - "$package$"
- "lib/versions.json"
- "lib/snippets/**" - "lib/snippets/**"
- "tool/write_versions.dart"
- "tool/snippets.dart" - "tool/snippets.dart"
$default: $default:
dependencies: [":prepare"] dependencies: [":codegen", ":syntax_highlighting"]
builders: builders:
built_site: built_site:
release_options: release_options:

View File

@ -0,0 +1,13 @@
import 'package:drift/drift.dart';
import 'example.drift.dart';
class DartExample extends ExampleDrift {
DartExample(GeneratedDatabase attachedDatabase) : super(attachedDatabase);
// #docregion watchInCategory
Stream<List<Todo>> watchInCategory(int category) {
return filterTodos((todos) => todos.category.equals(category)).watch();
}
// #enddocregion watchInCategory
}

View File

@ -0,0 +1,18 @@
CREATE TABLE todos (
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL,
category INTEGER REFERENCES categories(id)
);
CREATE TABLE categories (
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
description TEXT NOT NULL
) AS Category;
-- #docregion filterTodos
filterTodos: SELECT * FROM todos WHERE $predicate;
-- #enddocregion filterTodos
-- #docregion getTodos
getTodos ($predicate = TRUE): SELECT * FROM todos WHERE $predicate;
-- #enddocregion getTodos

View File

@ -0,0 +1,474 @@
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:drift_docs/snippets/modular/drift/example.drift.dart' as i1;
import 'package:drift/internal/modular.dart' as i2;
class Todos extends i0.Table with i0.TableInfo<Todos, i1.Todo> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
Todos(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
'id', aliasedName, false,
hasAutoIncrement: true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
static const i0.VerificationMeta _titleMeta =
const i0.VerificationMeta('title');
late final i0.GeneratedColumn<String> title = i0.GeneratedColumn<String>(
'title', aliasedName, false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL');
static const i0.VerificationMeta _contentMeta =
const i0.VerificationMeta('content');
late final i0.GeneratedColumn<String> content = i0.GeneratedColumn<String>(
'content', aliasedName, false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL');
static const i0.VerificationMeta _categoryMeta =
const i0.VerificationMeta('category');
late final i0.GeneratedColumn<int> category = i0.GeneratedColumn<int>(
'category', aliasedName, true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
$customConstraints: 'REFERENCES categories(id)');
@override
List<i0.GeneratedColumn> get $columns => [id, title, content, category];
@override
String get aliasedName => _alias ?? 'todos';
@override
String get actualTableName => 'todos';
@override
i0.VerificationContext validateIntegrity(i0.Insertable<i1.Todo> instance,
{bool isInserting = false}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
if (data.containsKey('title')) {
context.handle(
_titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta));
} else if (isInserting) {
context.missing(_titleMeta);
}
if (data.containsKey('content')) {
context.handle(_contentMeta,
content.isAcceptableOrUnknown(data['content']!, _contentMeta));
} else if (isInserting) {
context.missing(_contentMeta);
}
if (data.containsKey('category')) {
context.handle(_categoryMeta,
category.isAcceptableOrUnknown(data['category']!, _categoryMeta));
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {id};
@override
i1.Todo map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.Todo(
id: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}id'])!,
title: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}title'])!,
content: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}content'])!,
category: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}category']),
);
}
@override
Todos createAlias(String alias) {
return Todos(attachedDatabase, alias);
}
@override
bool get dontWriteConstraints => true;
}
class Todo extends i0.DataClass implements i0.Insertable<i1.Todo> {
final int id;
final String title;
final String content;
final int? category;
const Todo(
{required this.id,
required this.title,
required this.content,
this.category});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['id'] = i0.Variable<int>(id);
map['title'] = i0.Variable<String>(title);
map['content'] = i0.Variable<String>(content);
if (!nullToAbsent || category != null) {
map['category'] = i0.Variable<int>(category);
}
return map;
}
i1.TodosCompanion toCompanion(bool nullToAbsent) {
return i1.TodosCompanion(
id: i0.Value(id),
title: i0.Value(title),
content: i0.Value(content),
category: category == null && nullToAbsent
? const i0.Value.absent()
: i0.Value(category),
);
}
factory Todo.fromJson(Map<String, dynamic> json,
{i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return Todo(
id: serializer.fromJson<int>(json['id']),
title: serializer.fromJson<String>(json['title']),
content: serializer.fromJson<String>(json['content']),
category: serializer.fromJson<int?>(json['category']),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'title': serializer.toJson<String>(title),
'content': serializer.toJson<String>(content),
'category': serializer.toJson<int?>(category),
};
}
i1.Todo copyWith(
{int? id,
String? title,
String? content,
i0.Value<int?> category = const i0.Value.absent()}) =>
i1.Todo(
id: id ?? this.id,
title: title ?? this.title,
content: content ?? this.content,
category: category.present ? category.value : this.category,
);
@override
String toString() {
return (StringBuffer('Todo(')
..write('id: $id, ')
..write('title: $title, ')
..write('content: $content, ')
..write('category: $category')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, title, content, category);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.Todo &&
other.id == this.id &&
other.title == this.title &&
other.content == this.content &&
other.category == this.category);
}
class TodosCompanion extends i0.UpdateCompanion<i1.Todo> {
final i0.Value<int> id;
final i0.Value<String> title;
final i0.Value<String> content;
final i0.Value<int?> category;
const TodosCompanion({
this.id = const i0.Value.absent(),
this.title = const i0.Value.absent(),
this.content = const i0.Value.absent(),
this.category = const i0.Value.absent(),
});
TodosCompanion.insert({
this.id = const i0.Value.absent(),
required String title,
required String content,
this.category = const i0.Value.absent(),
}) : title = i0.Value(title),
content = i0.Value(content);
static i0.Insertable<i1.Todo> custom({
i0.Expression<int>? id,
i0.Expression<String>? title,
i0.Expression<String>? content,
i0.Expression<int>? category,
}) {
return i0.RawValuesInsertable({
if (id != null) 'id': id,
if (title != null) 'title': title,
if (content != null) 'content': content,
if (category != null) 'category': category,
});
}
i1.TodosCompanion copyWith(
{i0.Value<int>? id,
i0.Value<String>? title,
i0.Value<String>? content,
i0.Value<int?>? category}) {
return i1.TodosCompanion(
id: id ?? this.id,
title: title ?? this.title,
content: content ?? this.content,
category: category ?? this.category,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (id.present) {
map['id'] = i0.Variable<int>(id.value);
}
if (title.present) {
map['title'] = i0.Variable<String>(title.value);
}
if (content.present) {
map['content'] = i0.Variable<String>(content.value);
}
if (category.present) {
map['category'] = i0.Variable<int>(category.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('i1.TodosCompanion(')
..write('id: $id, ')
..write('title: $title, ')
..write('content: $content, ')
..write('category: $category')
..write(')'))
.toString();
}
}
class Categories extends i0.Table with i0.TableInfo<Categories, i1.Category> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
Categories(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
'id', aliasedName, false,
hasAutoIncrement: true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
static const i0.VerificationMeta _descriptionMeta =
const i0.VerificationMeta('description');
late final i0.GeneratedColumn<String> description =
i0.GeneratedColumn<String>('description', aliasedName, false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL');
@override
List<i0.GeneratedColumn> get $columns => [id, description];
@override
String get aliasedName => _alias ?? 'categories';
@override
String get actualTableName => 'categories';
@override
i0.VerificationContext validateIntegrity(i0.Insertable<i1.Category> instance,
{bool isInserting = false}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
if (data.containsKey('description')) {
context.handle(
_descriptionMeta,
description.isAcceptableOrUnknown(
data['description']!, _descriptionMeta));
} else if (isInserting) {
context.missing(_descriptionMeta);
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {id};
@override
i1.Category map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.Category(
id: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}id'])!,
description: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}description'])!,
);
}
@override
Categories createAlias(String alias) {
return Categories(attachedDatabase, alias);
}
@override
bool get dontWriteConstraints => true;
}
class Category extends i0.DataClass implements i0.Insertable<i1.Category> {
final int id;
final String description;
const Category({required this.id, required this.description});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['id'] = i0.Variable<int>(id);
map['description'] = i0.Variable<String>(description);
return map;
}
i1.CategoriesCompanion toCompanion(bool nullToAbsent) {
return i1.CategoriesCompanion(
id: i0.Value(id),
description: i0.Value(description),
);
}
factory Category.fromJson(Map<String, dynamic> json,
{i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return Category(
id: serializer.fromJson<int>(json['id']),
description: serializer.fromJson<String>(json['description']),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'description': serializer.toJson<String>(description),
};
}
i1.Category copyWith({int? id, String? description}) => i1.Category(
id: id ?? this.id,
description: description ?? this.description,
);
@override
String toString() {
return (StringBuffer('Category(')
..write('id: $id, ')
..write('description: $description')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, description);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.Category &&
other.id == this.id &&
other.description == this.description);
}
class CategoriesCompanion extends i0.UpdateCompanion<i1.Category> {
final i0.Value<int> id;
final i0.Value<String> description;
const CategoriesCompanion({
this.id = const i0.Value.absent(),
this.description = const i0.Value.absent(),
});
CategoriesCompanion.insert({
this.id = const i0.Value.absent(),
required String description,
}) : description = i0.Value(description);
static i0.Insertable<i1.Category> custom({
i0.Expression<int>? id,
i0.Expression<String>? description,
}) {
return i0.RawValuesInsertable({
if (id != null) 'id': id,
if (description != null) 'description': description,
});
}
i1.CategoriesCompanion copyWith(
{i0.Value<int>? id, i0.Value<String>? description}) {
return i1.CategoriesCompanion(
id: id ?? this.id,
description: description ?? this.description,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (id.present) {
map['id'] = i0.Variable<int>(id.value);
}
if (description.present) {
map['description'] = i0.Variable<String>(description.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('i1.CategoriesCompanion(')
..write('id: $id, ')
..write('description: $description')
..write(')'))
.toString();
}
}
class ExampleDrift extends i2.ModularAccessor {
ExampleDrift(i0.GeneratedDatabase db) : super(db);
i0.Selectable<i1.Todo> filterTodos(FilterTodos$predicate predicate) {
var $arrayStartIndex = 1;
final generatedpredicate =
$write(predicate(this.todos), startIndex: $arrayStartIndex);
$arrayStartIndex += generatedpredicate.amountOfVariables;
return customSelect('SELECT * FROM todos WHERE ${generatedpredicate.sql}',
variables: [
...generatedpredicate.introducedVariables
],
readsFrom: {
todos,
...generatedpredicate.watchedTables,
}).asyncMap(todos.mapFromRow);
}
i0.Selectable<i1.Todo> getTodos({GetTodos$predicate? predicate}) {
var $arrayStartIndex = 1;
final generatedpredicate = $write(
predicate?.call(this.todos) ?? const i0.CustomExpression('(TRUE)'),
startIndex: $arrayStartIndex);
$arrayStartIndex += generatedpredicate.amountOfVariables;
return customSelect('SELECT * FROM todos WHERE ${generatedpredicate.sql}',
variables: [
...generatedpredicate.introducedVariables
],
readsFrom: {
todos,
...generatedpredicate.watchedTables,
}).asyncMap(todos.mapFromRow);
}
i1.Todos get todos => this.resultSet<i1.Todos>('todos');
}
typedef FilterTodos$predicate = i0.Expression<bool> Function(i1.Todos todos);
typedef GetTodos$predicate = i0.Expression<bool> Function(i1.Todos todos);

View File

@ -15,6 +15,9 @@ template: layouts/docs/single
{% assign drift_tables = "package:drift_docs/snippets/drift_files/tables.drift.excerpt.json" | readString | json_decode %} {% assign drift_tables = "package:drift_docs/snippets/drift_files/tables.drift.excerpt.json" | readString | json_decode %}
{% assign small = "package:drift_docs/snippets/drift_files/small_snippets.drift.excerpt.json" | readString | json_decode %} {% assign small = "package:drift_docs/snippets/drift_files/small_snippets.drift.excerpt.json" | readString | json_decode %}
{% assign newDrift = "package:drift_docs/snippets/modular/drift/example.drift.excerpt.json" | readString | json_decode %}
{% assign newDart = "package:drift_docs/snippets/modular/drift/dart_example.dart.excerpt.json" | readString | json_decode %}
Drift files are a new feature that lets you write all your database code in SQL. Drift files are a new feature that lets you write all your database code in SQL.
But unlike raw SQL strings you might pass to simple database clients, everything in a drift file is verified But unlike raw SQL strings you might pass to simple database clients, everything in a drift file is verified
by drift's powerful SQL analyzer. by drift's powerful SQL analyzer.
@ -291,16 +294,14 @@ would generate a column serialized as "userId" in json.
You can make most of both SQL and Dart with "Dart Templates", which is a You can make most of both SQL and Dart with "Dart Templates", which is a
Dart expression that gets inlined to a query at runtime. To use them, declare a Dart expression that gets inlined to a query at runtime. To use them, declare a
$-variable in a query: $-variable in a query:
```sql
_filterTodos: SELECT * FROM todos WHERE $predicate; {% include "blocks/snippet" snippets = newDrift name = "filterTodos" %}
```
Drift will generate a `Selectable<Todo> _filterTodos(Expression<bool> predicate)` Drift will generate a `Selectable<Todo>` method with a `predicate` parameter that
method that can be used to construct dynamic filters at runtime: can be used to construct dynamic filters at runtime:
```dart
Stream<List<Todo>> watchInCategory(int category) { {% include "blocks/snippet" snippets = newDart name = "watchInCategory" %}
return _filterTodos(todos.category.equals(category)).watch();
}
```
This lets you write a single SQL query and dynamically apply a predicate at runtime! This lets you write a single SQL query and dynamically apply a predicate at runtime!
This feature works for This feature works for
@ -314,46 +315,11 @@ This feature works for
When used as expression, you can also supply a default value in your query: When used as expression, you can also supply a default value in your query:
```sql {% include "blocks/snippet" snippets = newDrift name = "getTodos" %}
_filterTodos ($predicate = TRUE): SELECT * FROM todos WHERE $predicate;
```
This will make the `predicate` parameter optional in Dart. It will use the This will make the `predicate` parameter optional in Dart. It will use the
default SQL value (here, `TRUE`) when not explicitly set. default SQL value (here, `TRUE`) when not explicitly set.
{% block "blocks/alert" title="Using column names in Dart" color="warning" %}
If your query uses table aliases, you'll need to account for that when embedding Dart
expressions in your SQL query. Consider this for instance:
```sql
findRoutes: SELECT r.* FROM routes r
INNER JOIN points "start" ON "start".id = r."start"
INNER JOIN points "end" ON "end".id = r."end"
WHERE $predicate
```
If you want to filter for the `start` point in Dart, you have to use
an explicit [`alias`](https://pub.dev/documentation/drift/latest/drift/DatabaseConnectionUser/alias.html):
```dart
Future<List<Route>> routesByStart(int startPointId) {
final start = alias(points, 'start');
return findRoutes(start.id.equals(startPointId));
}
```
You can enable the `scoped_dart_components` [build option]({{ '../Advanced Features/builder_options.md' | pageUrl }})
and let the generator help you here.
When the option is enabled, drift would generate a `Expression<bool> Function(Routes r, Points start, Points end)` as a parameter, which
makes this a lot easier:
```dart
Future<List<Route>> routesByStart(int startPointId) {
return findRoutes((r, start, end) => start.id.equals(startPointId));
}
```
{% endblock %}
### Type converters ### Type converters
You can import and use [type converters]({{ "../Advanced Features/type_converters.md" | pageUrl }}) You can import and use [type converters]({{ "../Advanced Features/type_converters.md" | pageUrl }})

View File

@ -14,7 +14,7 @@ dependencies:
version: ^0.2.2 version: ^0.2.2
code_snippets: code_snippets:
hosted: https://simonbinder.eu hosted: https://simonbinder.eu
version: ^0.0.8 version: ^0.0.11
# used in snippets # used in snippets
http: ^0.13.5 http: ^0.13.5
sqlite3: ^1.7.2 sqlite3: ^1.7.2

View File

@ -1,4 +1,2 @@
{% assign excerpt = args.name | default: '(full)' %} {% assign excerpt = args.name | default: '(full)' %}
<pre> <pre><code class="hljs">{{ args.snippets | get: excerpt }}</code></pre>
<code class="hljs">{{ args.snippets | get: excerpt }}</code>
</pre>

View File

@ -339,7 +339,7 @@ class _DriftBuildRun {
); );
writer = Writer(options, generationOptions: generationOptions); writer = Writer(options, generationOptions: generationOptions);
} else { } else {
final imports = LibraryInputManager(); final imports = LibraryInputManager(buildStep.allowedOutputs.single.uri);
final generationOptions = GenerationOptions( final generationOptions = GenerationOptions(
imports: imports, imports: imports,
isModular: true, isModular: true,

View File

@ -1,3 +1,5 @@
import 'package:path/path.dart' show url;
import '../utils/string_escaper.dart'; import '../utils/string_escaper.dart';
import 'writer.dart'; import 'writer.dart';
@ -16,9 +18,16 @@ class LibraryInputManager extends ImportManager {
static final _dartCore = Uri.parse('dart:core'); static final _dartCore = Uri.parse('dart:core');
final Map<Uri, String> _importAliases = {}; final Map<Uri, String> _importAliases = {};
/// The uri of the file being generated.
///
/// This allows constructing relative imports for assets that aren't in
/// `lib/`.
final Uri? _outputUri;
TextEmitter? emitter; TextEmitter? emitter;
LibraryInputManager(); LibraryInputManager([this._outputUri]);
void linkToWriter(Writer writer) { void linkToWriter(Writer writer) {
emitter = writer.leaf(); emitter = writer.leaf();
@ -33,8 +42,20 @@ class LibraryInputManager extends ImportManager {
return _importAliases.putIfAbsent(definitionUri, () { return _importAliases.putIfAbsent(definitionUri, () {
final alias = 'i${_importAliases.length}'; final alias = 'i${_importAliases.length}';
emitter?.writeln( final importedScheme = definitionUri.scheme;
'import ${asDartLiteral(definitionUri.toString())} as $alias;'); String importLiteral;
if (importedScheme != 'package' &&
importedScheme != 'dart' &&
importedScheme == _outputUri?.scheme) {
// Not a package nor a dart import, use a relative import instead
importLiteral = url.relative(definitionUri.path,
from: url.dirname(_outputUri!.path));
} else {
importLiteral = definitionUri.toString();
}
emitter?.writeln('import ${asDartLiteral(importLiteral)} as $alias;');
return alias; return alias;
}); });
} }

View File

@ -0,0 +1,48 @@
import 'package:build/build.dart';
import 'package:drift_dev/src/analysis/options.dart';
import 'package:drift_dev/src/analysis/results/results.dart';
import 'package:drift_dev/src/writer/import_manager.dart';
import 'package:drift_dev/src/writer/writer.dart';
import 'package:test/test.dart';
void main() {
group('LibraryInputManager', () {
final sourceUri = AssetId('a', 'example/main.dart').uri;
late LibraryInputManager imports;
late Writer writer;
setUp(() {
imports = LibraryInputManager(sourceUri);
final generationOptions =
GenerationOptions(imports: imports, isModular: true);
writer = Writer(const DriftOptions.defaults(),
generationOptions: generationOptions);
imports.linkToWriter(writer);
});
test('does not generate prefix for dart:core', () {
expect(imports.prefixFor(Uri.parse('dart:core'), 'String'), isNull);
});
test('writes imports', () {
expect(imports.prefixFor(AnnotatedDartCode.dartAsync, 'Future'), 'i0');
expect(imports.prefixFor(AnnotatedDartCode.drift, 'GeneratedDatabase'),
'i1');
expect(imports.prefixFor(AnnotatedDartCode.dartAsync, 'Stream'), 'i0');
expect(writer.writeGenerated(), '''
import 'dart:async' as i0;
import 'package:drift/drift.dart' as i1;
''');
});
test('can write imports for files outside of lib', () {
final uri = AssetId('a', 'example/imported.dart').uri;
expect(imports.prefixFor(uri, 'Test'), 'i0');
expect(
writer.writeGenerated(), contains("import 'imported.dart' as i0;"));
});
});
}