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

Enhance LSP for multi-editor support #38

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 2 additions & 22 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,12 @@ import {
} from 'vscode-languageclient/node';

// tslint:disable-next-line:no-duplicate-imports
import {
workspace, ExtensionContext, DiagnosticCollection,
languages, TextDocument,
FormattingOptions, CancellationToken,
ProviderResult, TextEdit,
DocumentSelector
} from 'vscode';

import { formatDocument } from './formatter';
import { workspace, ExtensionContext } from 'vscode';

let diagnosticCollection: DiagnosticCollection;
let clientDisposable: LanguageClient;

export async function activate(context: ExtensionContext) {
const ws = workspace.workspaceFolders;
diagnosticCollection = languages.createDiagnosticCollection('tact');

context.subscriptions.push(diagnosticCollection);

context.subscriptions.push(
languages.registerDocumentFormattingEditProvider('tact', {
provideDocumentFormattingEdits(document: TextDocument, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
return Promise.resolve(formatDocument(document, context));
},
})
);

const serverModule = path.join(__dirname, './server.js');

Expand Down Expand Up @@ -81,4 +61,4 @@ export function deactivate(): Thenable<void> | undefined {
return undefined;
}
return clientDisposable.stop();
}
}
62 changes: 33 additions & 29 deletions src/formatter.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
import * as prettier from 'prettier';
import { workspace, ExtensionContext, Range, TextDocument, TextEdit } from 'vscode';
import * as path from 'path';
import { TextEdit, Range } from 'vscode-languageserver-types';
import { TextDocument } from 'vscode-languageserver-textdocument';

