Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hover provider for crossrefs #473

Merged
merged 8 commits into from
Apr 25, 2022
4 changes: 2 additions & 2 deletions packages/langium/src/default-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { DefaultDocumentHighlighter } from './lsp/document-highlighter';
import { DefaultDocumentSymbolProvider } from './lsp/document-symbol-provider';
import { DefaultFoldingRangeProvider } from './lsp/folding-range-provider';
import { DefaultGoToResolverProvider } from './lsp/goto';
import { MultilineCommentHoverProvider } from './lsp/hover-provider';
import { LangiumGrammarHoverProvider } from './lsp/langium-grammar-hover-provider';
import { DefaultReferenceFinder } from './lsp/reference-finder';
import { DefaultRenameHandler } from './lsp/rename-refactoring';
import { createLangiumParser } from './parser/langium-parser-builder';
Expand Down Expand Up @@ -62,7 +62,7 @@ export function createDefaultModule(context: DefaultModuleContext): Module<Langi
RuleInterpreter: () => new RuleInterpreter()
},
DocumentSymbolProvider: (services) => new DefaultDocumentSymbolProvider(services),
HoverProvider: (services) => new MultilineCommentHoverProvider(services),
HoverProvider: (services) => new LangiumGrammarHoverProvider(services),
gfontorbe marked this conversation as resolved.
Show resolved Hide resolved
FoldingRangeProvider: (services) => new DefaultFoldingRangeProvider(services),
ReferenceFinder: (services) => new DefaultReferenceFinder(services),
GoToResolver: (services) => new DefaultGoToResolverProvider(services),
Expand Down
74 changes: 74 additions & 0 deletions packages/langium/src/lsp/langium-grammar-hover-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/******************************************************************************
* Copyright 2021 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
msujew marked this conversation as resolved.
Show resolved Hide resolved
import { Hover, HoverParams } from 'vscode-languageserver';
import {CrossReference, findLeafNodeAtOffset, findNameAssignment, Grammar, isCrossReference, isParserRule, isType, LangiumDocuments, LangiumServices, RuleCall } from '..';
import { AstNode } from '../syntax-tree';
import { findRelevantNode } from '../utils/cst-util';
import { MaybePromise } from '../utils/promise-util';
import { LangiumDocument } from '../workspace/documents';
import { MultilineCommentHoverProvider } from './hover-provider';

export class LangiumGrammarHoverProvider extends MultilineCommentHoverProvider {

readonly grammar: Grammar;
readonly documents: LangiumDocuments;
constructor(services: LangiumServices) {
super(services);
this.grammar = services.Grammar;
this.documents = services.shared.workspace.LangiumDocuments;
}

getHoverContent(document: LangiumDocument<AstNode>, params: HoverParams): MaybePromise<Hover | undefined> {
const rootNode = document.parseResult?.value?.$cstNode;
if(rootNode) {
const offset = document.textDocument.offsetAt(params.position);
const cstNode = findLeafNodeAtOffset(rootNode, offset);
if(cstNode){
const relevantNode = findRelevantNode(cstNode);
if(isCrossReference(relevantNode)){
return this.getCrossReferenceHoverContent(relevantNode);
} else {
return super.getHoverContent(document, params);
}
}
}
return undefined;
}
msujew marked this conversation as resolved.
Show resolved Hide resolved

getCrossReferenceHoverContent(node: CrossReference): MaybePromise<Hover | undefined> {

const ref = node.type.ref;

if(ref){
if(isType(ref)){
msujew marked this conversation as resolved.
Show resolved Hide resolved
return {
contents: {
kind: 'markdown',
value: ref.$cstNode!.text
gfontorbe marked this conversation as resolved.
Show resolved Hide resolved
}
};
}
else if(isParserRule(ref)){
let terminal;
gfontorbe marked this conversation as resolved.
Show resolved Hide resolved
if(node.$cstNode?.text.includes(':')){
terminal = node.$cstNode?.text.split(':')[1].replace(']', '');
gfontorbe marked this conversation as resolved.
Show resolved Hide resolved
} else {
terminal = (findNameAssignment(ref)?.terminal as RuleCall).rule.$refText;
}

return {
contents: {
kind: 'markdown',
value: `[${ref.name}:${terminal}]`,
},
};
}
}

return undefined;
}

}