Scaffold api to support type converters in moor files

I still don't know how to parse expressions though :(
This commit is contained in:
Simon Binder 2019-09-06 22:23:44 +02:00
parent 6ccaad866b
commit 71d1bfdc9c
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 69 additions and 2 deletions

View File

@ -0,0 +1,45 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:moor_generator/src/analyzer/session.dart';
/// Resolves the type of Dart expressions given as a string. The
/// [importStatements] are used to discover types.
///
/// The way this works is that we create a fake file for the analyzer. That file
/// has the following content:
/// ```
/// import 'package:moor/moor.dart'; // always imported
/// // all import statements
///
/// var expr = $expression;
/// ```
///
/// We can then obtain the type of an expression by reading the inferred type
/// of the top-level `expr` variable in that source.
class InlineDartResolver {
final List<String> importStatements = [];
final MoorTask task;
InlineDartResolver(this.task);
Future<DartType> resolveDartTypeOf(String expression) async {
final template = _createDartTemplate(expression);
final unit = await task.backendTask.parseSource(template);
final declaration = unit.declarations.single as TopLevelVariableDeclaration;
return declaration.variables.variables.single.initializer.staticType;
}
String _createDartTemplate(String expression) {
final fakeDart = StringBuffer();
fakeDart.write("import 'package:moor/moor.dart';\n");
for (var import in importStatements) {
fakeDart.write("import '$import';\n");
}
fakeDart.write('var expr = $expression;\n');
return fakeDart.toString();
}
}

View File

@ -16,7 +16,10 @@ class MoorParser {
final createdReaders = <CreateTableReader>[]; final createdReaders = <CreateTableReader>[];
for (var parsedStmt in results) { for (var parsedStmt in results) {
if (parsedStmt.rootNode is CreateTableStatement) { if (parsedStmt.rootNode is ImportStatement) {
final importStmt = (parsedStmt.rootNode) as ImportStatement;
task.inlineDartResolver.importStatements.add(importStmt.importedFile);
} else if (parsedStmt.rootNode is CreateTableStatement) {
createdReaders.add(CreateTableReader(parsedStmt)); createdReaders.add(CreateTableReader(parsedStmt));
} else { } else {
task.reportError(ErrorInMoorFile( task.reportError(ErrorInMoorFile(

View File

@ -6,6 +6,7 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:moor/moor.dart' show Table; import 'package:moor/moor.dart' show Table;
import 'package:moor_generator/src/analyzer/dart/parser.dart'; import 'package:moor_generator/src/analyzer/dart/parser.dart';
import 'package:moor_generator/src/analyzer/errors.dart'; import 'package:moor_generator/src/analyzer/errors.dart';
import 'package:moor_generator/src/analyzer/moor/inline_dart_resolver.dart';
import 'package:moor_generator/src/analyzer/moor/parser.dart'; import 'package:moor_generator/src/analyzer/moor/parser.dart';
import 'package:moor_generator/src/analyzer/results.dart'; import 'package:moor_generator/src/analyzer/results.dart';
import 'package:moor_generator/src/analyzer/sql_queries/sql_parser.dart'; import 'package:moor_generator/src/analyzer/sql_queries/sql_parser.dart';
@ -151,9 +152,12 @@ class DartTask extends FileTask<ParsedDartFile> {
class MoorTask extends FileTask<ParsedMoorFile> { class MoorTask extends FileTask<ParsedMoorFile> {
final String content; final String content;
final TypeMapper mapper = TypeMapper(); final TypeMapper mapper = TypeMapper();
/* late final */ InlineDartResolver inlineDartResolver;
MoorTask(BackendTask task, MoorSession session, this.content) MoorTask(BackendTask task, MoorSession session, this.content)
: super(task, session); : super(task, session) {
inlineDartResolver = InlineDartResolver(this);
}
@override @override
FutureOr<ParsedMoorFile> compute() { FutureOr<ParsedMoorFile> compute() {

View File

@ -1,3 +1,4 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/analyzer/session.dart';
@ -17,5 +18,6 @@ abstract class BackendTask {
Logger get log; Logger get log;
Future<LibraryElement> resolveDart(Uri uri); Future<LibraryElement> resolveDart(Uri uri);
Future<CompilationUnit> parseSource(String dart);
Future<String> readMoor(Uri uri); Future<String> readMoor(Uri uri);
} }

View File

@ -1,3 +1,5 @@
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart' hide log; import 'package:build/build.dart' hide log;
import 'package:build/build.dart' as build show log; import 'package:build/build.dart' as build show log;
@ -32,6 +34,11 @@ class BuildBackendTask extends BackendTask {
return step.resolver.libraryFor(_resolve(uri)); return step.resolver.libraryFor(_resolve(uri));
} }
@override
Future<CompilationUnit> parseSource(String dart) async {
return null;
}
@override @override
Logger get log => build.log; Logger get log => build.log;
} }

View File

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:build_test/build_test.dart'; import 'package:build_test/build_test.dart';
@ -60,4 +61,9 @@ class _TestBackendTask extends BackendTask {
await backend._ready; await backend._ready;
return await backend._resolver.libraryFor(AssetId.resolve(path.toString())); return await backend._resolver.libraryFor(AssetId.resolve(path.toString()));
} }
@override
Future<CompilationUnit> parseSource(String dart) {
return null;
}
} }