First draft for intermediate results

This commit is contained in:
Simon Binder 2022-08-21 23:45:42 +02:00
parent b088537b81
commit 5e4a65eace
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
10 changed files with 169 additions and 1 deletions

View File

@ -1,7 +1,9 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:logging/logging.dart';
abstract class DriftBackend {
Logger get log;
Future<String> readAsString(Uri uri);
Future<LibraryElement> readDart(Uri uri);
}

View File

@ -0,0 +1,79 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:collection/collection.dart';
import 'package:sqlparser/sqlparser.dart';
import 'package:path/path.dart' show url;
import 'results/element.dart';
class DriftAnalysisCache {
final Map<Uri, FileState> knownFiles = {};
final Map<DriftElementId, PendingDriftElement> knownElements = {};
FileState notifyFileChanged(Uri uri) {
// todo: Mark references for files that import this one as stale.
// todo: Mark elements that reference an element in this file as stale.
return knownFiles.putIfAbsent(uri, () => FileState(uri))
..errors.clear()
..kind = null
..parsedDartFile = null
..parsedDriftFile = null;
}
void notifyFileDeleted(Uri uri) {}
}
/// A [DriftElement] that is known to exist, but perhaps hasn't fully been
/// resolved yet.
class PendingDriftElement {
final DriftElementId ownId;
final List<Dependency> dependencies;
bool cleanState = false;
bool isOnCircularReferencePath = false;
PendingDriftElement(this.ownId, List<Dependency> dependencies)
: dependencies = UnmodifiableListView(dependencies);
}
abstract class Dependency {}
class ReferencesElement extends Dependency {
final DriftElementId referencedElement;
ReferencesElement(this.referencedElement);
}
class ReferencesUnknownElement extends Dependency {
final String name;
ReferencesUnknownElement(this.name);
}
enum FileKind {
driftFile,
dartLibrary,
/// A Dart part file, a file with an unknown extension or a file that doesn't
/// exist.
invalid,
}
class FileState {
final Uri uri;
final List<DriftElementId> locallyDefinedElements = [];
final List<Uri> directImports = [];
final List<AnalysisError> errors = [];
bool contentsFresh = false;
bool referencesFresh = false;
FileKind? kind;
DriftFile? parsedDriftFile;
LibraryElement? parsedDartFile;
FileState(this.uri);
String get extension => url.extension(uri.path);
}

View File

@ -0,0 +1,70 @@
import 'package:sqlparser/sqlparser.dart';
import '../analyzer/options.dart';
import 'backend.dart';
import 'cache.dart';
class DriftAnalysisDriver {
final DriftBackend backend;
final DriftAnalysisCache cache = DriftAnalysisCache();
final DriftOptions options;
DriftAnalysisDriver(this.backend, this.options);
SqlEngine _newSqlEngine() {
return SqlEngine(
EngineOptions(
useDriftExtensions: true,
enabledExtensions: [
// todo: Map from options
],
version: options.sqliteVersion,
),
);
}
/// Identify all [PendingDriftElement]s in a file.
Future<void> _discover(FileState state) async {
final extension = state.extension;
switch (extension) {
case '.dart':
try {
state
..parsedDartFile = await backend.readDart(state.uri)
..kind = FileKind.dartLibrary;
} catch (e, s) {
backend.log
.fine('Could not read Dart library from ${state.uri}', e, s);
state.kind = FileKind.invalid;
}
break;
case '.drift':
case '.moor':
final engine = _newSqlEngine();
String contents;
try {
contents = await backend.readAsString(state.uri);
state.kind = FileKind.driftFile;
} catch (e, s) {
backend.log.fine('Could not read drift sources ${state.uri}', e, s);
state.kind = FileKind.invalid;
break;
}
// todo: Handle parse errors
final parsed = engine.parseDriftFile(contents);
state.parsedDriftFile = parsed.rootNode as DriftFile;
break;
}
}
Future<void> fullyAnalyze(Uri uri) async {
var known = cache.knownFiles[uri];
if (known == null || !known.contentsFresh) {
await _discover(cache.notifyFileChanged(uri));
}
}
}

View File

@ -0,0 +1 @@
class AnalysisError {}

View File

@ -19,4 +19,5 @@ class DriftDeclaration {
abstract class DriftElement {
DriftElementId get id;
DriftDeclaration get declaration;
}

View File

@ -0,0 +1,15 @@
import 'package:sqlparser/sqlparser.dart';
abstract class TemporaryResult {}
class TemporaryDriftTable extends TemporaryResult {
final TableInducingStatement statement;
TemporaryDriftTable(this.statement);
}
class TemporaryDriftView extends TemporaryResult {
final CreateViewStatement statement;
TemporaryDriftView(this.statement);
}

View File

@ -6,7 +6,7 @@ homepage: https://drift.simonbinder.eu/
issue_tracker: https://github.com/simolus3/drift/issues
environment:
sdk: '>=2.14.0 <3.0.0'
sdk: '>=2.17.0 <3.0.0'
dependencies:
charcode: ^1.2.0