Skip to content

Commit

Permalink
feat: sync 2.0.0-alpha.14 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Jan 17, 2024
1 parent a59ed41 commit 4fb25e9
Show file tree
Hide file tree
Showing 37 changed files with 188 additions and 165 deletions.
2 changes: 1 addition & 1 deletion packages/eslint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function create(resolveConfig?: (program: ts.Program) => Linter.Config):
const eslint = getEslint(languageService.getProgram()!);
const lintResult = await eslint.lintText(
document.getText(),
{ filePath: context.env.uriToFileName(document.uri) },
{ filePath: context.env.typescript.uriToFileName(document.uri) },
);
uriToLintResult.set(document.uri, lintResult);
const diagnostics: Diagnostic[] = [];
Expand Down
29 changes: 16 additions & 13 deletions packages/markdown/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { forEachEmbeddedFile, type FileChangeType, type FileType, type ServicePlugin, ServicePluginInstance } from '@volar/language-service';
import { forEachEmbeddedCode, type FileChangeType, type FileType, type ServicePlugin, ServicePluginInstance } from '@volar/language-service';
import { Emitter } from 'vscode-jsonrpc';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import type { DiagnosticOptions, ILogger, IMdLanguageService, IMdParser, IWorkspace } from 'vscode-markdown-languageservice';
Expand Down Expand Up @@ -146,10 +146,11 @@ export function create(options: CreateOptions): ServicePlugin {

const sync = () => {

const languageServiceHost = context.language.typescript?.languageServiceHost;
if (!languageServiceHost)
if (!context.typescript) {
return;
}

const { languageServiceHost } = context.typescript;
const newProjectVersion = languageServiceHost.getProjectVersion?.();
const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
if (!shouldUpdate) {
Expand All @@ -161,11 +162,13 @@ export function create(options: CreateOptions): ServicePlugin {
const newVersions = new Map<string, TextDocument>();

for (const fileName of languageServiceHost.getScriptFileNames()) {
const [_, sourceFile] = context.language.files.getVirtualFile(fileName);
if (sourceFile?.virtualFile) {
for (const virtualFile of Array.from(forEachEmbeddedFile(sourceFile.virtualFile[0]))) {
if (virtualFile.languageId === 'markdown') {
const document = context.documents.get(virtualFile.fileName, virtualFile.languageId, virtualFile.snapshot);
const uri = context.env.typescript.fileNameToUri(fileName);
const [_, sourceFile] = context.documents.getVirtualCodeByUri(uri);
if (sourceFile?.generated) {
for (const virtualCode of forEachEmbeddedCode(sourceFile.generated.code)) {
if (virtualCode.languageId === 'markdown') {
const uri = context.documents.getVirtualCodeUri(sourceFile.id, virtualCode.id);
const document = context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
newVersions.set(document.uri, document);
}
}
Expand Down Expand Up @@ -327,13 +330,13 @@ export function create(options: CreateOptions): ServicePlugin {

function getTextDocument(uri: string, includeVirtualFile: boolean) {
if (includeVirtualFile) {
const virtualFile = context.language.files.getVirtualFile(context.env.uriToFileName(uri))[0];
if (virtualFile) {
return context.documents.get(uri, virtualFile.languageId, virtualFile.snapshot);
const virtualCode = context.documents.getVirtualCodeByUri(uri)[0];
if (virtualCode) {
return context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
}
}
const sourceFile = context.language.files.getSourceFile(context.env.uriToFileName(uri));
if (sourceFile && !sourceFile.virtualFile) {
const sourceFile = context.files.get(uri);
if (sourceFile) {
return context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/prettier/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ServicePluginInstance, ServicePlugin, ServiceEnvironment } from '@volar/language-service';
import type { Options, ResolveConfigOptions } from 'prettier';
import { URI } from 'vscode-uri';

export function create(
options: {
Expand Down Expand Up @@ -68,7 +69,7 @@ export function create(
return;
}

const filePath = context.env.uriToFileName(document.uri);
const filePath = URI.parse(document.uri).fsPath;
const fileInfo = await prettier.getFileInfo(filePath, { ignorePath: '.prettierignore', resolveConfig: false });

if (fileInfo.ignored) {
Expand Down
3 changes: 3 additions & 0 deletions packages/prettier/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
"email": "[email protected]",
"url": "https://www.polv.cc"
},
"dependencies": {
"vscode-uri": "^3.0.8"
},
"devDependencies": {
"@types/node": "latest",
"prettier": "^3.0.3"
Expand Down
3 changes: 2 additions & 1 deletion packages/tslint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export function create(rules: IRule[]): ServicePlugin {
provideSemanticDiagnostics(document, token) {

const languageService = context.inject<Provide, 'typescript/languageService'>('typescript/languageService');
const sourceFile = languageService.getProgram()?.getSourceFile(context.env.uriToFileName(document.uri));
const fileName = context.env.typescript.uriToFileName(document.uri);
const sourceFile = languageService.getProgram()?.getSourceFile(fileName);
if (!sourceFile) {
return;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/typescript-twoslash-queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export function create(): ServicePlugin {
character: pointerPosition.character,
});

const quickInfo = languageService.getQuickInfoAtPosition(context.env.uriToFileName(document.uri), hoverOffset);
const fileName = context.env.typescript.uriToFileName(document.uri);
const quickInfo = languageService.getQuickInfoAtPosition(fileName, hoverOffset);
if (quickInfo) {
inlayHints.push({
position: { line: pointerPosition.line, character: pointerPosition.character + 2 },
Expand Down
136 changes: 75 additions & 61 deletions packages/typescript/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { CancellationToken, CompletionList, CompletionTriggerKind, FileChangeType, ServicePluginInstance, ServicePlugin } from '@volar/language-service';
import * as semver from 'semver';
import type * as ts from 'typescript';
import { TextDocument } from 'vscode-languageserver-textdocument';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { getConfigTitle, isJsonDocument, isTsDocument } from './lib/shared';
import { URI } from 'vscode-uri';

import { getDocumentRegistry } from '@volar/typescript';
import * as tsFaster from 'typescript-auto-import-cache';
Expand Down Expand Up @@ -38,7 +39,6 @@ export * from '@volar/typescript';

export interface Provide {
'typescript/typescript': () => typeof import('typescript');
'typescript/sys': () => ts.System;
'typescript/languageService': () => ts.LanguageService;
'typescript/languageServiceHost': () => ts.LanguageServiceHost;
'typescript/syntacticLanguageService': () => ts.LanguageService;
Expand Down Expand Up @@ -75,30 +75,26 @@ export function create(ts: typeof import('typescript')): ServicePlugin {
};
const syntacticCtx: SharedContext = {
...context,
typescript: {
languageServiceHost: syntacticServiceHost,
languageService: ts.createLanguageService(syntacticServiceHost, undefined, 2 satisfies ts.LanguageServiceMode.Syntactic),
},
languageServiceHost: syntacticServiceHost,
languageService: ts.createLanguageService(syntacticServiceHost, undefined, 2 satisfies ts.LanguageServiceMode.Syntactic),
ts,
getTextDocument(uri) {
const fileName = context.env.uriToFileName(uri);
const virtualFile = context.language.files.getVirtualFile(fileName)[0];
if (virtualFile) {
return context.documents.get(uri, virtualFile.languageId, virtualFile.snapshot);
uriToFileName: uri => {
if (uri !== syntacticHostCtx.document?.uri) {
throw new Error(`uriToFileName: uri not found: ${uri}`);
}
const sourceFile = context.language.files.getSourceFile(fileName);
if (sourceFile && !sourceFile.virtualFile) {
return context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
return syntacticHostCtx.fileName;
},
fileNameToUri: fileName => {
if (fileName !== syntacticHostCtx.fileName) {
throw new Error(`fileNameToUri: fileName not found: ${fileName}`);
}
const snapshot = syntacticServiceHost.getScriptSnapshot(fileName);
if (snapshot) {
let document = documents.get(snapshot);
if (!document) {
document = TextDocument.create(uri, '', 0, snapshot.getText(0, snapshot.getLength()));
documents.set(snapshot, document);
}
return document;
return syntacticHostCtx.document!.uri;
},
getTextDocument(uri) {
if (uri !== syntacticHostCtx.document?.uri) {
throw new Error(`getTextDocument: uri not found: ${uri}`);
}
return syntacticHostCtx.document;
},
};
const findDocumentSymbols = documentSymbol.register(syntacticCtx);
Expand All @@ -108,11 +104,10 @@ export function create(ts: typeof import('typescript')): ServicePlugin {

provide: {
'typescript/typescript': () => ts,
'typescript/sys': () => sys,
'typescript/languageService': () => syntacticCtx.typescript.languageService,
'typescript/languageServiceHost': () => syntacticCtx.typescript.languageServiceHost,
'typescript/syntacticLanguageService': () => syntacticCtx.typescript.languageService,
'typescript/syntacticLanguageServiceHost': () => syntacticCtx.typescript.languageServiceHost,
'typescript/languageService': () => syntacticCtx.languageService,
'typescript/languageServiceHost': () => syntacticCtx.languageServiceHost,
'typescript/syntacticLanguageService': () => syntacticCtx.languageService,
'typescript/syntacticLanguageServiceHost': () => syntacticCtx.languageServiceHost,
},

provideAutoInsertionEdit(document, position, lastChange) {
Expand All @@ -123,9 +118,8 @@ export function create(ts: typeof import('typescript')): ServicePlugin {
const config = context.env.getConfiguration?.<boolean>(getConfigTitle(document) + '.autoClosingTags') ?? true;
if (config) {

prepareSyntacticService(document);

const close = syntacticCtx.typescript.languageService.getJsxClosingTagAtPosition(context.env.uriToFileName(document.uri), document.offsetAt(position));
const ctx = prepareSyntacticService(document);
const close = syntacticCtx.languageService.getJsxClosingTagAtPosition(ctx.fileName, document.offsetAt(position));

if (close) {
return '$0' + close.newText;
Expand Down Expand Up @@ -189,7 +183,8 @@ export function create(ts: typeof import('typescript')): ServicePlugin {
if (!isTsDocument(document))
return;

const sourceFile = ts.createSourceFile(context.env.uriToFileName(document.uri), document.getText(), ts.ScriptTarget.ESNext);
const ctx = prepareSyntacticService(document);
const sourceFile = ts.createSourceFile(ctx.fileName, document.getText(), ts.ScriptTarget.ESNext);

if (sourceFile) {

Expand Down Expand Up @@ -223,11 +218,11 @@ export function create(ts: typeof import('typescript')): ServicePlugin {
snapshot: ts.ScriptSnapshot.fromString(''),
};

if (!context.language.typescript) {
if (!context.typescript) {
return syntacticService;
}

const { sys, languageServiceHost, synchronizeFileSystem } = context.language.typescript;
const { sys, languageServiceHost } = context.typescript;
const created = tsFaster.createLanguageService(
ts,
sys,
Expand Down Expand Up @@ -264,7 +259,7 @@ export function create(ts: typeof import('typescript')): ServicePlugin {
updateSourceScriptFileNames();
}
for (const change of params.changes) {
const fileName = context.env.uriToFileName(change.uri);
const fileName = context.env.typescript.uriToFileName(change.uri);
if (sourceScriptNames.has(normalizeFileName(fileName))) {
created.projectUpdated?.(languageServiceHost.getCurrentDirectory());
}
Expand All @@ -274,35 +269,53 @@ export function create(ts: typeof import('typescript')): ServicePlugin {
function updateSourceScriptFileNames() {
sourceScriptNames.clear();
for (const fileName of languageServiceHost.getScriptFileNames()) {
const virtualFile = context.language.files.getVirtualFile(fileName);
if (virtualFile) {
sourceScriptNames.add(normalizeFileName(fileName));
continue;
const uri = context.env.typescript.fileNameToUri(fileName);
const sourceFile = context.files.get(uri);
if (sourceFile?.generated) {
const tsCode = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
if (tsCode) {
sourceScriptNames.add(normalizeFileName(fileName));
}
}
const sourceFile = context.language.files.getSourceFile(fileName);
if (sourceFile && !sourceFile.virtualFile) {
else if (sourceFile) {
sourceScriptNames.add(normalizeFileName(fileName));
continue;
}
}
}
}

const documents = new WeakMap<ts.IScriptSnapshot, TextDocument>();
const semanticCtx: SharedContext = {
...syntacticCtx,
typescript: {
languageServiceHost,
languageService,
...context,
languageServiceHost,
languageService,
ts,
uriToFileName: uri => {
const [_virtualCode, file] = context.documents.getVirtualCodeByUri(uri);
if (file) {
return context.env.typescript.uriToFileName(file.id);
}
else {
return context.env.typescript.uriToFileName(uri);
}
},
fileNameToUri: fileName => {
const uri = context.env.typescript.fileNameToUri(fileName);
const file = context.files.get(uri);
if (file?.generated) {
const script = file.generated.languagePlugin.typescript?.getScript(file.generated.code);
if (script) {
return context.documents.getVirtualCodeUri(uri, script.code.id);
}
}
return uri;
},
getTextDocument(uri) {
const fileName = context.env.uriToFileName(uri);
const virtualFile = context.language.files.getVirtualFile(fileName)[0];
if (virtualFile) {
return context.documents.get(uri, virtualFile.languageId, virtualFile.snapshot);
const virtualCode = context.documents.getVirtualCodeByUri(uri)[0];
if (virtualCode) {
return context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
}
const sourceFile = context.language.files.getSourceFile(fileName);
if (sourceFile && !sourceFile.virtualFile) {
const sourceFile = context.files.get(uri);
if (sourceFile) {
return context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
}
},
Expand Down Expand Up @@ -609,27 +622,28 @@ export function create(ts: typeof import('typescript')): ServicePlugin {

async function worker<T>(token: CancellationToken, callback: () => T): Promise<Awaited<T>> {

let oldSysVersion = await synchronizeFileSystem?.();
let oldSysVersion = await sys.sync?.();
let result = await callback();
let newSysVersion = await synchronizeFileSystem?.();
let newSysVersion = await sys.sync?.();

while (newSysVersion !== oldSysVersion && !token.isCancellationRequested) {
oldSysVersion = newSysVersion;
result = await callback();
newSysVersion = await synchronizeFileSystem?.();
newSysVersion = await sys.sync?.();
}

return result;
}

function prepareSyntacticService(document: TextDocument) {
if (syntacticHostCtx.document === document && syntacticHostCtx.fileVersion === document.version) {
return;
if (syntacticHostCtx.document !== document || syntacticHostCtx.fileVersion !== document.version) {
syntacticHostCtx.document = document;
syntacticHostCtx.fileName = URI.parse(document.uri).fsPath.replace(/\\/g, '/');
syntacticHostCtx.fileVersion = document.version;
syntacticHostCtx.snapshot = ts.ScriptSnapshot.fromString(document.getText());
syntacticHostCtx.projectVersion++;
}
syntacticHostCtx.fileName = context.env.uriToFileName(document.uri);
syntacticHostCtx.fileVersion = document.version;
syntacticHostCtx.snapshot = ts.ScriptSnapshot.fromString(document.getText());
syntacticHostCtx.projectVersion++;
return syntacticHostCtx;
}
},
};
Expand Down
2 changes: 1 addition & 1 deletion packages/typescript/lib/configs/getUserPreferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function getUserPreferences(
includeCompletionsWithSnippetText: config.suggest?.includeCompletionsWithSnippetText ?? true,
includeCompletionsWithClassMemberSnippets: config.suggest?.classMemberSnippets?.enabled ?? true,
includeCompletionsWithObjectLiteralMethodSnippets: config.suggest?.objectLiteralMethodSnippets?.enabled ?? true,
autoImportFileExcludePatterns: getAutoImportFileExcludePatternsPreference(preferencesConfig, ctx.typescript.languageServiceHost.getCurrentDirectory()),
autoImportFileExcludePatterns: getAutoImportFileExcludePatternsPreference(preferencesConfig, ctx.languageServiceHost.getCurrentDirectory()),
useLabelDetailsInCompletionEntries: true,
allowIncompleteCompletions: true,
displayPartsForJSDoc: true,
Expand Down

0 comments on commit 4fb25e9

Please sign in to comment.