Plugin: Navigation for column references in queries

This commit is contained in:
Simon Binder 2019-09-28 22:24:40 +02:00
parent b9f934c1d4
commit d91c69493f
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
3 changed files with 58 additions and 13 deletions

View File

@ -1,6 +1,9 @@
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/column_declaration.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:source_span/source_span.dart';
import 'package:sqlparser/sqlparser.dart';
class MoorNavigationContributor implements NavigationContributor {
@ -24,6 +27,13 @@ class _NavigationVisitor extends RecursiveVisitor<void> {
_NavigationVisitor(this.request, this.collector);
void _reportForSpan(SourceSpan span, ElementKind kind, Location target) {
final offset = span.start.offset;
final length = span.end.offset - offset;
collector.addRegion(offset, length, kind, target);
}
@override
void visitMoorImportStatement(ImportStatement e) {
if (request.isMoorAndParsed) {
@ -32,15 +42,32 @@ class _NavigationVisitor extends RecursiveVisitor<void> {
if (resolved != null) {
final span = e.importString.span;
final offset = span.start.offset;
final length = span.end.offset - offset;
_reportForSpan(
span, ElementKind.FILE, Location(resolved.uri.path, 0, 0, 1, 1));
}
}
collector.addRegion(
offset,
length,
ElementKind.FILE,
Location(resolved.uri.path, 0, 0, 1, 1),
);
super.visitChildren(e);
}
@override
void visitReference(Reference e) {
if (request.isMoorAndAnalyzed) {
final resolved = e.resolved;
if (resolved is Column) {
// if we know the declaration because the file was analyzed - use that
final declaration = resolved.meta<ColumnDeclaration>();
if (declaration != null) {
final location = locationOfDeclaration(declaration);
_reportForSpan(e.span, ElementKind.FIELD, location);
} else if (declaration is ExpressionColumn) {
// expression references don't have an explicit declaration, but they
// reference an expression that we can target
final expr = (declaration as ExpressionColumn).expression;
final target = locationOfNode(request.file, expr);
_reportForSpan(e.span, ElementKind.LOCAL_VARIABLE, target);
}
}
}

View File

@ -13,6 +13,7 @@ mixin _MoorBaseRequest {
bool get isMoor => file.type == FileType.moor;
bool get isMoorAndParsed => isMoor && file.isParsed;
bool get isMoorAndAnalyzed => isMoor && file.isAnalyzed;
String get path => file.uri.path;

View File

@ -1,12 +1,13 @@
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/sql_queries/meta/column_declaration.dart';
import 'package:source_gen/source_gen.dart' show spanForElement;
import 'package:source_span/source_span.dart';
import 'package:sqlparser/sqlparser.dart';
Location locationOfNode(FoundFile file, AstNode node) {
if (!node.hasSpan) return null;
final first = node.first.span.start;
final last = node.last.span.end;
Location _locationForSpan(SourceSpan span, FoundFile file) {
final first = span.start;
final last = span.end;
// in [Location], lines and columns are one-indexed, but in [SourceLocation]
// they're 0-based.
@ -18,3 +19,19 @@ Location locationOfNode(FoundFile file, AstNode node) {
first.column + 1,
);
}
Location locationOfNode(FoundFile file, AstNode node) {
if (!node.hasSpan) return null;
return _locationForSpan(node.span, file);
}
Location locationOfDeclaration(ColumnDeclaration 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);
}
return null;
}