Skip to content

Commit

Permalink
fix(typescript): virtual file should update based generated snapshot …
Browse files Browse the repository at this point in the history
…rather than source script version
  • Loading branch information
johnsoncodehk committed Mar 5, 2024
1 parent 410fa15 commit f041c79
Showing 1 changed file with 55 additions and 32 deletions.
87 changes: 55 additions & 32 deletions packages/typescript/lib/node/decorateLanguageServiceHost.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { resolveCommonLanguageId, type FileRegistry } from '@volar/language-core';
import type { FileRegistry } from '@volar/language-core';
import type * as ts from 'typescript';
import { createResolveModuleName } from '../resolveModuleName';

export function decorateLanguageServiceHost(
virtualFiles: FileRegistry,
files: FileRegistry,
languageServiceHost: ts.LanguageServiceHost,
ts: typeof import('typescript'),
) {

let extraProjectVersion = 0;

const { languagePlugins } = virtualFiles;
const { languagePlugins } = files;
const exts = languagePlugins
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
.flat();
const scripts = new Map<string, {
version: string;
projectVersion: string | undefined;
version: number;
snapshot: ts.IScriptSnapshot | undefined;
kind: ts.ScriptKind;
extension: string;
Expand All @@ -26,6 +27,7 @@ export function decorateLanguageServiceHost(
const resolveModuleNames = languageServiceHost.resolveModuleNames?.bind(languageServiceHost);
const getProjectVersion = languageServiceHost.getProjectVersion?.bind(languageServiceHost);
const getScriptSnapshot = languageServiceHost.getScriptSnapshot.bind(languageServiceHost);
const getScriptVersion = languageServiceHost.getScriptVersion.bind(languageServiceHost);
const getScriptKind = languageServiceHost.getScriptKind?.bind(languageServiceHost);

// path completion
Expand All @@ -44,7 +46,7 @@ export function decorateLanguageServiceHost(

if (languagePlugins.some(language => language.typescript?.extraFileExtensions.length)) {

const resolveModuleName = createResolveModuleName(ts, languageServiceHost, languagePlugins, fileName => virtualFiles.get(fileName));
const resolveModuleName = createResolveModuleName(ts, languageServiceHost, languagePlugins, fileName => files.get(fileName));

if (resolveModuleNameLiterals) {
languageServiceHost.resolveModuleNameLiterals = (
Expand Down Expand Up @@ -94,6 +96,13 @@ export function decorateLanguageServiceHost(
}
return getScriptSnapshot(fileName);
};
languageServiceHost.getScriptVersion = fileName => {
if (exts.some(ext => fileName.endsWith(ext))) {
updateScript(fileName);
return scripts.get(fileName)?.version.toString() ?? '';
}
return getScriptVersion(fileName);
};

if (getScriptKind) {
languageServiceHost.getScriptKind = fileName => {
Expand All @@ -111,45 +120,59 @@ export function decorateLanguageServiceHost(

function updateScript(fileName: string) {

const version = languageServiceHost.getScriptVersion(fileName);
const version = getProjectVersion?.();
const cache = scripts.get(fileName);

if (version !== scripts.get(fileName)?.version) {
if (version === undefined || version !== cache?.projectVersion) {

let extension = '.ts';
let snapshotSnapshot: ts.IScriptSnapshot | undefined;
let scriptKind = ts.ScriptKind.TS;
const file = files.get(fileName);
const script = file?.generated?.languagePlugin.typescript?.getScript(file.generated.code);

const snapshot = getScriptSnapshot(fileName);
if (script?.code.snapshot !== cache?.snapshot) {

let extension = '.ts';
let snapshotSnapshot: ts.IScriptSnapshot | undefined;
let scriptKind = ts.ScriptKind.TS;

if (snapshot) {
extraProjectVersion++;
const sourceFile = virtualFiles.set(fileName, resolveCommonLanguageId(fileName), snapshot);
if (sourceFile.generated) {
const text = snapshot.getText(0, snapshot.getLength());
let patchedText = text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
const script = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
if (script) {

if (script) {
if (file?.generated) {
const text = file.snapshot.getText(0, file.snapshot.getLength());
let patchedText = text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
extension = script.extension;
scriptKind = script.scriptKind;
patchedText += script.code.snapshot.getText(0, script.code.snapshot.getLength());
snapshotSnapshot = ts.ScriptSnapshot.fromString(patchedText);
if (file.generated.languagePlugin.typescript?.getExtraScripts) {
console.warn('getExtraScripts() is not available in this use case.');
}
}
snapshotSnapshot = ts.ScriptSnapshot.fromString(patchedText);
if (sourceFile.generated.languagePlugin.typescript?.getExtraScripts) {
console.warn('getExtraScripts() is not available in this use case.');
}
}
else if (files.get(fileName)) {
files.delete(fileName);
}

if (!cache) {
scripts.set(fileName, {
projectVersion: version,
version: 0,
extension,
snapshot: snapshotSnapshot,
kind: scriptKind,
});
}
else {
cache.projectVersion = version;
cache.version++;
cache.extension = extension;
cache.snapshot = snapshotSnapshot;
cache.kind = scriptKind;
}
}
else if (virtualFiles.get(fileName)) {
extraProjectVersion++;
virtualFiles.delete(fileName);
else if (cache) {
cache.projectVersion = version;
}

scripts.set(fileName, {
version,
extension,
snapshot: snapshotSnapshot,
kind: scriptKind,
});
}

return scripts.get(fileName);
Expand Down

0 comments on commit f041c79

Please sign in to comment.