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

Wrapped utility functions in namespaces #1320

Merged
merged 1 commit into from Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -9,7 +9,7 @@ import type { Range, WorkspaceEdit } from 'vscode-languageserver';
import type { RenameParams } from 'vscode-languageserver-protocol';
import type { DomainModelServices } from './domain-model-module.js';
import type { QualifiedNameProvider } from './domain-model-naming.js';
import { DefaultRenameProvider, findDeclarationNodeAtOffset, getDocument, isNamed, streamAst, toDocumentSegment } from 'langium';
import { AstUtils, CstUtils, DefaultRenameProvider, isNamed } from 'langium';
import { Location } from 'vscode-languageserver';
import { TextEdit } from 'vscode-languageserver-types';
import { isPackageDeclaration } from './generated/ast.js';
Expand All @@ -30,7 +30,7 @@ export class DomainModelRenameProvider extends DefaultRenameProvider {
const rootNode = document.parseResult.value.$cstNode;
if (!rootNode) return undefined;
const offset = document.textDocument.offsetAt(params.position);
const leafNode = findDeclarationNodeAtOffset(rootNode, offset, this.grammarConfig.nameRegexp);
const leafNode = CstUtils.findDeclarationNodeAtOffset(rootNode, offset, this.grammarConfig.nameRegexp);
if (!leafNode) return undefined;
const targetNode = this.references.findDeclaration(leafNode);
if (!targetNode) return undefined;
Expand All @@ -48,7 +48,7 @@ export class DomainModelRenameProvider extends DefaultRenameProvider {
}
}

