Skip to content

Commit

Permalink
Redo #86
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Jan 10, 2024
1 parent 60a16c5 commit bd46e3a
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 64 deletions.
48 changes: 24 additions & 24 deletions packages/language-core/lib/fileProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ export type FileProvider = ReturnType<typeof createFileProvider>;
export function createFileProvider(languagePlugins: LanguagePlugin[], caseSensitive: boolean, sync: (sourceFileUri: string) => void) {

const sourceFiles = new FileMap<SourceFile>(caseSensitive);
const virtualFileToSourceFileMap = new WeakMap<VirtualFile, [uri: string, SourceFile]>();
const virtualFileToSourceFileMap = new WeakMap<VirtualFile, SourceFile>();
const virtualFileToMaps = new WeakMap<ts.IScriptSnapshot, Map<string, [ts.IScriptSnapshot, SourceMap<CodeInformation>]>>();
const virtualFileToLinkedCodeMap = new WeakMap<ts.IScriptSnapshot, LinkedCodeMap | undefined>();

return {
updateSourceFile(uri: string, languageId: string, snapshot: ts.IScriptSnapshot): SourceFile {
updateSourceFile(id: string, languageId: string, snapshot: ts.IScriptSnapshot): SourceFile {

const value = sourceFiles.get(uri);
const value = sourceFiles.get(id);
if (value) {
if (value.languageId !== languageId) {
// languageId changed
this.deleteSourceFile(uri);
return this.updateSourceFile(uri, languageId, snapshot);
this.deleteSourceFile(id);
return this.updateSourceFile(id, languageId, snapshot);
}
else if (value.snapshot !== snapshot) {
// updated
Expand All @@ -31,7 +31,7 @@ export function createFileProvider(languagePlugins: LanguagePlugin[], caseSensit
value.generated.idToFileMap.clear();
for (const file of forEachEmbeddedFile(value.generated.virtualFile)) {
value.generated.idToFileMap.set(file.id, file);
virtualFileToSourceFileMap.set(file, [uri, value]);
virtualFileToSourceFileMap.set(file, value);
}
}
return value;
Expand All @@ -43,11 +43,11 @@ export function createFileProvider(languagePlugins: LanguagePlugin[], caseSensit
}

// created
const sourceFile: SourceFile = { languageId, snapshot };
sourceFiles.set(uri, sourceFile);
const sourceFile: SourceFile = { id, languageId, snapshot };
sourceFiles.set(id, sourceFile);

for (const languagePlugin of languagePlugins) {
const virtualFile = languagePlugin.createVirtualFile(uri, languageId, snapshot, this);
const virtualFile = languagePlugin.createVirtualFile(id, languageId, snapshot, this);
if (virtualFile) {
sourceFile.generated = {
virtualFile,
Expand All @@ -56,21 +56,21 @@ export function createFileProvider(languagePlugins: LanguagePlugin[], caseSensit
};
for (const file of forEachEmbeddedFile(virtualFile)) {
sourceFile.generated.idToFileMap.set(file.id, file);
virtualFileToSourceFileMap.set(file, [uri, sourceFile]);
virtualFileToSourceFileMap.set(file, sourceFile);
}
break;
}
}

return sourceFile;
},
deleteSourceFile(uri: string) {
const value = sourceFiles.get(uri);
deleteSourceFile(id: string) {
const value = sourceFiles.get(id);
if (value) {
if (value.generated) {
value.generated.languagePlugin.disposeVirtualFile?.(value.generated.virtualFile, this);
}
sourceFiles.delete(uri); // deleted
sourceFiles.delete(id);
}
},
getLinkedCodeMap(file: VirtualFile) {
Expand All @@ -90,25 +90,25 @@ export function createFileProvider(languagePlugins: LanguagePlugin[], caseSensit
virtualFileToMaps.set(virtualFile.snapshot, new Map());
}

updateVirtualFileMaps(virtualFile, sourceFileUri => {
if (sourceFileUri) {
const sourceFile = sourceFiles.get(sourceFileUri)!;
return [sourceFileUri, sourceFile.snapshot];
updateVirtualFileMaps(virtualFile, sourceFileId => {
if (sourceFileId) {
const sourceFile = sourceFiles.get(sourceFileId)!;
return [sourceFileId, sourceFile.snapshot];
}
else {
const [uri, sourceFile] = virtualFileToSourceFileMap.get(virtualFile)!;
return [uri, sourceFile.snapshot];
const sourceFile = virtualFileToSourceFileMap.get(virtualFile)!;
return [sourceFile.id, sourceFile.snapshot];
}
}, virtualFileToMaps.get(virtualFile.snapshot));

return virtualFileToMaps.get(virtualFile.snapshot)!;
},
getSourceFile(uri: string) {
sync(uri);
return sourceFiles.get(uri);
getSourceFile(id: string) {
sync(id);
return sourceFiles.get(id);
},
getVirtualFile(sourceFileUri: string, virtualFileId: string) {
const sourceFile = this.getSourceFile(sourceFileUri);
getVirtualFile(sourceFileId: string, virtualFileId: string) {
const sourceFile = this.getSourceFile(sourceFileId);
if (sourceFile) {
const virtualFile = sourceFile.generated?.idToFileMap.get(virtualFileId);
return [virtualFile, sourceFile] as const;
Expand Down
3 changes: 2 additions & 1 deletion packages/language-core/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type * as ts from 'typescript';
import type { FileProvider } from './fileProvider';

export interface SourceFile extends BaseFile {
id: string;
generated?: {
virtualFile: VirtualFile;
languagePlugin: LanguagePlugin;
Expand Down Expand Up @@ -56,7 +57,7 @@ export interface BaseFile {
}

export interface LanguagePlugin<T extends VirtualFile = VirtualFile> {
createVirtualFile(uri: string, languageId: string, snapshot: ts.IScriptSnapshot, files?: FileProvider): T | undefined;
createVirtualFile(id: string, languageId: string, snapshot: ts.IScriptSnapshot, files?: FileProvider): T | undefined;
updateVirtualFile(virtualFile: T, snapshot: ts.IScriptSnapshot, files?: FileProvider): void;
disposeVirtualFile?(virtualFile: T, files?: FileProvider): void;
typescript?: {
Expand Down
4 changes: 2 additions & 2 deletions packages/language-service/lib/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ export function createDocumentProvider(files: FileProvider) {
return [undefined, undefined] as const;
},
getVirtualFileUri(virtualFile: VirtualFile) {
const [uri] = files.getSourceFileOfVirtualFile(virtualFile);
return uri + `?virtualFileId=${virtualFile.id}`;
const sourceFile = files.getSourceFileOfVirtualFile(virtualFile);
return sourceFile.id + `?virtualFileId=${virtualFile.id}`;
},
};

Expand Down
8 changes: 3 additions & 5 deletions packages/typescript/lib/node/decorateLanguageServiceHost.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { FileProvider, forEachEmbeddedFile } from '@volar/language-core';
import { resolveCommonLanguageId } from '@volar/language-service';
import type * as ts from 'typescript';
import { fileNameToUri } from './utils';

export function decorateLanguageServiceHost(
virtualFiles: FileProvider,
Expand Down Expand Up @@ -165,11 +164,10 @@ export function decorateLanguageServiceHost(
let scriptKind = ts.ScriptKind.TS;

const snapshot = getScriptSnapshot(fileName);
const uri = fileNameToUri(fileName);

if (snapshot) {
extraProjectVersion++;
const sourceFile = virtualFiles.updateSourceFile(uri, resolveCommonLanguageId(uri), snapshot);
const sourceFile = virtualFiles.updateSourceFile(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');
Expand All @@ -183,9 +181,9 @@ export function decorateLanguageServiceHost(
snapshotSnapshot = ts.ScriptSnapshot.fromString(patchedText);
}
}
else if (virtualFiles.getSourceFile(uri)) {
else if (virtualFiles.getSourceFile(fileName)) {
extraProjectVersion++;
virtualFiles.deleteSourceFile(uri);
virtualFiles.deleteSourceFile(fileName);
}

scripts.set(fileName, {
Expand Down
16 changes: 7 additions & 9 deletions packages/typescript/lib/node/proxyCreateProgram.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type * as ts from 'typescript';
import { decorateProgram } from './decorateProgram';
import { LanguagePlugin, createFileProvider, forEachEmbeddedFile, resolveCommonLanguageId } from '@volar/language-core';
import { fileNameToUri } from './utils';

export function proxyCreateProgram(
ts: typeof import('typescript'),
Expand All @@ -19,10 +18,10 @@ export function proxyCreateProgram(
const files = createFileProvider(
getLanguagePlugins(ts, options),
ts.sys.useCaseSensitiveFileNames,
uri => {
fileName => {
let snapshot: ts.IScriptSnapshot | undefined;
assert(originalSourceFiles.has(uri), `originalSourceFiles.has(${uri})`);
const sourceFile = originalSourceFiles.get(uri);
assert(originalSourceFiles.has(fileName), `originalSourceFiles.has(${fileName})`);
const sourceFile = originalSourceFiles.get(fileName);
if (sourceFile) {
snapshot = sourceFileToSnapshotMap.get(sourceFile);
if (!snapshot) {
Expand All @@ -41,10 +40,10 @@ export function proxyCreateProgram(
}
}
if (snapshot) {
files.updateSourceFile(uri, resolveCommonLanguageId(uri), snapshot);
files.updateSourceFile(fileName, resolveCommonLanguageId(fileName), snapshot);
}
else {
files.deleteSourceFile(uri);
files.deleteSourceFile(fileName);
}
}
);
Expand Down Expand Up @@ -74,14 +73,13 @@ export function proxyCreateProgram(
) => {

const originalSourceFile = originalHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
const uri = fileNameToUri(fileName);

originalSourceFiles.set(uri, originalSourceFile);
originalSourceFiles.set(fileName, originalSourceFile);

if (originalSourceFile && extensions.some(ext => fileName.endsWith(ext))) {
let sourceFile2 = parsedSourceFiles.get(originalSourceFile);
if (!sourceFile2) {
const sourceFile = files.getSourceFile(uri);
const sourceFile = files.getSourceFile(fileName);
assert(!!sourceFile, '!!sourceFile');
let patchedText = originalSourceFile.text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
let scriptKind = ts.ScriptKind.TS;
Expand Down
8 changes: 1 addition & 7 deletions packages/typescript/lib/node/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { forEachEmbeddedFile, FileProvider } from '@volar/language-core';
import { URI } from 'vscode-uri';

export function notEmpty<T>(value: T | null | undefined): value is T {
return value !== null && value !== undefined;
}

export function getVirtualFileAndMap(files: FileProvider, fileName: string) {
const uri = fileNameToUri(fileName);
const sourceFile = files.getSourceFile(uri);
const sourceFile = files.getSourceFile(fileName);
if (sourceFile?.generated) {
for (const virtualFile of forEachEmbeddedFile(sourceFile.generated.virtualFile)) {
if (virtualFile.typescript) {
Expand All @@ -21,7 +19,3 @@ export function getVirtualFileAndMap(files: FileProvider, fileName: string) {
}
return [undefined, undefined, undefined] as const;
}

export const uriToFileName = (uri: string) => URI.parse(uri).fsPath.replace(/\\/g, '/');

export const fileNameToUri = (fileName: string) => URI.file(fileName).toString();
10 changes: 4 additions & 6 deletions packages/typescript/lib/quickstart/createAsyncTSServerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { decorateLanguageService } from '../node/decorateLanguageService';
import { decorateLanguageServiceHost, searchExternalFiles } from '../node/decorateLanguageServiceHost';
import { createFileProvider, LanguagePlugin, resolveCommonLanguageId } from '@volar/language-core';
import { arrayItemsEqual } from './createTSServerPlugin';
import { uriToFileName } from '../node/utils';

const externalFiles = new WeakMap<ts.server.Project, string[]>();
const decoratedLanguageServices = new WeakSet<ts.LanguageService>();
Expand Down Expand Up @@ -69,17 +68,16 @@ export function createAsyncTSServerPlugin(
const files = createFileProvider(
languagePlugins,
ts.sys.useCaseSensitiveFileNames,
uri => {
const fileName = uriToFileName(uri);
fileName => {
const snapshot = getScriptSnapshot(fileName);
if (snapshot) {
files.updateSourceFile(
uri,
resolveCommonLanguageId(uri),
fileName,
resolveCommonLanguageId(fileName),
snapshot
);
} else {
files.deleteSourceFile(uri);
files.deleteSourceFile(fileName);
}
}
);
Expand Down
8 changes: 3 additions & 5 deletions packages/typescript/lib/quickstart/createTSServerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type * as ts from 'typescript';
import { decorateLanguageService } from '../node/decorateLanguageService';
import { decorateLanguageServiceHost, searchExternalFiles } from '../node/decorateLanguageServiceHost';
import { createFileProvider, LanguagePlugin, resolveCommonLanguageId } from '@volar/language-core';
import { uriToFileName } from '../node/utils';

const externalFiles = new WeakMap<ts.server.Project, string[]>();
const projectExternalFileExtensions = new WeakMap<ts.server.Project, string[]>();
Expand Down Expand Up @@ -35,14 +34,13 @@ export function createTSServerPlugin(
const files = createFileProvider(
languagePlugins,
ts.sys.useCaseSensitiveFileNames,
uri => {
const fileName = uriToFileName(uri);
fileName => {
const snapshot = getScriptSnapshot(fileName);
if (snapshot) {
files.updateSourceFile(uri, resolveCommonLanguageId(uri), snapshot);
files.updateSourceFile(fileName, resolveCommonLanguageId(fileName), snapshot);
}
else {
files.deleteSourceFile(uri);
files.deleteSourceFile(fileName);
}
}
);
Expand Down
3 changes: 1 addition & 2 deletions packages/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
},
"dependencies": {
"@volar/language-core": "2.0.0-alpha.13",
"path-browserify": "^1.0.1",
"vscode-uri": "^3.0.8"
"path-browserify": "^1.0.1"
},
"devDependencies": {
"@types/node": "latest",
Expand Down
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bd46e3a

Please sign in to comment.