mirror of https://github.com/AMT-Cheif/drift.git
Specify analysis rules and conform to them
This commit is contained in:
parent
9090ded541
commit
75b3b25117
|
@ -0,0 +1,80 @@
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
strong-mode:
|
||||||
|
implicit-casts: false
|
||||||
|
errors:
|
||||||
|
unused_element: error
|
||||||
|
unused_import: error
|
||||||
|
unused_local_variable: error
|
||||||
|
dead_code: error
|
||||||
|
override_on_non_overriding_method: error
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- annotate_overrides
|
||||||
|
- avoid_empty_else
|
||||||
|
- avoid_function_literals_in_foreach_calls
|
||||||
|
- avoid_init_to_null
|
||||||
|
- avoid_null_checks_in_equality_operators
|
||||||
|
- avoid_relative_lib_imports
|
||||||
|
- avoid_return_types_on_setters
|
||||||
|
- avoid_returning_null
|
||||||
|
- avoid_types_as_parameter_names
|
||||||
|
- avoid_unused_constructor_parameters
|
||||||
|
- await_only_futures
|
||||||
|
- camel_case_types
|
||||||
|
- cancel_subscriptions
|
||||||
|
- cascade_invocations
|
||||||
|
- comment_references
|
||||||
|
- constant_identifier_names
|
||||||
|
- control_flow_in_finally
|
||||||
|
- directives_ordering
|
||||||
|
- empty_catches
|
||||||
|
- empty_constructor_bodies
|
||||||
|
- empty_statements
|
||||||
|
- hash_and_equals
|
||||||
|
- implementation_imports
|
||||||
|
- invariant_booleans
|
||||||
|
- iterable_contains_unrelated_type
|
||||||
|
- library_names
|
||||||
|
- library_prefixes
|
||||||
|
- list_remove_unrelated_type
|
||||||
|
- no_adjacent_strings_in_list
|
||||||
|
- no_duplicate_case_values
|
||||||
|
- non_constant_identifier_names
|
||||||
|
- null_closures
|
||||||
|
- omit_local_variable_types
|
||||||
|
- only_throw_errors
|
||||||
|
- overridden_fields
|
||||||
|
- package_api_docs
|
||||||
|
- package_names
|
||||||
|
- package_prefixed_library_names
|
||||||
|
- prefer_adjacent_string_concatenation
|
||||||
|
- prefer_collection_literals
|
||||||
|
- prefer_conditional_assignment
|
||||||
|
- prefer_const_constructors
|
||||||
|
- prefer_contains
|
||||||
|
- prefer_equal_for_default_values
|
||||||
|
- prefer_final_fields
|
||||||
|
- prefer_initializing_formals
|
||||||
|
- prefer_interpolation_to_compose_strings
|
||||||
|
- prefer_is_empty
|
||||||
|
- prefer_is_not_empty
|
||||||
|
- prefer_single_quotes
|
||||||
|
- prefer_typing_uninitialized_variables
|
||||||
|
- recursive_getters
|
||||||
|
- slash_for_doc_comments
|
||||||
|
- super_goes_last
|
||||||
|
- test_types_in_equals
|
||||||
|
- throw_in_finally
|
||||||
|
- type_init_formals
|
||||||
|
- unawaited_futures
|
||||||
|
- unnecessary_brace_in_string_interps
|
||||||
|
- unnecessary_getters_setters
|
||||||
|
- unnecessary_lambdas
|
||||||
|
- unnecessary_new
|
||||||
|
- unnecessary_null_aware_assignments
|
||||||
|
- unnecessary_statements
|
||||||
|
- unnecessary_this
|
||||||
|
- unrelated_type_equality_checks
|
||||||
|
- use_rethrow_when_possible
|
||||||
|
- valid_regexps
|
|
@ -0,0 +1 @@
|
||||||
|
../analysis_options.yaml
|
|
@ -9,7 +9,7 @@ class Where extends Component {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void writeInto(GenerationContext context) {
|
void writeInto(GenerationContext context) {
|
||||||
context.buffer.write("WHERE ");
|
context.buffer.write('WHERE ');
|
||||||
predicate.writeInto(context);
|
predicate.writeInto(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,6 @@ class SqlTypeSystem {
|
||||||
/// Returns the appropriate sql type for the dart type provided as the
|
/// Returns the appropriate sql type for the dart type provided as the
|
||||||
/// generic parameter.
|
/// generic parameter.
|
||||||
SqlType<T> forDartType<T>() {
|
SqlType<T> forDartType<T>() {
|
||||||
return types.singleWhere((t) => t is SqlType<T>);
|
return types.singleWhere((t) => t is SqlType<T>) as SqlType<T>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,21 @@ Expression<BoolType> and(Expression<BoolType> a, Expression<BoolType> b) =>
|
||||||
Expression<BoolType> not(Expression<BoolType> a) => NotExpression(a);
|
Expression<BoolType> not(Expression<BoolType> a) => NotExpression(a);
|
||||||
|
|
||||||
class AndExpression extends Expression<BoolType> with InfixOperator<BoolType> {
|
class AndExpression extends Expression<BoolType> with InfixOperator<BoolType> {
|
||||||
|
@override
|
||||||
Expression<BoolType> left, right;
|
Expression<BoolType> left, right;
|
||||||
|
|
||||||
final String operator = "AND";
|
@override
|
||||||
|
final String operator = 'AND';
|
||||||
|
|
||||||
AndExpression(this.left, this.right);
|
AndExpression(this.left, this.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrExpression extends Expression<BoolType> with InfixOperator<BoolType> {
|
class OrExpression extends Expression<BoolType> with InfixOperator<BoolType> {
|
||||||
|
@override
|
||||||
Expression<BoolType> left, right;
|
Expression<BoolType> left, right;
|
||||||
|
|
||||||
final String operator = "AND";
|
@override
|
||||||
|
final String operator = 'AND';
|
||||||
|
|
||||||
OrExpression(this.left, this.right);
|
OrExpression(this.left, this.right);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,21 +39,24 @@ abstract class InfixOperator<T extends SqlType> implements Expression<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ComparisonOperator { less, less_or_equal, equal, more_or_equal, more }
|
enum ComparisonOperator { less, lessOrEqual, equal, moreOrEqual, more }
|
||||||
|
|
||||||
class Comparison extends InfixOperator<BoolType> {
|
class Comparison extends InfixOperator<BoolType> {
|
||||||
static const Map<ComparisonOperator, String> operatorNames = {
|
static const Map<ComparisonOperator, String> operatorNames = {
|
||||||
ComparisonOperator.less: '<',
|
ComparisonOperator.less: '<',
|
||||||
ComparisonOperator.less_or_equal: '<=',
|
ComparisonOperator.lessOrEqual: '<=',
|
||||||
ComparisonOperator.equal: '=',
|
ComparisonOperator.equal: '=',
|
||||||
ComparisonOperator.more_or_equal: '>=',
|
ComparisonOperator.moreOrEqual: '>=',
|
||||||
ComparisonOperator.more: '>'
|
ComparisonOperator.more: '>'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
final Expression left;
|
final Expression left;
|
||||||
|
@override
|
||||||
final Expression right;
|
final Expression right;
|
||||||
final ComparisonOperator op;
|
final ComparisonOperator op;
|
||||||
|
|
||||||
|
@override
|
||||||
final bool placeBrackets = false;
|
final bool placeBrackets = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -61,5 +64,5 @@ class Comparison extends InfixOperator<BoolType> {
|
||||||
|
|
||||||
Comparison(this.left, this.op, this.right);
|
Comparison(this.left, this.op, this.right);
|
||||||
|
|
||||||
Comparison.equal(this.left, this.right) : this.op = ComparisonOperator.equal;
|
Comparison.equal(this.left, this.right) : op = ComparisonOperator.equal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Variable<T, S extends SqlType<T>> extends Expression<S> {
|
||||||
@override
|
@override
|
||||||
void writeInto(GenerationContext context) {
|
void writeInto(GenerationContext context) {
|
||||||
context.introduceVariable(value);
|
context.introduceVariable(value);
|
||||||
context.buffer.write("?");
|
context.buffer.write('?');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class BoolType extends SqlType<bool> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String mapToSqlConstant(bool content) {
|
String mapToSqlConstant(bool content) {
|
||||||
return content ? "1" : "0";
|
return content ? '1' : '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -40,7 +40,7 @@ class StringType extends SqlType<String> {
|
||||||
const StringType();
|
const StringType();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String mapFromDatabaseResponse(response) => response;
|
String mapFromDatabaseResponse(response) => response as String;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String mapToSqlConstant(String content) {
|
String mapToSqlConstant(String content) {
|
||||||
|
@ -56,7 +56,7 @@ class IntType extends SqlType<int> {
|
||||||
const IntType();
|
const IntType();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int mapFromDatabaseResponse(response) => response;
|
int mapFromDatabaseResponse(response) => response as int;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String mapToSqlConstant(int content) => content.toString();
|
String mapToSqlConstant(int content) => content.toString();
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:sally/src/runtime/structure/table_info.dart';
|
||||||
|
|
||||||
class SelectStatement<UserTable, DataType> extends Query<UserTable> {
|
class SelectStatement<UserTable, DataType> extends Query<UserTable> {
|
||||||
@override
|
@override
|
||||||
|
// ignore: overridden_fields
|
||||||
covariant TableInfo<UserTable, DataType> table;
|
covariant TableInfo<UserTable, DataType> table;
|
||||||
|
|
||||||
SelectStatement(GeneratedDatabase database, this.table)
|
SelectStatement(GeneratedDatabase database, this.table)
|
||||||
|
|
|
@ -23,6 +23,7 @@ abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
|
||||||
|
|
||||||
class GeneratedTextColumn extends GeneratedColumn<String, StringType>
|
class GeneratedTextColumn extends GeneratedColumn<String, StringType>
|
||||||
implements TextColumn {
|
implements TextColumn {
|
||||||
|
@override
|
||||||
final String $name;
|
final String $name;
|
||||||
|
|
||||||
GeneratedTextColumn(this.$name);
|
GeneratedTextColumn(this.$name);
|
||||||
|
@ -34,6 +35,7 @@ class GeneratedTextColumn extends GeneratedColumn<String, StringType>
|
||||||
|
|
||||||
class GeneratedBoolColumn extends GeneratedColumn<bool, BoolType>
|
class GeneratedBoolColumn extends GeneratedColumn<bool, BoolType>
|
||||||
implements BoolColumn {
|
implements BoolColumn {
|
||||||
|
@override
|
||||||
final String $name;
|
final String $name;
|
||||||
|
|
||||||
GeneratedBoolColumn(this.$name);
|
GeneratedBoolColumn(this.$name);
|
||||||
|
@ -48,6 +50,7 @@ class GeneratedBoolColumn extends GeneratedColumn<bool, BoolType>
|
||||||
|
|
||||||
class GeneratedIntColumn extends GeneratedColumn<int, IntType>
|
class GeneratedIntColumn extends GeneratedColumn<int, IntType>
|
||||||
implements IntColumn {
|
implements IntColumn {
|
||||||
|
@override
|
||||||
final String $name;
|
final String $name;
|
||||||
|
|
||||||
GeneratedIntColumn(this.$name);
|
GeneratedIntColumn(this.$name);
|
||||||
|
|
|
@ -19,13 +19,16 @@ class GeneratedUsersTable extends Users with TableInfo<Users, UserDataObject> {
|
||||||
|
|
||||||
GeneratedUsersTable(this.db);
|
GeneratedUsersTable(this.db);
|
||||||
|
|
||||||
IntColumn id = GeneratedIntColumn("id");
|
@override
|
||||||
TextColumn name = GeneratedTextColumn("name");
|
IntColumn id = GeneratedIntColumn('id');
|
||||||
BoolColumn isAwesome = GeneratedBoolColumn("is_awesome");
|
@override
|
||||||
|
TextColumn name = GeneratedTextColumn('name');
|
||||||
|
@override
|
||||||
|
BoolColumn isAwesome = GeneratedBoolColumn('is_awesome');
|
||||||
@override
|
@override
|
||||||
List<Column<dynamic, SqlType>> get $columns => [id, name, isAwesome];
|
List<Column<dynamic, SqlType>> get $columns => [id, name, isAwesome];
|
||||||
@override
|
@override
|
||||||
String get $tableName => "users";
|
String get $tableName => 'users';
|
||||||
@override
|
@override
|
||||||
Users get asDslTable => this;
|
Users get asDslTable => this;
|
||||||
@override
|
@override
|
||||||
|
@ -36,7 +39,7 @@ class GeneratedUsersTable extends Users with TableInfo<Users, UserDataObject> {
|
||||||
|
|
||||||
class TestDatabase extends GeneratedDatabase {
|
class TestDatabase extends GeneratedDatabase {
|
||||||
TestDatabase(QueryExecutor executor)
|
TestDatabase(QueryExecutor executor)
|
||||||
: super(SqlTypeSystem.withDefaults(), executor);
|
: super(const SqlTypeSystem.withDefaults(), executor);
|
||||||
|
|
||||||
GeneratedUsersTable get users => GeneratedUsersTable(this);
|
GeneratedUsersTable get users => GeneratedUsersTable(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,40 +17,40 @@ void main() {
|
||||||
when(executor.runSelect(any, any)).thenAnswer((_) => Future.value([]));
|
when(executor.runSelect(any, any)).thenAnswer((_) => Future.value([]));
|
||||||
});
|
});
|
||||||
|
|
||||||
group("Generates SELECT statements", () {
|
group('Generates SELECT statements', () {
|
||||||
test("generates simple statements", () {
|
test('generates simple statements', () {
|
||||||
db.select(db.users).get();
|
db.select(db.users).get();
|
||||||
verify(executor.runSelect("SELECT * FROM users;", argThat(isEmpty)));
|
verify(executor.runSelect('SELECT * FROM users;', argThat(isEmpty)));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("generates limit statements", () {
|
test('generates limit statements', () {
|
||||||
(db.select(db.users)..limit(10)).get();
|
(db.select(db.users)..limit(10)).get();
|
||||||
verify(executor.runSelect(
|
verify(executor.runSelect(
|
||||||
"SELECT * FROM users LIMIT 10;", argThat(isEmpty)));
|
'SELECT * FROM users LIMIT 10;', argThat(isEmpty)));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("generates like expressions", () {
|
test('generates like expressions', () {
|
||||||
(db.select(db.users)..where((u) => u.name.like("Dash%"))).get();
|
(db.select(db.users)..where((u) => u.name.like('Dash%'))).get();
|
||||||
verify(executor
|
verify(executor
|
||||||
.runSelect("SELECT * FROM users WHERE name LIKE ?;", ["Dash%"]));
|
.runSelect('SELECT * FROM users WHERE name LIKE ?;', ['Dash%']));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("generates complex predicates", () {
|
test('generates complex predicates', () {
|
||||||
(db.select(db.users)
|
(db.select(db.users)
|
||||||
..where((u) =>
|
..where((u) =>
|
||||||
and(not(u.name.equalsVal("Dash")), (u.id.isBiggerThan(12)))))
|
and(not(u.name.equalsVal('Dash')), (u.id.isBiggerThan(12)))))
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
verify(executor.runSelect(
|
verify(executor.runSelect(
|
||||||
"SELECT * FROM users WHERE (NOT name = ?) AND (id > ?);",
|
'SELECT * FROM users WHERE (NOT name = ?) AND (id > ?);',
|
||||||
["Dash", 12]));
|
['Dash', 12]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("generates expressions from boolean fields", () {
|
test('generates expressions from boolean fields', () {
|
||||||
(db.select(db.users)..where((u) => u.isAwesome)).get();
|
(db.select(db.users)..where((u) => u.isAwesome)).get();
|
||||||
|
|
||||||
verify(executor.runSelect(
|
verify(executor.runSelect(
|
||||||
"SELECT * FROM users WHERE (is_awesome = 1);", argThat(isEmpty)));
|
'SELECT * FROM users WHERE (is_awesome = 1);', argThat(isEmpty)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../analysis_options.yaml
|
|
@ -3,4 +3,4 @@ import 'package:source_gen/source_gen.dart';
|
||||||
import 'package:sally_generator/src/sally_generator.dart';
|
import 'package:sally_generator/src/sally_generator.dart';
|
||||||
|
|
||||||
Builder sallyBuilder(BuilderOptions _) =>
|
Builder sallyBuilder(BuilderOptions _) =>
|
||||||
new SharedPartBuilder([SallyGenerator()], "sally");
|
SharedPartBuilder([SallyGenerator()], 'sally');
|
||||||
|
|
|
@ -6,7 +6,7 @@ class SallyError {
|
||||||
final Element affectedElement;
|
final Element affectedElement;
|
||||||
|
|
||||||
SallyError(
|
SallyError(
|
||||||
{this.critical = false, this.message, this.affectedElement = null});
|
{this.critical = false, this.message, this.affectedElement});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ErrorStore {
|
class ErrorStore {
|
||||||
|
|
|
@ -54,6 +54,9 @@ class AutoIncrement extends ColumnFeature {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(other) => other is AutoIncrement;
|
bool operator ==(other) => other is AutoIncrement;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 1337420;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class LimitingTextLength extends ColumnFeature
|
abstract class LimitingTextLength extends ColumnFeature
|
||||||
|
|
|
@ -4,22 +4,22 @@ import 'package:sally_generator/src/model/specified_column.dart';
|
||||||
import 'package:sally_generator/src/parser/parser.dart';
|
import 'package:sally_generator/src/parser/parser.dart';
|
||||||
import 'package:sally_generator/src/sally_generator.dart';
|
import 'package:sally_generator/src/sally_generator.dart';
|
||||||
|
|
||||||
const String startInt = "integer";
|
const String startInt = 'integer';
|
||||||
const String startString = "text";
|
const String startString = 'text';
|
||||||
const String startBool = "boolean";
|
const String startBool = 'boolean';
|
||||||
|
|
||||||
// todo replace with set literal once dart supports it
|
// todo replace with set literal once dart supports it
|
||||||
final Set<String> starters = [startInt, startString, startBool].toSet();
|
final Set<String> starters = [startInt, startString, startBool].toSet();
|
||||||
|
|
||||||
const String functionNamed = "named";
|
const String functionNamed = 'named';
|
||||||
const String functionPrimaryKey = "primaryKey";
|
const String functionPrimaryKey = 'primaryKey';
|
||||||
const String functionReferences = "references";
|
const String functionReferences = 'references';
|
||||||
const String functionAutoIncrement = "autoIncrement";
|
const String functionAutoIncrement = 'autoIncrement';
|
||||||
const String functionWithLength = "withLength";
|
const String functionWithLength = 'withLength';
|
||||||
|
|
||||||
const String errorMessage = "This getter does not create a valid column that "
|
const String errorMessage = 'This getter does not create a valid column that '
|
||||||
"can be parsed by sally. Please refer to the readme from sally to see how "
|
'can be parsed by sally. Please refer to the readme from sally to see how '
|
||||||
"columns are formed. If you have any questions, feel free to raise an issue.";
|
'columns are formed. If you have any questions, feel free to raise an issue.';
|
||||||
|
|
||||||
class ColumnParser extends ParserBase {
|
class ColumnParser extends ParserBase {
|
||||||
ColumnParser(SallyGenerator generator) : super(generator);
|
ColumnParser(SallyGenerator generator) : super(generator);
|
||||||
|
@ -51,9 +51,9 @@ class ColumnParser extends ParserBase {
|
||||||
|
|
||||||
String foundStartMethod;
|
String foundStartMethod;
|
||||||
String foundExplicitName;
|
String foundExplicitName;
|
||||||
bool wasDeclaredAsPrimaryKey = false;
|
var wasDeclaredAsPrimaryKey = false;
|
||||||
// todo parse reference
|
// todo parse reference
|
||||||
List<ColumnFeature> foundFeatures = [];
|
final foundFeatures = <ColumnFeature>[];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
final methodName = remainingExpr.methodName.name;
|
final methodName = remainingExpr.methodName.name;
|
||||||
|
@ -71,7 +71,7 @@ class ColumnParser extends ParserBase {
|
||||||
affectedElement: getter.declaredElement,
|
affectedElement: getter.declaredElement,
|
||||||
message:
|
message:
|
||||||
"You're setting more than one name here, the first will "
|
"You're setting more than one name here, the first will "
|
||||||
"be used"));
|
'be used'));
|
||||||
}
|
}
|
||||||
|
|
||||||
foundExplicitName =
|
foundExplicitName =
|
||||||
|
@ -80,8 +80,8 @@ class ColumnParser extends ParserBase {
|
||||||
critical: false,
|
critical: false,
|
||||||
affectedElement: getter.declaredElement,
|
affectedElement: getter.declaredElement,
|
||||||
message:
|
message:
|
||||||
"This table name is cannot be resolved! Please only use "
|
'This table name is cannot be resolved! Please only use '
|
||||||
"a constant string as parameter for .named()."));
|
'a constant string as parameter for .named().'));
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case functionPrimaryKey:
|
case functionPrimaryKey:
|
||||||
|
@ -91,8 +91,8 @@ class ColumnParser extends ParserBase {
|
||||||
break; // todo: parsing this is going to suck
|
break; // todo: parsing this is going to suck
|
||||||
case functionWithLength:
|
case functionWithLength:
|
||||||
final args = remainingExpr.argumentList;
|
final args = remainingExpr.argumentList;
|
||||||
final minArg = findNamedArgument(args, "min");
|
final minArg = findNamedArgument(args, 'min');
|
||||||
final maxArg = findNamedArgument(args, "max");
|
final maxArg = findNamedArgument(args, 'max');
|
||||||
|
|
||||||
foundFeatures.add(LimitingTextLength.withLength(
|
foundFeatures.add(LimitingTextLength.withLength(
|
||||||
min: readIntLiteral(minArg, () {}),
|
min: readIntLiteral(minArg, () {}),
|
||||||
|
|
|
@ -22,7 +22,7 @@ class ParserBase {
|
||||||
affectedElement: method.declaredElement,
|
affectedElement: method.declaredElement,
|
||||||
critical: true,
|
critical: true,
|
||||||
message:
|
message:
|
||||||
"This method must have an expression body (use => instead of {return ...})"));
|
'This method must have an expression body (use => instead of {return ...})'));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class ParserBase {
|
||||||
if (!(expression is StringLiteral)) {
|
if (!(expression is StringLiteral)) {
|
||||||
onError();
|
onError();
|
||||||
} else {
|
} else {
|
||||||
String value = (expression as StringLiteral).stringValue;
|
final value = (expression as StringLiteral).stringValue;
|
||||||
if (value == null)
|
if (value == null)
|
||||||
onError();
|
onError();
|
||||||
else
|
else
|
||||||
|
@ -46,6 +46,7 @@ class ParserBase {
|
||||||
int readIntLiteral(Expression expression, void onError()) {
|
int readIntLiteral(Expression expression, void onError()) {
|
||||||
if (!(expression is IntegerLiteral)) {
|
if (!(expression is IntegerLiteral)) {
|
||||||
onError();
|
onError();
|
||||||
|
// ignore: avoid_returning_null
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return (expression as IntegerLiteral).value;
|
return (expression as IntegerLiteral).value;
|
||||||
|
|
|
@ -12,19 +12,19 @@ class TableParser extends ParserBase {
|
||||||
TableParser(SallyGenerator generator) : super(generator);
|
TableParser(SallyGenerator generator) : super(generator);
|
||||||
|
|
||||||
SpecifiedTable parse(ClassElement element) {
|
SpecifiedTable parse(ClassElement element) {
|
||||||
String sqlName = _parseTableName(element);
|
final sqlName = _parseTableName(element);
|
||||||
|
|
||||||
return SpecifiedTable(
|
return SpecifiedTable(
|
||||||
fromClass: element,
|
fromClass: element,
|
||||||
columns: _parseColumns(element),
|
columns: _parseColumns(element),
|
||||||
sqlName: sqlName,
|
sqlName: sqlName,
|
||||||
dartTypeName:
|
dartTypeName:
|
||||||
"${element.name}_Data" // TODO better name for generated data classes
|
'${element.name}_Data' // TODO better name for generated data classes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _parseTableName(ClassElement element) {
|
String _parseTableName(ClassElement element) {
|
||||||
final tableNameGetter = element.getGetter("tableName");
|
final tableNameGetter = element.getGetter('tableName');
|
||||||
if (tableNameGetter == null) {
|
if (tableNameGetter == null) {
|
||||||
// class does not override tableName. So just use the dart class name
|
// class does not override tableName. So just use the dart class name
|
||||||
// instead. Will use placed_orders for a class called PlacedOrders
|
// instead. Will use placed_orders for a class called PlacedOrders
|
||||||
|
@ -38,11 +38,11 @@ class TableParser extends ParserBase {
|
||||||
final returnExpr = returnExpressionOfMethod(
|
final returnExpr = returnExpressionOfMethod(
|
||||||
tableNameDeclaration.node as MethodDeclaration);
|
tableNameDeclaration.node as MethodDeclaration);
|
||||||
|
|
||||||
String tableName = readStringLiteral(returnExpr, () {
|
final tableName = readStringLiteral(returnExpr, () {
|
||||||
generator.errors.add(SallyError(
|
generator.errors.add(SallyError(
|
||||||
critical: true,
|
critical: true,
|
||||||
message:
|
message:
|
||||||
"This getter must return a string literal, and do nothing more",
|
'This getter must return a string literal, and do nothing more',
|
||||||
affectedElement: tableNameGetter));
|
affectedElement: tableNameGetter));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ import 'package:sally_generator/src/parser/table_parser.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
|
||||||
class SallyGenerator extends Generator {
|
class SallyGenerator extends Generator {
|
||||||
Map<String, ParsedLibraryResult> _astForLibs = Map();
|
final Map<String, ParsedLibraryResult> _astForLibs = {};
|
||||||
ErrorStore errors = ErrorStore();
|
final ErrorStore errors = ErrorStore();
|
||||||
|
|
||||||
TableParser tableParser;
|
TableParser tableParser;
|
||||||
ColumnParser columnParser;
|
ColumnParser columnParser;
|
||||||
|
@ -25,12 +25,12 @@ class SallyGenerator extends Generator {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String generate(LibraryReader library, BuildStep buildStep) {
|
String generate(LibraryReader library, BuildStep buildStep) {
|
||||||
final testUsers = library.findType("Users");
|
final testUsers = library.findType('Users');
|
||||||
|
|
||||||
if (testUsers == null) return "";
|
if (testUsers == null) return '';
|
||||||
|
|
||||||
TableParser(this).parse(testUsers);
|
TableParser(this).parse(testUsers);
|
||||||
|
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import 'package:analyzer/dart/element/type.dart';
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
|
|
||||||
bool isFromSally(DartType type) {
|
bool isFromSally(DartType type) {
|
||||||
return type.element.library.location.components.first.contains("sally");
|
return type.element.library.location.components.first.contains('sally');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isColumn(DartType type) {
|
bool isColumn(DartType type) {
|
||||||
return isFromSally(type) && type.name.contains("Column");
|
return isFromSally(type) && type.name.contains('Column');
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ void main() async {
|
||||||
@override
|
@override
|
||||||
String get tableName => constructTableName();"
|
String get tableName => constructTableName();"
|
||||||
}
|
}
|
||||||
''', (r) => r.findLibraryByName("test_parser"));
|
''', (r) => r.findLibraryByName('test_parser'));
|
||||||
});
|
});
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
|
@ -44,57 +44,57 @@ void main() async {
|
||||||
generator.columnParser = ColumnParser(generator);
|
generator.columnParser = ColumnParser(generator);
|
||||||
});
|
});
|
||||||
|
|
||||||
group("SQL table name", () {
|
group('SQL table name', () {
|
||||||
test("should parse correctly when valid", () {
|
test('should parse correctly when valid', () {
|
||||||
expect(
|
expect(
|
||||||
TableParser(generator)
|
TableParser(generator)
|
||||||
.parse(testLib.getType("TableWithCustomName"))
|
.parse(testLib.getType('TableWithCustomName'))
|
||||||
.sqlName,
|
.sqlName,
|
||||||
equals("my-fancy-table"));
|
equals('my-fancy-table'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should use class name if table name is not specified", () {
|
test('should use class name if table name is not specified', () {
|
||||||
expect(TableParser(generator).parse(testLib.getType("Users")).sqlName,
|
expect(TableParser(generator).parse(testLib.getType('Users')).sqlName,
|
||||||
equals("users"));
|
equals('users'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should not parse for complex methods", () async {
|
test('should not parse for complex methods', () async {
|
||||||
TableParser(generator).parse(testLib.getType("WrongName"));
|
TableParser(generator).parse(testLib.getType('WrongName'));
|
||||||
|
|
||||||
expect(generator.errors.errors, isNotEmpty);
|
expect(generator.errors.errors, isNotEmpty);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group("Columns", () {
|
group('Columns', () {
|
||||||
test("should use field name if no name has been set explicitely", () {
|
test('should use field name if no name has been set explicitely', () {
|
||||||
final table = TableParser(generator).parse(testLib.getType("Users"));
|
final table = TableParser(generator).parse(testLib.getType('Users'));
|
||||||
final idColumn =
|
final idColumn =
|
||||||
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')));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should use explicit name, if it exists", () {
|
test('should use explicit name, if it exists', () {
|
||||||
final table = TableParser(generator).parse(testLib.getType("Users"));
|
final table = TableParser(generator).parse(testLib.getType('Users'));
|
||||||
final idColumn =
|
final idColumn =
|
||||||
table.columns.singleWhere((col) => col.name.name == "user_name");
|
table.columns.singleWhere((col) => col.name.name == 'user_name');
|
||||||
|
|
||||||
expect(idColumn.name, equals(ColumnName.explicitly("user_name")));
|
expect(idColumn.name, equals(ColumnName.explicitly('user_name')));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should parse min and max length for text columns", () {
|
test('should parse min and max length for text columns', () {
|
||||||
final table = TableParser(generator).parse(testLib.getType("Users"));
|
final table = TableParser(generator).parse(testLib.getType('Users'));
|
||||||
final idColumn =
|
final idColumn =
|
||||||
table.columns.singleWhere((col) => col.name.name == "user_name");
|
table.columns.singleWhere((col) => col.name.name == 'user_name');
|
||||||
|
|
||||||
expect(idColumn.features,
|
expect(idColumn.features,
|
||||||
contains(LimitingTextLength.withLength(min: 6, max: 32)));
|
contains(LimitingTextLength.withLength(min: 6, max: 32)));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should only parse max length when relevant", () {
|
test('should only parse max length when relevant', () {
|
||||||
final table = TableParser(generator).parse(testLib.getType("Users"));
|
final table = TableParser(generator).parse(testLib.getType('Users'));
|
||||||
final idColumn =
|
final idColumn =
|
||||||
table.columns.singleWhere((col) => col.name.name == "onlyMax");
|
table.columns.singleWhere((col) => col.name.name == 'onlyMax');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
idColumn.features, contains(LimitingTextLength.withLength(max: 100)));
|
idColumn.features, contains(LimitingTextLength.withLength(max: 100)));
|
||||||
|
|
Loading…
Reference in New Issue