From ab55fb23f367fe8972f67e5c2ed7d63e179d64f8 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Thu, 23 May 2024 14:43:27 +0200 Subject: [PATCH] Add test for incremental parsing --- server/src/analyzer.ts | 8 +++--- server/src/project/document.ts | 32 +++++++++++++----------- server/src/project/test/document.test.ts | 21 ++++++++++++++++ server/src/server.ts | 4 +-- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/server/src/analyzer.ts b/server/src/analyzer.ts index 4c28edb..609184e 100644 --- a/server/src/analyzer.ts +++ b/server/src/analyzer.ts @@ -98,8 +98,8 @@ export default class Analyzer { * @param uri uri to document to add * @throws if the document does not belong to a library */ - public addDocument(uri: LSP.DocumentUri): void { - this.#project.addDocument(uriToPath(uri)); + public async addDocument(uri: LSP.DocumentUri): Promise { + await this.#project.addDocument(uriToPath(uri)); } /** @@ -110,8 +110,8 @@ export default class Analyzer { * @param text the modification * @param range range to update, or `undefined` to replace the whole file */ - public updateDocument(uri: LSP.DocumentUri, text: string, range?: LSP.Range): void { - this.#project.updateDocument(url.fileURLToPath(uri), text, range); + public async updateDocument(uri: LSP.DocumentUri, text: string, range?: LSP.Range): Promise { + await this.#project.updateDocument(url.fileURLToPath(uri), text, range); } /** diff --git a/server/src/project/document.ts b/server/src/project/document.ts index 81afeb0..ea7e26c 100644 --- a/server/src/project/document.ts +++ b/server/src/project/document.ts @@ -33,16 +33,15 @@ * */ -import { TextDocument } from "vscode-languageserver-textdocument"; -import * as LSP from "vscode-languageserver/node"; -import Parser from "web-tree-sitter"; -import * as fs from "node:fs/promises"; -import * as url from "node:url"; -import * as TreeSitterUtil from "../util/tree-sitter"; - -import { logger } from "../util/logger"; -import { ModelicaLibrary } from "./library"; -import { ModelicaProject } from "./project"; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import * as LSP from 'vscode-languageserver/node'; +import Parser from 'web-tree-sitter'; +import * as fs from 'node:fs/promises'; +import * as TreeSitterUtil from '../util/tree-sitter'; + +import { logger } from '../util/logger'; +import { ModelicaLibrary } from './library'; +import { ModelicaProject } from './project'; import { positionToPoint } from '../util/tree-sitter'; import { pathToUri, uriToPath } from '../util'; @@ -52,7 +51,12 @@ export class ModelicaDocument implements TextDocument { readonly #document: TextDocument; #tree: Parser.Tree; - public constructor(project: ModelicaProject, library: ModelicaLibrary | null, document: TextDocument, tree: Parser.Tree) { + public constructor( + project: ModelicaProject, + library: ModelicaLibrary | null, + document: TextDocument, + tree: Parser.Tree, + ) { this.#project = project; this.#library = library; this.#document = document; @@ -182,7 +186,7 @@ export class ModelicaDocument implements TextDocument { public get within(): string[] { const withinClause = this.#tree.rootNode.children .find((node) => node.type === 'within_clause') - ?.childForFieldName("name"); + ?.childForFieldName('name'); if (!withinClause) { return []; } @@ -190,11 +194,11 @@ export class ModelicaDocument implements TextDocument { // TODO: Use a helper function from TreeSitterUtil const identifiers: string[] = []; TreeSitterUtil.forEach(withinClause, (node) => { - if (node.type === "name") { + if (node.type === 'name') { return true; } - if (node.type === "IDENT") { + if (node.type === 'IDENT') { identifiers.push(node.text); } diff --git a/server/src/project/test/document.test.ts b/server/src/project/test/document.test.ts index 09f7431..24472ed 100644 --- a/server/src/project/test/document.test.ts +++ b/server/src/project/test/document.test.ts @@ -82,6 +82,27 @@ describe('ModelicaDocument', () => { assert.equal(document.getText().trim(), UPDATED_TEST_PACKAGE_CONTENT.trim()); }); + it('can update incrementally', () => { + const textDocument = createTextDocument('.', TEST_PACKAGE_CONTENT); + const tree = project.parser.parse(TEST_PACKAGE_CONTENT); + const document = new ModelicaDocument(project, library, textDocument, tree); + document.update( + '1.0.1', + { + start: { + line: 1, + character: 22, + }, + end: { + line: 1, + character: 27, + }, + } + ); + + assert.equal(document.getText().trim(), UPDATED_TEST_PACKAGE_CONTENT.trim()); + }); + it('a file with no `within` clause has the correct package path', () => { const textDocument = createTextDocument('./package.mo', TEST_PACKAGE_CONTENT); const tree = project.parser.parse(TEST_PACKAGE_CONTENT); diff --git a/server/src/server.ts b/server/src/server.ts index 912a78d..5ac20d0 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -151,7 +151,7 @@ export class ModelicaServer { logger.debug('onDidChangeTextDocument'); for (const change of params.contentChanges) { const range = 'range' in change ? change.range : undefined; - this.#analyzer.updateDocument(params.textDocument.uri, change.text, range); + await this.#analyzer.updateDocument(params.textDocument.uri, change.text, range); } } @@ -161,7 +161,7 @@ export class ModelicaServer { for (const change of params.changes) { switch (change.type) { case LSP.FileChangeType.Created: - this.#analyzer.addDocument(change.uri); + await this.#analyzer.addDocument(change.uri); break; case LSP.FileChangeType.Changed: { // TODO: incremental?