Skip to content

Commit

Permalink
Add incremental parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
ehedbor authored and PaddiM8 committed May 29, 2024
1 parent 5cb52b8 commit d1b6a0e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 28 deletions.
6 changes: 3 additions & 3 deletions server/src/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ import * as fsSync from 'node:fs';
import * as url from 'node:url';

import { ModelicaDocument, ModelicaLibrary, ModelicaProject } from './project';
import { uriToPath } from "./util";
import { getAllDeclarationsInTree } from './util/declarations';
import { logger } from './util/logger';
import { uriToPath } from './util';

export default class Analyzer {
#project: ModelicaProject;
Expand Down Expand Up @@ -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 async updateDocument(uri: LSP.DocumentUri, text: string): Promise<void> {
await this.#project.updateDocument(uriToPath(uri), text);
public updateDocument(uri: LSP.DocumentUri, text: string, range?: LSP.Range): void {
this.#project.updateDocument(url.fileURLToPath(uri), text, range);
}

/**
Expand Down
70 changes: 57 additions & 13 deletions server/src/project/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@
*
*/

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 { 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 { positionToPoint } from '../util/tree-sitter';
import { pathToUri, uriToPath } from '../util';
import { logger } from '../util/logger';
import { ModelicaLibrary } from './library';
import { ModelicaProject } from './project';

export class ModelicaDocument implements TextDocument {
readonly #project: ModelicaProject;
Expand Down Expand Up @@ -90,12 +92,54 @@ export class ModelicaDocument implements TextDocument {

/**
* Updates a document.
*
* @param text the modification
* @param range the range to update, or `undefined` to replace the whole file
*/
public async update(text: string): Promise<void> {
TextDocument.update(this.#document, [{ text }], this.version + 1);
this.#tree = this.project.parser.parse(text);
return;
public async update(text: string, range?: LSP.Range): Promise<void> {
if (range === undefined) {
TextDocument.update(this.#document, [{ text }], this.version + 1);
this.#tree = this.project.parser.parse(text);
return;
}

const startIndex = this.offsetAt(range.start);
const startPosition = positionToPoint(range.start);
const oldEndIndex = this.offsetAt(range.end);
const oldEndPosition = positionToPoint(range.end);
const newEndIndex = startIndex + text.length;

TextDocument.update(this.#document, [{ text, range }], this.version + 1);
const newEndPosition = positionToPoint(this.positionAt(newEndIndex));

this.#tree.edit({
startIndex,
startPosition,
oldEndIndex,
oldEndPosition,
newEndIndex,
newEndPosition,
});

this.#tree = this.project.parser.parse((index: number, position?: Parser.Point) => {
if (position) {
return this.getText({
start: {
character: position.column,
line: position.row,
},
end: {
character: position.column + 1,
line: position.row,
},
});
} else {
return this.getText({
start: this.positionAt(index),
end: this.positionAt(index + 1),
});
}
}, this.#tree);
}

public getText(range?: LSP.Range | undefined): string {
Expand Down
19 changes: 9 additions & 10 deletions server/src/project/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
*
*/

import Parser from "web-tree-sitter";
import * as LSP from "vscode-languageserver";
import url from "node:url";
import path from "node:path";
import Parser from 'web-tree-sitter';
import * as LSP from 'vscode-languageserver';
import url from 'node:url';
import path from 'node:path';

import { ModelicaLibrary } from "./library";
import { ModelicaLibrary } from './library';
import { ModelicaDocument } from './document';
import { logger } from "../util/logger";
import { logger } from '../util/logger';

/** Options for {@link ModelicaProject.getDocument} */
export interface GetDocumentOptions {
Expand Down Expand Up @@ -117,7 +117,7 @@ export class ModelicaProject {

for (const library of this.#libraries) {
const relative = path.relative(library.path, documentPath);
const isSubdirectory = relative && !relative.startsWith("..") && !path.isAbsolute(relative);
const isSubdirectory = relative && !relative.startsWith('..') && !path.isAbsolute(relative);

// Assume that files can't be inside multiple libraries at the same time
if (!isSubdirectory) {
Expand Down Expand Up @@ -155,12 +155,12 @@ export class ModelicaProject {
* @param text the modification
* @returns if the document was updated
*/
public async updateDocument(documentPath: string, text: string): Promise<boolean> {
public async updateDocument(documentPath: string, text: string, range?: LSP.Range): Promise<boolean> {
logger.debug(`Updating document at '${documentPath}'...`);

const doc = await this.getDocument(documentPath, { load: true });
if (doc) {
doc.update(text);
doc.update(text, range);
logger.debug(`Updated document '${documentPath}'`);
return true;
} else {
Expand Down Expand Up @@ -191,5 +191,4 @@ export class ModelicaProject {
public get parser(): Parser {
return this.#parser;
}

}
5 changes: 3 additions & 2 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class ModelicaServer {
documentSymbolProvider: true,
colorProvider: false,
semanticTokensProvider: undefined,
textDocumentSync: LSP.TextDocumentSyncKind.Full,
textDocumentSync: LSP.TextDocumentSyncKind.Incremental,
workspace: {
workspaceFolders: {
supported: true,
Expand Down Expand Up @@ -150,7 +150,8 @@ export class ModelicaServer {
private async onDidChangeTextDocument(params: LSP.DidChangeTextDocumentParams): Promise<void> {
logger.debug('onDidChangeTextDocument');
for (const change of params.contentChanges) {
await this.#analyzer.updateDocument(params.textDocument.uri, change.text);
const range = 'range' in change ? change.range : undefined;
this.#analyzer.updateDocument(params.textDocument.uri, change.text, range);
}
}

Expand Down
9 changes: 9 additions & 0 deletions server/src/util/tree-sitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* -----------------------------------------------------------------------------
*/

import Parser from 'web-tree-sitter';
import * as LSP from 'vscode-languageserver/node';
import { SyntaxNode } from 'web-tree-sitter';

Expand Down Expand Up @@ -169,3 +170,11 @@ export function getClassPrefixes(node: SyntaxNode): string | null {

return classPrefixNode.text;
}

export function positionToPoint(position: LSP.Position): Parser.Point {
return { row: position.line, column: position.character };
}

export function pointToPosition(point: Parser.Point): LSP.Position {
return { line: point.row, character: point.column };
}

0 comments on commit d1b6a0e

Please sign in to comment.