Introduce single visitor method for moor-specific nodes

This commit is contained in:
Simon Binder 2021-09-08 23:20:45 +02:00
parent 3be320d0c5
commit 16bc11540b
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
15 changed files with 180 additions and 178 deletions

View File

@ -78,6 +78,16 @@ class _LintingVisitor extends RecursiveVisitor<void, void> {
}
@override
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is DartPlaceholder) {
return visitDartPlaceholder(e, arg);
} else if (e is NestedStarResultColumn) {
return visitResultColumn(e, arg);
}
visitChildren(e, arg);
}
void visitDartPlaceholder(DartPlaceholder e, void arg) {
if (e is! DartExpressionPlaceholder) {
// Default values are supported for expressions only

View File

@ -25,6 +25,14 @@ class _FoldingVisitor extends RecursiveVisitor<void, void> {
_FoldingVisitor(this.collector);
@override
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is MoorFile) {
visitMoorFile(e, arg);
} else {
visitChildren(e, arg);
}
}
void visitMoorFile(MoorFile e, void arg) {
// construct a folding region for import statements
final imports = e.imports.toList();

View File

@ -42,6 +42,14 @@ class _NavigationVisitor extends RecursiveVisitor<void, void> {
}
@override
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is ImportStatement) {
return visitMoorImportStatement(e, arg);
}
visitChildren(e, arg);
}
void visitMoorImportStatement(ImportStatement e, void arg) {
if (request.isMoorAndParsed) {
final moor = request.parsedMoor;

View File

@ -77,13 +77,20 @@ class _OutlineVisitor extends RecursiveVisitor<void, void> {
}
@override
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is MoorFile) {
visitMoorFile(e, arg);
} else if (e is DeclaredStatement) {
visitMoorDeclaredStatement(e, arg);
}
}
void visitMoorFile(MoorFile e, void arg) {
_startElement(ElementKind.LIBRARY, request.file.shortName, e);
visitChildren(e, arg);
collector.endElement();
}
@override
void visitMoorDeclaredStatement(DeclaredStatement e, void arg) {
if (!e.isRegularQuery) {
visitChildren(e, arg);

View File

@ -147,20 +147,22 @@ class _HighlightingVisitor extends RecursiveVisitor<void, void> {
}
@override
void visitMoorDeclaredStatement(DeclaredStatement e, void arg) {
final identifier = e.identifier;
if (identifier is SimpleName && identifier.identifier != null) {
_contribute(identifier.identifier,
HighlightRegionType.TOP_LEVEL_FUNCTION_DECLARATION);
} else if (identifier is SpecialStatementIdentifier &&
identifier.nameToken != null) {
_contribute(identifier.nameToken, HighlightRegionType.ANNOTATION);
}
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is DeclaredStatement) {
final identifier = e.identifier;
if (identifier is SimpleName && identifier.identifier != null) {
_contribute(identifier.identifier,
HighlightRegionType.TOP_LEVEL_FUNCTION_DECLARATION);
} else if (identifier is SpecialStatementIdentifier &&
identifier.nameToken != null) {
_contribute(identifier.nameToken, HighlightRegionType.ANNOTATION);
}
if (e.parameters != null) {
isDeclaringVariables = true;
visitList(e.parameters, arg);
isDeclaringVariables = false;
if (e.parameters != null) {
isDeclaringVariables = true;
visitList(e.parameters, arg);
isDeclaringVariables = false;
}
}
visitChildren(e, arg);

View File

@ -71,14 +71,6 @@ class SqlWriter extends NodeSqlBuilder {
needsSpace = true;
}
@override
void visitDartPlaceholder(DartPlaceholder e, void arg) {
final moorPlaceholder =
query.placeholders.singleWhere((p) => p.astNode == e);
_writeRawInSpaces('\${${placeholderContextName(moorPlaceholder)}.sql}');
}
@override
void visitNamedVariable(ColonNamedVariable e, void arg) {
final moor = _findMoorVar(e);
@ -100,29 +92,38 @@ class SqlWriter extends NodeSqlBuilder {
}
@override
void visitMoorNestedStarResultColumn(NestedStarResultColumn e, void arg) {
final result = _starColumnToResolved[e];
if (result == null) {
return super.visitMoorNestedStarResultColumn(e, arg);
}
final select = query as SqlSelectQuery;
final prefix = select.resultSet.nestedPrefixFor(result);
final table = e.tableName;
// Convert foo.** to "foo.a" AS "nested_0.a", ... for all columns in foo
var isFirst = true;
for (final column in result.table.columns) {
if (isFirst) {
isFirst = false;
} else {
_out.write(', ');
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is NestedStarResultColumn) {
final result = _starColumnToResolved[e];
if (result == null) {
return super.visitMoorSpecificNode(e, arg);
}
final columnName = column.name.name;
_out.write('"$table"."$columnName" AS "$prefix.$columnName"');
final select = query as SqlSelectQuery;
final prefix = select.resultSet.nestedPrefixFor(result);
final table = e.tableName;
// Convert foo.** to "foo.a" AS "nested_0.a", ... for all columns in foo
var isFirst = true;
for (final column in result.table.columns) {
if (isFirst) {
isFirst = false;
} else {
_out.write(', ');
}
final columnName = column.name.name;
_out.write('"$table"."$columnName" AS "$prefix.$columnName"');
}
} else if (e is DartPlaceholder) {
final moorPlaceholder =
query.placeholders.singleWhere((p) => p.astNode == e);
_writeRawInSpaces('\${${placeholderContextName(moorPlaceholder)}.sql}');
}
return super.visitMoorSpecificNode(e, arg);
}
}

View File

@ -171,11 +171,11 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
}
@override
void visitDartPlaceholder(DartPlaceholder e, TypeExpectation arg) {
void visitMoorSpecificNode(MoorSpecificNode e, TypeExpectation arg) {
if (e is DartExpressionPlaceholder) {
_inferAsVariable(e, arg);
} else {
super.visitDartPlaceholder(e, arg);
super.visitMoorSpecificNode(e, arg);
}
}

View File

@ -28,7 +28,7 @@ class DeclaredStatement extends Statement implements PartOfMoorFile {
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorDeclaredStatement(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
@override
@ -95,10 +95,10 @@ class SpecialStatementIdentifier extends DeclaredStatementIdentifier {
/// identifier.
/// In `selectString(:name AS TEXT): SELECT :name`, `:name AS TEXT` is a
/// statement parameter.
abstract class StatementParameter extends AstNode {
abstract class StatementParameter extends AstNode implements MoorSpecificNode {
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorStatementParameter(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
}

View File

@ -14,7 +14,7 @@ class ImportStatement extends Statement implements PartOfMoorFile {
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorImportStatement(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
@override

View File

@ -16,7 +16,7 @@ import '../visitor.dart';
/// moor.
/// 4. A list of order-by clauses, which will be exposed as a `OrderBy` from
/// moor.
abstract class DartPlaceholder extends AstNode {
abstract class DartPlaceholder extends AstNode implements MoorSpecificNode {
final String name;
DollarSignVariableToken? token;
@ -31,7 +31,7 @@ abstract class DartPlaceholder extends AstNode {
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitDartPlaceholder(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
T? when<T>({

View File

@ -4,21 +4,24 @@ import '../visitor.dart';
import 'declared_statement.dart';
import 'import_statement.dart';
/// Marker interface for AST nodes that are moor-specific.
abstract class MoorSpecificNode implements AstNode {}
/// Something that can appear as a top-level declaration inside a `.moor` file.
abstract class PartOfMoorFile implements Statement {}
abstract class PartOfMoorFile implements Statement, MoorSpecificNode {}
/// A moor file.
///
/// A moor file consists of [ImportStatement], followed by ddl statements,
/// followed by [DeclaredStatement]s.
class MoorFile extends AstNode {
class MoorFile extends AstNode implements MoorSpecificNode {
List<PartOfMoorFile> statements;
MoorFile(this.statements);
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorFile(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
@override
@ -34,7 +37,7 @@ class MoorFile extends AstNode {
childNodes.whereType<ImportStatement>();
}
class MoorTableName extends AstNode {
class MoorTableName extends AstNode implements MoorSpecificNode {
final String overriddenDataClassName;
final bool useExistingDartClass;
@ -42,7 +45,7 @@ class MoorTableName extends AstNode {
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorTableName(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
@override

View File

@ -2,13 +2,14 @@ import '../../analysis/analysis.dart';
import '../ast.dart' show StarResultColumn, ResultColumn;
import '../node.dart';
import '../visitor.dart';
import 'moor_file.dart';
/// A nested star result column, denoted by `**` in user queries.
///
/// Nested star result columns behave similar to a regular [StarResultColumn]
/// when the query is actually run. However, they will affect generated code
/// when using moor.
class NestedStarResultColumn extends ResultColumn {
class NestedStarResultColumn extends ResultColumn implements MoorSpecificNode {
final String tableName;
ResultSet? resultSet;
@ -22,6 +23,6 @@ class NestedStarResultColumn extends ResultColumn {
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorNestedStarResultColumn(this, arg);
return visitor.visitMoorSpecificNode(this, arg);
}
}

View File

@ -93,13 +93,7 @@ abstract class AstVisitor<A, R> {
R visitBeginTransaction(BeginTransactionStatement e, A arg);
R visitCommitStatement(CommitStatement e, A arg);
R visitMoorFile(MoorFile e, A arg);
R visitMoorImportStatement(ImportStatement e, A arg);
R visitMoorDeclaredStatement(DeclaredStatement e, A arg);
R visitMoorStatementParameter(StatementParameter e, A arg);
R visitMoorNestedStarResultColumn(NestedStarResultColumn e, A arg);
R visitMoorTableName(MoorTableName e, A arg);
R visitDartPlaceholder(DartPlaceholder e, A arg);
R visitMoorSpecificNode(MoorSpecificNode e, A arg);
}
/// Visitor that walks down the entire tree, visiting all children in order.
@ -207,16 +201,6 @@ class RecursiveVisitor<A, R> implements AstVisitor<A, R?> {
return visitResultColumn(e, arg);
}
@override
R? visitMoorNestedStarResultColumn(NestedStarResultColumn e, A arg) {
return visitResultColumn(e, arg);
}
@override
R? visitMoorTableName(MoorTableName e, A arg) {
return defaultNode(e, arg);
}
@override
R? visitReturning(Returning e, A arg) {
return defaultNode(e, arg);
@ -403,29 +387,8 @@ class RecursiveVisitor<A, R> implements AstVisitor<A, R?> {
return visitStatement(e, arg);
}
// Moor-specific additions
@override
R? visitMoorFile(MoorFile e, A arg) {
return defaultNode(e, arg);
}
@override
R? visitMoorImportStatement(ImportStatement e, A arg) {
return visitStatement(e, arg);
}
@override
R? visitMoorDeclaredStatement(DeclaredStatement e, A arg) {
return visitStatement(e, arg);
}
@override
R? visitDartPlaceholder(DartPlaceholder e, A arg) {
return defaultNode(e, arg);
}
@override
R? visitMoorStatementParameter(StatementParameter e, A arg) {
R? visitMoorSpecificNode(MoorSpecificNode e, A arg) {
return defaultNode(e, arg);
}

View File

@ -228,7 +228,6 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
_checkChildren(e);
}
@override
void visitDartPlaceholder(DartPlaceholder e, void arg) {
final current = _currentAs<DartPlaceholder>(e);
_assert(current.name == e.name && current.runtimeType == e.runtimeType, e);
@ -413,27 +412,23 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
_checkChildren(e);
}
@override
void visitMoorDeclaredStatement(DeclaredStatement e, void arg) {
final current = _currentAs<DeclaredStatement>(e);
_assert(current.identifier == e.identifier && current.as == e.as, e);
_checkChildren(e);
}
@override
void visitMoorFile(MoorFile e, void arg) {
_currentAs<MoorFile>(e);
_checkChildren(e);
}
@override
void visitMoorImportStatement(ImportStatement e, void arg) {
final current = _currentAs<ImportStatement>(e);
_assert(current.importedFile == e.importedFile, e);
_checkChildren(e);
}
@override
void visitMoorNestedStarResultColumn(NestedStarResultColumn e, void arg) {
final current = _currentAs<NestedStarResultColumn>(e);
_assert(current.tableName == e.tableName, e);
@ -441,6 +436,24 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
}
@override
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is DartPlaceholder) {
return visitDartPlaceholder(e, arg);
} else if (e is DeclaredStatement) {
return visitMoorDeclaredStatement(e, arg);
} else if (e is MoorFile) {
return visitMoorFile(e, arg);
} else if (e is ImportStatement) {
return visitMoorImportStatement(e, arg);
} else if (e is NestedStarResultColumn) {
return visitMoorNestedStarResultColumn(e, arg);
} else if (e is StatementParameter) {
return visitMoorStatementParameter(e, arg);
} else if (e is MoorTableName) {
return visitMoorTableName(e, arg);
}
}
void visitMoorStatementParameter(StatementParameter e, void arg) {
if (e is VariableTypeHint) {
final current = _currentAs<VariableTypeHint>(e);
@ -457,7 +470,6 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
_checkChildren(e);
}
@override
void visitMoorTableName(MoorTableName e, void arg) {
final current = _currentAs<MoorTableName>(e);
_assert(

View File

@ -397,9 +397,69 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
}
@override
void visitDartPlaceholder(DartPlaceholder e, void arg) {
_symbol(r'$', spaceBefore: true);
_symbol(e.name, spaceAfter: true);
void visitMoorSpecificNode(MoorSpecificNode e, void arg) {
if (e is DartPlaceholder) {
_symbol(r'$', spaceBefore: true);
_symbol(e.name, spaceAfter: true);
} else if (e is DeclaredStatement) {
_identifier(e.identifier.name);
if (e.parameters.isNotEmpty) {
_symbol('(');
_join(e.parameters, ',');
_symbol(')');
}
if (e.as != null) {
_keyword(TokenType.as);
_identifier(e.as!);
}
_symbol(':', spaceAfter: true);
visit(e.statement, arg);
_symbol(';');
} else if (e is MoorFile) {
for (final stmt in e.statements) {
visit(stmt, arg);
buffer.write('\n');
needsSpace = false;
}
} else if (e is ImportStatement) {
_keyword(TokenType.import);
_stringLiteral(e.importedFile);
_symbol(';', spaceAfter: true);
} else if (e is NestedStarResultColumn) {
_identifier(e.tableName);
_symbol('.**', spaceAfter: true);
} else if (e is StatementParameter) {
if (e is VariableTypeHint) {
if (e.isRequired) _keyword(TokenType.required);
visit(e.variable, arg);
final typeName = e.typeName;
if (typeName != null) {
_keyword(TokenType.as);
_symbol(typeName, spaceBefore: true, spaceAfter: true);
}
if (e.orNull) {
_keyword(TokenType.or);
_keyword(TokenType.$null);
}
} else if (e is DartPlaceholderDefaultValue) {
_symbol('\$${e.variableName}', spaceAfter: true);
_symbol('=', spaceBefore: true, spaceAfter: true);
visit(e.defaultValue, arg);
} else {
throw AssertionError('Unknown StatementParameter: $e');
}
} else if (e is MoorTableName) {
_keyword(e.useExistingDartClass ? TokenType.$with : TokenType.as);
_identifier(e.overriddenDataClassName);
} else if (e is NestedStarResultColumn) {
_identifier(e.tableName);
_symbol('.**', spaceAfter: true);
}
}
@override
@ -755,79 +815,6 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
}
}
@override
void visitMoorDeclaredStatement(DeclaredStatement e, void arg) {
_identifier(e.identifier.name);
if (e.parameters.isNotEmpty) {
_symbol('(');
_join(e.parameters, ',');
_symbol(')');
}
if (e.as != null) {
_keyword(TokenType.as);
_identifier(e.as!);
}
_symbol(':', spaceAfter: true);
visit(e.statement, arg);
_symbol(';');
}
@override
void visitMoorFile(MoorFile e, void arg) {
for (final stmt in e.statements) {
visit(stmt, arg);
buffer.write('\n');
needsSpace = false;
}
}
@override
void visitMoorImportStatement(ImportStatement e, void arg) {
_keyword(TokenType.import);
_stringLiteral(e.importedFile);
_symbol(';', spaceAfter: true);
}
@override
void visitMoorNestedStarResultColumn(NestedStarResultColumn e, void arg) {
_identifier(e.tableName);
_symbol('.**', spaceAfter: true);
}
@override
void visitMoorStatementParameter(StatementParameter e, void arg) {
if (e is VariableTypeHint) {
if (e.isRequired) _keyword(TokenType.required);
visit(e.variable, arg);
final typeName = e.typeName;
if (typeName != null) {
_keyword(TokenType.as);
_symbol(typeName, spaceBefore: true, spaceAfter: true);
}
if (e.orNull) {
_keyword(TokenType.or);
_keyword(TokenType.$null);
}
} else if (e is DartPlaceholderDefaultValue) {
_symbol('\$${e.variableName}', spaceAfter: true);
_symbol('=', spaceBefore: true, spaceAfter: true);
visit(e.defaultValue, arg);
} else {
throw AssertionError('Unknown StatementParameter: $e');
}
}
@override
void visitMoorTableName(MoorTableName e, void arg) {
_keyword(e.useExistingDartClass ? TokenType.$with : TokenType.as);
_identifier(e.overriddenDataClassName);
}
@override
void visitNamedVariable(ColonNamedVariable e, void arg) {
// Note: The name already starts with the colon