Refactoring on the model classes in moor_generator

This commit is contained in:
Simon Binder 2019-12-14 21:43:04 +01:00
parent 6b776d47d7
commit 8661e0a28a
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
47 changed files with 505 additions and 328 deletions

View File

@ -48,7 +48,7 @@ You can learn more about the json1 extension on [sqlite.org](https://www.sqlite.
## fts5 ## fts5
The fts5 extensions provides full-text search capabilities in sqlite tables. The fts5 extension provides full-text search capabilities in sqlite tables.
To enable the fts5 extension in moor files and compiled queries, modify the To enable the fts5 extension in moor files and compiled queries, modify the
[build options]({{<relref "../Advanced Features/builder_options.md">}}) to include [build options]({{<relref "../Advanced Features/builder_options.md">}}) to include
`fts5` in the `sqlite_module` section. `fts5` in the `sqlite_module` section.

View File

@ -1,4 +1,6 @@
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:moor_generator/src/backends/build/moor_builder.dart'; import 'package:moor_generator/src/backends/build/moor_builder.dart';
export 'src/model/model.dart';
Builder moorBuilder(BuilderOptions options) => MoorBuilder(options); Builder moorBuilder(BuilderOptions options) => MoorBuilder(options);

View File

@ -46,7 +46,7 @@ class ColumnParser {
ColumnParser(this.base); ColumnParser(this.base);
SpecifiedColumn parse(MethodDeclaration getter, Element element) { MoorColumn parse(MethodDeclaration getter, Element element) {
final expr = base.returnExpressionOfMethod(getter); final expr = base.returnExpressionOfMethod(getter);
if (expr is! FunctionExpressionInvocation) { if (expr is! FunctionExpressionInvocation) {
@ -180,20 +180,18 @@ class ColumnParser {
sqlType: columnType); sqlType: columnType);
} }
final column = SpecifiedColumn( return MoorColumn(
type: columnType, type: columnType,
dartGetterName: getter.name.name, dartGetterName: getter.name.name,
name: name, name: name,
overriddenJsonName: _readJsonKey(element), overriddenJsonName: _readJsonKey(element),
customConstraints: foundCustomConstraint, customConstraints: foundCustomConstraint,
nullable: nullable, nullable: nullable,
features: foundFeatures, features: foundFeatures,
defaultArgument: foundDefaultExpression?.toSource(), defaultArgument: foundDefaultExpression?.toSource(),
typeConverter: converter); typeConverter: converter,
declaration: DartColumnDeclaration(element, base.step.file),
final declaration = );
ColumnDeclaration(column, base.step.file, element, null);
return column..declaration = declaration;
} }
ColumnType _startMethodToColumnType(String startMethod) { ColumnType _startMethodToColumnType(String startMethod) {

View File

@ -4,12 +4,10 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:moor/sqlite_keywords.dart'; import 'package:moor/sqlite_keywords.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/errors.dart'; import 'package:moor_generator/src/analyzer/errors.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/declarations.dart'; import 'package:moor_generator/src/model/declarations/declaration.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_db_classes.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/used_type_converter.dart'; import 'package:moor_generator/src/model/used_type_converter.dart';
import 'package:moor_generator/src/utils/names.dart'; import 'package:moor_generator/src/utils/names.dart';
import 'package:moor_generator/src/utils/type_utils.dart'; import 'package:moor_generator/src/utils/type_utils.dart';
@ -32,11 +30,11 @@ class MoorDartParser {
_tableParser = TableParser(this); _tableParser = TableParser(this);
} }
Future<SpecifiedTable> parseTable(ClassElement classElement) { Future<MoorTable> parseTable(ClassElement classElement) {
return _tableParser.parseTable(classElement); return _tableParser.parseTable(classElement);
} }
Future<SpecifiedColumn> parseColumn( Future<MoorColumn> parseColumn(
MethodDeclaration declaration, Element element) { MethodDeclaration declaration, Element element) {
return Future.value(_columnParser.parse(declaration, element)); return Future.value(_columnParser.parse(declaration, element));
} }

View File

@ -1,25 +1,25 @@
part of 'parser.dart'; part of 'parser.dart';
/// Parses a [SpecifiedTable] from a Dart class. /// Parses a [MoorTable] from a Dart class.
class TableParser { class TableParser {
final MoorDartParser base; final MoorDartParser base;
TableParser(this.base); TableParser(this.base);
Future<SpecifiedTable> parseTable(ClassElement element) async { Future<MoorTable> parseTable(ClassElement element) async {
final sqlName = await _parseTableName(element); final sqlName = await _parseTableName(element);
if (sqlName == null) return null; if (sqlName == null) return null;
final columns = await _parseColumns(element); final columns = await _parseColumns(element);
final table = SpecifiedTable( final table = MoorTable(
fromClass: element, fromClass: element,
columns: columns, columns: columns,
sqlName: escapeIfNeeded(sqlName), sqlName: escapeIfNeeded(sqlName),
dartTypeName: _readDartTypeName(element), dartTypeName: _readDartTypeName(element),
primaryKey: await _readPrimaryKey(element, columns), primaryKey: await _readPrimaryKey(element, columns),
declaration: DartTableDeclaration(element, base.step.file),
); );
table.declaration = TableDeclaration(table, base.step.file, element, null);
var index = 0; var index = 0;
for (final converter in table.converters) { for (final converter in table.converters) {
@ -71,8 +71,8 @@ class TableParser {
return tableName; return tableName;
} }
Future<Set<SpecifiedColumn>> _readPrimaryKey( Future<Set<MoorColumn>> _readPrimaryKey(
ClassElement element, List<SpecifiedColumn> columns) async { ClassElement element, List<MoorColumn> columns) async {
final primaryKeyGetter = element.getGetter('primaryKey'); final primaryKeyGetter = element.getGetter('primaryKey');
if (primaryKeyGetter == null) { if (primaryKeyGetter == null) {
return null; return null;
@ -88,7 +88,7 @@ class TableParser {
return null; return null;
} }
final expression = (body as ExpressionFunctionBody).expression; final expression = (body as ExpressionFunctionBody).expression;
final parsedPrimaryKey = <SpecifiedColumn>{}; final parsedPrimaryKey = <MoorColumn>{};
if (expression is SetOrMapLiteral) { if (expression is SetOrMapLiteral) {
for (final entry in expression.elements) { for (final entry in expression.elements) {
@ -109,7 +109,7 @@ class TableParser {
return parsedPrimaryKey; return parsedPrimaryKey;
} }
Future<List<SpecifiedColumn>> _parseColumns(ClassElement element) { Future<List<MoorColumn>> _parseColumns(ClassElement element) {
final columnNames = element.allSupertypes final columnNames = element.allSupertypes
.map((t) => t.element) .map((t) => t.element)
.followedBy([element]) .followedBy([element])

View File

@ -7,8 +7,7 @@ class UseDaoParser {
/// If [element] has a `@UseDao` annotation, parses the database model /// If [element] has a `@UseDao` annotation, parses the database model
/// declared by that class and the referenced tables. /// declared by that class and the referenced tables.
Future<SpecifiedDao> parseDao( Future<Dao> parseDao(ClassElement element, ConstantReader annotation) async {
ClassElement element, ConstantReader annotation) async {
final dbType = element.supertype; final dbType = element.supertype;
if (dbType.name != 'DatabaseAccessor') { if (dbType.name != 'DatabaseAccessor') {
step.reportError(ErrorInDartCode( step.reportError(ErrorInDartCode(
@ -47,6 +46,12 @@ class UseDaoParser {
final parsedTables = await step.parseTables(tableTypes, element); final parsedTables = await step.parseTables(tableTypes, element);
final parsedQueries = step.readDeclaredQueries(queryStrings); final parsedQueries = step.readDeclaredQueries(queryStrings);
return SpecifiedDao(element, dbImpl, parsedTables, includes, parsedQueries); return Dao(
declaration: DatabaseOrDaoDeclaration(element, step.file),
dbClass: dbImpl,
declaredTables: parsedTables,
declaredIncludes: includes,
declaredQueries: parsedQueries,
);
} }
} }

View File

@ -7,7 +7,7 @@ class UseMoorParser {
/// If [element] has a `@UseMoor` annotation, parses the database model /// If [element] has a `@UseMoor` annotation, parses the database model
/// declared by that class and the referenced tables. /// declared by that class and the referenced tables.
Future<SpecifiedDatabase> parseDatabase( Future<Database> parseDatabase(
ClassElement element, ConstantReader annotation) async { ClassElement element, ConstantReader annotation) async {
// the types declared in UseMoor.tables // the types declared in UseMoor.tables
final tableTypes = final tableTypes =
@ -27,8 +27,13 @@ class UseMoorParser {
final parsedQueries = step.readDeclaredQueries(queryStrings); final parsedQueries = step.readDeclaredQueries(queryStrings);
final daoTypes = _readDaoTypes(annotation); final daoTypes = _readDaoTypes(annotation);
return SpecifiedDatabase( return Database(
element, parsedTables, daoTypes, includes, parsedQueries); declaration: DatabaseOrDaoDeclaration(element, step.file),
declaredTables: parsedTables,
daos: daoTypes,
declaredIncludes: includes,
declaredQueries: parsedQueries,
);
} }
List<DartType> _readDaoTypes(ConstantReader annotation) { List<DartType> _readDaoTypes(ConstantReader annotation) {

View File

@ -1,8 +1,7 @@
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/declarations.dart';
import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart'; import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart';
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/src/model/declarations/declaration.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/used_type_converter.dart'; import 'package:moor_generator/src/model/used_type_converter.dart';
import 'package:moor_generator/src/utils/names.dart'; import 'package:moor_generator/src/utils/names.dart';
import 'package:moor_generator/src/utils/string_escaper.dart'; import 'package:moor_generator/src/utils/string_escaper.dart';
@ -16,11 +15,11 @@ class CreateTableReader {
CreateTableReader(this.stmt, this.step); CreateTableReader(this.stmt, this.step);
SpecifiedTable extractTable(TypeMapper mapper) { MoorTable extractTable(TypeMapper mapper) {
final table = SchemaFromCreateTable(moorExtensions: true).read(stmt); final table = SchemaFromCreateTable(moorExtensions: true).read(stmt);
final foundColumns = <String, SpecifiedColumn>{}; final foundColumns = <String, MoorColumn>{};
final primaryKey = <SpecifiedColumn>{}; final primaryKey = <MoorColumn>{};
for (final column in table.resultColumns) { for (final column in table.resultColumns) {
var isPrimaryKey = false; var isPrimaryKey = false;
@ -71,7 +70,12 @@ class CreateTableReader {
constraintWriter.write(constraint.span.text); constraintWriter.write(constraint.span.text);
} }
final parsed = SpecifiedColumn( // if the column definition isn't set - which can happen for CREATE
// VIRTUAL TABLE statements - use the entire statement as declaration.
final declaration =
MoorColumnDeclaration(column.definition ?? stmt, step.file);
final parsed = MoorColumn(
type: moorType, type: moorType,
nullable: column.type.nullable, nullable: column.type.nullable,
dartGetterName: dartName, dartGetterName: dartName,
@ -81,12 +85,9 @@ class CreateTableReader {
defaultArgument: defaultValue, defaultArgument: defaultValue,
typeConverter: converter, typeConverter: converter,
overriddenJsonName: overriddenJsonKey, overriddenJsonName: overriddenJsonKey,
declaration: declaration,
); );
final declaration =
ColumnDeclaration(parsed, step.file, null, column.definition);
parsed.declaration = declaration;
foundColumns[column.name] = parsed; foundColumns[column.name] = parsed;
if (isPrimaryKey) { if (isPrimaryKey) {
primaryKey.add(parsed); primaryKey.add(parsed);
@ -108,7 +109,7 @@ class CreateTableReader {
} }
} }
final specifiedTable = SpecifiedTable( return MoorTable(
fromClass: null, fromClass: null,
columns: foundColumns.values.toList(), columns: foundColumns.values.toList(),
sqlName: table.name, sqlName: table.name,
@ -119,13 +120,8 @@ class CreateTableReader {
overrideTableConstraints: constraints.isNotEmpty ? constraints : null, overrideTableConstraints: constraints.isNotEmpty ? constraints : null,
// we take care of writing the primary key ourselves // we take care of writing the primary key ourselves
overrideDontWriteConstraints: true, overrideDontWriteConstraints: true,
); declaration: MoorTableDeclaration(stmt, step.file),
)..parserTable = table;
final declaration = TableDeclaration(
specifiedTable, step.file, null, table.definition,
tableFromSqlParser: table);
return specifiedTable..declaration = declaration;
} }
UsedTypeConverter _readTypeConverter(MappedBy mapper) { UsedTypeConverter _readTypeConverter(MappedBy mapper) {

View File

@ -1,8 +1,8 @@
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/errors.dart'; import 'package:moor_generator/src/analyzer/errors.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/analyzer/moor/create_table_reader.dart'; import 'package:moor_generator/src/analyzer/moor/create_table_reader.dart';
import 'package:moor_generator/src/analyzer/runner/results.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
@ -40,8 +40,8 @@ class MoorParser {
)); ));
} }
final createdTables = <SpecifiedTable>[]; final createdTables = <MoorTable>[];
final tableDeclarations = <TableInducingStatement, SpecifiedTable>{}; final tableDeclarations = <TableInducingStatement, MoorTable>{};
for (final reader in createdReaders) { for (final reader in createdReaders) {
final table = reader.extractTable(step.mapper); final table = reader.extractTable(step.mapper);
createdTables.add(table); createdTables.add(table);

View File

@ -1,16 +1,16 @@
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/errors.dart'; import 'package:moor_generator/src/analyzer/errors.dart';
import 'package:moor_generator/src/analyzer/runner/results.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
/// Handles `REFERENCES` clauses in tables by resolving their columns and /// Handles `REFERENCES` clauses in tables by resolving their columns and
/// reporting errors if they don't exist. Further, sets the /// reporting errors if they don't exist. Further, sets the
/// [SpecifiedTable.references] field for tables declared in moor. /// [MoorTable.references] field for tables declared in moor.
class TableHandler { class TableHandler {
final AnalyzeMoorStep step; final AnalyzeMoorStep step;
final ParsedMoorFile file; final ParsedMoorFile file;
final List<SpecifiedTable> availableTables; final List<MoorTable> availableTables;
TableHandler(this.step, this.file, this.availableTables); TableHandler(this.step, this.file, this.availableTables);

View File

@ -1,13 +1,12 @@
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/model/specified_db_classes.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
abstract class FileResult { abstract class FileResult {
final List<SpecifiedTable> declaredTables; final List<MoorTable> declaredTables;
FileResult(this.declaredTables); FileResult(this.declaredTables);
} }
@ -15,15 +14,15 @@ abstract class FileResult {
class ParsedDartFile extends FileResult { class ParsedDartFile extends FileResult {
final LibraryElement library; final LibraryElement library;
final List<SpecifiedDao> declaredDaos; final List<Dao> declaredDaos;
final List<SpecifiedDatabase> declaredDatabases; final List<Database> declaredDatabases;
Iterable<SpecifiedDbAccessor> get dbAccessors => Iterable<BaseMoorAccessor> get dbAccessors =>
declaredDatabases.cast<SpecifiedDbAccessor>().followedBy(declaredDaos); declaredDatabases.cast<BaseMoorAccessor>().followedBy(declaredDaos);
ParsedDartFile( ParsedDartFile(
{@required this.library, {@required this.library,
List<SpecifiedTable> declaredTables = const [], List<MoorTable> declaredTables = const [],
this.declaredDaos = const [], this.declaredDaos = const [],
this.declaredDatabases = const []}) this.declaredDatabases = const []})
: super(declaredTables); : super(declaredTables);
@ -37,11 +36,11 @@ class ParsedMoorFile extends FileResult {
final List<DeclaredQuery> queries; final List<DeclaredQuery> queries;
List<SqlQuery> resolvedQueries; List<SqlQuery> resolvedQueries;
Map<TableInducingStatement, SpecifiedTable> tableDeclarations; Map<TableInducingStatement, MoorTable> tableDeclarations;
Map<ImportStatement, FoundFile> resolvedImports; Map<ImportStatement, FoundFile> resolvedImports;
ParsedMoorFile(this.parseResult, ParsedMoorFile(this.parseResult,
{List<SpecifiedTable> declaredTables = const [], {List<MoorTable> declaredTables = const [],
this.queries = const [], this.queries = const [],
this.imports = const [], this.imports = const [],
this.tableDeclarations = const {}}) this.tableDeclarations = const {}})

View File

@ -2,6 +2,7 @@ import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type.dart';
import 'package:moor/moor.dart'; import 'package:moor/moor.dart';
import 'package:moor_generator/moor_generator.dart';
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/table_handler.dart'; import 'package:moor_generator/src/analyzer/moor/table_handler.dart';
@ -12,8 +13,6 @@ import 'package:moor_generator/src/analyzer/moor/parser.dart';
import 'package:moor_generator/src/analyzer/sql_queries/sql_parser.dart'; import 'package:moor_generator/src/analyzer/sql_queries/sql_parser.dart';
import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart'; import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart';
import 'package:moor_generator/src/analyzer/runner/task.dart'; import 'package:moor_generator/src/analyzer/runner/task.dart';
import 'package:moor_generator/src/model/specified_db_classes.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:moor_generator/src/utils/table_reference_sorter.dart'; import 'package:moor_generator/src/utils/table_reference_sorter.dart';
import 'package:source_gen/source_gen.dart'; import 'package:source_gen/source_gen.dart';
@ -54,8 +53,8 @@ abstract class AnalyzingStep extends Step {
.toList(); .toList();
} }
Iterable<SpecifiedTable> _availableTables(List<FoundFile> imports) { Iterable<MoorTable> _availableTables(List<FoundFile> imports) {
return imports.expand<SpecifiedTable>( return imports.expand<MoorTable>(
(file) => file.currentResult?.declaredTables ?? const Iterable.empty()); (file) => file.currentResult?.declaredTables ?? const Iterable.empty());
} }
} }

View File

@ -8,10 +8,10 @@ class AnalyzeDartStep extends AnalyzingStep {
final parseResult = file.currentResult as ParsedDartFile; final parseResult = file.currentResult as ParsedDartFile;
for (final accessor in parseResult.dbAccessors) { for (final accessor in parseResult.dbAccessors) {
final transitiveImports = _transitiveImports(accessor.resolvedImports); final transitiveImports = _transitiveImports(accessor.imports);
var availableTables = _availableTables(transitiveImports) var availableTables = _availableTables(transitiveImports)
.followedBy(accessor.tables) .followedBy(accessor.declaredTables)
.toList(); .toList();
try { try {
@ -39,13 +39,12 @@ class AnalyzeDartStep extends AnalyzingStep {
.whereType<ParsedMoorFile>() .whereType<ParsedMoorFile>()
.expand((f) => f.resolvedQueries); .expand((f) => f.resolvedQueries);
final parser = SqlParser(this, availableTables, accessor.queries); final parser = SqlParser(this, availableTables, accessor.declaredQueries);
parser.parse(); parser.parse();
accessor.allTables = availableTables; accessor
..tables = availableTables
accessor.resolvedQueries = ..queries = availableQueries.followedBy(parser.foundQueries).toList();
availableQueries.followedBy(parser.foundQueries).toList();
} }
} }
} }

View File

@ -1,9 +1,9 @@
part of '../steps.dart'; part of '../steps.dart';
/// Extracts the following information from a Dart file: /// Extracts the following information from a Dart file:
/// - [SpecifiedTable]s, which are read from Dart classes extending `Table`. /// - [MoorTable]s, which are read from Dart classes extending `Table`.
/// - [SpecifiedDatabase]s, which are read from `@UseMoor`-annotated classes /// - [Database]s, which are read from `@UseMoor`-annotated classes
/// - [SpecifiedDao]s, which are read from `@UseDao`-annotated classes. /// - [Dao]s, which are read from `@UseDao`-annotated classes.
/// ///
/// Notably, this step does not analyze defined queries. /// Notably, this step does not analyze defined queries.
class ParseDartStep extends Step { class ParseDartStep extends Step {
@ -16,7 +16,7 @@ class ParseDartStep extends Step {
MoorDartParser _parser; MoorDartParser _parser;
MoorDartParser get parser => _parser; MoorDartParser get parser => _parser;
final Map<ClassElement, SpecifiedTable> _tables = {}; final Map<ClassElement, MoorTable> _tables = {};
ParseDartStep(Task task, FoundFile file, this.library) : super(task, file) { ParseDartStep(Task task, FoundFile file, this.library) : super(task, file) {
_parser = MoorDartParser(this); _parser = MoorDartParser(this);
@ -24,8 +24,8 @@ class ParseDartStep extends Step {
Future<ParsedDartFile> parse() async { Future<ParsedDartFile> parse() async {
final reader = LibraryReader(library); final reader = LibraryReader(library);
final databases = <SpecifiedDatabase>[]; final databases = <Database>[];
final daos = <SpecifiedDao>[]; final daos = <Dao>[];
for (final declaredClass in reader.classes) { for (final declaredClass in reader.classes) {
// check if the table inherits from the moor table class. The !isExactly // check if the table inherits from the moor table class. The !isExactly
@ -55,33 +55,32 @@ class ParseDartStep extends Step {
); );
} }
Future<SpecifiedTable> _parseTable(ClassElement element) async { Future<MoorTable> _parseTable(ClassElement element) async {
if (!_tables.containsKey(element)) { if (!_tables.containsKey(element)) {
_tables[element] = await parser.parseTable(element); _tables[element] = await parser.parseTable(element);
} }
return _tables[element]; return _tables[element];
} }
/// Parses a [SpecifiedDatabase] from the [ClassElement] which was annotated /// Parses a [Database] from the [ClassElement] which was annotated
/// with `@UseMoor` and the [annotation] reader that reads the `@UseMoor` /// with `@UseMoor` and the [annotation] reader that reads the `@UseMoor`
/// annotation. /// annotation.
Future<SpecifiedDatabase> parseDatabase( Future<Database> parseDatabase(
ClassElement element, ConstantReader annotation) { ClassElement element, ConstantReader annotation) {
return UseMoorParser(this).parseDatabase(element, annotation); return UseMoorParser(this).parseDatabase(element, annotation);
} }
/// Parses a [SpecifiedDao] from a class declaration that has a `UseDao` /// Parses a [Dao] from a class declaration that has a `UseDao`
/// [annotation]. /// [annotation].
Future<SpecifiedDao> parseDao( Future<Dao> parseDao(ClassElement element, ConstantReader annotation) {
ClassElement element, ConstantReader annotation) {
return UseDaoParser(this).parseDao(element, annotation); return UseDaoParser(this).parseDao(element, annotation);
} }
/// Resolves a [SpecifiedTable] for the class of each [DartType] in [types]. /// Resolves a [MoorTable] for the class of each [DartType] in [types].
/// The [initializedBy] element should be the piece of code that caused the /// The [initializedBy] element should be the piece of code that caused the
/// parsing (e.g. the database class that is annotated with `@UseMoor`). This /// parsing (e.g. the database class that is annotated with `@UseMoor`). This
/// will allow for more descriptive error messages. /// will allow for more descriptive error messages.
Future<List<SpecifiedTable>> parseTables( Future<List<MoorTable>> parseTables(
Iterable<DartType> types, Element initializedBy) { Iterable<DartType> types, Element initializedBy) {
return Future.wait(types.map((type) { return Future.wait(types.map((type) {
if (!_tableTypeChecker.isAssignableFrom(type.element)) { if (!_tableTypeChecker.isAssignableFrom(type.element)) {

View File

@ -1,10 +1,10 @@
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/errors.dart'; import 'package:moor_generator/src/analyzer/errors.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/runner/results.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/analyzer/session.dart';
import 'package:moor_generator/src/backends/backend.dart'; import 'package:moor_generator/src/backends/backend.dart';
import 'package:moor_generator/src/model/specified_db_classes.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
/// A task is used to fully parse and analyze files based on an input file. To /// A task is used to fully parse and analyze files based on an input file. To
@ -109,13 +109,13 @@ class Task {
file.currentResult = parsed; file.currentResult = parsed;
final daosAndDatabases = parsed.declaredDaos final daosAndDatabases = parsed.declaredDaos
.cast<SpecifiedDbAccessor>() .cast<BaseMoorAccessor>()
.followedBy(parsed.declaredDatabases); .followedBy(parsed.declaredDatabases);
for (final accessor in daosAndDatabases) { for (final accessor in daosAndDatabases) {
final resolvedForAccessor = <FoundFile>[]; final resolvedForAccessor = <FoundFile>[];
for (final import in accessor.includes) { for (final import in accessor.declaredIncludes) {
final found = session.resolve(file, import); final found = session.resolve(file, import);
if (!await backend.exists(found.uri)) { if (!await backend.exists(found.uri)) {
step.reportError(ErrorInDartCode( step.reportError(ErrorInDartCode(
@ -129,7 +129,7 @@ class Task {
} }
} }
accessor.resolvedImports = resolvedForAccessor; accessor.imports = resolvedForAccessor;
} }
break; break;
default: default:

View File

@ -1,48 +0,0 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:sqlparser/sqlparser.dart';
class BaseDeclaration {
final FoundFile declarationFile;
/// If the column was declared in Dart, contains an enclosing getter element
/// that declared the column
final Element dartDeclaration;
/// If the column was declared in a moor file, contains the ast node that
/// contains the column definition
final AstNode moorDeclaration;
BaseDeclaration(
this.declarationFile, this.dartDeclaration, this.moorDeclaration);
}
/// Column declaration that is used as a metadata on a [Column] so that the
/// analysis plugin can know where a referenced column was declared and provide
/// navigation hints.
class ColumnDeclaration extends BaseDeclaration {
/// The moor version of the declared column.
final SpecifiedColumn column;
/// Whether this declaration is from a moor file (e.g. inside a `CREATE TABLE`
/// statement).
bool get isDefinedInMoorFile => moorDeclaration != null;
ColumnDeclaration(this.column, FoundFile declarationFile,
Element dartDeclaration, AstNode moorDeclaration)
: super(declarationFile, dartDeclaration, moorDeclaration);
}
/// Meta information set on a [Table] so that the analysis plugin can know where
/// a referenced table was declared and provide navigation hints.
class TableDeclaration extends BaseDeclaration {
final SpecifiedTable table;
final Table tableFromSqlParser;
TableDeclaration(this.table, FoundFile declarationFile,
Element dartDeclaration, AstNode moorDeclaration,
{this.tableFromSqlParser})
: super(declarationFile, dartDeclaration, moorDeclaration);
}

View File

@ -1,15 +1,15 @@
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/errors.dart'; import 'package:moor_generator/src/analyzer/errors.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:moor_generator/src/analyzer/sql_queries/query_handler.dart'; import 'package:moor_generator/src/analyzer/sql_queries/query_handler.dart';
import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart'; import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart';
import 'package:sqlparser/sqlparser.dart' hide ResultColumn; import 'package:sqlparser/sqlparser.dart' hide ResultColumn;
class SqlParser { class SqlParser {
final List<SpecifiedTable> tables; final List<MoorTable> tables;
final Step step; final Step step;
final List<DeclaredQuery> definedQueries; final List<DeclaredQuery> definedQueries;
@ -62,6 +62,7 @@ class SqlParser {
..declaredInMoorFile = declaredInMoor; ..declaredInMoorFile = declaredInMoor;
foundQueries.add(query); foundQueries.add(query);
} catch (e, s) { } catch (e, s) {
// todo remove dependency on build package here
log.warning('Error while generating APIs for $name', e, s); log.warning('Error while generating APIs for $name', e, s);
} }
} }

View File

@ -1,23 +1,20 @@
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:moor_generator/src/utils/type_converter_hint.dart'; import 'package:moor_generator/src/utils/type_converter_hint.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
import 'meta/declarations.dart';
/// Converts tables and types between the moor_generator and the sqlparser /// Converts tables and types between the moor_generator and the sqlparser
/// library. /// library.
class TypeMapper { class TypeMapper {
final Map<Table, SpecifiedTable> _engineTablesToSpecified = {}; final Map<Table, MoorTable> _engineTablesToSpecified = {};
/// Convert a [SpecifiedTable] from moor into something that can be understood /// Convert a [MoorTable] from moor into something that can be understood
/// by the sqlparser library. /// by the sqlparser library.
Table extractStructure(SpecifiedTable table) { Table extractStructure(MoorTable table) {
final existingTable = table.declaration?.tableFromSqlParser; if (table.parserTable != null) {
if (existingTable != null) { final parserTbl = table.parserTable;
_engineTablesToSpecified[existingTable] = table; _engineTablesToSpecified[parserTbl] = table;
return existingTable; return parserTbl;
} }
final columns = <TableColumn>[]; final columns = <TableColumn>[];
@ -29,13 +26,13 @@ class TypeMapper {
.withNullable(specified.nullable); .withNullable(specified.nullable);
final column = TableColumn(specified.name.name, type); final column = TableColumn(specified.name.name, type);
column.setMeta<ColumnDeclaration>(specified.declaration); column.setMeta<MoorColumn>(specified);
columns.add(column); columns.add(column);
} }
final engineTable = Table(name: table.sqlName, resolvedColumns: columns); final engineTable = Table(name: table.sqlName, resolvedColumns: columns);
engineTable.setMeta<TableDeclaration>(table.declaration); engineTable.setMeta<MoorTable>(table);
_engineTablesToSpecified[engineTable] = table; _engineTablesToSpecified[engineTable] = table;
return engineTable; return engineTable;
} }
@ -222,7 +219,7 @@ class TypeMapper {
return FoundDartPlaceholder(type, columnType, name)..astNode = placeholder; return FoundDartPlaceholder(type, columnType, name)..astNode = placeholder;
} }
SpecifiedTable tableToMoor(Table table) { MoorTable tableToMoor(Table table) {
return _engineTablesToSpecified[table]; return _engineTablesToSpecified[table];
} }
} }

View File

@ -21,7 +21,7 @@ class DaoGenerator extends Generator implements BaseGenerator {
classScope.leaf().write('mixin _\$${daoName}Mixin on ' classScope.leaf().write('mixin _\$${daoName}Mixin on '
'DatabaseAccessor<${dao.dbClass.displayName}> {\n'); 'DatabaseAccessor<${dao.dbClass.displayName}> {\n');
for (final table in dao.allTables) { for (final table in dao.tables) {
final infoType = table.tableInfoName; final infoType = table.tableInfoName;
final getterName = table.tableFieldName; final getterName = table.tableFieldName;
classScope classScope
@ -30,7 +30,7 @@ class DaoGenerator extends Generator implements BaseGenerator {
} }
final writtenMappingMethods = <String>{}; final writtenMappingMethods = <String>{};
for (final query in dao.resolvedQueries) { for (final query in dao.queries) {
QueryWriter(query, classScope.child(), writtenMappingMethods).write(); QueryWriter(query, classScope.child(), writtenMappingMethods).write();
} }

View File

@ -1,6 +1,6 @@
import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation.dart'; import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/declarations.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/backends/plugin/services/requests.dart'; import 'package:moor_generator/src/backends/plugin/services/requests.dart';
import 'package:moor_generator/src/backends/plugin/utils/ast_to_location.dart'; import 'package:moor_generator/src/backends/plugin/utils/ast_to_location.dart';
import 'package:moor_generator/src/backends/plugin/utils/span_utils.dart'; import 'package:moor_generator/src/backends/plugin/utils/span_utils.dart';
@ -73,7 +73,7 @@ class _NavigationVisitor extends RecursiveVisitor<void> {
} }
Iterable<Location> _locationOfColumn(Column column) sync* { Iterable<Location> _locationOfColumn(Column column) sync* {
final declaration = column.meta<ColumnDeclaration>(); final declaration = column.meta<MoorColumn>()?.declaration;
if (declaration != null) { if (declaration != null) {
// the column was declared in a table and we happen to know where the // the column was declared in a table and we happen to know where the
// declaration is - point to that declaration. // declaration is - point to that declaration.
@ -101,7 +101,7 @@ class _NavigationVisitor extends RecursiveVisitor<void> {
final resolved = e.resolved; final resolved = e.resolved;
if (resolved is Table && resolved != null) { if (resolved is Table && resolved != null) {
final declaration = resolved.meta<TableDeclaration>(); final declaration = resolved.meta<MoorTable>()?.declaration;
_reportForSpan( _reportForSpan(
e.span, ElementKind.CLASS, locationOfDeclaration(declaration)); e.span, ElementKind.CLASS, locationOfDeclaration(declaration));
} }

View File

@ -1,6 +1,6 @@
import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/declarations.dart';
import 'package:source_gen/source_gen.dart' show spanForElement; import 'package:source_gen/source_gen.dart' show spanForElement;
import 'package:source_span/source_span.dart'; import 'package:source_span/source_span.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
@ -25,13 +25,13 @@ Location locationOfNode(FoundFile file, AstNode node) {
return _locationForSpan(node.span, file); return _locationForSpan(node.span, file);
} }
Location locationOfDeclaration(BaseDeclaration declaration) { Location locationOfDeclaration(Declaration declaration) {
if (declaration.dartDeclaration != null) { final file = declaration.declaration.file;
final span = spanForElement(declaration.dartDeclaration); if (declaration is DartDeclaration) {
return _locationForSpan(span, declaration.declarationFile); return _locationForSpan(spanForElement(declaration.element), file);
} else if (declaration.moorDeclaration != null) { } else if (declaration is MoorDeclaration) {
return locationOfNode( return locationOfNode(file, declaration.node);
declaration.declarationFile, declaration.moorDeclaration);
} }
return null; return null;
} }

View File

@ -1,6 +1,7 @@
import 'package:moor_generator/src/analyzer/options.dart'; import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/declarations.dart';
import 'package:moor_generator/src/model/used_type_converter.dart'; import 'declarations/declaration.dart';
import 'used_type_converter.dart';
/// The column types in sql. /// The column types in sql.
enum ColumnType { integer, text, boolean, datetime, blob, real } enum ColumnType { integer, text, boolean, datetime, blob, real }
@ -77,7 +78,7 @@ const Map<ColumnType, String> sqlTypes = {
}; };
/// A column, as specified by a getter in a table. /// A column, as specified by a getter in a table.
class SpecifiedColumn { class MoorColumn implements HasDeclaration {
/// The getter name of this column in the table class. It will also be used /// The getter name of this column in the table class. It will also be used
/// as getter name in the TableInfo class (as it needs to override the field) /// as getter name in the TableInfo class (as it needs to override the field)
/// and in the generated data class that will be generated for each table. /// and in the generated data class that will be generated for each table.
@ -85,7 +86,8 @@ class SpecifiedColumn {
/// The declaration of this column, contains information about where this /// The declaration of this column, contains information about where this
/// column was created in source code. /// column was created in source code.
ColumnDeclaration declaration; @override
final ColumnDeclaration declaration;
/// Whether this column was declared inside a moor file. /// Whether this column was declared inside a moor file.
bool get declaredInMoorFile => declaration?.isDefinedInMoorFile ?? false; bool get declaredInMoorFile => declaration?.isDefinedInMoorFile ?? false;
@ -176,7 +178,7 @@ class SpecifiedColumn {
/// this column. /// this column.
String get sqlTypeName => sqlTypes[type]; String get sqlTypeName => sqlTypes[type];
SpecifiedColumn({ MoorColumn({
this.type, this.type,
this.dartGetterName, this.dartGetterName,
this.name, this.name,
@ -186,6 +188,7 @@ class SpecifiedColumn {
this.features = const [], this.features = const [],
this.defaultArgument, this.defaultArgument,
this.typeConverter, this.typeConverter,
this.declaration,
}); });
} }
@ -231,9 +234,3 @@ class LimitingTextLength extends ColumnFeature {
typedOther.maxLength == maxLength; typedOther.maxLength == maxLength;
} }
} }
class Reference extends ColumnFeature {
final SpecifiedColumn referencedColumn;
const Reference(this.referencedColumn);
}

View File

@ -0,0 +1,72 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:meta/meta.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/model/sql_query.dart';
import 'declarations/declaration.dart';
import 'table.dart';
/// Abstract class for database and dao elements.
abstract class BaseMoorAccessor implements HasDeclaration {
@override
final DatabaseOrDaoDeclaration declaration;
/// The [ClassElement] that was annotated with `UseMoor` or `UseDao`.
ClassElement get fromClass => declaration.fromClass;
/// All tables that have been declared on this accessor directly.
///
/// This contains the `tables` field from a `UseMoor` or `UseDao` annotation,
/// but not tables that are declared in imported moor files. Use
final List<MoorTable> declaredTables;
/// The `includes` field from the `UseMoor` or `UseDao` annotation.
final List<String> declaredIncludes;
/// All queries declared directly in the `UseMoor` or `UseDao` annotation.
final List<DeclaredQuery> declaredQueries;
/// All tables for this database accessor. This contains the [declaredTables]
/// and all tables that are reachable through
List<MoorTable> tables = [];
/// All resolved queries.
///
/// This includes the resolve result for queries that were declared in the
/// same annotation, and queries that were in declared files.
List<SqlQuery> queries = [];
/// Resolved imports from this file.
List<FoundFile> imports = [];
BaseMoorAccessor._(this.declaration, this.declaredTables,
this.declaredIncludes, this.declaredQueries);
}
/// A database, declared via a `UseMoor` annotation on a Dart class.
class Database extends BaseMoorAccessor {
final List<DartType> daos;
Database({
this.daos = const [],
DatabaseOrDaoDeclaration declaration,
List<MoorTable> declaredTables,
List<String> declaredIncludes,
List<DeclaredQuery> declaredQueries,
}) : super._(declaration, declaredTables, declaredIncludes, declaredQueries);
}
/// A dao, declared via an `UseDao` annotation on a Dart class.
class Dao extends BaseMoorAccessor {
/// The database class this dao belongs to.
final DartType dbClass;
Dao({
@required this.dbClass,
DatabaseOrDaoDeclaration declaration,
List<MoorTable> declaredTables,
List<String> declaredIncludes,
List<DeclaredQuery> declaredQueries,
}) : super._(declaration, declaredTables, declaredIncludes, declaredQueries);
}

View File

@ -0,0 +1,48 @@
part of 'declaration.dart';
abstract class ColumnDeclaration extends Declaration {
/// Whether this column was declared in a moor file (e.g. in a `CREATE TABLE`
/// statement).
bool get isDefinedInMoorFile;
}
class DartColumnDeclaration implements DartDeclaration, ColumnDeclaration {
@override
final SourceRange declaration;
/// In the Dart api, columns declared via getters.
@override
final Element element;
DartColumnDeclaration._(this.declaration, this.element);
factory DartColumnDeclaration(Element element, FoundFile file) {
return DartColumnDeclaration._(
SourceRange.fromElementAndFile(element, file),
element,
);
}
@override
bool get isDefinedInMoorFile => false;
}
class MoorColumnDeclaration implements MoorDeclaration, ColumnDeclaration {
@override
final SourceRange declaration;
@override
final AstNode node;
MoorColumnDeclaration._(this.declaration, this.node);
factory MoorColumnDeclaration(AstNode node, FoundFile file) {
return MoorColumnDeclaration._(
SourceRange.fromNodeAndFile(node, file),
node,
);
}
@override
bool get isDefinedInMoorFile => true;
}

View File

@ -0,0 +1,21 @@
part of 'declaration.dart';
/// Declaration of a database or dao in a Dart file.
class DatabaseOrDaoDeclaration implements DartDeclaration {
/// The [ClassElement] with the `UseMoor` or `UseDao` annotation.
final ClassElement fromClass;
@override
final SourceRange declaration;
DatabaseOrDaoDeclaration._(this.fromClass, this.declaration);
factory DatabaseOrDaoDeclaration(ClassElement fromClass, FoundFile file) {
return DatabaseOrDaoDeclaration._(
fromClass,
SourceRange.fromElementAndFile(fromClass, file),
);
}
@override
Element get element => fromClass;
}

View File

@ -0,0 +1,32 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/model/sources.dart';
import 'package:sqlparser/sqlparser.dart';
part 'columns.dart';
part 'database.dart';
part 'tables.dart';
/// Interface for model elements that are declared somewhere.
abstract class HasDeclaration {
/// Gets the declaration of this element, if set.
Declaration get declaration;
}
/// Base class for all declarations in the generator model.
abstract class Declaration {
/// The file and text span where this element was declared.
SourceRange get declaration;
}
/// Declaration for elements that are declared in a `.dart` file.
abstract class DartDeclaration extends Declaration {
/// A fitting, enclosing element for this declaration.
Element get element;
}
/// Declaration for elements that are declared in a `.moor` file.
abstract class MoorDeclaration extends Declaration {
/// The ast node from a moor file for this declaration.
AstNode get node;
}

View File

@ -0,0 +1,37 @@
part of 'declaration.dart';
abstract class TableDeclaration extends Declaration {}
class DartTableDeclaration implements TableDeclaration, DartDeclaration {
@override
final SourceRange declaration;
@override
final ClassElement element;
DartTableDeclaration._(this.declaration, this.element);
factory DartTableDeclaration(ClassElement element, FoundFile file) {
return DartTableDeclaration._(
SourceRange.fromElementAndFile(element, file),
element,
);
}
}
class MoorTableDeclaration implements TableDeclaration, MoorDeclaration {
@override
final SourceRange declaration;
@override
final TableInducingStatement node;
MoorTableDeclaration._(this.declaration, this.node);
factory MoorTableDeclaration(TableInducingStatement node, FoundFile file) {
return MoorTableDeclaration._(
SourceRange.fromNodeAndFile(node, file),
node,
);
}
}

View File

@ -0,0 +1,7 @@
export 'column.dart';
export 'database.dart';
export 'declarations/declaration.dart';
export 'sources.dart';
export 'sql_query.dart';
export 'table.dart';
export 'used_type_converter.dart';

View File

@ -0,0 +1,40 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:sqlparser/sqlparser.dart';
/// Represents a single location accessible to analysis services.
class SourceLocation {
final FoundFile file;
final int offset;
SourceLocation(this.file, this.offset);
}
/// Represents a range in a source file, accessible to analysis services
class SourceRange {
final SourceLocation start;
final int length;
SourceLocation _end;
FoundFile get file => start.file;
SourceLocation get end {
return _end ??= SourceLocation(start.file, start.offset + length);
}
SourceRange(this.start, this.length);
factory SourceRange.fromElementAndFile(Element element, FoundFile file) {
return SourceRange(
SourceLocation(file, element.nameOffset),
element.nameLength,
);
}
factory SourceRange.fromNodeAndFile(AstNode node, FoundFile file) {
return SourceRange(
SourceLocation(file, node.firstPosition),
node.length,
);
}
}

View File

@ -1,47 +0,0 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart';
class SpecifiedDbAccessor {
final ClassElement fromClass;
final List<SpecifiedTable> tables;
final List<String> includes;
final List<DeclaredQuery> queries;
List<FoundFile> resolvedImports = [];
/// Resolved queries. This includes queries that weren't declared on this
/// class but imported via an `includes` directive.
List<SqlQuery> resolvedQueries = const [];
/// All tables available to this class. This includes the [tables] and all
/// tables defined in a [includes] table.
List<SpecifiedTable> allTables = [];
SpecifiedDbAccessor(this.fromClass, this.tables, this.includes, this.queries);
}
/// Model generated from a class that is annotated with `UseDao`.
class SpecifiedDao extends SpecifiedDbAccessor {
/// The database class this dao belongs to.
final DartType dbClass;
SpecifiedDao(
ClassElement fromClass,
this.dbClass,
List<SpecifiedTable> tables,
List<String> includes,
List<DeclaredQuery> queries)
: super(fromClass, tables, includes, queries);
}
class SpecifiedDatabase extends SpecifiedDbAccessor {
final List<DartType> daos;
SpecifiedDatabase(ClassElement fromClass, List<SpecifiedTable> tables,
this.daos, List<String> includes, List<DeclaredQuery> queries)
: super(fromClass, tables, includes, queries);
}

View File

@ -1,11 +1,12 @@
import 'package:moor_generator/src/analyzer/runner/results.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/used_type_converter.dart';
import 'package:moor_generator/src/utils/hash.dart'; import 'package:moor_generator/src/utils/hash.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
import 'column.dart';
import 'table.dart';
import 'used_type_converter.dart';
final _illegalChars = RegExp(r'[^0-9a-zA-Z_]'); final _illegalChars = RegExp(r'[^0-9a-zA-Z_]');
final _leadingDigits = RegExp(r'^\d*'); final _leadingDigits = RegExp(r'^\d*');
@ -95,7 +96,7 @@ abstract class SqlQuery {
} }
class SqlSelectQuery extends SqlQuery { class SqlSelectQuery extends SqlQuery {
final List<SpecifiedTable> readsFrom; final List<MoorTable> readsFrom;
final InferredResultSet resultSet; final InferredResultSet resultSet;
String get resultClassName { String get resultClassName {
@ -116,7 +117,7 @@ class SqlSelectQuery extends SqlQuery {
} }
class UpdatingQuery extends SqlQuery { class UpdatingQuery extends SqlQuery {
final List<SpecifiedTable> updates; final List<MoorTable> updates;
final bool isInsert; final bool isInsert;
UpdatingQuery(String name, AnalysisContext fromContext, UpdatingQuery(String name, AnalysisContext fromContext,
@ -129,7 +130,7 @@ class InferredResultSet {
/// If the result columns of a SELECT statement exactly match one table, we /// If the result columns of a SELECT statement exactly match one table, we
/// can just use the data class generated for that table. Otherwise, we'd have /// can just use the data class generated for that table. Otherwise, we'd have
/// to create another class. /// to create another class.
final SpecifiedTable matchingTable; final MoorTable matchingTable;
final List<ResultColumn> columns; final List<ResultColumn> columns;
final Map<ResultColumn, String> _dartNames = {}; final Map<ResultColumn, String> _dartNames = {};

View File

@ -1,19 +1,25 @@
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:moor_generator/src/analyzer/options.dart'; import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/declarations.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/used_type_converter.dart'; import 'package:moor_generator/src/model/used_type_converter.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
import 'column.dart';
import 'declarations/declaration.dart';
/// A parsed table, declared in code by extending `Table` and referencing that /// A parsed table, declared in code by extending `Table` and referencing that
/// table in `@UseMoor` or `@UseDao`. /// table in `@UseMoor` or `@UseDao`.
class SpecifiedTable { class MoorTable implements HasDeclaration {
/// The [ClassElement] for the class that declares this table or null if /// The [ClassElement] for the class that declares this table or null if
/// the table was inferred from a `CREATE TABLE` statement. /// the table was inferred from a `CREATE TABLE` statement.
final ClassElement fromClass; final ClassElement fromClass;
TableDeclaration declaration; @override
final TableDeclaration declaration;
/// The associated table to use for the sqlparser package when analyzing
/// sql queries. Note that this field is set lazily.
Table parserTable;
/// If [fromClass] is null, another source to use when determining the name /// If [fromClass] is null, another source to use when determining the name
/// of this table in generated Dart code. /// of this table in generated Dart code.
@ -26,7 +32,7 @@ class SpecifiedTable {
String get _baseName => _overriddenName ?? fromClass.name; String get _baseName => _overriddenName ?? fromClass.name;
/// The columns declared in this table. /// The columns declared in this table.
final List<SpecifiedColumn> columns; final List<MoorColumn> columns;
/// The name of this table when stored in the database /// The name of this table when stored in the database
final String sqlName; final String sqlName;
@ -60,7 +66,7 @@ class SpecifiedTable {
/// The set of primary keys, if they have been explicitly defined by /// The set of primary keys, if they have been explicitly defined by
/// overriding `primaryKey` in the table class. `null` if the primary key has /// overriding `primaryKey` in the table class. `null` if the primary key has
/// not been defined that way. /// not been defined that way.
final Set<SpecifiedColumn> primaryKey; final Set<MoorColumn> primaryKey;
/// When non-null, the generated table class will override the `withoutRowId` /// When non-null, the generated table class will override the `withoutRowId`
/// getter on the table class with this value. /// getter on the table class with this value.
@ -76,7 +82,7 @@ class SpecifiedTable {
/// The set of tables referenced somewhere in the declaration of this table, /// The set of tables referenced somewhere in the declaration of this table,
/// for instance by using a `REFERENCES` column constraint. /// for instance by using a `REFERENCES` column constraint.
final Set<SpecifiedTable> references = {}; final Set<MoorTable> references = {};
/// Returns whether this table was created from a `CREATE VIRTUAL TABLE` /// Returns whether this table was created from a `CREATE VIRTUAL TABLE`
/// statement in a moor file /// statement in a moor file
@ -84,26 +90,27 @@ class SpecifiedTable {
if (declaration == null) { if (declaration == null) {
throw StateError("Couldn't determine whether $displayName is a virtual " throw StateError("Couldn't determine whether $displayName is a virtual "
'table since its declaration is unknown.'); 'table since its declaration is unknown.');
} else if (declaration is! MoorTableDeclaration) {
// tables declared in Dart can't be virtual
return false;
} }
final node = declaration?.moorDeclaration;
// tables declared in Dart can't be virtual
if (node == null) return false;
assert(node is TableInducingStatement); final node = (declaration as MoorTableDeclaration).node;
return node is CreateVirtualTableStatement; return node is CreateVirtualTableStatement;
} }
SpecifiedTable( MoorTable({
{this.fromClass, this.fromClass,
this.columns, this.columns,
this.sqlName, this.sqlName,
this.dartTypeName, this.dartTypeName,
this.primaryKey, this.primaryKey,
String overriddenName, String overriddenName,
this.overrideWithoutRowId, this.overrideWithoutRowId,
this.overrideTableConstraints, this.overrideTableConstraints,
this.overrideDontWriteConstraints}) this.overrideDontWriteConstraints,
: _overriddenName = overriddenName; this.declaration,
}) : _overriddenName = overriddenName;
/// Finds all type converters used in this tables. /// Finds all type converters used in this tables.
Iterable<UsedTypeConverter> get converters => Iterable<UsedTypeConverter> get converters =>

View File

@ -1,13 +1,16 @@
import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/src/model/table.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'column.dart';
class UsedTypeConverter { class UsedTypeConverter {
/// Index of this converter in the table in which it has been created. /// Index of this converter in the table in which it has been created.
int index; int index;
SpecifiedTable table;
/// The table using this type converter.
MoorTable table;
/// The [Expression] that will construct the type converter at runtime. The /// The [Expression] that will construct the type converter at runtime. The
/// type converter constructed will map a [mappedType] to the [sqlType] and /// type converter constructed will map a [mappedType] to the [sqlType] and

View File

@ -1,13 +1,13 @@
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/moor_generator.dart';
/// Topologically sorts a list of [SpecifiedTable]s by their /// Topologically sorts a list of [MoorTable]s by their
/// [SpecifiedTable.references] relationship: Tables appearing first in the /// [MoorTable.references] relationship: Tables appearing first in the
/// output have to be created first so the table creation script doesn't crash /// output have to be created first so the table creation script doesn't crash
/// because of tables not existing. /// because of tables not existing.
/// ///
/// If there is a circular reference between [SpecifiedTable]s, an error will /// If there is a circular reference between [MoorTable]s, an error will
/// be added that contains the name of the tables in question. /// be added that contains the name of the tables in question.
List<SpecifiedTable> sortTablesTopologically(Iterable<SpecifiedTable> tables) { List<MoorTable> sortTablesTopologically(Iterable<MoorTable> tables) {
final run = _SortRun(); final run = _SortRun();
for (final table in tables) { for (final table in tables) {
@ -20,7 +20,7 @@ List<SpecifiedTable> sortTablesTopologically(Iterable<SpecifiedTable> tables) {
return run.result; return run.result;
} }
void _visit(SpecifiedTable table, _SortRun run) { void _visit(MoorTable table, _SortRun run) {
for (final reference in table.references) { for (final reference in table.references) {
if (run.result.contains(reference)) { if (run.result.contains(reference)) {
// already handled, nothing to do // already handled, nothing to do
@ -38,14 +38,14 @@ void _visit(SpecifiedTable table, _SortRun run) {
} }
class _SortRun { class _SortRun {
final Map<SpecifiedTable, SpecifiedTable> previous = {}; final Map<MoorTable, MoorTable> previous = {};
final List<SpecifiedTable> result = []; final List<MoorTable> result = [];
/// Throws a [CircularReferenceException] because the [last] table depends on /// Throws a [CircularReferenceException] because the [last] table depends on
/// [first], which (transitively) depends on [last] as well. The path in the /// [first], which (transitively) depends on [last] as well. The path in the
/// thrown exception will go from [first] to [last]. /// thrown exception will go from [first] to [last].
void throwCircularException(SpecifiedTable last, SpecifiedTable first) { void throwCircularException(MoorTable last, MoorTable first) {
final constructedPath = <SpecifiedTable>[]; final constructedPath = <MoorTable>[];
for (var current = last; current != first; current = previous[current]) { for (var current = last; current != first; current = previous[current]) {
constructedPath.insert(0, current); constructedPath.insert(0, current);
} }
@ -54,18 +54,18 @@ class _SortRun {
throw CircularReferenceException(constructedPath); throw CircularReferenceException(constructedPath);
} }
bool didVisitAlready(SpecifiedTable table) { bool didVisitAlready(MoorTable table) {
return previous[table] != null || result.contains(table); return previous[table] != null || result.contains(table);
} }
} }
/// Thrown by [sortTablesTopologically] when the graph formed by /// Thrown by [sortTablesTopologically] when the graph formed by
/// [SpecifiedTable]s and their [SpecifiedTable.references] is not acyclic. /// [MoorTable]s and their [MoorTable.references] is not acyclic.
class CircularReferenceException implements Exception { class CircularReferenceException implements Exception {
/// The list of tables forming a circular reference, so that the first table /// The list of tables forming a circular reference, so that the first table
/// in this list references the second one and so on. The last table in this /// in this list references the second one and so on. The last table in this
/// list references the first one. /// list references the first one.
final List<SpecifiedTable> affected; final List<MoorTable> affected;
CircularReferenceException(this.affected); CircularReferenceException(this.affected);
} }

View File

@ -1,18 +1,18 @@
import 'package:moor_generator/src/model/specified_db_classes.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/writer.dart'; import 'package:moor_generator/writer.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
/// Generates the Dart code put into a `.g.dart` file when running the /// Generates the Dart code put into a `.g.dart` file when running the
/// generator. /// generator.
class DatabaseWriter { class DatabaseWriter {
final SpecifiedDatabase db; final Database db;
final Scope scope; final Scope scope;
DatabaseWriter(this.db, this.scope); DatabaseWriter(this.db, this.scope);
void write() { void write() {
// Write referenced tables // Write referenced tables
for (final table in db.allTables) { for (final table in db.tables) {
TableWriter(table, scope.child()).writeInto(); TableWriter(table, scope.child()).writeInto();
} }
@ -32,7 +32,7 @@ class DatabaseWriter {
final tableGetters = <String>[]; final tableGetters = <String>[];
for (final table in db.allTables) { for (final table in db.tables) {
tableGetters.add(table.tableFieldName); tableGetters.add(table.tableFieldName);
final tableClassName = table.tableInfoName; final tableClassName = table.tableInfoName;
@ -60,7 +60,7 @@ class DatabaseWriter {
// Write implementation for query methods // Write implementation for query methods
final writtenMappingMethods = <String>{}; final writtenMappingMethods = <String>{};
for (final query in db.resolvedQueries) { for (final query in db.queries) {
QueryWriter(query, dbScope.child(), writtenMappingMethods).write(); QueryWriter(query, dbScope.child(), writtenMappingMethods).write();
} }

View File

@ -1,7 +1,7 @@
import 'dart:math' show max; import 'dart:math' show max;
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/options.dart'; import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:moor_generator/src/utils/string_escaper.dart'; import 'package:moor_generator/src/utils/string_escaper.dart';
import 'package:moor_generator/writer.dart'; import 'package:moor_generator/writer.dart';

View File

@ -1,9 +1,9 @@
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/writer.dart'; import 'package:moor_generator/writer.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
class DataClassWriter { class DataClassWriter {
final SpecifiedTable table; final MoorTable table;
final Scope scope; final Scope scope;
StringBuffer _buffer; StringBuffer _buffer;

View File

@ -1,11 +1,11 @@
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/src/model/declarations/declaration.dart';
import 'package:moor_generator/src/utils/string_escaper.dart'; import 'package:moor_generator/src/utils/string_escaper.dart';
import 'package:moor_generator/writer.dart'; import 'package:moor_generator/writer.dart';
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
class TableWriter { class TableWriter {
final SpecifiedTable table; final MoorTable table;
final Scope scope; final Scope scope;
StringBuffer _buffer; StringBuffer _buffer;
@ -132,7 +132,7 @@ class TableWriter {
_buffer.write('return map; \n}\n'); _buffer.write('return map; \n}\n');
} }
void _writeColumnGetter(SpecifiedColumn column) { void _writeColumnGetter(MoorColumn column) {
final isNullable = column.nullable; final isNullable = column.nullable;
final additionalParams = <String, String>{}; final additionalParams = <String, String>{};
final expressionBuffer = StringBuffer(); final expressionBuffer = StringBuffer();
@ -192,7 +192,7 @@ class TableWriter {
); );
} }
void _writeColumnVerificationMeta(SpecifiedColumn column) { void _writeColumnVerificationMeta(MoorColumn column) {
if (!scope.writer.options.skipVerificationCode) { if (!scope.writer.options.skipVerificationCode) {
_buffer _buffer
..write('final VerificationMeta ${_fieldNameForColumnMeta(column)} = ') ..write('final VerificationMeta ${_fieldNameForColumnMeta(column)} = ')
@ -233,7 +233,7 @@ class TableWriter {
_buffer.write('return context;\n}\n'); _buffer.write('return context;\n}\n');
} }
String _fieldNameForColumnMeta(SpecifiedColumn column) { String _fieldNameForColumnMeta(MoorColumn column) {
return '_${column.dartGetterName}Meta'; return '_${column.dartGetterName}Meta';
} }
@ -299,8 +299,8 @@ class TableWriter {
} }
if (table.isVirtualTable) { if (table.isVirtualTable) {
final stmt = final declaration = table.declaration as MoorTableDeclaration;
table.declaration.moorDeclaration as CreateVirtualTableStatement; final stmt = declaration.node as CreateVirtualTableStatement;
final moduleAndArgs = asDartLiteral( final moduleAndArgs = asDartLiteral(
'${stmt.moduleName}(${stmt.argumentContent.join(', ')})'); '${stmt.moduleName}(${stmt.argumentContent.join(', ')})');
_buffer _buffer

View File

@ -1,9 +1,8 @@
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/writer.dart'; import 'package:moor_generator/writer.dart';
class UpdateCompanionWriter { class UpdateCompanionWriter {
final SpecifiedTable table; final MoorTable table;
final Scope scope; final Scope scope;
StringBuffer _buffer; StringBuffer _buffer;
@ -44,7 +43,7 @@ class UpdateCompanionWriter {
/// absent during insert are marked `@required` here. Also, we don't need to /// absent during insert are marked `@required` here. Also, we don't need to
/// use value wrappers here - `Value.absent` simply isn't an option. /// use value wrappers here - `Value.absent` simply isn't an option.
void _writeInsertConstructor() { void _writeInsertConstructor() {
final requiredColumns = <SpecifiedColumn>{}; final requiredColumns = <MoorColumn>{};
// can't be constant because we use initializers (this.a = Value(a)). // can't be constant because we use initializers (this.a = Value(a)).
// for a parameter a which is only potentially constant. // for a parameter a which is only potentially constant.

View File

@ -51,7 +51,7 @@ CREATE TABLE bars (
final result = file.currentResult as ParsedDartFile; final result = file.currentResult as ParsedDartFile;
final database = result.declaredDatabases.single; final database = result.declaredDatabases.single;
expect(database.allTables.map((t) => t.sqlName), expect(
containsAll(['foos', 'bars'])); database.tables.map((t) => t.sqlName), containsAll(['foos', 'bars']));
}); });
} }

View File

@ -2,11 +2,10 @@
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:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/dart/parser.dart'; import 'package:moor_generator/src/analyzer/dart/parser.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart'; import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/analyzer/session.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import '../../utils/test_backend.dart'; import '../../utils/test_backend.dart';
@ -85,7 +84,7 @@ void main() {
parser = MoorDartParser(dartStep); parser = MoorDartParser(dartStep);
}); });
Future<SpecifiedTable> parse(String name) async { Future<MoorTable> parse(String name) async {
return parser.parseTable(dartStep.library.getType(name)); return parser.parseTable(dartStep.library.getType(name));
} }
@ -113,8 +112,14 @@ void main() {
table.columns.singleWhere((col) => col.name.name == 'id'); table.columns.singleWhere((col) => col.name.name == 'id');
expect(idColumn.name, equals(ColumnName.implicitly('id'))); expect(idColumn.name, equals(ColumnName.implicitly('id')));
expect(idColumn.declaration.dartDeclaration, expect(
const TypeMatcher<PropertyAccessorElement>()); idColumn.declaration,
const TypeMatcher<DartColumnDeclaration>().having(
(c) => c.element,
'element',
const TypeMatcher<PropertyAccessorElement>(),
),
);
}); });
test('should use explicit name, if it exists', () async { test('should use explicit name, if it exists', () async {

View File

@ -1,9 +1,9 @@
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/runner/results.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart';
import 'package:moor_generator/src/analyzer/runner/task.dart'; import 'package:moor_generator/src/analyzer/runner/task.dart';
import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/analyzer/session.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
@ -92,14 +92,14 @@ class ProgrammingLanguages extends Table {
final result = file.currentResult as ParsedDartFile; final result = file.currentResult as ParsedDartFile;
final database = result.declaredDatabases.single; final database = result.declaredDatabases.single;
expect(database.allTables.map((t) => t.sqlName), expect(database.tables.map((t) => t.sqlName),
containsAll(['used_languages', 'libraries', 'programming_languages'])); containsAll(['used_languages', 'libraries', 'programming_languages']));
final tableWithReferences = final tableWithReferences =
database.allTables.singleWhere((r) => r.sqlName == 'reference_test'); database.tables.singleWhere((r) => r.sqlName == 'reference_test');
expect(tableWithReferences.references.single.sqlName, 'libraries'); expect(tableWithReferences.references.single.sqlName, 'libraries');
final importQuery = database.resolvedQueries final importQuery = database.queries
.singleWhere((q) => q.name == 'transitiveImportTest') as SqlSelectQuery; .singleWhere((q) => q.name == 'transitiveImportTest') as SqlSelectQuery;
expect(importQuery.resultClassName, 'ProgrammingLanguage'); expect(importQuery.resultClassName, 'ProgrammingLanguage');
expect(importQuery.declaredInMoorFile, isFalse); expect(importQuery.declaredInMoorFile, isFalse);
@ -108,7 +108,7 @@ class ProgrammingLanguages extends Table {
contains(equals( contains(equals(
FoundDartPlaceholder(DartPlaceholderType.orderBy, null, 'o')))); FoundDartPlaceholder(DartPlaceholderType.orderBy, null, 'o'))));
final librariesQuery = database.resolvedQueries final librariesQuery = database.queries
.singleWhere((q) => q.name == 'findLibraries') as SqlSelectQuery; .singleWhere((q) => q.name == 'findLibraries') as SqlSelectQuery;
expect(librariesQuery.variables.single.type, ColumnType.text); expect(librariesQuery.variables.single.type, ColumnType.text);
expect(librariesQuery.declaredInMoorFile, isTrue); expect(librariesQuery.declaredInMoorFile, isTrue);

View File

@ -1,9 +1,9 @@
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/runner/results.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart';
import 'package:moor_generator/src/analyzer/runner/task.dart'; import 'package:moor_generator/src/analyzer/runner/task.dart';
import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/analyzer/session.dart';
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/sql_query.dart'; import 'package:moor_generator/src/model/sql_query.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';

View File

@ -1,11 +1,10 @@
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/analyzer/options.dart'; import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
void main() { void main() {
test('companion names', () { test('companion names', () {
final table = final table = MoorTable(overriddenName: 'GoogleUser', dartTypeName: 'User');
SpecifiedTable(overriddenName: 'GoogleUser', dartTypeName: 'User');
expect(table.getNameForCompanionClass(const MoorOptions()), expect(table.getNameForCompanionClass(const MoorOptions()),
'GoogleUserCompanion'); 'GoogleUserCompanion');

View File

@ -1,11 +1,11 @@
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/utils/table_reference_sorter.dart'; import 'package:moor_generator/src/utils/table_reference_sorter.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
void main() { void main() {
test('throws cyclic exception when two tables reference each other', () { test('throws cyclic exception when two tables reference each other', () {
final first = SpecifiedTable(sqlName: 'a'); final first = MoorTable(sqlName: 'a');
final second = SpecifiedTable(sqlName: 'b'); final second = MoorTable(sqlName: 'b');
first.references.add(second); first.references.add(second);
second.references.add(first); second.references.add(first);
@ -15,10 +15,10 @@ void main() {
}); });
test('throws cyclic exception on a circular reference with three tables', () { test('throws cyclic exception on a circular reference with three tables', () {
final a = SpecifiedTable(sqlName: 'a'); final a = MoorTable(sqlName: 'a');
final b = SpecifiedTable(sqlName: 'b'); final b = MoorTable(sqlName: 'b');
final c = SpecifiedTable(sqlName: 'c'); final c = MoorTable(sqlName: 'c');
final d = SpecifiedTable(sqlName: 'd'); final d = MoorTable(sqlName: 'd');
a.references.add(b); a.references.add(b);
b.references.add(c); b.references.add(c);
@ -31,10 +31,10 @@ void main() {
}); });
test('sorts tables topologically when no cycles exist', () { test('sorts tables topologically when no cycles exist', () {
final a = SpecifiedTable(sqlName: 'a'); final a = MoorTable(sqlName: 'a');
final b = SpecifiedTable(sqlName: 'b'); final b = MoorTable(sqlName: 'b');
final c = SpecifiedTable(sqlName: 'c'); final c = MoorTable(sqlName: 'c');
final d = SpecifiedTable(sqlName: 'd'); final d = MoorTable(sqlName: 'd');
a.references.add(b); a.references.add(b);
b.references.add(c); b.references.add(c);
@ -44,7 +44,7 @@ void main() {
}); });
} }
CircularReferenceException _expectFails(Iterable<SpecifiedTable> table) { CircularReferenceException _expectFails(Iterable<MoorTable> table) {
try { try {
sortTablesTopologically(table); sortTablesTopologically(table);
fail('Expected sortTablesTopologically to throw here'); fail('Expected sortTablesTopologically to throw here');

View File

@ -26,3 +26,9 @@ abstract class SyntacticEntity {
/// actual source. /// actual source.
bool get synthetic; bool get synthetic;
} }
/// Extension to report the length of a [SyntacticEntity].
extension SyntacticLengthExtension on SyntacticEntity {
/// The length of this entity, in characters.
int get length => lastPosition - firstPosition;
}

View File

@ -7,7 +7,7 @@ issue_tracker: https://github.com/simolus3/moor/issues
author: Simon Binder <oss@simonbinder.eu> author: Simon Binder <oss@simonbinder.eu>
environment: environment:
sdk: '>=2.2.2 <3.0.0' sdk: '>=2.6.0 <3.0.0'
dependencies: dependencies:
meta: ^1.1.0 meta: ^1.1.0