for (const node of streamAst(targetNode)) {
for (const node of AstUtils.streamAst(targetNode)) {
const qn = this.buildQualifiedName(node);
if (qn) {
const options = { onlyLocal: false, includeDeclaration: false };
Expand Down Expand Up @@ -88,10 +88,10 @@ export class DomainModelRenameProvider extends DefaultRenameProvider {
getNodeLocation(targetNode: AstNode): Location | undefined {
const nameNode = this.nameProvider.getNameNode(targetNode);
if (nameNode) {
const doc = getDocument(targetNode);
const doc = AstUtils.getDocument(targetNode);
return Location.create(
doc.uri.toString(),
toDocumentSegment(nameNode).range
CstUtils.toDocumentSegment(nameNode).range
);
}
return undefined;
Expand Down
Expand Up @@ -8,7 +8,7 @@ import type { AstNode, AstNodeDescription, LangiumDocument, PrecomputedScopes }
import type { DomainModelServices } from './domain-model-module.js';
import type { QualifiedNameProvider } from './domain-model-naming.js';
import type { Domainmodel, PackageDeclaration } from './generated/ast.js';
import { DefaultScopeComputation, interruptAndCheck, MultiMap, streamAllContents } from 'langium';
import { AstUtils, DefaultScopeComputation, interruptAndCheck, MultiMap } from 'langium';
import { CancellationToken } from 'vscode-jsonrpc';
import { isType, isPackageDeclaration } from './generated/ast.js';

Expand All @@ -26,7 +26,7 @@ export class DomainModelScopeComputation extends DefaultScopeComputation {
*/
override async computeExports(document: LangiumDocument, cancelToken = CancellationToken.None): Promise<AstNodeDescription[]> {
const descr: AstNodeDescription[] = [];
for (const modelNode of streamAllContents(document.parseResult.value)) {
for (const modelNode of AstUtils.streamAllContents(document.parseResult.value)) {
await interruptAndCheck(cancelToken);
if (isType(modelNode)) {
let name = this.nameProvider.getName(modelNode);
Expand Down
4 changes: 2 additions & 2 deletions examples/domainmodel/test/refs-index.test.ts
Expand Up @@ -7,7 +7,7 @@
import type { AstNode, LangiumDocument, ReferenceDescription, URI } from 'langium';
import type { Domainmodel } from '../src/language-server/generated/ast.js';
import { describe, expect, test } from 'vitest';
import { EmptyFileSystem, getDocument } from 'langium';
import { AstUtils, EmptyFileSystem } from 'langium';
import { parseDocument, setTextDocument } from 'langium/test';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { createDomainModelServices } from '../src/language-server/domain-model-module.js';
Expand Down Expand Up @@ -62,7 +62,7 @@ function refString(ref: ReferenceDescription): string {
}

function nodeRefString(from: AstNode, to: AstNode): string {
return asString(getDocument(from).uri, createPath(from), getDocument(to).uri, createPath(to));
return asString(AstUtils.getDocument(from).uri, createPath(from), AstUtils.getDocument(to).uri, createPath(to));
}

function createPath(node: AstNode): string {
Expand Down
10 changes: 5 additions & 5 deletions packages/langium-cli/src/generate.ts
Expand Up @@ -8,7 +8,7 @@ import type { AstNode, Grammar, LangiumDocument, Mutable } from 'langium';
import type { LangiumConfig, LangiumLanguageConfig} from './package.js';
import { URI } from 'langium';
import { loadConfig } from './package.js';
import { copyAstNode, getDocument, GrammarAST, linkContentToContainer } from 'langium';
import { AstUtils, GrammarAST } from 'langium';
import { createLangiumGrammarServices, resolveImport, resolveImportUri, resolveTransitiveImports } from 'langium/grammar';
import { NodeFileSystem } from 'langium/node';
import { generateAst } from './generator/ast-generator.js';
Expand Down Expand Up @@ -148,7 +148,7 @@ async function eagerLoad(document: LangiumDocument, uris: Set<string> = new Set(
*/
function mapGrammarElements(grammars: Grammar[], visited: Set<string> = new Set(), map: Map<Grammar, GrammarElement[]> = new Map()): Map<Grammar, GrammarElement[]> {
for (const grammar of grammars) {
const doc = getDocument(grammar);
const doc = AstUtils.getDocument(grammar);
const uriString = doc.uri.toString();
if (!visited.has(uriString)) {
visited.add(uriString);
Expand All @@ -172,7 +172,7 @@ function embedReferencedGrammar(grammar: Grammar, map: Map<Grammar, GrammarEleme
for (const importedGrammar of allGrammars) {
const grammarElements = map.get(importedGrammar) ?? [];
for (const element of grammarElements) {
const copy = copyAstNode(element, buildReference);
const copy = AstUtils.copyAstNode(element, buildReference);
// Deactivate copied entry rule
if (GrammarAST.isParserRule(copy)) {
copy.entry = false;
Expand All @@ -194,7 +194,7 @@ function embedReferencedGrammar(grammar: Grammar, map: Map<Grammar, GrammarEleme
imports: []
};
// Link newly added elements to grammar
linkContentToContainer(grammarCopy);
AstUtils.linkContentToContainer(grammarCopy);
return grammarCopy;
}

Expand All @@ -211,7 +211,7 @@ async function relinkGrammars(grammars: Grammar[]): Promise<void> {
await documentBuilder.update([], documents.map(e => e.uri));
// Create and build new documents
const newDocuments = grammars.map(e => {
const uri = getDocument(e).uri;
const uri = AstUtils.getDocument(e).uri;
const newDoc = documentFactory.fromModel(e, uri);
(e as Mutable<AstNode>).$document = newDoc;
return newDoc;
Expand Down
4 changes: 2 additions & 2 deletions packages/langium-cli/src/generator/ast-generator.ts
Expand Up @@ -7,7 +7,7 @@ import type { Grammar, LangiumServices } from 'langium';
import { type Generated, expandToNode, joinToNode, toString } from 'langium/generate';
import type { AstTypes, Property, PropertyDefaultValue } from 'langium/grammar';
import type { LangiumConfig } from '../package.js';
import { streamAllContents, MultiMap, GrammarAST } from 'langium';
import { AstUtils, MultiMap, GrammarAST } from 'langium';
import { collectAst, collectTypeHierarchy, findReferenceTypes, isAstType, mergeTypesAndInterfaces } from 'langium/grammar';
import { collectTerminalRegexps, generatedHeader } from './util.js';

Expand Down Expand Up @@ -37,7 +37,7 @@ export function generateAst(services: LangiumServices, grammars: Grammar[], conf
}

function hasCrossReferences(grammar: Grammar): boolean {
return Boolean(streamAllContents(grammar).find(GrammarAST.isCrossReference));
return Boolean(AstUtils.streamAllContents(grammar).find(GrammarAST.isCrossReference));
}

function generateAstReflection(config: LangiumConfig, astTypes: AstTypes): Generated {
Expand Down
Expand Up @@ -4,7 +4,7 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { type Grammar, getTerminalParts, isCommentTerminal, escapeRegExp, GrammarAST, isWhitespaceRegExp, terminalRegex } from 'langium';
import { type Grammar, GrammarAST, GrammarUtils, RegExpUtils } from 'langium';
import { type Generated, expandToNode, joinToNode, toString } from 'langium/generate';
import type { LangiumLanguageConfig } from '../../package.js';
import { collectKeywords } from '../util.js';
Expand Down Expand Up @@ -225,7 +225,7 @@ function prettyPrintLangDef(languageDef: LanguageDefinition): Generated {
${genLanguageDefEntry('keywords', languageDef.keywords)}
${genLanguageDefEntry('operators', languageDef.operators)}
${/* special case, identify symbols via singular regex*/ undefined}
symbols: ${new RegExp(languageDef.symbols.map(escapeRegExp).join('|')).toString()},
symbols: ${new RegExp(languageDef.symbols.map(RegExpUtils.escapeRegExp).join('|')).toString()},
`;
}

Expand Down Expand Up @@ -315,20 +315,20 @@ function getWhitespaceRules(grammar: Grammar): Rule[] {
const rules: Rule[] = [];
for (const rule of grammar.rules) {
if (GrammarAST.isTerminalRule(rule)) {
const regex = terminalRegex(rule);
const regex = GrammarUtils.terminalRegex(rule);

if (!isCommentTerminal(rule) && !isWhitespaceRegExp(regex)) {
if (!GrammarUtils.isCommentTerminal(rule) && !RegExpUtils.isWhitespace(regex)) {
// skip rules that are not comments or whitespace
continue;
}

// token name is either comment or whitespace
const tokenName = isCommentTerminal(rule) ? 'comment' : 'white';
const tokenName = GrammarUtils.isCommentTerminal(rule) ? 'comment' : 'white';

const part = getTerminalParts(regex)[0];
const part = RegExpUtils.getTerminalParts(regex)[0];

// check if this is a comment terminal w/ a start & end sequence (multi-line)
if (part.start !== '' && part.end !== '' && isCommentTerminal(rule)) {
if (part.start !== '' && part.end !== '' && GrammarUtils.isCommentTerminal(rule)) {
// state-based comment rule, only add push to jump into it
rules.push({
regex: part.start,
Expand Down Expand Up @@ -356,9 +356,9 @@ function getWhitespaceRules(grammar: Grammar): Rule[] {
function getCommentRules(grammar: Grammar): Rule[] {
const rules: Rule[] = [];
for (const rule of grammar.rules) {
if (GrammarAST.isTerminalRule(rule) && isCommentTerminal(rule)) {
if (GrammarAST.isTerminalRule(rule) && GrammarUtils.isCommentTerminal(rule)) {
const tokenName = 'comment';
const part = getTerminalParts(terminalRegex(rule))[0];
const part = RegExpUtils.getTerminalParts(GrammarUtils.terminalRegex(rule))[0];
if (part.start !== '' && part.end !== '') {
// rules to manage comment start/end
// rule order matters
Expand Down Expand Up @@ -398,10 +398,10 @@ function getCommentRules(grammar: Grammar): Rule[] {
function getTerminalRules(grammar: Grammar): Rule[] {
const rules: Rule[] = [];
for (const rule of grammar.rules) {
if (GrammarAST.isTerminalRule(rule) && !isCommentTerminal(rule)) {
const regex = terminalRegex(rule);
if (GrammarAST.isTerminalRule(rule) && !GrammarUtils.isCommentTerminal(rule)) {
const regex = GrammarUtils.terminalRegex(rule);

if (isWhitespaceRegExp(regex)) {
if (RegExpUtils.isWhitespace(regex)) {
// disallow terminal rules that match whitespace
continue;
}
Expand Down
Expand Up @@ -3,7 +3,7 @@
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import { terminalRegex, GrammarAST, escapeRegExp, isCommentTerminal, type Grammar } from 'langium';
import { GrammarAST, type Grammar, GrammarUtils, RegExpUtils } from 'langium';
import { expandToNode, joinToNode, toString, type Generated } from 'langium/generate';
import _ from 'lodash';
import type { LangiumLanguageConfig } from '../../package.js';
Expand All @@ -23,26 +23,26 @@ export function generatePrismHighlighting(grammar: Grammar, config: LangiumLangu
const terminals = getTerminals(grammar);
const modifier = config.caseInsensitive ? 'i' : '';

const commentTerminals = terminals.filter(isCommentTerminal);
const commentTerminals = terminals.filter(GrammarUtils.isCommentTerminal);
if (commentTerminals.length === 1) {
highlighter.comment = {
pattern: terminalRegex(commentTerminals[0]).toString(),
pattern: GrammarUtils.terminalRegex(commentTerminals[0]).toString(),
greedy: true
};
} else if (commentTerminals.length > 0) {
highlighter.comment = commentTerminals.map(e => ({
pattern: terminalRegex(e).toString(),
pattern: GrammarUtils.terminalRegex(e).toString(),
greedy: true
}));
}
const stringTerminal = terminals.find(e => e.name.toLowerCase() === 'string');
if (stringTerminal) {
highlighter.string = {
pattern: terminalRegex(stringTerminal).toString(),
pattern: GrammarUtils.terminalRegex(stringTerminal).toString(),
greedy: true
};
}
const filteredKeywords = keywords.filter(e => idRegex.test(e)).sort((a, b) => b.length - a.length).map(escapeRegExp);
const filteredKeywords = keywords.filter(e => idRegex.test(e)).sort((a, b) => b.length - a.length).map(RegExpUtils.escapeRegExp);
highlighter.keyword = {
pattern: `/\\b(${filteredKeywords.join('|')})\\b/${modifier}`
};
Expand Down
Expand Up @@ -4,7 +4,7 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import type { Grammar } from 'langium';
import { escapeRegExp, getCaseInsensitivePattern, getTerminalParts, GrammarAST, isCommentTerminal, stream, terminalRegex } from 'langium';
import { GrammarAST, GrammarUtils, RegExpUtils, stream } from 'langium';
import type { LangiumLanguageConfig } from '../../package.js';
import { collectKeywords } from '../util.js';

Expand Down Expand Up @@ -74,8 +74,8 @@ function getRepository(grammar: Grammar, config: LangiumLanguageConfig): Reposit
const commentPatterns: Pattern[] = [];
let stringEscapePattern: Pattern | undefined;
for (const rule of grammar.rules) {
if (GrammarAST.isTerminalRule(rule) && isCommentTerminal(rule)) {
const parts = getTerminalParts(terminalRegex(rule));
if (GrammarAST.isTerminalRule(rule) && GrammarUtils.isCommentTerminal(rule)) {
const parts = RegExpUtils.getTerminalParts(GrammarUtils.terminalRegex(rule));
for (const part of parts) {
if (part.end) {
commentPatterns.push({
Expand Down Expand Up @@ -144,7 +144,7 @@ function groupKeywords(keywords: string[], caseInsensitive: boolean | undefined)
} = { letter: [], leftSpecial: [], rightSpecial: [], special: [] };

keywords.forEach(keyword => {
const keywordPattern = caseInsensitive ? getCaseInsensitivePattern(keyword) : escapeRegExp(keyword);
const keywordPattern = caseInsensitive ? RegExpUtils.getCaseInsensitivePattern(keyword) : RegExpUtils.escapeRegExp(keyword);
if (/\w/.test(keyword[0])) {
if (/\w/.test(keyword[keyword.length - 1])) {
groups.letter.push(keywordPattern);
Expand Down Expand Up @@ -173,7 +173,7 @@ function getStringPatterns(grammar: Grammar, pack: LangiumLanguageConfig): Patte
const stringTerminal = terminals.find(e => e.name.toLowerCase() === 'string');
const stringPatterns: Pattern[] = [];
if (stringTerminal) {
const parts = getTerminalParts(terminalRegex(stringTerminal));
const parts = RegExpUtils.getTerminalParts(GrammarUtils.terminalRegex(stringTerminal));
for (const part of parts) {
if (part.end) {
stringPatterns.push({
Expand Down
10 changes: 5 additions & 5 deletions packages/langium-cli/src/generator/util.ts
Expand Up @@ -3,7 +3,7 @@
* 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 Grammar, getAllReachableRules, GrammarAST, stream, streamAllContents, terminalRegex } from 'langium';
import { AstUtils, type Grammar, GrammarAST, GrammarUtils, stream } from 'langium';
import { type Generated, expandToNode } from 'langium/generate';
import fs from 'fs-extra';
import * as path from 'node:path';
Expand Down Expand Up @@ -59,11 +59,11 @@ function getGeneratedHeader(): Generated {

export function collectKeywords(grammar: Grammar): string[] {
const keywords = new Set<string>();
const reachableRules = getAllReachableRules(grammar, false);
const reachableRules = GrammarUtils.getAllReachableRules(grammar, false);

for (const keyword of stream(reachableRules)
.filter(GrammarAST.isParserRule)
.flatMap(rule => streamAllContents(rule).filter(GrammarAST.isKeyword))) {
.flatMap(rule => AstUtils.streamAllContents(rule).filter(GrammarAST.isKeyword))) {
keywords.add(keyword.value);
}

Expand Down Expand Up @@ -97,10 +97,10 @@ export async function getUserChoice<R extends string>(text: string, values: R[],

export function collectTerminalRegexps(grammar: Grammar): Record<string, RegExp> {
const result: Record<string, RegExp> = {};
const reachableRules = getAllReachableRules(grammar, false);
const reachableRules = GrammarUtils.getAllReachableRules(grammar, false);
for (const terminalRule of stream(reachableRules).filter(GrammarAST.isTerminalRule)) {
const name = terminalRule.name;
const regexp = terminalRegex(terminalRule);
const regexp = GrammarUtils.terminalRegex(terminalRule);
result[name] = regexp;
}
return result;
Expand Down
4 changes: 2 additions & 2 deletions packages/langium-cli/src/parser-validation.ts
Expand Up @@ -5,7 +5,7 @@
******************************************************************************/
import type { Grammar, IParserConfig, LangiumDocuments, LangiumParser, LanguageMetaData } from 'langium';
import type { LangiumConfig, LangiumLanguageConfig } from './package.js';
import { getDocument, GrammarAST, prepareLangiumParser } from 'langium';
import { AstUtils, GrammarAST, prepareLangiumParser } from 'langium';
import type { LangiumGrammarServices} from 'langium/grammar';
import { createServicesForGrammar } from 'langium/grammar';
import { getFilePath } from './package.js';
Expand Down Expand Up @@ -39,7 +39,7 @@ export async function validateParser(grammar: Grammar, config: LangiumConfig, gr
if (defError.ruleName) {
const rule = findRule(defError.ruleName, grammar, grammarServices.shared.workspace.LangiumDocuments);
if (rule && rule.$cstNode) {
const filePath = getFilePath(getDocument(rule).uri.fsPath, config);
const filePath = getFilePath(AstUtils.getDocument(rule).uri.fsPath, config);
const line = rule.$cstNode.range.start.line + 1;
message += `${filePath}:${line} - `;
}
Expand Down