Skip to content

Commit

Permalink
Resolve imports across exports
Browse files Browse the repository at this point in the history
  • Loading branch information
simolus3 committed Sep 3, 2023
1 parent 9ada08d commit 79dda86
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 27 deletions.
4 changes: 4 additions & 0 deletions drift_dev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.11.2-dev

- Follow `export` directives when looking for table imports.

## 2.11.1

- Reduce the amount of assets read by drift, improving build performance and enabling faster
Expand Down
6 changes: 3 additions & 3 deletions drift_dev/lib/src/analysis/driver/cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ class DriftAnalysisCache {
final found = pending.removeLast();
yield found;

for (final imported in found.imports ?? const <Uri>[]) {
for (final imported in found.imports ?? const <DriftImport>[]) {
// We might not have a known file for all imports of a Dart file, since
// not all imports are drift-related there.
final knownImport = knownFiles[imported];
final knownImport = knownFiles[imported.uri];

if (seenUris.add(imported) && knownImport != null) {
if (seenUris.add(imported.uri) && knownImport != null) {
pending.add(knownImport);
}
}
Expand Down
13 changes: 6 additions & 7 deletions drift_dev/lib/src/analysis/driver/driver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,11 @@ class DriftAnalysisDriver {
warnIfFileDoesntExist: true,
);

// Drift file imports are transitive, Dart imports aren't.
if (file == known.ownUri || fileState.extension == '.drift') {
for (final dependency in fileState.imports ?? const <Uri>[]) {
if (!seen.contains(dependency)) {
pending.add(dependency);
}
for (final dependency in fileState.imports ?? const <DriftImport>[]) {
final considerImport = file == known.ownUri || dependency.transitive;

if (considerImport && !seen.contains(dependency.uri)) {
pending.add(dependency.uri);
}
}
}
Expand Down Expand Up @@ -289,7 +288,7 @@ class DriftAnalysisDriver {
final imports = state.discovery?.importDependencies;
if (imports != null) {
data.serializedData['imports'] = [
for (final import in imports) import.toString()
for (final import in imports) import.uri.toString()
];
}

Expand Down
17 changes: 12 additions & 5 deletions drift_dev/lib/src/analysis/driver/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import '../results/query.dart';
import 'driver.dart';
import 'error.dart';

typedef DriftImport = ({Uri uri, bool transitive});

class FileState {
final Uri ownUri;

Expand All @@ -30,7 +32,7 @@ class FileState {
return (cachedDiscovery?.isValidImport ?? discovery?.isValidImport) == true;
}

Iterable<Uri>? get imports =>
Iterable<DriftImport>? get imports =>
discovery?.importDependencies ?? cachedDiscovery?.imports;

String get extension => url.extension(ownUri.path);
Expand Down Expand Up @@ -110,7 +112,7 @@ class FileState {

class CachedDiscoveryResults {
final bool isValidImport;
final List<Uri> imports;
final List<DriftImport> imports;
final List<ExistingDriftElement> locallyDefinedElements;

CachedDiscoveryResults(
Expand All @@ -125,7 +127,7 @@ abstract class DiscoveredFileState {

bool get isValidImport => false;

Iterable<Uri> get importDependencies => const [];
Iterable<DriftImport> get importDependencies => const [];

DiscoveredFileState(this.locallyDefinedElements);
}
Expand All @@ -139,7 +141,12 @@ class DiscoveredDriftFile extends DiscoveredFileState {
bool get isValidImport => true;

@override
Iterable<Uri> get importDependencies => imports.map((e) => e.importedUri);
Iterable<DriftImport> get importDependencies => imports.map((e) => (
uri: e.importedUri,
// Imports in drift files are always transitive (visible to files
// importing this drift file).
transitive: true,
));

DiscoveredDriftFile({
required this.originalSource,
Expand All @@ -160,7 +167,7 @@ class DiscoveredDartLibrary extends DiscoveredFileState {
final LibraryElement library;

@override
final List<Uri> importDependencies;
final List<DriftImport> importDependencies;

@override
bool get isValidImport => true;
Expand Down
19 changes: 13 additions & 6 deletions drift_dev/lib/src/analysis/resolver/discover.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class _FindDartElements extends RecursiveElementVisitor<void> {
final DiscoverStep _discoverStep;
final LibraryElement _library;

final List<Uri> imports = [];
final List<DriftImport> imports = [];

final TypeChecker _isTable, _isView, _isTableInfo, _isDatabase, _isDao;

Expand Down Expand Up @@ -237,18 +237,25 @@ class _FindDartElements extends RecursiveElementVisitor<void> {
super.visitClassElement(element);
}

@override
void visitLibraryImportElement(LibraryImportElement element) {
final imported = element.importedLibrary;

void _handleImportOrExport(LibraryElement? imported, bool isExported) {
if (imported != null && !imported.isInSdk) {
_pendingWork.add(Future(() async {
final uri = await _discoverStep._driver.backend.uriOfDart(imported);
imports.add(uri);
imports.add((uri: uri, transitive: isExported));
}));
}
}

@override
void visitLibraryExportElement(LibraryExportElement element) {
_handleImportOrExport(element.exportedLibrary, true);
}

@override
void visitLibraryImportElement(LibraryImportElement element) {
_handleImportOrExport(element.importedLibrary, false);
}

String _defaultNameForTableOrView(ClassElement definingElement) {
return _discoverStep._driver.options.caseFromDartToSql
.apply(definingElement.name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ abstract class DriftElementResolver<T extends DiscoveredElement>
file.ownUri,
code,
file.discovery!.importDependencies
.map((e) => e.toString())
.map((e) => e.uri.toString())
.where((e) => e.endsWith('.dart')),
);
} on CannotReadExpressionException catch (e) {
Expand Down Expand Up @@ -62,6 +62,7 @@ abstract class DriftElementResolver<T extends DiscoveredElement>

Future<Element?> _findInDart(String identifier) async {
final dartImports = file.discovery!.importDependencies
.map((e) => e.uri)
.where((importUri) => importUri.path.endsWith('.dart'))
// Also add `dart:core` as a default import so that types like `Record`
// are available.
Expand Down
5 changes: 4 additions & 1 deletion drift_dev/lib/src/backends/build/analyzer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ class DriftDiscover extends Builder {
'valid_import': discovery.isValidImport,
'imports': [
for (final import in discovery.importDependencies)
import.toString(),
{
'uri': import.uri.toString(),
'transitive': import.transitive,
}
],
'elements': [
for (final entry in discovery.locallyDefinedElements)
Expand Down
8 changes: 7 additions & 1 deletion drift_dev/lib/src/backends/build/backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,13 @@ class BuildCacheReader implements AnalysisResultCacheReader {

return CachedDiscoveryResults(
results['valid_import'] as bool,
[for (final import in rawImports) Uri.parse(import as String)],
[
for (final import in rawImports.cast<Map<String, Object?>>())
(
uri: Uri.parse(import['uri'] as String),
transitive: import['transitive'] as bool,
)
],
[
for (final element in rawElements)
ExistingDriftElement(
Expand Down
2 changes: 1 addition & 1 deletion drift_dev/lib/src/writer/modules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class ModularAccessorWriter {
final file = driver.cache.knownFiles[import];

if (file != null && file.needsModularAccessor(driver)) {
final moduleClass = restOfClass.modularAccessor(import);
final moduleClass = restOfClass.modularAccessor(import.uri);
final getterName = ReCase(moduleClass.toString()).camelCase;

restOfClass
Expand Down
2 changes: 1 addition & 1 deletion drift_dev/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: drift_dev
description: Dev-dependency for users of drift. Contains the generator and development tools.
version: 2.11.1
version: 2.11.2-dev
repository: https:/simolus3/drift
homepage: https://drift.simonbinder.eu/
issue_tracker: https:/simolus3/drift/issues
Expand Down
2 changes: 1 addition & 1 deletion drift_dev/test/analysis/resolver/discover_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ CREATE VIEW a AS VALUES(1,2,3);
isA<DiscoveredDriftFile>().having(
(e) => e.importDependencies,
'importDependencies',
[Uri.parse('package:a/b.drift')],
[(uri: Uri.parse('package:a/b.drift'), transitive: true)],
),
);

Expand Down
37 changes: 37 additions & 0 deletions drift_dev/test/backends/build/build_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,43 @@ class MyDatabase {}
}, outputs.dartOutputs, outputs.writer);
});

test('crawl imports through export', () async {
final outputs = await emulateDriftBuild(
inputs: {
'a|lib/table.dart': '''
import 'package:drift/drift.dart';

class MyTable extends Table {
IntColumn get id => integer().autoIncrement()();
}
''',
'a|lib/barrel.dart': '''
export 'table.dart';
''',
'a|lib/database.dart': r'''
import 'package:drift/drift.dart';

import 'barrel.dart';

@DriftDatabase(tables: [MyTable])
class AppDatabase extends $AppDatabase {
AppDatabase(super.e);

@override
int get schemaVersion => 1;
}
''',
},
modularBuild: true,
logger: loggerThat(neverEmits(anything)),
);

checkOutputs({
'a|lib/table.drift.dart': anything,
'a|lib/database.drift.dart': decodedMatches(contains('myTable')),
}, outputs.dartOutputs, outputs.writer);
});

test('does not read unecessary files', () async {
final inputs = <String, String>{
'a|lib/groups.drift': '''
Expand Down

0 comments on commit 79dda86

Please sign in to comment.