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
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
[build options]({{<relref "../Advanced Features/builder_options.md">}}) to include
`fts5` in the `sqlite_module` section.

View File

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

View File

@ -46,7 +46,7 @@ class ColumnParser {
ColumnParser(this.base);
SpecifiedColumn parse(MethodDeclaration getter, Element element) {
MoorColumn parse(MethodDeclaration getter, Element element) {
final expr = base.returnExpressionOfMethod(getter);
if (expr is! FunctionExpressionInvocation) {
@ -180,20 +180,18 @@ class ColumnParser {
sqlType: columnType);
}
final column = SpecifiedColumn(
type: columnType,
dartGetterName: getter.name.name,
name: name,
overriddenJsonName: _readJsonKey(element),
customConstraints: foundCustomConstraint,
nullable: nullable,
features: foundFeatures,
defaultArgument: foundDefaultExpression?.toSource(),
typeConverter: converter);
final declaration =
ColumnDeclaration(column, base.step.file, element, null);
return column..declaration = declaration;
return MoorColumn(
type: columnType,
dartGetterName: getter.name.name,
name: name,
overriddenJsonName: _readJsonKey(element),
customConstraints: foundCustomConstraint,
nullable: nullable,
features: foundFeatures,
defaultArgument: foundDefaultExpression?.toSource(),
typeConverter: converter,
declaration: DartColumnDeclaration(element, base.step.file),
);
}
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:meta/meta.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/runner/steps.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/specified_db_classes.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/model/declarations/declaration.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/type_utils.dart';
@ -32,11 +30,11 @@ class MoorDartParser {
_tableParser = TableParser(this);
}
Future<SpecifiedTable> parseTable(ClassElement classElement) {
Future<MoorTable> parseTable(ClassElement classElement) {
return _tableParser.parseTable(classElement);
}
Future<SpecifiedColumn> parseColumn(
Future<MoorColumn> parseColumn(
MethodDeclaration declaration, Element element) {
return Future.value(_columnParser.parse(declaration, element));
}

View File

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

View File

@ -7,8 +7,7 @@ class UseDaoParser {
/// If [element] has a `@UseDao` annotation, parses the database model
/// declared by that class and the referenced tables.
Future<SpecifiedDao> parseDao(
ClassElement element, ConstantReader annotation) async {
Future<Dao> parseDao(ClassElement element, ConstantReader annotation) async {
final dbType = element.supertype;
if (dbType.name != 'DatabaseAccessor') {
step.reportError(ErrorInDartCode(
@ -47,6 +46,12 @@ class UseDaoParser {
final parsedTables = await step.parseTables(tableTypes, element);
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
/// declared by that class and the referenced tables.
Future<SpecifiedDatabase> parseDatabase(
Future<Database> parseDatabase(
ClassElement element, ConstantReader annotation) async {
// the types declared in UseMoor.tables
final tableTypes =
@ -27,8 +27,13 @@ class UseMoorParser {
final parsedQueries = step.readDeclaredQueries(queryStrings);
final daoTypes = _readDaoTypes(annotation);
return SpecifiedDatabase(
element, parsedTables, daoTypes, includes, parsedQueries);
return Database(
declaration: DatabaseOrDaoDeclaration(element, step.file),
declaredTables: parsedTables,
daos: daoTypes,
declaredIncludes: includes,
declaredQueries: parsedQueries,
);
}
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/sql_queries/meta/declarations.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/specified_table.dart';
import 'package:moor_generator/src/model/declarations/declaration.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/string_escaper.dart';
@ -16,11 +15,11 @@ class CreateTableReader {
CreateTableReader(this.stmt, this.step);
SpecifiedTable extractTable(TypeMapper mapper) {
MoorTable extractTable(TypeMapper mapper) {
final table = SchemaFromCreateTable(moorExtensions: true).read(stmt);
final foundColumns = <String, SpecifiedColumn>{};
final primaryKey = <SpecifiedColumn>{};
final foundColumns = <String, MoorColumn>{};
final primaryKey = <MoorColumn>{};
for (final column in table.resultColumns) {
var isPrimaryKey = false;
@ -71,7 +70,12 @@ class CreateTableReader {
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,
nullable: column.type.nullable,
dartGetterName: dartName,
@ -81,12 +85,9 @@ class CreateTableReader {
defaultArgument: defaultValue,
typeConverter: converter,
overriddenJsonName: overriddenJsonKey,
declaration: declaration,
);
final declaration =
ColumnDeclaration(parsed, step.file, null, column.definition);
parsed.declaration = declaration;
foundColumns[column.name] = parsed;
if (isPrimaryKey) {
primaryKey.add(parsed);
@ -108,7 +109,7 @@ class CreateTableReader {
}
}
final specifiedTable = SpecifiedTable(
return MoorTable(
fromClass: null,
columns: foundColumns.values.toList(),
sqlName: table.name,
@ -119,13 +120,8 @@ class CreateTableReader {
overrideTableConstraints: constraints.isNotEmpty ? constraints : null,
// we take care of writing the primary key ourselves
overrideDontWriteConstraints: true,
);
final declaration = TableDeclaration(
specifiedTable, step.file, null, table.definition,
tableFromSqlParser: table);
return specifiedTable..declaration = declaration;
declaration: MoorTableDeclaration(stmt, step.file),
)..parserTable = table;
}
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/runner/steps.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/model/specified_table.dart';
import 'package:moor_generator/src/model/sql_query.dart';
import 'package:sqlparser/sqlparser.dart';
@ -40,8 +40,8 @@ class MoorParser {
));
}
final createdTables = <SpecifiedTable>[];
final tableDeclarations = <TableInducingStatement, SpecifiedTable>{};
final createdTables = <MoorTable>[];
final tableDeclarations = <TableInducingStatement, MoorTable>{};
for (final reader in createdReaders) {
final table = reader.extractTable(step.mapper);
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/runner/results.dart';
import 'package:moor_generator/src/analyzer/runner/steps.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:sqlparser/sqlparser.dart';
/// Handles `REFERENCES` clauses in tables by resolving their columns and
/// 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 {
final AnalyzeMoorStep step;
final ParsedMoorFile file;
final List<SpecifiedTable> availableTables;
final List<MoorTable> availableTables;
TableHandler(this.step, this.file, this.availableTables);

View File

@ -1,13 +1,12 @@
import 'package:meta/meta.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/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:sqlparser/sqlparser.dart';
abstract class FileResult {
final List<SpecifiedTable> declaredTables;
final List<MoorTable> declaredTables;
FileResult(this.declaredTables);
}
@ -15,15 +14,15 @@ abstract class FileResult {
class ParsedDartFile extends FileResult {
final LibraryElement library;
final List<SpecifiedDao> declaredDaos;
final List<SpecifiedDatabase> declaredDatabases;
final List<Dao> declaredDaos;
final List<Database> declaredDatabases;
Iterable<SpecifiedDbAccessor> get dbAccessors =>
declaredDatabases.cast<SpecifiedDbAccessor>().followedBy(declaredDaos);
Iterable<BaseMoorAccessor> get dbAccessors =>
declaredDatabases.cast<BaseMoorAccessor>().followedBy(declaredDaos);
ParsedDartFile(
{@required this.library,
List<SpecifiedTable> declaredTables = const [],
List<MoorTable> declaredTables = const [],
this.declaredDaos = const [],
this.declaredDatabases = const []})
: super(declaredTables);
@ -37,11 +36,11 @@ class ParsedMoorFile extends FileResult {
final List<DeclaredQuery> queries;
List<SqlQuery> resolvedQueries;
Map<TableInducingStatement, SpecifiedTable> tableDeclarations;
Map<TableInducingStatement, MoorTable> tableDeclarations;
Map<ImportStatement, FoundFile> resolvedImports;
ParsedMoorFile(this.parseResult,
{List<SpecifiedTable> declaredTables = const [],
{List<MoorTable> declaredTables = const [],
this.queries = const [],
this.imports = 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/type.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/errors.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/type_mapping.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/utils/table_reference_sorter.dart';
import 'package:source_gen/source_gen.dart';
@ -54,8 +53,8 @@ abstract class AnalyzingStep extends Step {
.toList();
}
Iterable<SpecifiedTable> _availableTables(List<FoundFile> imports) {
return imports.expand<SpecifiedTable>(
Iterable<MoorTable> _availableTables(List<FoundFile> imports) {
return imports.expand<MoorTable>(
(file) => file.currentResult?.declaredTables ?? const Iterable.empty());
}
}

View File

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

View File

@ -1,9 +1,9 @@
part of '../steps.dart';
/// Extracts the following information from a Dart file:
/// - [SpecifiedTable]s, which are read from Dart classes extending `Table`.
/// - [SpecifiedDatabase]s, which are read from `@UseMoor`-annotated classes
/// - [SpecifiedDao]s, which are read from `@UseDao`-annotated classes.
/// - [MoorTable]s, which are read from Dart classes extending `Table`.
/// - [Database]s, which are read from `@UseMoor`-annotated classes
/// - [Dao]s, which are read from `@UseDao`-annotated classes.
///
/// Notably, this step does not analyze defined queries.
class ParseDartStep extends Step {
@ -16,7 +16,7 @@ class ParseDartStep extends Step {
MoorDartParser _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) {
_parser = MoorDartParser(this);
@ -24,8 +24,8 @@ class ParseDartStep extends Step {
Future<ParsedDartFile> parse() async {
final reader = LibraryReader(library);
final databases = <SpecifiedDatabase>[];
final daos = <SpecifiedDao>[];
final databases = <Database>[];
final daos = <Dao>[];
for (final declaredClass in reader.classes) {
// 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)) {
_tables[element] = await parser.parseTable(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`
/// annotation.
Future<SpecifiedDatabase> parseDatabase(
Future<Database> parseDatabase(
ClassElement element, ConstantReader 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].
Future<SpecifiedDao> parseDao(
ClassElement element, ConstantReader annotation) {
Future<Dao> parseDao(ClassElement element, ConstantReader 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
/// parsing (e.g. the database class that is annotated with `@UseMoor`). This
/// will allow for more descriptive error messages.
Future<List<SpecifiedTable>> parseTables(
Future<List<MoorTable>> parseTables(
Iterable<DartType> types, Element initializedBy) {
return Future.wait(types.map((type) {
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/runner/file_graph.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/session.dart';
import 'package:moor_generator/src/backends/backend.dart';
import 'package:moor_generator/src/model/specified_db_classes.dart';
import 'package:sqlparser/sqlparser.dart';
/// 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;
final daosAndDatabases = parsed.declaredDaos
.cast<SpecifiedDbAccessor>()
.cast<BaseMoorAccessor>()
.followedBy(parsed.declaredDatabases);
for (final accessor in daosAndDatabases) {
final resolvedForAccessor = <FoundFile>[];
for (final import in accessor.includes) {
for (final import in accessor.declaredIncludes) {
final found = session.resolve(file, import);
if (!await backend.exists(found.uri)) {
step.reportError(ErrorInDartCode(
@ -129,7 +129,7 @@ class Task {
}
}
accessor.resolvedImports = resolvedForAccessor;
accessor.imports = resolvedForAccessor;
}
break;
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:moor_generator/moor_generator.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/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/analyzer/sql_queries/query_handler.dart';
import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart';
import 'package:sqlparser/sqlparser.dart' hide ResultColumn;
class SqlParser {
final List<SpecifiedTable> tables;
final List<MoorTable> tables;
final Step step;
final List<DeclaredQuery> definedQueries;
@ -62,6 +62,7 @@ class SqlParser {
..declaredInMoorFile = declaredInMoor;
foundQueries.add(query);
} catch (e, s) {
// todo remove dependency on build package here
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/src/model/specified_table.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/src/model/sql_query.dart';
import 'package:moor_generator/src/utils/type_converter_hint.dart';
import 'package:sqlparser/sqlparser.dart';
import 'meta/declarations.dart';
/// Converts tables and types between the moor_generator and the sqlparser
/// library.
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.
Table extractStructure(SpecifiedTable table) {
final existingTable = table.declaration?.tableFromSqlParser;
if (existingTable != null) {
_engineTablesToSpecified[existingTable] = table;
return existingTable;
Table extractStructure(MoorTable table) {
if (table.parserTable != null) {
final parserTbl = table.parserTable;
_engineTablesToSpecified[parserTbl] = table;
return parserTbl;
}
final columns = <TableColumn>[];
@ -29,13 +26,13 @@ class TypeMapper {
.withNullable(specified.nullable);
final column = TableColumn(specified.name.name, type);
column.setMeta<ColumnDeclaration>(specified.declaration);
column.setMeta<MoorColumn>(specified);
columns.add(column);
}
final engineTable = Table(name: table.sqlName, resolvedColumns: columns);
engineTable.setMeta<TableDeclaration>(table.declaration);
engineTable.setMeta<MoorTable>(table);
_engineTablesToSpecified[engineTable] = table;
return engineTable;
}
@ -222,7 +219,7 @@ class TypeMapper {
return FoundDartPlaceholder(type, columnType, name)..astNode = placeholder;
}
SpecifiedTable tableToMoor(Table table) {
MoorTable tableToMoor(Table table) {
return _engineTablesToSpecified[table];
}
}

View File

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

View File

@ -1,6 +1,6 @@
import 'package:analyzer_plugin/protocol/protocol_common.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/utils/ast_to_location.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* {
final declaration = column.meta<ColumnDeclaration>();
final declaration = column.meta<MoorColumn>()?.declaration;
if (declaration != null) {
// the column was declared in a table and we happen to know where the
// declaration is - point to that declaration.
@ -101,7 +101,7 @@ class _NavigationVisitor extends RecursiveVisitor<void> {
final resolved = e.resolved;
if (resolved is Table && resolved != null) {
final declaration = resolved.meta<TableDeclaration>();
final declaration = resolved.meta<MoorTable>()?.declaration;
_reportForSpan(
e.span, ElementKind.CLASS, locationOfDeclaration(declaration));
}

View File

@ -1,6 +1,6 @@
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/sql_queries/meta/declarations.dart';
import 'package:source_gen/source_gen.dart' show spanForElement;
import 'package:source_span/source_span.dart';
import 'package:sqlparser/sqlparser.dart';
@ -25,13 +25,13 @@ Location locationOfNode(FoundFile file, AstNode node) {
return _locationForSpan(node.span, file);
}
Location locationOfDeclaration(BaseDeclaration declaration) {
if (declaration.dartDeclaration != null) {
final span = spanForElement(declaration.dartDeclaration);
return _locationForSpan(span, declaration.declarationFile);
} else if (declaration.moorDeclaration != null) {
return locationOfNode(
declaration.declarationFile, declaration.moorDeclaration);
Location locationOfDeclaration(Declaration declaration) {
final file = declaration.declaration.file;
if (declaration is DartDeclaration) {
return _locationForSpan(spanForElement(declaration.element), file);
} else if (declaration is MoorDeclaration) {
return locationOfNode(file, declaration.node);
}
return null;
}

View File

@ -1,6 +1,7 @@
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.
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.
class SpecifiedColumn {
class MoorColumn implements HasDeclaration {
/// 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)
/// 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
/// column was created in source code.
ColumnDeclaration declaration;
@override
final ColumnDeclaration declaration;
/// Whether this column was declared inside a moor file.
bool get declaredInMoorFile => declaration?.isDefinedInMoorFile ?? false;
@ -176,7 +178,7 @@ class SpecifiedColumn {
/// this column.
String get sqlTypeName => sqlTypes[type];
SpecifiedColumn({
MoorColumn({
this.type,
this.dartGetterName,
this.name,
@ -186,6 +188,7 @@ class SpecifiedColumn {
this.features = const [],
this.defaultArgument,
this.typeConverter,
this.declaration,
});
}
@ -231,9 +234,3 @@ class LimitingTextLength extends ColumnFeature {
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/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:recase/recase.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 _leadingDigits = RegExp(r'^\d*');
@ -95,7 +96,7 @@ abstract class SqlQuery {
}
class SqlSelectQuery extends SqlQuery {
final List<SpecifiedTable> readsFrom;
final List<MoorTable> readsFrom;
final InferredResultSet resultSet;
String get resultClassName {
@ -116,7 +117,7 @@ class SqlSelectQuery extends SqlQuery {
}
class UpdatingQuery extends SqlQuery {
final List<SpecifiedTable> updates;
final List<MoorTable> updates;
final bool isInsert;
UpdatingQuery(String name, AnalysisContext fromContext,
@ -129,7 +130,7 @@ class InferredResultSet {
/// 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
/// to create another class.
final SpecifiedTable matchingTable;
final MoorTable matchingTable;
final List<ResultColumn> columns;
final Map<ResultColumn, String> _dartNames = {};

View File

@ -1,19 +1,25 @@
import 'package:analyzer/dart/element/element.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:recase/recase.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
/// table in `@UseMoor` or `@UseDao`.
class SpecifiedTable {
class MoorTable implements HasDeclaration {
/// The [ClassElement] for the class that declares this table or null if
/// the table was inferred from a `CREATE TABLE` statement.
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
/// of this table in generated Dart code.
@ -26,7 +32,7 @@ class SpecifiedTable {
String get _baseName => _overriddenName ?? fromClass.name;
/// The columns declared in this table.
final List<SpecifiedColumn> columns;
final List<MoorColumn> columns;
/// The name of this table when stored in the database
final String sqlName;
@ -60,7 +66,7 @@ class SpecifiedTable {
/// The set of primary keys, if they have been explicitly defined by
/// overriding `primaryKey` in the table class. `null` if the primary key has
/// not been defined that way.
final Set<SpecifiedColumn> primaryKey;
final Set<MoorColumn> primaryKey;
/// When non-null, the generated table class will override the `withoutRowId`
/// 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,
/// 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`
/// statement in a moor file
@ -84,26 +90,27 @@ class SpecifiedTable {
if (declaration == null) {
throw StateError("Couldn't determine whether $displayName is a virtual "
'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;
}
SpecifiedTable(
{this.fromClass,
this.columns,
this.sqlName,
this.dartTypeName,
this.primaryKey,
String overriddenName,
this.overrideWithoutRowId,
this.overrideTableConstraints,
this.overrideDontWriteConstraints})
: _overriddenName = overriddenName;
MoorTable({
this.fromClass,
this.columns,
this.sqlName,
this.dartTypeName,
this.primaryKey,
String overriddenName,
this.overrideWithoutRowId,
this.overrideTableConstraints,
this.overrideDontWriteConstraints,
this.declaration,
}) : _overriddenName = overriddenName;
/// Finds all type converters used in this tables.
Iterable<UsedTypeConverter> get converters =>

View File

@ -1,13 +1,16 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:meta/meta.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/table.dart';
import 'column.dart';
class UsedTypeConverter {
/// Index of this converter in the table in which it has been created.
int index;
SpecifiedTable table;
/// The table using this type converter.
MoorTable table;
/// The [Expression] that will construct the type converter at runtime. The
/// 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
/// [SpecifiedTable.references] relationship: Tables appearing first in the
/// Topologically sorts a list of [MoorTable]s by their
/// [MoorTable.references] relationship: Tables appearing first in the
/// output have to be created first so the table creation script doesn't crash
/// 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.
List<SpecifiedTable> sortTablesTopologically(Iterable<SpecifiedTable> tables) {
List<MoorTable> sortTablesTopologically(Iterable<MoorTable> tables) {
final run = _SortRun();
for (final table in tables) {
@ -20,7 +20,7 @@ List<SpecifiedTable> sortTablesTopologically(Iterable<SpecifiedTable> tables) {
return run.result;
}
void _visit(SpecifiedTable table, _SortRun run) {
void _visit(MoorTable table, _SortRun run) {
for (final reference in table.references) {
if (run.result.contains(reference)) {
// already handled, nothing to do
@ -38,14 +38,14 @@ void _visit(SpecifiedTable table, _SortRun run) {
}
class _SortRun {
final Map<SpecifiedTable, SpecifiedTable> previous = {};
final List<SpecifiedTable> result = [];
final Map<MoorTable, MoorTable> previous = {};
final List<MoorTable> result = [];
/// Throws a [CircularReferenceException] because the [last] table depends on
/// [first], which (transitively) depends on [last] as well. The path in the
/// thrown exception will go from [first] to [last].
void throwCircularException(SpecifiedTable last, SpecifiedTable first) {
final constructedPath = <SpecifiedTable>[];
void throwCircularException(MoorTable last, MoorTable first) {
final constructedPath = <MoorTable>[];
for (var current = last; current != first; current = previous[current]) {
constructedPath.insert(0, current);
}
@ -54,18 +54,18 @@ class _SortRun {
throw CircularReferenceException(constructedPath);
}
bool didVisitAlready(SpecifiedTable table) {
bool didVisitAlready(MoorTable table) {
return previous[table] != null || result.contains(table);
}
}
/// 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 {
/// 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
/// list references the first one.
final List<SpecifiedTable> affected;
final List<MoorTable> 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:recase/recase.dart';
/// Generates the Dart code put into a `.g.dart` file when running the
/// generator.
class DatabaseWriter {
final SpecifiedDatabase db;
final Database db;
final Scope scope;
DatabaseWriter(this.db, this.scope);
void write() {
// Write referenced tables
for (final table in db.allTables) {
for (final table in db.tables) {
TableWriter(table, scope.child()).writeInto();
}
@ -32,7 +32,7 @@ class DatabaseWriter {
final tableGetters = <String>[];
for (final table in db.allTables) {
for (final table in db.tables) {
tableGetters.add(table.tableFieldName);
final tableClassName = table.tableInfoName;
@ -60,7 +60,7 @@ class DatabaseWriter {
// Write implementation for query methods
final writtenMappingMethods = <String>{};
for (final query in db.resolvedQueries) {
for (final query in db.queries) {
QueryWriter(query, dbScope.child(), writtenMappingMethods).write();
}

View File

@ -1,7 +1,7 @@
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/model/specified_column.dart';
import 'package:moor_generator/src/model/sql_query.dart';
import 'package:moor_generator/src/utils/string_escaper.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:recase/recase.dart';
class DataClassWriter {
final SpecifiedTable table;
final MoorTable table;
final Scope scope;
StringBuffer _buffer;

View File

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

View File

@ -1,9 +1,8 @@
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/moor_generator.dart';
import 'package:moor_generator/writer.dart';
class UpdateCompanionWriter {
final SpecifiedTable table;
final MoorTable table;
final Scope scope;
StringBuffer _buffer;
@ -44,7 +43,7 @@ class UpdateCompanionWriter {
/// absent during insert are marked `@required` here. Also, we don't need to
/// use value wrappers here - `Value.absent` simply isn't an option.
void _writeInsertConstructor() {
final requiredColumns = <SpecifiedColumn>{};
final requiredColumns = <MoorColumn>{};
// can't be constant because we use initializers (this.a = Value(a)).
// 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 database = result.declaredDatabases.single;
expect(database.allTables.map((t) => t.sqlName),
containsAll(['foos', 'bars']));
expect(
database.tables.map((t) => t.sqlName), containsAll(['foos', 'bars']));
});
}

View File

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

View File

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

View File

@ -1,9 +1,9 @@
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/results.dart';
import 'package:moor_generator/src/analyzer/runner/task.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: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/model/specified_table.dart';
import 'package:test/test.dart';
void main() {
test('companion names', () {
final table =
SpecifiedTable(overriddenName: 'GoogleUser', dartTypeName: 'User');
final table = MoorTable(overriddenName: 'GoogleUser', dartTypeName: 'User');
expect(table.getNameForCompanionClass(const MoorOptions()),
'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:test/test.dart';
void main() {
test('throws cyclic exception when two tables reference each other', () {
final first = SpecifiedTable(sqlName: 'a');
final second = SpecifiedTable(sqlName: 'b');
final first = MoorTable(sqlName: 'a');
final second = MoorTable(sqlName: 'b');
first.references.add(second);
second.references.add(first);
@ -15,10 +15,10 @@ void main() {
});
test('throws cyclic exception on a circular reference with three tables', () {
final a = SpecifiedTable(sqlName: 'a');
final b = SpecifiedTable(sqlName: 'b');
final c = SpecifiedTable(sqlName: 'c');
final d = SpecifiedTable(sqlName: 'd');
final a = MoorTable(sqlName: 'a');
final b = MoorTable(sqlName: 'b');
final c = MoorTable(sqlName: 'c');
final d = MoorTable(sqlName: 'd');
a.references.add(b);
b.references.add(c);
@ -31,10 +31,10 @@ void main() {
});
test('sorts tables topologically when no cycles exist', () {
final a = SpecifiedTable(sqlName: 'a');
final b = SpecifiedTable(sqlName: 'b');
final c = SpecifiedTable(sqlName: 'c');
final d = SpecifiedTable(sqlName: 'd');
final a = MoorTable(sqlName: 'a');
final b = MoorTable(sqlName: 'b');
final c = MoorTable(sqlName: 'c');
final d = MoorTable(sqlName: 'd');
a.references.add(b);
b.references.add(c);
@ -44,7 +44,7 @@ void main() {
});
}
CircularReferenceException _expectFails(Iterable<SpecifiedTable> table) {
CircularReferenceException _expectFails(Iterable<MoorTable> table) {
try {
sortTablesTopologically(table);
fail('Expected sortTablesTopologically to throw here');

View File

@ -26,3 +26,9 @@ abstract class SyntacticEntity {
/// actual source.
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>
environment:
sdk: '>=2.2.2 <3.0.0'
sdk: '>=2.6.0 <3.0.0'
dependencies:
meta: ^1.1.0