From 16bc11540b0ed2799ff74a2434a5549015084250 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Wed, 8 Sep 2021 23:20:45 +0200 Subject: [PATCH] Introduce single visitor method for moor-specific nodes --- .../analyzer/sql_queries/lints/linter.dart | 10 ++ .../src/backends/plugin/services/folding.dart | 8 + .../backends/plugin/services/navigation.dart | 8 + .../src/backends/plugin/services/outline.dart | 9 +- .../lib/src/services/ide/highlights.dart | 28 ++-- .../lib/src/writer/queries/sql_writer.dart | 57 +++---- .../src/analysis/types/resolving_visitor.dart | 4 +- .../lib/src/ast/moor/declared_statement.dart | 6 +- .../lib/src/ast/moor/import_statement.dart | 2 +- sqlparser/lib/src/ast/moor/inline_dart.dart | 4 +- sqlparser/lib/src/ast/moor/moor_file.dart | 13 +- .../ast/moor/nested_star_result_column.dart | 5 +- sqlparser/lib/src/ast/visitor.dart | 41 +----- sqlparser/lib/src/utils/ast_equality.dart | 24 ++- sqlparser/lib/utils/node_to_text.dart | 139 ++++++++---------- 15 files changed, 180 insertions(+), 178 deletions(-) diff --git a/moor_generator/lib/src/analyzer/sql_queries/lints/linter.dart b/moor_generator/lib/src/analyzer/sql_queries/lints/linter.dart index 8973cbc1..72863eac 100644 --- a/moor_generator/lib/src/analyzer/sql_queries/lints/linter.dart +++ b/moor_generator/lib/src/analyzer/sql_queries/lints/linter.dart @@ -78,6 +78,16 @@ class _LintingVisitor extends RecursiveVisitor { } @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 diff --git a/moor_generator/lib/src/backends/plugin/services/folding.dart b/moor_generator/lib/src/backends/plugin/services/folding.dart index 96dd3401..26641eb2 100644 --- a/moor_generator/lib/src/backends/plugin/services/folding.dart +++ b/moor_generator/lib/src/backends/plugin/services/folding.dart @@ -25,6 +25,14 @@ class _FoldingVisitor extends RecursiveVisitor { _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(); diff --git a/moor_generator/lib/src/backends/plugin/services/navigation.dart b/moor_generator/lib/src/backends/plugin/services/navigation.dart index c7d12a49..6c95ed0d 100644 --- a/moor_generator/lib/src/backends/plugin/services/navigation.dart +++ b/moor_generator/lib/src/backends/plugin/services/navigation.dart @@ -42,6 +42,14 @@ class _NavigationVisitor extends RecursiveVisitor { } @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; diff --git a/moor_generator/lib/src/backends/plugin/services/outline.dart b/moor_generator/lib/src/backends/plugin/services/outline.dart index e020b654..adb67a54 100644 --- a/moor_generator/lib/src/backends/plugin/services/outline.dart +++ b/moor_generator/lib/src/backends/plugin/services/outline.dart @@ -77,13 +77,20 @@ class _OutlineVisitor extends RecursiveVisitor { } @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); diff --git a/moor_generator/lib/src/services/ide/highlights.dart b/moor_generator/lib/src/services/ide/highlights.dart index d5c66a14..09837ffd 100644 --- a/moor_generator/lib/src/services/ide/highlights.dart +++ b/moor_generator/lib/src/services/ide/highlights.dart @@ -147,20 +147,22 @@ class _HighlightingVisitor extends RecursiveVisitor { } @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); diff --git a/moor_generator/lib/src/writer/queries/sql_writer.dart b/moor_generator/lib/src/writer/queries/sql_writer.dart index 264abc06..d902532e 100644 --- a/moor_generator/lib/src/writer/queries/sql_writer.dart +++ b/moor_generator/lib/src/writer/queries/sql_writer.dart @@ -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); } } diff --git a/sqlparser/lib/src/analysis/types/resolving_visitor.dart b/sqlparser/lib/src/analysis/types/resolving_visitor.dart index 584a14d9..fd807b1b 100644 --- a/sqlparser/lib/src/analysis/types/resolving_visitor.dart +++ b/sqlparser/lib/src/analysis/types/resolving_visitor.dart @@ -171,11 +171,11 @@ class TypeResolver extends RecursiveVisitor { } @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); } } diff --git a/sqlparser/lib/src/ast/moor/declared_statement.dart b/sqlparser/lib/src/ast/moor/declared_statement.dart index 2a9269fd..7266cbab 100644 --- a/sqlparser/lib/src/ast/moor/declared_statement.dart +++ b/sqlparser/lib/src/ast/moor/declared_statement.dart @@ -28,7 +28,7 @@ class DeclaredStatement extends Statement implements PartOfMoorFile { @override R accept(AstVisitor 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(AstVisitor visitor, A arg) { - return visitor.visitMoorStatementParameter(this, arg); + return visitor.visitMoorSpecificNode(this, arg); } } diff --git a/sqlparser/lib/src/ast/moor/import_statement.dart b/sqlparser/lib/src/ast/moor/import_statement.dart index 890cdc99..7b6ec9f6 100644 --- a/sqlparser/lib/src/ast/moor/import_statement.dart +++ b/sqlparser/lib/src/ast/moor/import_statement.dart @@ -14,7 +14,7 @@ class ImportStatement extends Statement implements PartOfMoorFile { @override R accept(AstVisitor visitor, A arg) { - return visitor.visitMoorImportStatement(this, arg); + return visitor.visitMoorSpecificNode(this, arg); } @override diff --git a/sqlparser/lib/src/ast/moor/inline_dart.dart b/sqlparser/lib/src/ast/moor/inline_dart.dart index 81f17097..065d3ad9 100644 --- a/sqlparser/lib/src/ast/moor/inline_dart.dart +++ b/sqlparser/lib/src/ast/moor/inline_dart.dart @@ -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(AstVisitor visitor, A arg) { - return visitor.visitDartPlaceholder(this, arg); + return visitor.visitMoorSpecificNode(this, arg); } T? when({ diff --git a/sqlparser/lib/src/ast/moor/moor_file.dart b/sqlparser/lib/src/ast/moor/moor_file.dart index 2b6a7075..1ddd5859 100644 --- a/sqlparser/lib/src/ast/moor/moor_file.dart +++ b/sqlparser/lib/src/ast/moor/moor_file.dart @@ -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 statements; MoorFile(this.statements); @override R accept(AstVisitor visitor, A arg) { - return visitor.visitMoorFile(this, arg); + return visitor.visitMoorSpecificNode(this, arg); } @override @@ -34,7 +37,7 @@ class MoorFile extends AstNode { childNodes.whereType(); } -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(AstVisitor visitor, A arg) { - return visitor.visitMoorTableName(this, arg); + return visitor.visitMoorSpecificNode(this, arg); } @override diff --git a/sqlparser/lib/src/ast/moor/nested_star_result_column.dart b/sqlparser/lib/src/ast/moor/nested_star_result_column.dart index a9658280..f9bd1711 100644 --- a/sqlparser/lib/src/ast/moor/nested_star_result_column.dart +++ b/sqlparser/lib/src/ast/moor/nested_star_result_column.dart @@ -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(AstVisitor visitor, A arg) { - return visitor.visitMoorNestedStarResultColumn(this, arg); + return visitor.visitMoorSpecificNode(this, arg); } } diff --git a/sqlparser/lib/src/ast/visitor.dart b/sqlparser/lib/src/ast/visitor.dart index 51434ba2..d41a8f10 100644 --- a/sqlparser/lib/src/ast/visitor.dart +++ b/sqlparser/lib/src/ast/visitor.dart @@ -93,13 +93,7 @@ abstract class AstVisitor { 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 implements AstVisitor { 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 implements AstVisitor { 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); } diff --git a/sqlparser/lib/src/utils/ast_equality.dart b/sqlparser/lib/src/utils/ast_equality.dart index 05f6eda9..284095fa 100644 --- a/sqlparser/lib/src/utils/ast_equality.dart +++ b/sqlparser/lib/src/utils/ast_equality.dart @@ -228,7 +228,6 @@ class EqualityEnforcingVisitor implements AstVisitor { _checkChildren(e); } - @override void visitDartPlaceholder(DartPlaceholder e, void arg) { final current = _currentAs(e); _assert(current.name == e.name && current.runtimeType == e.runtimeType, e); @@ -413,27 +412,23 @@ class EqualityEnforcingVisitor implements AstVisitor { _checkChildren(e); } - @override void visitMoorDeclaredStatement(DeclaredStatement e, void arg) { final current = _currentAs(e); _assert(current.identifier == e.identifier && current.as == e.as, e); _checkChildren(e); } - @override void visitMoorFile(MoorFile e, void arg) { _currentAs(e); _checkChildren(e); } - @override void visitMoorImportStatement(ImportStatement e, void arg) { final current = _currentAs(e); _assert(current.importedFile == e.importedFile, e); _checkChildren(e); } - @override void visitMoorNestedStarResultColumn(NestedStarResultColumn e, void arg) { final current = _currentAs(e); _assert(current.tableName == e.tableName, e); @@ -441,6 +436,24 @@ class EqualityEnforcingVisitor implements AstVisitor { } @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(e); @@ -457,7 +470,6 @@ class EqualityEnforcingVisitor implements AstVisitor { _checkChildren(e); } - @override void visitMoorTableName(MoorTableName e, void arg) { final current = _currentAs(e); _assert( diff --git a/sqlparser/lib/utils/node_to_text.dart b/sqlparser/lib/utils/node_to_text.dart index b4bff023..2f62c8ac 100644 --- a/sqlparser/lib/utils/node_to_text.dart +++ b/sqlparser/lib/utils/node_to_text.dart @@ -397,9 +397,69 @@ class NodeSqlBuilder extends AstVisitor { } @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 { } } - @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