mirror of https://github.com/AMT-Cheif/drift.git
First draft for intermediate results
This commit is contained in:
parent
b088537b81
commit
5e4a65eace
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
class AnalysisError {}
|
|
@ -19,4 +19,5 @@ class DriftDeclaration {
|
|||
|
||||
abstract class DriftElement {
|
||||
DriftElementId get id;
|
||||
DriftDeclaration get declaration;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue