Skip to content

Commit

Permalink
Manager references across modular files
Browse files Browse the repository at this point in the history
Closes #3446
  • Loading branch information
simolus3 committed Feb 2, 2025
1 parent 35e16a5 commit 0ca679c
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 8 deletions.
2 changes: 2 additions & 0 deletions drift_dev/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
JSON type to nullable column.
- Fix missing outputs for drift files only consisting of imports in modular
generation mode.
- Allow generating manager references across different files in modular
generation mode.

## 2.24.0

Expand Down
7 changes: 7 additions & 0 deletions drift_dev/lib/src/analysis/resolver/file_analysis.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ class FileAnalyzer {
final knownTypes = await driver.knownTypes;
final typeMapping = await driver.typeMapping;

for (final file in driver.cache.crawl(state).toList()) {
await driver.resolveElements(file.ownUri);

result.allAvailableElements
.addAll(file.analysis.values.map((e) => e.result).whereType());
}

if (state.extension == '.dart') {
for (final elementAnalysis in state.analysis.values) {
final element = elementAnalysis.result;
Expand Down
3 changes: 3 additions & 0 deletions drift_dev/lib/src/analysis/results/file_results.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import 'query.dart';
class FileAnalysisResult {
final List<DriftAnalysisError> analysisErrors = [];

/// All elements either declared in this file or transitively imported.
final List<DriftElement> allAvailableElements = [];

final Map<DriftElementId, SqlQuery> resolvedQueries = {};
final Map<DriftElementId, ResolvedDatabaseAccessor> resolvedDatabases = {};
}
Expand Down
10 changes: 10 additions & 0 deletions drift_dev/lib/src/backends/build/drift_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,16 @@ class _DriftBuildRun {
ModularAccessorWriter(writer.child(), entrypointState, driver).write();

if (options.generateManager) {
final all = entrypointState.fileAnalysis?.allAvailableElements
.whereType<DriftTable>() ??
const Iterable.empty();

for (final element in all) {
if (element.id.libraryUri != entrypointState.ownUri) {
managerWriter.addTableWithoutGeneration(element);
}
}

managerWriter.writeTableManagers();
}
}
Expand Down
26 changes: 19 additions & 7 deletions drift_dev/lib/src/writer/manager/database_manager_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ part 'table_manager_writer.dart';
class DatabaseManagerWriter {
final Scope _scope;
final String _dbClassName;
final List<DriftTable> _addedTables;
final List<DriftTable> _addedTables = [];

/// Tables which may be referenced in added tables, but for which no code
/// should be generated.
final List<DriftTable> _additionalTables = [];

/// Class used to write a manager for a database
DatabaseManagerWriter(this._scope, this._dbClassName) : _addedTables = [];
DatabaseManagerWriter(this._scope, this._dbClassName);

_ManagerCodeTemplates get _templates => _ManagerCodeTemplates(_scope);

Expand All @@ -24,15 +28,23 @@ class DatabaseManagerWriter {
_addedTables.add(table);
}

/// Add a table for which no code should be generated by this manager writer.
///
/// This is useful to track external tables in modular code generation mode.
void addTableWithoutGeneration(DriftTable table) {
_additionalTables.add(table);
}

/// Write a table manager for each table.
void writeTableManagers() {
final leaf = _scope.leaf();
for (var table in _addedTables) {
final otherTables = _addedTables
.whereNot(
(otherTable) => otherTable.equals(table),
)
.toList();
final otherTables = [
for (final other in _addedTables)
if (other != table) other,
..._additionalTables,
];

_TableManagerWriter(
table: table,
scope: _scope,
Expand Down
40 changes: 40 additions & 0 deletions drift_dev/test/backends/build/build_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1298,4 +1298,44 @@ second: SELECT 2;
'a|lib/src/second.drift.dart': anything,
}, build.dartOutputs, build.writer);
});

test('generates manager references for tables in different files', () async {
final build = await emulateDriftBuild(
inputs: {
'a|lib/users.dart': '''
import 'package:drift/drift.dart';
import 'groups.dart';
class Users extends Table {
late final id = integer().autoIncrement()();
late final name = text()();
}
''',
'a|lib/groups.dart': '''
import 'package:drift/drift.dart';
import 'users.dart';
class Groups extends Table {
late final id = integer().autoIncrement()();
late final name = text()();
@ReferenceName('administeredGroups')
late final admin = integer().nullable().references(Users, #id)();
@ReferenceName('ownedGroups')
late final owner = integer().references(Users, #id)();
}
''',
},
modularBuild: true,
logger: loggerThat(neverEmits(anything)),
);

checkOutputs({
'a|lib/users.drift.dart': decodedMatches(
allOf(contains('ownedGroups'), contains('administeredGroups')),
),
'a|lib/groups.drift.dart': anything,
}, build.dartOutputs, build.writer);
});
}
2 changes: 1 addition & 1 deletion examples/modular/lib/src/posts.drift.dart
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ class $PostsTableManager extends i0.RootTableManager<
getPrefetchedDataCallback: (items) async {
return [
if (likesRefs)
await i0.$_getPrefetchedData(
await i0.$_getPrefetchedData<i1.Post, i1.Posts, i1.Like>(
currentTable: table,
referencedTable:
i1.$PostsReferences._likesRefsTable(db),
Expand Down

0 comments on commit 0ca679c

Please sign in to comment.