Skip to content

Commit f82721c

Browse files
committed
Go to definition
1 parent d5eeca2 commit f82721c

File tree

8 files changed

+973
-20
lines changed

8 files changed

+973
-20
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'package:lsp_server/lsp_server.dart' as lsp;
2+
import 'package:sass_language_services/sass_language_services.dart';
3+
import 'package:sass_language_services/src/features/node_at_offset_visitor.dart';
4+
5+
import '../language_feature.dart';
6+
7+
class GoToDefinitionFeature extends LanguageFeature {
8+
GoToDefinitionFeature({required super.ls});
9+
10+
/// Find the definition of whatever is at [position] in [document] if possible.
11+
///
12+
/// At the end of this method we want to end up with two values:
13+
///
14+
/// 1. The URI of the document containing the definition.
15+
/// 2. The selectionRange (or "nameRange") of the definition.
16+
///
17+
/// To get that we compare the symbol at [position] in [document] with all
18+
/// symbols in all other documents.
19+
///
20+
/// In order to support prefixes, show and hide we use links to traverse
21+
/// the workspace from [document]. If we find no match that way we fall
22+
/// back to "@import-style" and check all documents in the workspace for
23+
/// a match.
24+
Future<lsp.Location?> findDefinition(
25+
TextDocument document, lsp.Position position) async {
26+
var stylesheet = ls.parseStylesheet(document);
27+
28+
29+
var offset = document.offsetAt(position);
30+
var nodeAtOffset = stylesheet.accept(NodeAtOffsetVisitor(offset));
31+
32+
var definition = findInWorkspace<lsp.Location>(
33+
lazy: true,
34+
initialDocument: document,
35+
callback: ({
36+
required TextDocument document,
37+
required String prefix,
38+
required List<String> hiddenMixinsAndFunctions,
39+
required List<String> hiddenVariables,
40+
required List<String> shownMixinsAndFunctions,
41+
required List<String> shownVariables,
42+
}) async {
43+
var symbols = ls.findDocumentSymbols(document);
44+
for (var symbol in symbols) {
45+
if (symbol.kind == lsp.SymbolKind.Class) {
46+
// Placeholder selectors are not prefixed the same way other symbols are.
47+
if (nodeAtOffset != null && nodeAtOffset.span)
48+
}
49+
}
50+
},
51+
);
52+
53+
// If we can't essentially do what we do in workspace symbols
54+
55+
// Remember to include upstream
56+
57+
return null;
58+
}
59+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'package:sass_api/sass_api.dart' as sass;
2+
3+
import '../document_symbols/document_symbols_visitor.dart';
4+
5+
class GoToDefinitionVisitor extends DocumentSymbolsVisitor {}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import 'scoped_document_symbol.dart';
2+
3+
class Scope {
4+
Scope? parent;
5+
final List<Scope> children = [];
6+
final int offset;
7+
final int length;
8+
9+
final _symbols = <ScopedDocumentSymbol>[];
10+
11+
Scope({required this.offset, required this.length});
12+
13+
void addChild(Scope scope) {
14+
children.add(scope);
15+
scope.setParent(scope);
16+
}
17+
18+
void setParent(Scope scope) {
19+
parent = scope;
20+
}
21+
22+
Scope? findScope({required int offset, int length = 0}) {
23+
if ((this.offset <= offset &&
24+
this.offset + this.length > offset + length) ||
25+
(this.offset == offset && this.length == length)) {
26+
return findInScope(offset: offset, length: length);
27+
}
28+
return null;
29+
}
30+
31+
Scope findInScope({required int offset, int length = 0}) {
32+
var limit = offset + length;
33+
var index = children.indexWhere((scope) => scope.offset > limit);
34+
if (index == 0) {
35+
return this;
36+
}
37+
38+
var childScope = children.elementAt(index - 1);
39+
var childScopeHasOffset = childScope.offset <= offset &&
40+
childScope.offset + childScope.length >= offset + length;
41+
42+
if (childScopeHasOffset) {
43+
return childScope.findInScope(offset: offset, length: length);
44+
}
45+
46+
return this;
47+
}
48+
49+
void addSymbol(ScopedDocumentSymbol symbol) {
50+
_symbols.add(symbol);
51+
}
52+
53+
ScopedDocumentSymbol? getSymbol(
54+
{required String name, required ReferenceKind referenceKind}) {
55+
for (var symbol in _symbols) {
56+
if (symbol.referenceKind == referenceKind && symbol.name == name) {
57+
return symbol;
58+
}
59+
}
60+
return null;
61+
}
62+
63+
List<ScopedDocumentSymbol> getSymbols() {
64+
return _symbols;
65+
}
66+
}

0 commit comments

Comments
 (0)