+15
@@ -0,0 +1,15 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
import type { CallHierarchyIncomingCall, CallHierarchyOutgoingCall } from 'vscode-languageserver';
|
||||
import type { AstNode } from '../../syntax-tree.js';
|
||||
import type { Stream } from '../../utils/stream.js';
|
||||
import type { ReferenceDescription } from '../../workspace/ast-descriptions.js';
|
||||
import { AbstractCallHierarchyProvider } from '../../lsp/call-hierarchy-provider.js';
|
||||
export declare class LangiumGrammarCallHierarchyProvider extends AbstractCallHierarchyProvider {
|
||||
protected getIncomingCalls(node: AstNode, references: Stream<ReferenceDescription>): CallHierarchyIncomingCall[] | undefined;
|
||||
protected getOutgoingCalls(node: AstNode): CallHierarchyOutgoingCall[] | undefined;
|
||||
}
|
||||
//# sourceMappingURL=grammar-call-hierarchy.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-call-hierarchy.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-call-hierarchy.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,KAAK,EAAE,yBAAyB,EAAE,yBAAyB,EAAS,MAAM,uBAAuB,CAAC;AACzG,OAAO,KAAK,EAAE,OAAO,EAAW,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAEhF,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAKrF,qBAAa,mCAAoC,SAAQ,6BAA6B;IAElF,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,oBAAoB,CAAC,GAAG,yBAAyB,EAAE,GAAG,SAAS;IAiD5H,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,yBAAyB,EAAE,GAAG,SAAS;CAmErF"}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
import { SymbolKind } from 'vscode-languageserver';
|
||||
import { AbstractCallHierarchyProvider } from '../../lsp/call-hierarchy-provider.js';
|
||||
import { getContainerOfType, getDocument, streamAllContents } from '../../utils/ast-utils.js';
|
||||
import { findLeafNodeAtOffset } from '../../utils/cst-utils.js';
|
||||
import { isAbstractParserRule, isInfixRule, isParserRule, isRuleCall } from '../../languages/generated/ast.js';
|
||||
export class LangiumGrammarCallHierarchyProvider extends AbstractCallHierarchyProvider {
|
||||
getIncomingCalls(node, references) {
|
||||
if (!isAbstractParserRule(node)) {
|
||||
return undefined;
|
||||
}
|
||||
// This map is used to group incoming calls to avoid duplicates.
|
||||
const uniqueRules = new Map();
|
||||
references.forEach(ref => {
|
||||
const doc = this.documents.getDocument(ref.sourceUri);
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
const rootNode = doc.parseResult.value;
|
||||
if (!rootNode.$cstNode) {
|
||||
return;
|
||||
}
|
||||
const targetNode = findLeafNodeAtOffset(rootNode.$cstNode, ref.segment.offset);
|
||||
if (!targetNode) {
|
||||
return;
|
||||
}
|
||||
const parserRule = getContainerOfType(targetNode.astNode, isAbstractParserRule);
|
||||
if (!parserRule || !parserRule.$cstNode) {
|
||||
return;
|
||||
}
|
||||
const nameNode = this.nameProvider.getNameNode(parserRule);
|
||||
if (!nameNode) {
|
||||
return;
|
||||
}
|
||||
const refDocUri = ref.sourceUri.toString();
|
||||
const ruleId = refDocUri + '@' + nameNode.text;
|
||||
uniqueRules.has(ruleId) ?
|
||||
uniqueRules.set(ruleId, { parserRule: parserRule.$cstNode, nameNode, targetNodes: [...uniqueRules.get(ruleId).targetNodes, targetNode], docUri: refDocUri })
|
||||
: uniqueRules.set(ruleId, { parserRule: parserRule.$cstNode, nameNode, targetNodes: [targetNode], docUri: refDocUri });
|
||||
});
|
||||
if (uniqueRules.size === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return Array.from(uniqueRules.values()).map(rule => ({
|
||||
from: {
|
||||
kind: SymbolKind.Method,
|
||||
name: rule.nameNode.text,
|
||||
range: rule.parserRule.range,
|
||||
selectionRange: rule.nameNode.range,
|
||||
uri: rule.docUri
|
||||
},
|
||||
fromRanges: rule.targetNodes.map(node => node.range)
|
||||
}));
|
||||
}
|
||||
getOutgoingCalls(node) {
|
||||
if (isParserRule(node)) {
|
||||
const ruleCalls = streamAllContents(node).filter(isRuleCall).toArray();
|
||||
// This map is used to group outgoing calls to avoid duplicates.
|
||||
const uniqueRules = new Map();
|
||||
ruleCalls.forEach(ruleCall => {
|
||||
const cstNode = ruleCall.$cstNode;
|
||||
if (!cstNode) {
|
||||
return;
|
||||
}
|
||||
const refCstNode = ruleCall.rule.ref?.$cstNode;
|
||||
if (!refCstNode) {
|
||||
return;
|
||||
}
|
||||
const refNameNode = this.nameProvider.getNameNode(refCstNode.astNode);
|
||||
if (!refNameNode) {
|
||||
return;
|
||||
}
|
||||
const refDocUri = getDocument(refCstNode.astNode).uri.toString();
|
||||
const ruleId = refDocUri + '@' + refNameNode.text;
|
||||
uniqueRules.has(ruleId) ?
|
||||
uniqueRules.set(ruleId, { refCstNode: refCstNode, to: refNameNode, from: [...uniqueRules.get(ruleId).from, cstNode.range], docUri: refDocUri })
|
||||
: uniqueRules.set(ruleId, { refCstNode: refCstNode, to: refNameNode, from: [cstNode.range], docUri: refDocUri });
|
||||
});
|
||||
if (uniqueRules.size === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return Array.from(uniqueRules.values()).map(rule => ({
|
||||
to: {
|
||||
kind: SymbolKind.Method,
|
||||
name: rule.to.text,
|
||||
range: rule.refCstNode.range,
|
||||
selectionRange: rule.to.range,
|
||||
uri: rule.docUri
|
||||
},
|
||||
fromRanges: rule.from
|
||||
}));
|
||||
}
|
||||
else if (isInfixRule(node)) {
|
||||
const ruleCall = node.call;
|
||||
const cstNode = ruleCall.$cstNode;
|
||||
if (!cstNode) {
|
||||
return undefined;
|
||||
}
|
||||
const refCstNode = ruleCall.rule.ref?.$cstNode;
|
||||
if (!refCstNode) {
|
||||
return undefined;
|
||||
}
|
||||
const refNameNode = this.nameProvider.getNameNode(refCstNode.astNode);
|
||||
if (!refNameNode) {
|
||||
return undefined;
|
||||
}
|
||||
const refDocUri = getDocument(refCstNode.astNode).uri.toString();
|
||||
return [{
|
||||
to: {
|
||||
kind: SymbolKind.Method,
|
||||
name: refNameNode.text,
|
||||
range: refCstNode.range,
|
||||
selectionRange: refNameNode.range,
|
||||
uri: refDocUri
|
||||
},
|
||||
fromRanges: [cstNode.range]
|
||||
}];
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-call-hierarchy.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-call-hierarchy.js","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-call-hierarchy.ts"],"names":[],"mappings":"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"}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
import type { CodeActionParams } from 'vscode-languageserver-protocol';
|
||||
import type { CodeAction, Command } from 'vscode-languageserver-types';
|
||||
import * as ast from '../../languages/generated/ast.js';
|
||||
import type { CodeActionProvider } from '../../lsp/code-action.js';
|
||||
import type { LangiumServices } from '../../lsp/lsp-services.js';
|
||||
import type { AstReflection } from '../../syntax-tree.js';
|
||||
import type { MaybePromise } from '../../utils/promise-utils.js';
|
||||
import type { LangiumDocument } from '../../workspace/documents.js';
|
||||
import type { IndexManager } from '../../workspace/index-manager.js';
|
||||
export declare class LangiumGrammarCodeActionProvider implements CodeActionProvider {
|
||||
protected readonly reflection: AstReflection;
|
||||
protected readonly indexManager: IndexManager;
|
||||
constructor(services: LangiumServices);
|
||||
getCodeActions(document: LangiumDocument<ast.Grammar>, params: CodeActionParams): MaybePromise<Array<Command | CodeAction>>;
|
||||
private createCodeActions;
|
||||
/**
|
||||
* Adds missing returns for parser rule
|
||||
*/
|
||||
private fixMissingReturns;
|
||||
private fixInvalidReturnsInfers;
|
||||
private fixMissingInfer;
|
||||
private fixMissingCrossRefTerminal;
|
||||
private fixSuperfluousInfer;
|
||||
private isRuleReplaceable;
|
||||
private replaceRule;
|
||||
private isDefinitionReplaceable;
|
||||
private replaceDefinition;
|
||||
private replaceParserRuleByTypeDeclaration;
|
||||
private fixUnnecessaryFileExtension;
|
||||
private makeUpperCase;
|
||||
private addEntryKeyword;
|
||||
private fixRegexTokens;
|
||||
private fixCrossRefSyntax;
|
||||
private addNewRule;
|
||||
private lookInGlobalScope;
|
||||
}
|
||||
//# sourceMappingURL=grammar-code-actions.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-code-actions.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-code-actions.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAIhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAY,MAAM,6BAA6B,CAAC;AACjF,OAAO,KAAK,GAAG,MAAM,kCAAkC,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAA4B,MAAM,sBAAsB,CAAC;AAGpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAOjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE,qBAAa,gCAAiC,YAAW,kBAAkB;IAEvE,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;gBAElC,QAAQ,EAAE,eAAe;IAKrC,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,gBAAgB,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,CAAC;IAS3H,OAAO,CAAC,iBAAiB;IAmDzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,uBAAuB;IAqB/B,OAAO,CAAC,eAAe;IAuBvB,OAAO,CAAC,0BAA0B;IAwBlC,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kCAAkC;IA8B1C,OAAO,CAAC,2BAA2B;IAwBnC,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,cAAc;IA4BtB,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,UAAU;IA6BlB,OAAO,CAAC,iBAAiB;CA0E5B"}
|
||||
+458
@@ -0,0 +1,458 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
import { CodeActionKind } from 'vscode-languageserver';
|
||||
import * as ast from '../../languages/generated/ast.js';
|
||||
import { getContainerOfType } from '../../utils/ast-utils.js';
|
||||
import { findLeafNodeAtOffset } from '../../utils/cst-utils.js';
|
||||
import { escapeRegExp } from '../../utils/regexp-utils.js';
|
||||
import { UriUtils } from '../../utils/uri-utils.js';
|
||||
import { DocumentValidator } from '../../validation/document-validator.js';
|
||||
import { IssueCodes } from '../validation/validator.js';
|
||||
export class LangiumGrammarCodeActionProvider {
|
||||
constructor(services) {
|
||||
this.reflection = services.shared.AstReflection;
|
||||
this.indexManager = services.shared.workspace.IndexManager;
|
||||
}
|
||||
getCodeActions(document, params) {
|
||||
const result = [];
|
||||
const acceptor = (ca) => ca && result.push(ca);
|
||||
for (const diagnostic of params.context.diagnostics) {
|
||||
this.createCodeActions(diagnostic, document, acceptor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
createCodeActions(diagnostic, document, accept) {
|
||||
switch (diagnostic.data?.code) {
|
||||
case IssueCodes.GrammarNameUppercase:
|
||||
case IssueCodes.RuleNameUppercase:
|
||||
accept(this.makeUpperCase(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.UseRegexTokens:
|
||||
accept(this.fixRegexTokens(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.EntryRuleTokenSyntax:
|
||||
accept(this.addEntryKeyword(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.CrossRefTokenSyntax:
|
||||
accept(this.fixCrossRefSyntax(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.ParserRuleToTypeDecl:
|
||||
accept(this.replaceParserRuleByTypeDeclaration(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.UnnecessaryFileExtension:
|
||||
accept(this.fixUnnecessaryFileExtension(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.MissingReturns:
|
||||
accept(this.fixMissingReturns(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.InvalidInfers:
|
||||
case IssueCodes.InvalidReturns:
|
||||
accept(this.fixInvalidReturnsInfers(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.MissingInfer:
|
||||
accept(this.fixMissingInfer(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.MissingCrossRefTerminal:
|
||||
accept(this.fixMissingCrossRefTerminal(diagnostic, document));
|
||||
break;
|
||||
case IssueCodes.SuperfluousInfer:
|
||||
accept(this.fixSuperfluousInfer(diagnostic, document));
|
||||
break;
|
||||
case DocumentValidator.LinkingError: {
|
||||
const data = diagnostic.data;
|
||||
if (data && data.containerType === 'RuleCall' && data.property === 'rule') {
|
||||
accept(this.addNewRule(diagnostic, data, document));
|
||||
}
|
||||
if (data) {
|
||||
this.lookInGlobalScope(diagnostic, data, document).forEach(accept);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Adds missing returns for parser rule
|
||||
*/
|
||||
fixMissingReturns(diagnostic, document) {
|
||||
const text = document.textDocument.getText(diagnostic.range);
|
||||
if (text) {
|
||||
return {
|
||||
title: `Add explicit return type for parser rule ${text}`,
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: diagnostic.range,
|
||||
newText: `${text} returns ${text}` // suggestion adds missing 'return'
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
fixInvalidReturnsInfers(diagnostic, document) {
|
||||
const data = diagnostic.data;
|
||||
if (data && data.actionSegment) {
|
||||
const text = document.textDocument.getText(data.actionSegment.range);
|
||||
return {
|
||||
title: `Correct ${text} usage`,
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: data.actionSegment.range,
|
||||
newText: text === 'infers' ? 'returns' : 'infers'
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
fixMissingInfer(diagnostic, document) {
|
||||
const data = diagnostic.data;
|
||||
if (data && data.actionSegment) {
|
||||
return {
|
||||
title: "Correct 'infer' usage",
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: {
|
||||
start: data.actionSegment.range.end,
|
||||
end: data.actionSegment.range.end
|
||||
},
|
||||
newText: 'infer '
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
fixMissingCrossRefTerminal(diagnostic, document) {
|
||||
const grammar = document.parseResult.value;
|
||||
const idTerminal = grammar.rules.find(rule => ast.isTerminalRule(rule) && rule.name === 'ID');
|
||||
if (idTerminal) {
|
||||
return {
|
||||
title: 'Use ID token to resolve cross-reference',
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: {
|
||||
start: diagnostic.range.end,
|
||||
end: diagnostic.range.end
|
||||
},
|
||||
newText: ':ID'
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
fixSuperfluousInfer(diagnostic, document) {
|
||||
const data = diagnostic.data;
|
||||
if (data && data.actionRange) {
|
||||
return {
|
||||
title: "Remove the 'infer' keyword",
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: data.actionRange,
|
||||
newText: ''
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
isRuleReplaceable(rule) {
|
||||
/** at the moment, only "pure" parser rules are supported:
|
||||
* - supported are only Alternatives (recursively) and "infers"
|
||||
* - "returns" is not relevant, since cross-references would not refer to the parser rule, but to its "return type" instead
|
||||
*/
|
||||
return !rule.fragment && !rule.entry && rule.parameters.length === 0 && !rule.returnType && !rule.dataType;
|
||||
}
|
||||
replaceRule(rule) {
|
||||
const type = rule.inferredType ?? rule;
|
||||
return type.name;
|
||||
}
|
||||
isDefinitionReplaceable(node) {
|
||||
if (ast.isRuleCall(node)) {
|
||||
return node.arguments.length === 0 && ast.isParserRule(node.rule.ref) && this.isRuleReplaceable(node.rule.ref);
|
||||
}
|
||||
if (ast.isAlternatives(node)) {
|
||||
return node.elements.every(child => this.isDefinitionReplaceable(child));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
replaceDefinition(node) {
|
||||
if (ast.isRuleCall(node) && node.rule.ref) {
|
||||
return node.rule.ref.name;
|
||||
}
|
||||
if (ast.isAlternatives(node)) {
|
||||
return node.elements.map(child => this.replaceDefinition(child)).join(' | ');
|
||||
}
|
||||
throw new Error('missing code for ' + node);
|
||||
}
|
||||
replaceParserRuleByTypeDeclaration(diagnostic, document) {
|
||||
const rootCst = document.parseResult.value.$cstNode;
|
||||
if (rootCst) {
|
||||
const offset = document.textDocument.offsetAt(diagnostic.range.start);
|
||||
const cstNode = findLeafNodeAtOffset(rootCst, offset);
|
||||
const rule = getContainerOfType(cstNode?.astNode, ast.isParserRule);
|
||||
if (rule && rule.$cstNode) {
|
||||
const isReplaceable = this.isRuleReplaceable(rule) && this.isDefinitionReplaceable(rule.definition);
|
||||
if (isReplaceable) {
|
||||
const newText = `type ${this.replaceRule(rule)} = ${this.replaceDefinition(rule.definition)};`;
|
||||
return {
|
||||
title: 'Replace with type declaration',
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: true,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: diagnostic.range,
|
||||
newText
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
fixUnnecessaryFileExtension(diagnostic, document) {
|
||||
const end = { ...diagnostic.range.end };
|
||||
end.character -= 1;
|
||||
const start = { ...end };
|
||||
start.character -= '.langium'.length;
|
||||
return {
|
||||
title: 'Remove file extension',
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: true,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: {
|
||||
start,
|
||||
end
|
||||
},
|
||||
newText: ''
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
makeUpperCase(diagnostic, document) {
|
||||
const range = {
|
||||
start: diagnostic.range.start,
|
||||
end: {
|
||||
line: diagnostic.range.start.line,
|
||||
character: diagnostic.range.start.character + 1
|
||||
}
|
||||
};
|
||||
return {
|
||||
title: 'First letter to upper case',
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: true,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range,
|
||||
newText: document.textDocument.getText(range).toUpperCase()
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
addEntryKeyword(diagnostic, document) {
|
||||
return {
|
||||
title: 'Add entry keyword',
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: true,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: { start: diagnostic.range.start, end: diagnostic.range.start },
|
||||
newText: 'entry '
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
fixRegexTokens(diagnostic, document) {
|
||||
const offset = document.textDocument.offsetAt(diagnostic.range.start);
|
||||
const rootCst = document.parseResult.value.$cstNode;
|
||||
if (rootCst) {
|
||||
const cstNode = findLeafNodeAtOffset(rootCst, offset);
|
||||
const container = getContainerOfType(cstNode?.astNode, ast.isCharacterRange);
|
||||
if (container && container.right && container.$cstNode) {
|
||||
const left = container.left.value;
|
||||
const right = container.right.value;
|
||||
return {
|
||||
title: 'Refactor into regular expression',
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: true,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: container.$cstNode.range,
|
||||
newText: `/[${escapeRegExp(left)}-${escapeRegExp(right)}]/`
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
fixCrossRefSyntax(diagnostic, document) {
|
||||
return {
|
||||
title: "Replace '|' with ':'",
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: true,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: diagnostic.range,
|
||||
newText: ':'
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
addNewRule(diagnostic, data, document) {
|
||||
const offset = document.textDocument.offsetAt(diagnostic.range.start);
|
||||
const rootCst = document.parseResult.value.$cstNode;
|
||||
if (rootCst) {
|
||||
const cstNode = findLeafNodeAtOffset(rootCst, offset);
|
||||
const container = getContainerOfType(cstNode?.astNode, ast.isParserRule);
|
||||
if (container && container.$cstNode) {
|
||||
return {
|
||||
title: `Add new rule '${data.refText}'`,
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: false,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: {
|
||||
start: container.$cstNode.range.end,
|
||||
end: container.$cstNode.range.end
|
||||
},
|
||||
newText: '\n\n' + data.refText + ':\n /* TODO implement rule */ {infer ' + data.refText + '};'
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
lookInGlobalScope(diagnostic, data, document) {
|
||||
const refInfo = {
|
||||
container: {
|
||||
$type: data.containerType
|
||||
},
|
||||
property: data.property,
|
||||
reference: {
|
||||
$refText: data.refText
|
||||
}
|
||||
};
|
||||
const referenceType = this.reflection.getReferenceType(refInfo);
|
||||
const candidates = this.indexManager.allElements(referenceType).filter(e => e.name === data.refText);
|
||||
const result = [];
|
||||
let shortestPathIndex = -1;
|
||||
let shortestPathLength = -1;
|
||||
for (const candidate of candidates) {
|
||||
if (UriUtils.equals(candidate.documentUri, document.uri)) {
|
||||
continue;
|
||||
}
|
||||
// Find an import path and a position to insert the import
|
||||
const importPath = getRelativeImport(document.uri, candidate.documentUri);
|
||||
let position;
|
||||
let suffix = '';
|
||||
const grammar = document.parseResult.value;
|
||||
const nextImport = grammar.imports.find(imp => imp.path && importPath < imp.path);
|
||||
if (nextImport) {
|
||||
// Insert the new import alphabetically
|
||||
position = nextImport.$cstNode?.range.start;
|
||||
}
|
||||
else if (grammar.imports.length > 0) {
|
||||
// Put the new import after the last import
|
||||
const rangeEnd = grammar.imports[grammar.imports.length - 1].$cstNode.range.end;
|
||||
if (rangeEnd) {
|
||||
position = { line: rangeEnd.line + 1, character: 0 };
|
||||
}
|
||||
}
|
||||
else if (grammar.rules.length > 0) {
|
||||
// Put the new import before the first rule
|
||||
position = grammar.rules[0].$cstNode?.range.start;
|
||||
suffix = '\n';
|
||||
}
|
||||
if (position) {
|
||||
if (shortestPathIndex < 0 || importPath.length < shortestPathLength) {
|
||||
shortestPathIndex = result.length;
|
||||
shortestPathLength = importPath.length;
|
||||
}
|
||||
// Add an import declaration for the candidate in the global scope
|
||||
result.push({
|
||||
title: `Add import to '${importPath}'`,
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
isPreferred: false,
|
||||
edit: {
|
||||
changes: {
|
||||
[document.textDocument.uri]: [{
|
||||
range: {
|
||||
start: position,
|
||||
end: position
|
||||
},
|
||||
newText: `import '${importPath}'\n${suffix}`
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// Mark the code action with the shortest import path as preferred
|
||||
if (shortestPathIndex >= 0) {
|
||||
result[shortestPathIndex].isPreferred = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
function getRelativeImport(source, target) {
|
||||
const sourceDir = UriUtils.dirname(source);
|
||||
let relativePath = UriUtils.relative(sourceDir, target);
|
||||
if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {
|
||||
relativePath = './' + relativePath;
|
||||
}
|
||||
if (relativePath.endsWith('.langium')) {
|
||||
relativePath = relativePath.substring(0, relativePath.length - '.langium'.length);
|
||||
}
|
||||
return relativePath;
|
||||
}
|
||||
//# sourceMappingURL=grammar-code-actions.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+18
@@ -0,0 +1,18 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2023 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.
|
||||
******************************************************************************/
|
||||
import type { NextFeature } from '../../lsp/completion/follow-element-computation.js';
|
||||
import { DefaultCompletionProvider, type CompletionAcceptor, type CompletionContext } from '../../lsp/completion/completion-provider.js';
|
||||
import type { MaybePromise } from '../../utils/promise-utils.js';
|
||||
import type { AbstractElement } from '../../languages/generated/ast.js';
|
||||
import type { LangiumServices } from '../../lsp/lsp-services.js';
|
||||
export declare class LangiumGrammarCompletionProvider extends DefaultCompletionProvider {
|
||||
private readonly documents;
|
||||
constructor(services: LangiumServices);
|
||||
protected completionFor(context: CompletionContext, next: NextFeature<AbstractElement>, acceptor: CompletionAcceptor): MaybePromise<void>;
|
||||
private completeImportPath;
|
||||
private getAllFiles;
|
||||
}
|
||||
//# sourceMappingURL=grammar-completion-provider.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-completion-provider.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-completion-provider.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAIhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oDAAoD,CAAC;AACtF,OAAO,EAAE,yBAAyB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AACzI,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,qBAAa,gCAAiC,SAAQ,yBAAyB;IAE3E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;gBAEvC,QAAQ,EAAE,eAAe;cAKlB,aAAa,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,WAAW,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,kBAAkB,GAAG,YAAY,CAAC,IAAI,CAAC;IASlJ,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,WAAW;CAmBtB"}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2023 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.
|
||||
******************************************************************************/
|
||||
import { CompletionItemKind } from 'vscode-languageserver-types';
|
||||
import { DefaultCompletionProvider } from '../../lsp/completion/completion-provider.js';
|
||||
import { getContainerOfType } from '../../utils/ast-utils.js';
|
||||
import { isAssignment } from '../../languages/generated/ast.js';
|
||||
import { UriUtils } from '../../utils/uri-utils.js';
|
||||
export class LangiumGrammarCompletionProvider extends DefaultCompletionProvider {
|
||||
constructor(services) {
|
||||
super(services);
|
||||
this.documents = () => services.shared.workspace.LangiumDocuments;
|
||||
}
|
||||
completionFor(context, next, acceptor) {
|
||||
const assignment = getContainerOfType(next.feature, isAssignment);
|
||||
if (assignment?.feature === 'path') {
|
||||
this.completeImportPath(context, acceptor);
|
||||
}
|
||||
else {
|
||||
return super.completionFor(context, next, acceptor);
|
||||
}
|
||||
}
|
||||
completeImportPath(context, acceptor) {
|
||||
const text = context.textDocument.getText();
|
||||
const existingText = text.substring(context.tokenOffset, context.offset);
|
||||
let allPaths = this.getAllFiles(context.document);
|
||||
let range = {
|
||||
start: context.position,
|
||||
end: context.position
|
||||
};
|
||||
if (existingText.length > 0) {
|
||||
const existingPath = existingText.substring(1);
|
||||
allPaths = allPaths.filter(path => path.startsWith(existingPath));
|
||||
// Completely replace the current token
|
||||
const start = context.textDocument.positionAt(context.tokenOffset + 1);
|
||||
const end = context.textDocument.positionAt(context.tokenEndOffset - 1);
|
||||
range = {
|
||||
start,
|
||||
end
|
||||
};
|
||||
}
|
||||
for (const path of allPaths) {
|
||||
// Only insert quotes if there is no `path` token yet.
|
||||
const delimiter = existingText.length > 0 ? '' : '"';
|
||||
const completionValue = `${delimiter}${path}${delimiter}`;
|
||||
acceptor(context, {
|
||||
label: path,
|
||||
textEdit: {
|
||||
newText: completionValue,
|
||||
range
|
||||
},
|
||||
kind: CompletionItemKind.File,
|
||||
sortText: '0'
|
||||
});
|
||||
}
|
||||
}
|
||||
getAllFiles(document) {
|
||||
const documents = this.documents().all;
|
||||
const uri = document.uri.toString();
|
||||
const dirname = UriUtils.dirname(document.uri).toString();
|
||||
const paths = [];
|
||||
for (const doc of documents) {
|
||||
if (!UriUtils.equals(doc.uri, uri)) {
|
||||
const docUri = doc.uri.toString();
|
||||
const uriWithoutExt = docUri.substring(0, docUri.length - UriUtils.extname(doc.uri).length);
|
||||
let relativePath = UriUtils.relative(dirname, uriWithoutExt);
|
||||
if (!relativePath.startsWith('.')) {
|
||||
relativePath = `./${relativePath}`;
|
||||
}
|
||||
paths.push(relativePath);
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-completion-provider.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-completion-provider.js","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-completion-provider.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAGhF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEjE,OAAO,EAAE,yBAAyB,EAAmD,MAAM,6CAA6C,CAAC;AAEzI,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD,MAAM,OAAO,gCAAiC,SAAQ,yBAAyB;IAI3E,YAAY,QAAyB;QACjC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC;IACtE,CAAC;IAEkB,aAAa,CAAC,OAA0B,EAAE,IAAkC,EAAE,QAA4B;QACzH,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAClE,IAAI,UAAU,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACJ,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,CAAC;IACL,CAAC;IAEO,kBAAkB,CAAC,OAA0B,EAAE,QAA4B;QAC/E,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACzE,IAAI,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,KAAK,GAAU;YACf,KAAK,EAAE,OAAO,CAAC,QAAQ;YACvB,GAAG,EAAE,OAAO,CAAC,QAAQ;SACxB,CAAC;QACF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC/C,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;YAClE,uCAAuC;YACvC,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;YACvE,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;YACxE,KAAK,GAAG;gBACJ,KAAK;gBACL,GAAG;aACN,CAAC;QACN,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,sDAAsD;YACtD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACrD,MAAM,eAAe,GAAG,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,EAAE,CAAC;YAC1D,QAAQ,CAAC,OAAO,EAAE;gBACd,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE;oBACN,OAAO,EAAE,eAAe;oBACxB,KAAK;iBACR;gBACD,IAAI,EAAE,kBAAkB,CAAC,IAAI;gBAC7B,QAAQ,EAAE,GAAG;aAChB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAEO,WAAW,CAAC,QAAyB;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC;QACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAClC,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;gBAC5F,IAAI,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;gBAC7D,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChC,YAAY,GAAG,KAAK,YAAY,EAAE,CAAC;gBACvC,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7B,CAAC;QACL,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;CAEJ"}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2022 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.
|
||||
******************************************************************************/
|
||||
import type { DefinitionParams } from 'vscode-languageserver';
|
||||
import type { LangiumServices } from '../../lsp/lsp-services.js';
|
||||
import type { AstNode, LeafCstNode } from '../../syntax-tree.js';
|
||||
import type { MaybePromise } from '../../utils/promise-utils.js';
|
||||
import type { LangiumDocuments } from '../../workspace/documents.js';
|
||||
import type { Grammar } from '../../languages/generated/ast.js';
|
||||
import { LocationLink } from 'vscode-languageserver';
|
||||
import { DefaultDefinitionProvider } from '../../lsp/index.js';
|
||||
export declare class LangiumGrammarDefinitionProvider extends DefaultDefinitionProvider {
|
||||
protected documents: LangiumDocuments;
|
||||
constructor(services: LangiumServices);
|
||||
protected collectLocationLinks(sourceCstNode: LeafCstNode, _params: DefinitionParams): MaybePromise<LocationLink[] | undefined>;
|
||||
protected findTargetObject(importedGrammar: Grammar): AstNode | undefined;
|
||||
}
|
||||
//# sourceMappingURL=grammar-definition.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-definition.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-definition.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAc,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAS,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAM/D,qBAAa,gCAAiC,SAAQ,yBAAyB;IAE3E,SAAS,CAAC,SAAS,EAAE,gBAAgB,CAAC;gBAE1B,QAAQ,EAAE,eAAe;cAKlB,oBAAoB,CAAC,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,GAAG,YAAY,CAAC,YAAY,EAAE,GAAG,SAAS,CAAC;IAsBxI,SAAS,CAAC,gBAAgB,CAAC,eAAe,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS;CAO5E"}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2022 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.
|
||||
******************************************************************************/
|
||||
import { LocationLink, Range } from 'vscode-languageserver';
|
||||
import { DefaultDefinitionProvider } from '../../lsp/index.js';
|
||||
import { streamContents } from '../../utils/ast-utils.js';
|
||||
import { findAssignment } from '../../utils/grammar-utils.js';
|
||||
import { isGrammarImport } from '../../languages/generated/ast.js';
|
||||
import { resolveImport } from '../internal-grammar-util.js';
|
||||
export class LangiumGrammarDefinitionProvider extends DefaultDefinitionProvider {
|
||||
constructor(services) {
|
||||
super(services);
|
||||
this.documents = services.shared.workspace.LangiumDocuments;
|
||||
}
|
||||
collectLocationLinks(sourceCstNode, _params) {
|
||||
const pathFeature = 'path';
|
||||
if (isGrammarImport(sourceCstNode.astNode) && findAssignment(sourceCstNode)?.feature === pathFeature) {
|
||||
const importedGrammar = resolveImport(this.documents, sourceCstNode.astNode);
|
||||
if (importedGrammar?.$document) {
|
||||
const targetObject = this.findTargetObject(importedGrammar) ?? importedGrammar;
|
||||
const selectionRange = this.nameProvider.getNameNode(targetObject)?.range ?? Range.create(0, 0, 0, 0);
|
||||
const previewRange = targetObject.$cstNode?.range ?? Range.create(0, 0, 0, 0);
|
||||
return [
|
||||
LocationLink.create(importedGrammar.$document.uri.toString(), previewRange, selectionRange, sourceCstNode.range)
|
||||
];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return super.collectLocationLinks(sourceCstNode, _params);
|
||||
}
|
||||
findTargetObject(importedGrammar) {
|
||||
// Jump to grammar name or the first element
|
||||
if (importedGrammar.isDeclared) {
|
||||
return importedGrammar;
|
||||
}
|
||||
return streamContents(importedGrammar).head();
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-definition.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-definition.js","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-definition.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAQhF,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,OAAO,gCAAiC,SAAQ,yBAAyB;IAI3E,YAAY,QAAyB;QACjC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC;IAChE,CAAC;IAEkB,oBAAoB,CAAC,aAA0B,EAAE,OAAyB;QACzF,MAAM,WAAW,GAA8B,MAAM,CAAC;QACtD,IAAI,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,aAAa,CAAC,EAAE,OAAO,KAAK,WAAW,EAAE,CAAC;YACnG,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;YAC7E,IAAI,eAAe,EAAE,SAAS,EAAE,CAAC;gBAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,IAAI,eAAe,CAAC;gBAC/E,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtG,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC9E,OAAO;oBACH,YAAY,CAAC,MAAM,CACf,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,EACxC,YAAY,EACZ,cAAc,EACd,aAAa,CAAC,KAAK,CACtB;iBACJ,CAAC;YACN,CAAC;YACD,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,OAAO,KAAK,CAAC,oBAAoB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAES,gBAAgB,CAAC,eAAwB;QAC/C,4CAA4C;QAC5C,IAAI,eAAe,CAAC,UAAU,EAAE,CAAC;YAC7B,OAAO,eAAe,CAAC;QAC3B,CAAC;QACD,OAAO,cAAc,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,CAAC;CACJ"}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
import type { AstNode } from '../../syntax-tree.js';
|
||||
import { DefaultFoldingRangeProvider } from '../../lsp/folding-range-provider.js';
|
||||
/**
|
||||
* A specialized folding range provider for the grammar language
|
||||
*/
|
||||
export declare class LangiumGrammarFoldingRangeProvider extends DefaultFoldingRangeProvider {
|
||||
shouldProcessContent(node: AstNode): boolean;
|
||||
}
|
||||
//# sourceMappingURL=grammar-folding-ranges.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-folding-ranges.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-folding-ranges.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAGlF;;GAEG;AACH,qBAAa,kCAAmC,SAAQ,2BAA2B;IAEtE,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;CAIxD"}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
import { DefaultFoldingRangeProvider } from '../../lsp/folding-range-provider.js';
|
||||
import { isParserRule } from '../../languages/generated/ast.js';
|
||||
/**
|
||||
* A specialized folding range provider for the grammar language
|
||||
*/
|
||||
export class LangiumGrammarFoldingRangeProvider extends DefaultFoldingRangeProvider {
|
||||
shouldProcessContent(node) {
|
||||
// Exclude parser rules from folding
|
||||
return !isParserRule(node);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-folding-ranges.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-folding-ranges.js","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-folding-ranges.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAGhF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAEhE;;GAEG;AACH,MAAM,OAAO,kCAAmC,SAAQ,2BAA2B;IAEtE,oBAAoB,CAAC,IAAa;QACvC,oCAAoC;QACpC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;CACJ"}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2022 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.
|
||||
******************************************************************************/
|
||||
import type { AstNode } from '../../syntax-tree.js';
|
||||
import { AbstractFormatter } from '../../lsp/formatter.js';
|
||||
export declare class LangiumGrammarFormatter extends AbstractFormatter {
|
||||
protected format(node: AstNode): void;
|
||||
}
|
||||
//# sourceMappingURL=grammar-formatter.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-formatter.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-formatter.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAc,MAAM,wBAAwB,CAAC;AAKvE,qBAAa,uBAAwB,SAAQ,iBAAiB;IAE1D,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CA0FxC"}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2022 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.
|
||||
******************************************************************************/
|
||||
import { AbstractFormatter, Formatting } from '../../lsp/formatter.js';
|
||||
import * as ast from '../../languages/generated/ast.js';
|
||||
const indentOrSpace = Formatting.fit(Formatting.oneSpace(), Formatting.indent());
|
||||
export class LangiumGrammarFormatter extends AbstractFormatter {
|
||||
format(node) {
|
||||
if (ast.isCrossReference(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.properties('type', 'terminal').surround(Formatting.noSpace());
|
||||
}
|
||||
else if (ast.isParserRule(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keywords('entry', 'fragment', 'returns').append(Formatting.oneSpace());
|
||||
if ((node.inferredType || node.returnType || node.dataType) && node.parameters.length === 0) {
|
||||
formatter.property('name').append(Formatting.oneSpace());
|
||||
}
|
||||
else {
|
||||
formatter.property('name').append(Formatting.noSpace());
|
||||
}
|
||||
formatter.properties('parameters').append(Formatting.noSpace());
|
||||
formatter.keywords(',').append(Formatting.oneSpace());
|
||||
formatter.keywords('<').append(Formatting.noSpace());
|
||||
const semicolon = formatter.keyword(';');
|
||||
const colon = formatter.keyword(':');
|
||||
colon.prepend(Formatting.noSpace());
|
||||
formatter.interior(colon, semicolon).prepend(Formatting.indent());
|
||||
semicolon.prepend(Formatting.fit(Formatting.noSpace(), Formatting.newLine()));
|
||||
formatter.node(node).prepend(Formatting.noIndent());
|
||||
}
|
||||
else if (ast.isTerminalRule(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
if (node.type) {
|
||||
formatter.property('name').append(Formatting.oneSpace());
|
||||
formatter.keyword('returns').append(Formatting.oneSpace());
|
||||
}
|
||||
formatter.keywords('hidden', 'terminal', 'fragment').append(Formatting.oneSpace());
|
||||
formatter.keyword(':').prepend(Formatting.noSpace());
|
||||
formatter.keyword(';').prepend(Formatting.fit(Formatting.noSpace(), Formatting.newLine()));
|
||||
formatter.node(node).prepend(Formatting.noIndent());
|
||||
}
|
||||
else if (ast.isAction(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keyword('{').append(Formatting.noSpace());
|
||||
formatter.keywords('.', '+=', '=').surround(Formatting.noSpace());
|
||||
formatter.keyword('}').prepend(Formatting.noSpace());
|
||||
}
|
||||
else if (ast.isInferredType(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keywords('infer', 'infers').append(Formatting.oneSpace());
|
||||
}
|
||||
else if (ast.isAssignment(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keywords('=', '+=', '?=').surround(Formatting.noSpace());
|
||||
}
|
||||
else if (ast.isRuleCall(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keyword('<').surround(Formatting.noSpace());
|
||||
formatter.keyword(',').append(Formatting.oneSpace());
|
||||
formatter.properties('arguments').append(Formatting.noSpace());
|
||||
}
|
||||
else if (ast.isInterface(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keyword('interface').append(Formatting.oneSpace());
|
||||
formatter.keyword('extends').prepend(Formatting.oneSpace()).append(indentOrSpace);
|
||||
formatter.keywords(',').prepend(Formatting.noSpace()).append(indentOrSpace);
|
||||
const bracesOpen = formatter.keyword('{');
|
||||
bracesOpen.prepend(Formatting.fit(Formatting.oneSpace(), Formatting.newLine()));
|
||||
const bracesClose = formatter.keyword('}');
|
||||
bracesClose.prepend(Formatting.newLine());
|
||||
formatter.interior(bracesOpen, bracesClose).prepend(Formatting.indent());
|
||||
}
|
||||
else if (ast.isType(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keyword('type').append(Formatting.oneSpace());
|
||||
formatter.keyword('=').prepend(Formatting.oneSpace()).append(indentOrSpace);
|
||||
formatter.keyword(';').prepend(Formatting.noSpace()).append(Formatting.newLine());
|
||||
}
|
||||
else if (ast.isGrammar(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
const nodes = formatter.nodes(...node.rules, ...node.interfaces, ...node.types, ...node.imports);
|
||||
nodes.prepend(Formatting.noIndent());
|
||||
formatter.keyword('grammar').prepend(Formatting.noSpace()).append(Formatting.oneSpace());
|
||||
}
|
||||
else if (ast.isInfixRuleOperatorList(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keywords('left', 'right').append(Formatting.oneSpace());
|
||||
formatter.keywords('|').surround(Formatting.oneSpace());
|
||||
}
|
||||
else if (ast.isInfixRuleOperators(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keywords('>').prepend(Formatting.newLine());
|
||||
}
|
||||
else if (ast.isInfixRule(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.keyword('infix').append(Formatting.oneSpace());
|
||||
formatter.keyword('on').append(Formatting.oneSpace());
|
||||
const semicolon = formatter.keyword(';');
|
||||
const colon = formatter.keyword(':');
|
||||
colon.prepend(Formatting.noSpace());
|
||||
formatter.interior(colon, semicolon).prepend(Formatting.indent());
|
||||
}
|
||||
if (ast.isAbstractElement(node)) {
|
||||
const formatter = this.getNodeFormatter(node);
|
||||
formatter.property('cardinality').prepend(Formatting.noSpace());
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-formatter.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+12
@@ -0,0 +1,12 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2022 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.
|
||||
******************************************************************************/
|
||||
import type { AstNode } from '../../syntax-tree.js';
|
||||
import type { SemanticTokenAcceptor } from '../../lsp/semantic-token-provider.js';
|
||||
import { AbstractSemanticTokenProvider } from '../../lsp/semantic-token-provider.js';
|
||||
export declare class LangiumGrammarSemanticTokenProvider extends AbstractSemanticTokenProvider {
|
||||
protected highlightElement(node: AstNode, acceptor: SemanticTokenAcceptor): void;
|
||||
}
|
||||
//# sourceMappingURL=grammar-semantic-tokens.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-semantic-tokens.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-semantic-tokens.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAElF,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAGrF,qBAAa,mCAAoC,SAAQ,6BAA6B;IAElF,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI;CA0DnF"}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2022 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.
|
||||
******************************************************************************/
|
||||
import { SemanticTokenTypes } from 'vscode-languageserver';
|
||||
import { AbstractSemanticTokenProvider } from '../../lsp/semantic-token-provider.js';
|
||||
import { isAction, isAssignment, isInfixRule, isParameter, isParameterReference, isReturnType, isRuleCall, isSimpleType, isTypeAttribute } from '../../languages/generated/ast.js';
|
||||
export class LangiumGrammarSemanticTokenProvider extends AbstractSemanticTokenProvider {
|
||||
highlightElement(node, acceptor) {
|
||||
if (isAssignment(node)) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'feature',
|
||||
type: SemanticTokenTypes.property
|
||||
});
|
||||
}
|
||||
else if (isAction(node)) {
|
||||
if (node.feature) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'feature',
|
||||
type: SemanticTokenTypes.property
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (isReturnType(node)) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'name',
|
||||
type: SemanticTokenTypes.type
|
||||
});
|
||||
}
|
||||
else if (isSimpleType(node)) {
|
||||
if (node.primitiveType || node.typeRef) {
|
||||
acceptor({
|
||||
node,
|
||||
property: node.primitiveType ? 'primitiveType' : 'typeRef',
|
||||
type: SemanticTokenTypes.type
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (isParameter(node)) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'name',
|
||||
type: SemanticTokenTypes.parameter
|
||||
});
|
||||
}
|
||||
else if (isParameterReference(node)) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'parameter',
|
||||
type: SemanticTokenTypes.parameter
|
||||
});
|
||||
}
|
||||
else if (isRuleCall(node)) {
|
||||
if (!isInfixRule(node.rule.ref) && node.rule.ref?.fragment) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'rule',
|
||||
type: SemanticTokenTypes.type
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (isTypeAttribute(node)) {
|
||||
acceptor({
|
||||
node,
|
||||
property: 'name',
|
||||
type: SemanticTokenTypes.property
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-semantic-tokens.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-semantic-tokens.js","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-semantic-tokens.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAIhF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEnL,MAAM,OAAO,mCAAoC,SAAQ,6BAA6B;IAExE,gBAAgB,CAAC,IAAa,EAAE,QAA+B;QACrE,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,QAAQ,CAAC;gBACL,IAAI;gBACJ,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,kBAAkB,CAAC,QAAQ;aACpC,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,QAAQ,CAAC;oBACL,IAAI;oBACJ,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,kBAAkB,CAAC,QAAQ;iBACpC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;aAAM,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,QAAQ,CAAC;gBACL,IAAI;gBACJ,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,kBAAkB,CAAC,IAAI;aAChC,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrC,QAAQ,CAAC;oBACL,IAAI;oBACJ,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;oBAC1D,IAAI,EAAE,kBAAkB,CAAC,IAAI;iBAChC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;aAAM,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,QAAQ,CAAC;gBACL,IAAI;gBACJ,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,kBAAkB,CAAC,SAAS;aACrC,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,QAAQ,CAAC;gBACL,IAAI;gBACJ,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,kBAAkB,CAAC,SAAS;aACrC,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC;gBACzD,QAAQ,CAAC;oBACL,IAAI;oBACJ,QAAQ,EAAE,MAAM;oBAChB,IAAI,EAAE,kBAAkB,CAAC,IAAI;iBAChC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;aAAM,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC;gBACL,IAAI;gBACJ,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,kBAAkB,CAAC,QAAQ;aACpC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;CAEJ"}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2023 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.
|
||||
******************************************************************************/
|
||||
import type { AstNode } from '../../syntax-tree.js';
|
||||
import type { TypeHierarchyItem } from 'vscode-languageserver';
|
||||
import { AbstractTypeHierarchyProvider } from '../../lsp/type-hierarchy-provider.js';
|
||||
export declare class LangiumGrammarTypeHierarchyProvider extends AbstractTypeHierarchyProvider {
|
||||
protected getSupertypes(node: AstNode): TypeHierarchyItem[] | undefined;
|
||||
protected getSubtypes(node: AstNode): TypeHierarchyItem[] | undefined;
|
||||
}
|
||||
//# sourceMappingURL=grammar-type-hierarchy.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-type-hierarchy.d.ts","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-type-hierarchy.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAKrF,qBAAa,mCAAoC,SAAQ,6BAA6B;IAClF,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,iBAAiB,EAAE,GAAG,SAAS;IAiBvE,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,iBAAiB,EAAE,GAAG,SAAS;CAmCxE"}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2023 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.
|
||||
******************************************************************************/
|
||||
import { AbstractTypeHierarchyProvider } from '../../lsp/type-hierarchy-provider.js';
|
||||
import { getDocument } from '../../utils/ast-utils.js';
|
||||
import { findLeafNodeAtOffset } from '../../utils/cst-utils.js';
|
||||
import { isInterface } from '../../languages/generated/ast.js';
|
||||
export class LangiumGrammarTypeHierarchyProvider extends AbstractTypeHierarchyProvider {
|
||||
getSupertypes(node) {
|
||||
if (!isInterface(node)) {
|
||||
return undefined;
|
||||
}
|
||||
const items = node.superTypes.flatMap(superType => {
|
||||
const ref = superType.ref;
|
||||
if (!ref) {
|
||||
return [];
|
||||
}
|
||||
return this.getTypeHierarchyItems(ref, getDocument(ref)) ?? [];
|
||||
});
|
||||
return items.length === 0 ? undefined : items;
|
||||
}
|
||||
getSubtypes(node) {
|
||||
if (!isInterface(node)) {
|
||||
return undefined;
|
||||
}
|
||||
const items = this.references
|
||||
.findReferences(node, { includeDeclaration: false })
|
||||
.flatMap(ref => {
|
||||
const document = this.documents.getDocument(ref.sourceUri);
|
||||
if (!document) {
|
||||
return [];
|
||||
}
|
||||
const rootNode = document.parseResult.value;
|
||||
if (!rootNode.$cstNode) {
|
||||
return [];
|
||||
}
|
||||
const refCstNode = findLeafNodeAtOffset(rootNode.$cstNode, ref.segment.offset);
|
||||
if (!refCstNode) {
|
||||
return [];
|
||||
}
|
||||
// Only consider references that occur as a superType of an interface
|
||||
const refNode = refCstNode.astNode;
|
||||
if (!isInterface(refNode) || refNode.superTypes.every(superType => superType.$refNode !== refCstNode)) {
|
||||
return [];
|
||||
}
|
||||
return this.getTypeHierarchyItems(refNode, document) ?? [];
|
||||
})
|
||||
.toArray();
|
||||
return items.length === 0 ? undefined : items;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=grammar-type-hierarchy.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"grammar-type-hierarchy.js","sourceRoot":"","sources":["../../../src/grammar/lsp/grammar-type-hierarchy.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAIhF,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,MAAM,OAAO,mCAAoC,SAAQ,6BAA6B;IACxE,aAAa,CAAC,IAAa;QACjC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;YAC9C,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC;YAC1B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACP,OAAO,EAAE,CAAC;YACd,CAAC;YAED,OAAO,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IAES,WAAW,CAAC,IAAa;QAC/B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU;aACxB,cAAc,CAAC,IAAI,EAAE,EAAC,kBAAkB,EAAE,KAAK,EAAC,CAAC;aACjD,OAAO,CAAC,GAAG,CAAC,EAAE;YACX,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACZ,OAAO,EAAE,CAAC;YACd,CAAC;YAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACrB,OAAO,EAAE,CAAC;YACd,CAAC;YAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/E,IAAI,CAAC,UAAU,EAAE,CAAC;gBACd,OAAO,EAAE,CAAC;YACd,CAAC;YAED,qEAAqE;YACrE,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;YACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU,CAAC,EAAE,CAAC;gBACpG,OAAO,EAAE,CAAC;YACd,CAAC;YAED,OAAO,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/D,CAAC,CAAC;aACD,OAAO,EAAE,CAAC;QAEf,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;CACJ"}
|
||||
Reference in New Issue
Block a user