Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion packages/language-server/src/plugins/PluginHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import {
TextEdit,
WorkspaceEdit,
InlayHint,
WorkspaceSymbol
WorkspaceSymbol,
DocumentSymbol
} from 'vscode-languageserver';
import { DocumentManager, getNodeIfIsInHTMLStartTag } from '../lib/documents';
import { Logger } from '../logger';
Expand Down Expand Up @@ -307,6 +308,7 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
if (cancellationToken.isCancellationRequested) {
return [];
}

return flatten(
await this.execute<SymbolInformation[]>(
'getDocumentSymbols',
Expand All @@ -317,6 +319,63 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
);
}

private comparePosition(pos1: Position, pos2: Position) {
if (pos1.line < pos2.line) return -1;
if (pos1.line > pos2.line) return 1;
if (pos1.character < pos2.character) return -1;
if (pos1.character > pos2.character) return 1;
return 0;
}

private rangeContains(parent: Range, child: Range) {
return (
this.comparePosition(parent.start, child.start) <= 0 &&
this.comparePosition(child.end, parent.end) <= 0
);
}

async getHierarchicalDocumentSymbols(
textDocument: TextDocumentIdentifier,
cancellationToken: CancellationToken
): Promise<DocumentSymbol[]> {
const flat = await this.getDocumentSymbols(textDocument, cancellationToken);
const symbols = flat
.map((s) =>
DocumentSymbol.create(
s.name,
undefined,
s.kind,
s.location.range,
s.location.range,
[]
)
)
.sort((a, b) => {
const start = this.comparePosition(a.range.start, b.range.start);
if (start !== 0) return start;
return this.comparePosition(b.range.end, a.range.end);
});

const stack: DocumentSymbol[] = [];
const roots: DocumentSymbol[] = [];

for (const node of symbols) {
while (stack.length > 0 && !this.rangeContains(stack.at(-1)!.range, node.range)) {
stack.pop();
}

if (stack.length > 0) {
stack.at(-1)!.children!.push(node);
} else {
roots.push(node);
}

stack.push(node);
}

return roots;
}

async getDefinitions(
textDocument: TextDocumentIdentifier,
position: Position
Expand Down
13 changes: 10 additions & 3 deletions packages/language-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,16 @@ export function startServer(options?: LSOptions) {
connection.onColorPresentation((evt) =>
pluginHost.getColorPresentations(evt.textDocument, evt.range, evt.color)
);
connection.onDocumentSymbol((evt, cancellationToken) =>
pluginHost.getDocumentSymbols(evt.textDocument, cancellationToken)
);
connection.onDocumentSymbol((evt, cancellationToken) => {
if (
configManager.getClientCapabilities()?.textDocument?.documentSymbol
?.hierarchicalDocumentSymbolSupport
) {
return pluginHost.getHierarchicalDocumentSymbols(evt.textDocument, cancellationToken);
} else {
return pluginHost.getDocumentSymbols(evt.textDocument, cancellationToken);
}
});
connection.onDefinition((evt) => pluginHost.getDefinitions(evt.textDocument, evt.position));
connection.onReferences((evt, cancellationToken) =>
pluginHost.findReferences(evt.textDocument, evt.position, evt.context, cancellationToken)
Expand Down