export function formatDocument(document: TextDocument, context: ExtensionContext): TextEdit[] | undefined {
const rootPath = workspace.getWorkspaceFolder(document.uri)?.name;

const ignoreOptions = { ignorePath: path.join(rootPath ? rootPath: "", '.prettierignore') };

const fileInfo = prettier.getFileInfo.sync(document.uri.fsPath, ignoreOptions);

if (!fileInfo.ignored) {
const source = document.getText();
// @TODO create npm module later
const pluginPath = path.join(context.extensionPath, 'out', 'prettier-plugin-tact', 'prettier-plugin-tact.js'); // 'node_modules',
const options = {
export function formatDocument(document: TextDocument, rootPath: string): TextEdit[] | undefined {

if (rootPath) {
const ignoreOptions = { ignorePath: path.join(rootPath, '.prettierignore') };
const fileInfo = prettier.getFileInfo.sync(document.uri, ignoreOptions);
if (fileInfo.ignored) return;
}

const lspPath = __dirname;

const source = document.getText();
// @TODO create npm module later
const pluginPath = path.join(lspPath, 'prettier-plugin-tact', 'prettier-plugin-tact.js'); // 'node_modules',
const options = {
'parser': 'tact-parser',
'pluginSearchDirs': [context.extensionPath],
'pluginSearchDirs': [lspPath],
'plugins': [pluginPath],
};
//
const config = prettier.resolveConfig.sync(document.uri.fsPath);
if (config !== null) {
};

const config = prettier.resolveConfig.sync(document.uri);

if (config !== null) {
prettier.clearConfigCache();
}
Object.assign(options, config);

const firstLine = document.lineAt(0);
const lastLine = document.lineAt(document.lineCount - 1);
const fullTextRange = new Range(firstLine.range.start, lastLine.range.end);
let formatted = "";
try {
}
Object.assign(options, config);

const startIndex = document.positionAt(0);
const endIndex = document.positionAt(document.getText().length);

const fullTextRange = Range.create(startIndex, endIndex);
let formatted = "";
try {
formatted = prettier.format(source, options);
} catch(e) {
} catch (e) {
formatted = source;
console.log(e);
}
return [TextEdit.replace(fullTextRange, formatted)];
}
return [TextEdit.replace(fullTextRange, formatted)];
}
18 changes: 14 additions & 4 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { HoverService } from './hoverService';
import { RefactorService } from './refactorService';
import { TactCompiler } from './tactCompiler';
import { URI } from 'vscode-uri';
import { formatDocument } from './formatter';

interface Settings {
tact: TactSettings;
Expand All @@ -40,7 +41,7 @@ const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
let rootPath: string | undefined;
let tactCompiler: TactCompiler;

let enabledAsYouTypeErrorCheck = false;
let enabledAsYouTypeErrorCheck = true;
let validationDelay = 1500;

// flags to avoid trigger concurrent validations (compiling is slow)
Expand Down Expand Up @@ -68,12 +69,12 @@ async function validate(document: TextDocument) {
let newDocumentsWithErrors: any = [];
for (let fileName in compileErrorDiagnostics) {
newDocumentsWithErrors.push(URI.file(fileName).path);
connection.sendDiagnostics({diagnostics: compileErrorDiagnostics[fileName], uri: URI.file(fileName).path});
connection.sendDiagnostics({diagnostics: compileErrorDiagnostics[fileName], uri: "file://"+URI.file(fileName).path});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this. Will it work for web version? What for should we need add "file://"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the web version, similar to the Monaco editor, a few additional changes are required. I'll push those by this weekend.

}
let difference = documentsWithErrors.filter((x: any) => !newDocumentsWithErrors.includes(x));
// if an error is resolved, we must to send empty diagnostics for the URI contained it;
for(let item in difference) {
connection.sendDiagnostics({diagnostics: [], uri: difference[item]});
connection.sendDiagnostics({diagnostics: [], uri: "file://"+difference[item]});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as "file://" above.

}
documentsWithErrors = newDocumentsWithErrors;
}
Expand Down Expand Up @@ -213,7 +214,8 @@ connection.onInitialize((result): InitializeResult => {
codeActionProvider: {
resolveProvider: true
},
textDocumentSync: TextDocumentSyncKind.Full,
documentFormattingProvider: true,
textDocumentSync: TextDocumentSyncKind.Incremental,
},
};
});
Expand Down Expand Up @@ -250,6 +252,14 @@ connection.onRenameRequest((params) => {
return provider.rename(documents.get(params.textDocument.uri) as TextDocument, params.position, params.newName);
});

connection.onDocumentFormatting((params) => {
const document = documents.get(params.textDocument.uri);
if (document == undefined) {
return [];
}
return formatDocument(document as any, rootPath as string);
});

// Make the text document manager listen on the connection
// for open, change and close text document events
documents.listen(connection);
Expand Down
17 changes: 13 additions & 4 deletions src/tactCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,23 @@ export class TactCompiler {
}

const pathKey = path.relative( this.rootPath, args.file).replaceAll('\\','/');

let rootPath = this.rootPath;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we change let rootPath = this.rootPath; on let localRootPath = this.rootPath; ? just because we can misunderstand later this.rootPath and rootPath
The same below by code. We can leave this, of course, just to better read the code.
Please decide.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that would be a better.


// If the root path is not set, which occurs when a single file is opened separately, set the root path to the directory containing the file.
if(!this.isRootPathSet()) {
rootPath = path.dirname(args.file);
}

const pathContent = fs.readFileSync(pathKey);
const fsObject = {} as any;
fsObject[pathKey] = pathContent.toString('base64');
for (let pathKey in args.sources) {
fsObject[path.relative( this.rootPath, pathKey).replaceAll('\\','/')] = Buffer.from(args.sources[pathKey].content).toString('base64');
const fileContent = args.sources[pathKey].content || args.sources[pathKey];
fsObject[path.relative( rootPath, pathKey).replaceAll('\\','/')] = Buffer.from(fileContent).toString('base64');
}
const result: CheckResult = check({ project: createVirtualFileSystem(path.resolve(this.rootPath).replaceAll('\\','/'), fsObject),
entrypoint: path.relative( this.rootPath, args.file).replaceAll('\\','/')
const result: CheckResult = check({ project: createVirtualFileSystem(path.resolve(rootPath).replaceAll('\\','/'), fsObject),
entrypoint: path.relative( rootPath, args.file).replaceAll('\\','/')
});
return result;
}
Expand Down Expand Up @@ -92,4 +101,4 @@ export class TactCompiler {
return [];
}

}
}