Analyze views before other entities

This commit is contained in:
Simon Binder 2022-01-19 20:53:25 +01:00
parent 09b13bdc64
commit 2a347b2f40
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 70 additions and 12 deletions

View File

@ -1,3 +1,7 @@
## 1.4.0-dev
- Fix imported views in `.drift` files not being available in all cases.
## 1.3.0
- Support `drift` version `1.3.x`.

View File

@ -45,16 +45,16 @@ abstract class AnalyzingStep extends Step {
@override
final bool isParsing = false;
Iterable<MoorSchemaEntity> _availableEntities(List<FoundFile> imports) {
Iterable<MoorSchemaEntity> _availableEntities(Iterable<FoundFile> imports) {
return imports.expand<MoorSchemaEntity>((file) =>
file.currentResult?.declaredEntities ?? const Iterable.empty());
}
Iterable<MoorTable> _availableTables(List<FoundFile> imports) {
Iterable<MoorTable> _availableTables(Iterable<FoundFile> imports) {
return _availableEntities(imports).whereType<MoorTable>();
}
Iterable<MoorView> _availableViews(List<FoundFile> imports) {
Iterable<MoorView> _availableViews(Iterable<FoundFile> imports) {
return _availableEntities(imports).whereType<MoorView>();
}
}

View File

@ -1,5 +1,26 @@
part of '../steps.dart';
class AnalyzeViewsInDriftFileStep extends AnalyzingStep {
AnalyzeViewsInDriftFileStep(Task task, FoundFile file) : super(task, file);
Future<void> analyze() async {
if (file.currentResult == null) {
// Error during parsing, ignore.
return;
}
final parseResult = file.currentResult as ParsedMoorFile;
final availableTables =
_availableTables(task.crawlImports(parseResult.resolvedImports!.values))
.followedBy(parseResult.declaredTables)
.toList();
await ViewAnalyzer(this, availableTables, parseResult.imports)
.resolve(parseResult.declaredViews);
file.errors.consume(errors);
}
}
class AnalyzeMoorStep extends AnalyzingStep {
AnalyzeMoorStep(Task task, FoundFile file) : super(task, file);
@ -28,15 +49,10 @@ class AnalyzeMoorStep extends AnalyzingStep {
final availableTables = _availableTables(transitiveImports)
.followedBy(parseResult.declaredTables)
.toList();
final importedViews = _availableViews(transitiveImports).toList();
EntityHandler(this, parseResult, availableTables).handle();
await ViewAnalyzer(
this, availableTables, importedViews, parseResult.imports)
.resolve(parseResult.declaredViews);
final availableViews =
importedViews.followedBy(parseResult.declaredViews).toList();
final parser =

View File

@ -56,8 +56,20 @@ class Task {
final moorFiles = _analyzedFiles.where((f) => f.type == FileType.moor);
final otherFiles = _analyzedFiles.where((f) => f.type != FileType.moor);
for (final moorFile in moorFiles) {
moorFile.errors.clearNonParsingErrors();
// Resolve views before anything else. This ensures that views from
// imports can be accessed.
await AnalyzeViewsInDriftFileStep(this, moorFile).analyze();
}
for (final file in moorFiles.followedBy(otherFiles)) {
file.errors.clearNonParsingErrors();
if (file.type == FileType.dartLibrary) {
// Drift file errors are already cleared before analyzing views.
file.errors.clearNonParsingErrors();
}
await _analyze(file);
}

View File

@ -12,9 +12,8 @@ import '../custom_row_class.dart';
class ViewAnalyzer extends BaseAnalyzer {
final List<ImportStatement> imports;
ViewAnalyzer(
Step step, List<MoorTable> tables, List<MoorView> views, this.imports)
: super(tables, views, step);
ViewAnalyzer(Step step, List<MoorTable> tables, this.imports)
: super(tables, const [], step);
/// Resolves all the views in topological order.
Future<void> resolve(Iterable<MoorView> viewsToAnalyze) async {

View File

@ -0,0 +1,27 @@
import 'package:test/test.dart';
import '../utils.dart';
void main() {
// Regression test for https://github.com/simolus3/moor/issues/1639
test('imported views are analyzed', () async {
final testState = TestState.withContent({
'a|lib/imported.drift': '''
CREATE TABLE a (
b TEXT NOT NULL
);
CREATE VIEW my_view AS SELECT * FROM a;
''',
'a|lib/main.drift': '''
import 'imported.drift';
query: SELECT * FROM my_view;
''',
});
addTearDown(testState.close);
final file = await testState.analyze('package:a/main.drift');
expect(file.errors.errors, isEmpty);
});
}