From 016ba060ff5d5dbe1b741420fe1adabebf6353cc Mon Sep 17 00:00:00 2001 From: Evan Hedbor Date: Wed, 22 May 2024 10:59:23 +0200 Subject: [PATCH] Add prettier --- .prettierrc.js | 13 ++++ .vscode/settings.json | 12 +++- client/src/extension.ts | 20 +++--- client/src/getLanguage.ts | 2 +- client/src/test/helper.ts | 2 +- client/src/test/index.ts | 8 +-- client/src/test/symbolinformation.test.ts | 85 ++++++++++++++--------- server/src/analyzer.ts | 28 ++++---- server/src/parser.ts | 2 +- server/src/server.ts | 48 ++++++------- server/src/test/server.test.ts | 3 +- server/src/util/declarations.ts | 26 +++---- server/src/util/logger.ts | 8 +-- server/src/util/test/declarations.test.ts | 18 ++--- server/src/util/test/util.test.ts | 6 +- server/src/util/tree-sitter.ts | 22 +++--- 16 files changed, 171 insertions(+), 132 deletions(-) create mode 100644 .prettierrc.js diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..e5f3afa --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,13 @@ +module.exports = { + printWidth: 100, + tabWidth: 2, + useTabs: false, + semi: true, + singleQuote: true, + quoteProps: 'as-needed', + trailingComma: 'all', + bracketSpacing: true, + arrowParens: 'always', + proseWrap: 'preserve', + endOfLine: 'lf', +}; diff --git a/.vscode/settings.json b/.vscode/settings.json index 2fb4fd9..bded9c2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,15 @@ "typescript.preferences.quoteStyle": "single", "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" - } + }, + "prettier.configPath": "./.prettierrc.js", + "cSpell.words": [ + "metamodelica", + "Modelica", + "nodelib", + "OSMC", + "redeclaration" + ], + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, } diff --git a/client/src/extension.ts b/client/src/extension.ts index 0bb63d0..4348345 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -40,7 +40,7 @@ import { LanguageClient, LanguageClientOptions, ServerOptions, - TransportKind + TransportKind, } from 'vscode-languageclient/node'; import { getFileExtension, getLanguage } from './getLanguage'; import { fstat } from 'fs'; @@ -49,7 +49,7 @@ let client: LanguageClient; export function activate(context: ExtensionContext) { // Register event listener to set language for '.mo' files. - const checkedFiles: { [id: string]: boolean} = {}; + const checkedFiles: { [id: string]: boolean } = {}; workspace.onDidOpenTextDocument((document: TextDocument) => { if (checkedFiles[document.fileName]) { return; @@ -73,9 +73,7 @@ export function activate(context: ExtensionContext) { }); // The server is implemented in node, point to packed module - const serverModule = context.asAbsolutePath( - path.join('out', 'server.js') - ); + const serverModule = context.asAbsolutePath(path.join('out', 'server.js')); if (!fs.existsSync(serverModule)) { throw new Error(`Can't find server module in ${serverModule}`); } @@ -87,7 +85,7 @@ export function activate(context: ExtensionContext) { debug: { module: serverModule, transport: TransportKind.ipc, - } + }, }; // Options to control the language client @@ -96,13 +94,13 @@ export function activate(context: ExtensionContext) { documentSelector: [ { language: 'modelica', - scheme: 'file' - } + scheme: 'file', + }, ], synchronize: { // Notify the server about file changes to '.clientrc files contained in the workspace - fileEvents: workspace.createFileSystemWatcher('**/.clientrc') - } + fileEvents: workspace.createFileSystemWatcher('**/.clientrc'), + }, }; // Create the language client and start the client. @@ -110,7 +108,7 @@ export function activate(context: ExtensionContext) { 'modelicaLanguageServer', 'Modelica Language Server', serverOptions, - clientOptions + clientOptions, ); // Start the client. This will also launch the server diff --git a/client/src/getLanguage.ts b/client/src/getLanguage.ts index 777e95a..8414ce6 100644 --- a/client/src/getLanguage.ts +++ b/client/src/getLanguage.ts @@ -36,7 +36,7 @@ import * as path from 'path'; import { TextDocument } from 'vscode'; -type LanguageTypes = 'modelica' | 'metamodelica' | 'unknown' +type LanguageTypes = 'modelica' | 'metamodelica' | 'unknown'; export function getFileExtension(document: TextDocument): string | undefined { const uri = document.uri; diff --git a/client/src/test/helper.ts b/client/src/test/helper.ts index 6d7c7ff..70a95b7 100644 --- a/client/src/test/helper.ts +++ b/client/src/test/helper.ts @@ -58,7 +58,7 @@ export async function activate(docUri: vscode.Uri) { } async function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } export const getDocPath = (p: string) => { diff --git a/client/src/test/index.ts b/client/src/test/index.ts index 5e09ff6..ecf15a2 100644 --- a/client/src/test/index.ts +++ b/client/src/test/index.ts @@ -41,7 +41,7 @@ export function run(): Promise { // Create the mocha test const mocha = new Mocha({ ui: 'tdd', - color: true + color: true, }); mocha.timeout(100000); @@ -54,11 +54,11 @@ export function run(): Promise { } // Add files to the test suite - files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); + files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); try { // Run the mocha test - mocha.run(failures => { + mocha.run((failures) => { if (failures > 0) { reject(new Error(`${failures} tests failed.`)); } else { @@ -71,4 +71,4 @@ export function run(): Promise { } }); }); -} \ No newline at end of file +} diff --git a/client/src/test/symbolinformation.test.ts b/client/src/test/symbolinformation.test.ts index 97d71bc..c2ddfb6 100644 --- a/client/src/test/symbolinformation.test.ts +++ b/client/src/test/symbolinformation.test.ts @@ -43,21 +43,22 @@ suite('Symbol Information', () => { test('onDocumentSymbol()', async () => { const documentSymbols: vscode.DocumentSymbol[] = [ new vscode.DocumentSymbol( - 'MyLibrary', - '', - vscode.SymbolKind.Package, - new vscode.Range(new vscode.Position(0, 0), new vscode.Position(6, 13)), - new vscode.Range(new vscode.Position(0, 0), new vscode.Position(6, 13)), - ) + 'MyLibrary', + '', + vscode.SymbolKind.Package, + new vscode.Range(new vscode.Position(0, 0), new vscode.Position(6, 13)), + new vscode.Range(new vscode.Position(0, 0), new vscode.Position(6, 13)), + ), ]; documentSymbols[0].children.push( new vscode.DocumentSymbol( - 'M', - '', - vscode.SymbolKind.Class, - new vscode.Range(new vscode.Position(1, 2), new vscode.Position(5, 7)), - new vscode.Range(new vscode.Position(1, 2), new vscode.Position(5, 7)) - )); + 'M', + '', + vscode.SymbolKind.Class, + new vscode.Range(new vscode.Position(1, 2), new vscode.Position(5, 7)), + new vscode.Range(new vscode.Position(1, 2), new vscode.Position(5, 7)), + ), + ); await testSymbolInformation(docUri, documentSymbols); }); @@ -65,12 +66,15 @@ suite('Symbol Information', () => { async function testSymbolInformation( docUri: vscode.Uri, - expectedDocumentSymbols: vscode.DocumentSymbol[] + expectedDocumentSymbols: vscode.DocumentSymbol[], ) { await activate(docUri); // Execute `vscode.executeDocumentSymbolProvider` to get file outline - const actualSymbolInformation = await vscode.commands.executeCommand("vscode.executeDocumentSymbolProvider", docUri); + const actualSymbolInformation = await vscode.commands.executeCommand( + 'vscode.executeDocumentSymbolProvider', + docUri, + ); //printDocumentSymbols(actualSymbolInformation); assertDocumentSymbolsEqual(expectedDocumentSymbols, actualSymbolInformation); @@ -78,51 +82,66 @@ async function testSymbolInformation( function printDocumentSymbols(documentSymbols: vscode.DocumentSymbol[]) { documentSymbols.forEach((symbol, index) => { - console.log(`Document Symbol ${index + 1}:`); - console.log(`Name: ${symbol.name}`); - console.log(`Kind: ${vscode.SymbolKind[symbol.kind]}`); - console.log(`Range: ${symbol.range.start.line}:${symbol.range.start.character}, ${symbol.range.end.line}:${symbol.range.end.character}`); - console.log(`SelectionRange: ${symbol.selectionRange.start.line}:${symbol.selectionRange.start.character}, ${symbol.selectionRange.end.line}:${symbol.selectionRange.end.character}`); - console.log('Children:'); - - if (symbol.children && symbol.children.length > 0) { - printDocumentSymbols(symbol.children); - } - - console.log('---'); + console.log(`Document Symbol ${index + 1}:`); + console.log(`Name: ${symbol.name}`); + console.log(`Kind: ${vscode.SymbolKind[symbol.kind]}`); + console.log( + `Range: ${symbol.range.start.line}:${symbol.range.start.character}, ${symbol.range.end.line}:${symbol.range.end.character}`, + ); + console.log( + `SelectionRange: ${symbol.selectionRange.start.line}:${symbol.selectionRange.start.character}, ${symbol.selectionRange.end.line}:${symbol.selectionRange.end.character}`, + ); + console.log('Children:'); + + if (symbol.children && symbol.children.length > 0) { + printDocumentSymbols(symbol.children); + } + + console.log('---'); }); } -function assertDocumentSymbolsEqual(expected: vscode.DocumentSymbol[], actual: vscode.DocumentSymbol[]) { +function assertDocumentSymbolsEqual( + expected: vscode.DocumentSymbol[], + actual: vscode.DocumentSymbol[], +) { assert.strictEqual(expected.length, actual.length, 'Array lengths do not match.'); for (let i = 0; i < expected.length; i++) { const expectedSymbol = expected[i]; const actualSymbol = actual[i]; - assert.strictEqual(expectedSymbol.name, actualSymbol.name, `Symbol names do not match at index ${i}.`); - assert.strictEqual(expectedSymbol.kind, actualSymbol.kind, `Symbol kinds do not match at index ${i}.`); + assert.strictEqual( + expectedSymbol.name, + actualSymbol.name, + `Symbol names do not match at index ${i}.`, + ); + assert.strictEqual( + expectedSymbol.kind, + actualSymbol.kind, + `Symbol kinds do not match at index ${i}.`, + ); assert.strictEqual( expectedSymbol.range.start.line, actualSymbol.range.start.line, - `Symbol start line does not match at index ${i}.` + `Symbol start line does not match at index ${i}.`, ); assert.strictEqual( expectedSymbol.range.start.character, actualSymbol.range.start.character, - `Symbol start character does not match at index ${i}.` + `Symbol start character does not match at index ${i}.`, ); assert.strictEqual( expectedSymbol.range.end.line, actualSymbol.range.end.line, - `Symbol end line does not match at index ${i}.` + `Symbol end line does not match at index ${i}.`, ); assert.strictEqual( expectedSymbol.range.end.character, actualSymbol.range.end.character, - `Symbol end character does not match at index ${i}.` + `Symbol end character does not match at index ${i}.`, ); // Recursive check for children symbols diff --git a/server/src/analyzer.ts b/server/src/analyzer.ts index 0dd93cb..a5d5ec2 100644 --- a/server/src/analyzer.ts +++ b/server/src/analyzer.ts @@ -44,23 +44,21 @@ import { TextDocument } from 'vscode-languageserver-textdocument'; import Parser = require('web-tree-sitter'); -import { - getAllDeclarationsInTree -} from './util/declarations'; +import { getAllDeclarationsInTree } from './util/declarations'; import { logger } from './util/logger'; type AnalyzedDocument = { - document: TextDocument, - declarations: LSP.SymbolInformation[], - tree: Parser.Tree -} + document: TextDocument; + declarations: LSP.SymbolInformation[]; + tree: Parser.Tree; +}; export default class Analyzer { - private parser: Parser; - private uriToAnalyzedDocument: Record = {}; + #parser: Parser; + #uriToAnalyzedDocument: Record = {}; - constructor (parser: Parser) { - this.parser = parser; + public constructor(parser: Parser) { + this.#parser = parser; } public analyze(document: TextDocument): LSP.Diagnostic[] { @@ -70,17 +68,17 @@ export default class Analyzer { const fileContent = document.getText(); const uri = document.uri; - const tree = this.parser.parse(fileContent); + const tree = this.#parser.parse(fileContent); logger.debug(tree.rootNode.toString()); // Get declarations const declarations = getAllDeclarationsInTree(tree, uri); // Update saved analysis for document uri - this.uriToAnalyzedDocument[uri] = { + this.#uriToAnalyzedDocument[uri] = { document, declarations, - tree + tree, }; return diagnostics; @@ -92,7 +90,7 @@ export default class Analyzer { * TODO: convert to DocumentSymbol[] which is a hierarchy of symbols found in a given text document. */ public getDeclarationsForUri(uri: string): LSP.SymbolInformation[] { - const tree = this.uriToAnalyzedDocument[uri]?.tree; + const tree = this.#uriToAnalyzedDocument[uri]?.tree; if (!tree?.rootNode) { return []; diff --git a/server/src/parser.ts b/server/src/parser.ts index 57596df..1913e62 100644 --- a/server/src/parser.ts +++ b/server/src/parser.ts @@ -50,7 +50,7 @@ import * as path from 'path'; */ export async function initializeParser(): Promise { await Parser.init(); - const parser = new Parser; + const parser = new Parser(); const modelicaWasmFile = path.join(__dirname, 'tree-sitter-modelica.wasm'); if (!fs.existsSync(modelicaWasmFile)) { diff --git a/server/src/server.ts b/server/src/server.ts index 4bc00e4..f16d085 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -40,7 +40,7 @@ */ import * as LSP from 'vscode-languageserver/node'; -import { TextDocument} from 'vscode-languageserver-textdocument'; +import { TextDocument } from 'vscode-languageserver-textdocument'; import { initializeParser } from './parser'; import Analyzer from './analyzer'; @@ -50,26 +50,25 @@ import { logger, setLogConnection, setLogLevel } from './util/logger'; * ModelicaServer collection all the important bits and bobs. */ export class ModelicaServer { - analyzer: Analyzer; - private clientCapabilities: LSP.ClientCapabilities; - private connection: LSP.Connection; - private documents: LSP.TextDocuments = new LSP.TextDocuments(TextDocument); + #analyzer: Analyzer; + #clientCapabilities: LSP.ClientCapabilities; + #connection: LSP.Connection; + #documents: LSP.TextDocuments = new LSP.TextDocuments(TextDocument); private constructor( analyzer: Analyzer, clientCapabilities: LSP.ClientCapabilities, - connection: LSP.Connection + connection: LSP.Connection, ) { - this.analyzer = analyzer; - this.clientCapabilities = clientCapabilities; - this.connection = connection; + this.#analyzer = analyzer; + this.#clientCapabilities = clientCapabilities; + this.#connection = connection; } public static async initialize( connection: LSP.Connection, { capabilities }: LSP.InitializeParams, ): Promise { - // Initialize logger setLogConnection(connection); setLogLevel('debug'); @@ -95,18 +94,17 @@ export class ModelicaServer { signatureHelpProvider: undefined, documentSymbolProvider: true, colorProvider: false, - semanticTokensProvider: undefined + semanticTokensProvider: undefined, }; } public register(connection: LSP.Connection): void { - let currentDocument: TextDocument | null = null; let initialized = false; // Make the text document manager listen on the connection // for open, change and close text document events - this.documents.listen(this.connection); + this.#documents.listen(this.#connection); connection.onDocumentSymbol(this.onDocumentSymbol.bind(this)); @@ -121,7 +119,7 @@ export class ModelicaServer { // The content of a text document has changed. This event is emitted // when the text document first opened or when its content has changed. - this.documents.onDidChangeContent(({ document }) => { + this.#documents.onDidChangeContent(({ document }) => { logger.debug('onDidChangeContent'); // We need to define some timing to wait some time or until whitespace is typed @@ -134,9 +132,8 @@ export class ModelicaServer { }); } - private async analyzeDocument(document: TextDocument) { - const diagnostics = this.analyzer.analyze(document); + const diagnostics = this.#analyzer.analyze(document); } /** @@ -150,24 +147,21 @@ export class ModelicaServer { // which is a hierarchy of symbols. // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol logger.debug(`onDocumentSymbol`); - return this.analyzer.getDeclarationsForUri(params.textDocument.uri); + return this.#analyzer.getDeclarationsForUri(params.textDocument.uri); } - } // Create a connection for the server, using Node's IPC as a transport. // Also include all preview / proposed LSP features. const connection = LSP.createConnection(LSP.ProposedFeatures.all); -connection.onInitialize( - async (params: LSP.InitializeParams): Promise => { - const server = await ModelicaServer.initialize(connection, params); - server.register(connection); - return { - capabilities: server.capabilities(), - }; - } -); +connection.onInitialize(async (params: LSP.InitializeParams): Promise => { + const server = await ModelicaServer.initialize(connection, params); + server.register(connection); + return { + capabilities: server.capabilities(), + }; +}); // Listen on the connection connection.listen(); diff --git a/server/src/test/server.test.ts b/server/src/test/server.test.ts index e107fab..8c982d2 100644 --- a/server/src/test/server.test.ts +++ b/server/src/test/server.test.ts @@ -46,7 +46,8 @@ equations der(x) = -0.5*x; end M; `; -const parsedModelicaTestString = "(stored_definitions storedDefinitions: (stored_definition classDefinition: (class_definition classPrefixes: (class_prefixes) classSpecifier: (long_class_specifier identifier: (IDENT) descriptionString: (description_string value: (STRING)) (element_list element: (named_element componentClause: (component_clause typeSpecifier: (type_specifier name: (name identifier: (IDENT))) componentDeclarations: (component_list componentDeclaration: (component_declaration declaration: (declaration identifier: (IDENT) modification: (modification classModification: (class_modification arguments: (argument_list argument: (element_modification name: (name identifier: (IDENT)) modification: (modification expression: (expression (simple_expression (primary_expression (literal_expression (unsigned_integer_literal_expression (UNSIGNED_INTEGER)))))))) argument: (element_modification name: (name identifier: (IDENT)) modification: (modification expression: (expression (simple_expression (primary_expression (literal_expression (logical_literal_expression))))))))))) descriptionString: (description_string value: (STRING)))))) element: (named_element componentClause: (component_clause typeSpecifier: (type_specifier name: (name identifier: (IDENT))) componentDeclarations: (component_list componentDeclaration: (component_declaration declaration: (declaration identifier: (IDENT) modification: (modification classModification: (class_modification arguments: (argument_list argument: (element_modification name: (name identifier: (IDENT))))) expression: (expression (simple_expression (binary_expression operand1: (simple_expression (unary_expression operand: (simple_expression (primary_expression (literal_expression (unsigned_real_literal_expression (UNSIGNED_REAL))))))) operand2: (simple_expression (primary_expression (component_reference identifier: (IDENT)))))))))))))) endIdentifier: (IDENT)))))"; +const parsedModelicaTestString = + '(stored_definitions storedDefinitions: (stored_definition classDefinition: (class_definition classPrefixes: (class_prefixes) classSpecifier: (long_class_specifier identifier: (IDENT) descriptionString: (description_string value: (STRING)) (element_list element: (named_element componentClause: (component_clause typeSpecifier: (type_specifier name: (name identifier: (IDENT))) componentDeclarations: (component_list componentDeclaration: (component_declaration declaration: (declaration identifier: (IDENT) modification: (modification classModification: (class_modification arguments: (argument_list argument: (element_modification name: (name identifier: (IDENT)) modification: (modification expression: (expression (simple_expression (primary_expression (literal_expression (unsigned_integer_literal_expression (UNSIGNED_INTEGER)))))))) argument: (element_modification name: (name identifier: (IDENT)) modification: (modification expression: (expression (simple_expression (primary_expression (literal_expression (logical_literal_expression))))))))))) descriptionString: (description_string value: (STRING)))))) element: (named_element componentClause: (component_clause typeSpecifier: (type_specifier name: (name identifier: (IDENT))) componentDeclarations: (component_list componentDeclaration: (component_declaration declaration: (declaration identifier: (IDENT) modification: (modification classModification: (class_modification arguments: (argument_list argument: (element_modification name: (name identifier: (IDENT))))) expression: (expression (simple_expression (binary_expression operand1: (simple_expression (unary_expression operand: (simple_expression (primary_expression (literal_expression (unsigned_real_literal_expression (UNSIGNED_REAL))))))) operand2: (simple_expression (primary_expression (component_reference identifier: (IDENT)))))))))))))) endIdentifier: (IDENT)))))'; describe('Modelica tree-sitter parser', () => { it('Initialize parser', async () => { diff --git a/server/src/util/declarations.ts b/server/src/util/declarations.ts index fbcface..eb60c68 100644 --- a/server/src/util/declarations.ts +++ b/server/src/util/declarations.ts @@ -44,15 +44,12 @@ import * as Parser from 'web-tree-sitter'; import * as TreeSitterUtil from './tree-sitter'; import { logger } from './logger'; -const isEmpty = (data: string): boolean => typeof data === "string" && data.trim().length == 0; +const isEmpty = (data: string): boolean => typeof data === 'string' && data.trim().length == 0; -export type GlobalDeclarations = { [word: string]: LSP.SymbolInformation } -export type Declarations = { [word: string]: LSP.SymbolInformation[] } +export type GlobalDeclarations = { [word: string]: LSP.SymbolInformation }; +export type Declarations = { [word: string]: LSP.SymbolInformation[] }; -const GLOBAL_DECLARATION_LEAF_NODE_TYPES = new Set([ - 'if_statement', - 'function_definition', -]); +const GLOBAL_DECLARATION_LEAF_NODE_TYPES = new Set(['if_statement', 'function_definition']); /** * Returns all declarations (functions or variables) from a given tree. @@ -81,7 +78,10 @@ export function getAllDeclarationsInTree(tree: Parser.Tree, uri: string): LSP.Sy * @param uri The document's uri. * @returns Symbol information from node. */ -export function nodeToSymbolInformation(node: Parser.SyntaxNode, uri: string): LSP.SymbolInformation | null { +export function nodeToSymbolInformation( + node: Parser.SyntaxNode, + uri: string, +): LSP.SymbolInformation | null { const named = node.firstNamedChild; if (named === null) { @@ -96,8 +96,8 @@ export function nodeToSymbolInformation(node: Parser.SyntaxNode, uri: string): L const kind = getKind(node); const containerName = - TreeSitterUtil.findParent(node, (p) => p.type === 'function_definition') - ?.firstNamedChild?.text || ''; + TreeSitterUtil.findParent(node, (p) => p.type === 'function_definition')?.firstNamedChild + ?.text || ''; return LSP.SymbolInformation.create( name, @@ -115,7 +115,10 @@ export function nodeToSymbolInformation(node: Parser.SyntaxNode, uri: string): L * @param uri The associated URI for this document. * @returns LSP symbol information for definition. */ -function getDeclarationSymbolFromNode(node: Parser.SyntaxNode, uri: string): LSP.SymbolInformation | null { +function getDeclarationSymbolFromNode( + node: Parser.SyntaxNode, + uri: string, +): LSP.SymbolInformation | null { if (TreeSitterUtil.isDefinition(node)) { return nodeToSymbolInformation(node, uri); } @@ -130,7 +133,6 @@ function getDeclarationSymbolFromNode(node: Parser.SyntaxNode, uri: string): LSP * @returns Symbol kind or `undefined`. */ function getKind(node: Parser.SyntaxNode): LSP.SymbolKind | undefined { - const classPrefixes = TreeSitterUtil.getClassPrefixes(node)?.split(/\s+/); if (classPrefixes === undefined) { return undefined; diff --git a/server/src/util/logger.ts b/server/src/util/logger.ts index be3df8d..2e33c09 100644 --- a/server/src/util/logger.ts +++ b/server/src/util/logger.ts @@ -45,10 +45,10 @@ export const LOG_LEVEL_ENV_VAR = 'MODELICA_IDE_LOG_LEVEL'; export const LOG_LEVELS = ['debug', 'log', 'info', 'warning', 'error'] as const; export const DEFAULT_LOG_LEVEL: LogLevel = 'info'; -type LogLevel = (typeof LOG_LEVELS)[number] +type LogLevel = (typeof LOG_LEVELS)[number]; const LOG_LEVELS_TO_MESSAGE_TYPES: { - [logLevel in LogLevel]: LSP.MessageType + [logLevel in LogLevel]: LSP.MessageType; } = { debug: LSP.MessageType.Debug, log: LSP.MessageType.Log, @@ -87,7 +87,7 @@ export class Logger { [LSP.MessageType.Warning]: 'WARNING ⛔️', [LSP.MessageType.Info]: 'INFO', [LSP.MessageType.Log]: 'LOG', - [LSP.MessageType.Debug]: 'DEBUG' + [LSP.MessageType.Debug]: 'DEBUG', }; public log(severity: LSP.MessageType, messageObjects: any[]) { @@ -165,4 +165,4 @@ export function getLogLevelFromEnvironment(): LSP.MessageType { } return LOG_LEVELS_TO_MESSAGE_TYPES[DEFAULT_LOG_LEVEL]; -} \ No newline at end of file +} diff --git a/server/src/util/test/declarations.test.ts b/server/src/util/test/declarations.test.ts index 9e01d5b..4119634 100644 --- a/server/src/util/test/declarations.test.ts +++ b/server/src/util/test/declarations.test.ts @@ -49,19 +49,21 @@ end foo; type Temperature = Real(unit = "K"); `; -const expectedDefinitions = ["M", "foo", "Temperature"]; +const expectedDefinitions = ['M', 'foo', 'Temperature']; const expectedTypes = [LSP.SymbolKind.Class, LSP.SymbolKind.Function, LSP.SymbolKind.TypeParameter]; describe('nodeToSymbolInformation', () => { it('type to TypeParameter', async () => { - const parser = await initializeParser(); - const tree = parser.parse("type Temperature = Real(unit = \"K \");"); + const parser = await initializeParser(); + const tree = parser.parse('type Temperature = Real(unit = "K ");'); - const classNode = tree.rootNode.childForFieldName('storedDefinitions')!.childForFieldName('classDefinition')!; - const symbol = nodeToSymbolInformation(classNode, "file.mo"); + const classNode = tree.rootNode + .childForFieldName('storedDefinitions')! + .childForFieldName('classDefinition')!; + const symbol = nodeToSymbolInformation(classNode, 'file.mo'); - assert.equal(symbol?.name, 'Temperature'); - assert.equal(symbol?.kind, LSP.SymbolKind.TypeParameter); + assert.equal(symbol?.name, 'Temperature'); + assert.equal(symbol?.kind, LSP.SymbolKind.TypeParameter); }); }); @@ -69,7 +71,7 @@ describe('getAllDeclarationsInTree', () => { it('Definitions and types', async () => { const parser = await initializeParser(); const tree = parser.parse(modelicaTestString); - const symbols = getAllDeclarationsInTree(tree, "file.mo"); + const symbols = getAllDeclarationsInTree(tree, 'file.mo'); const definitions: string[] = []; const types: LSP.SymbolKind[] = []; diff --git a/server/src/util/test/util.test.ts b/server/src/util/test/util.test.ts index 1476970..ad519f5 100644 --- a/server/src/util/test/util.test.ts +++ b/server/src/util/test/util.test.ts @@ -41,8 +41,10 @@ import * as TreeSitterUtil from '../tree-sitter'; describe('getIdentifier', () => { it('Identifier of type class', async () => { const parser = await initializeParser(); - const tree = parser.parse("type Temperature = Real(unit = \"K \");"); - const classNode = tree.rootNode.childForFieldName('storedDefinitions')!.childForFieldName('classDefinition')!; + const tree = parser.parse('type Temperature = Real(unit = "K ");'); + const classNode = tree.rootNode + .childForFieldName('storedDefinitions')! + .childForFieldName('classDefinition')!; const name = TreeSitterUtil.getIdentifier(classNode); assert.equal(name, 'Temperature'); diff --git a/server/src/util/tree-sitter.ts b/server/src/util/tree-sitter.ts index 90a37b2..f159ce5 100644 --- a/server/src/util/tree-sitter.ts +++ b/server/src/util/tree-sitter.ts @@ -65,15 +65,17 @@ export function forEach(node: SyntaxNode, callback: (n: SyntaxNode) => void | bo * @param start The node to start iterating from * @param callback Callback returning true if node is searched node. */ -export function findFirst(start: SyntaxNode, callback: (n: SyntaxNode) => boolean): SyntaxNode | null { - +export function findFirst( + start: SyntaxNode, + callback: (n: SyntaxNode) => boolean, +): SyntaxNode | null { const cursor = start.walk(); let reachedRoot = false; let retracing = false; while (!reachedRoot) { const node = cursor.currentNode(); - if (callback(node) === true ) { + if (callback(node) === true) { return node; } @@ -87,14 +89,14 @@ export function findFirst(start: SyntaxNode, callback: (n: SyntaxNode) => boolea retracing = true; while (retracing) { - if (!cursor.gotoParent()) { - retracing = false; - reachedRoot = true; - } + if (!cursor.gotoParent()) { + retracing = false; + reachedRoot = true; + } - if (cursor.gotoNextSibling()) { + if (cursor.gotoNextSibling()) { retracing = false; - } + } } } @@ -145,7 +147,6 @@ export function findParent( * @param start Syntax tree node. */ export function getIdentifier(start: SyntaxNode): string | undefined { - const node = findFirst(start, (n: SyntaxNode) => n.type == 'IDENT'); return node?.text; } @@ -157,7 +158,6 @@ export function getIdentifier(start: SyntaxNode): string | undefined { * @returns String with class prefixes or `null` if no `class_prefixes` can be found. */ export function getClassPrefixes(node: SyntaxNode): string | null { - if (node.type !== 'class_definition') { return null; }