@volar/typescript
Advanced tools
Comparing version 2.2.5 to 2.3.0-alpha.0
@@ -7,1 +7,2 @@ export * from './lib/node/decorateLanguageService'; | ||
export * from './lib/protocol/createSys'; | ||
export * from './lib/common'; |
@@ -23,2 +23,3 @@ "use strict"; | ||
__exportStar(require("./lib/protocol/createSys"), exports); | ||
__exportStar(require("./lib/common"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,1 @@ | ||
import type { LanguagePlugin } from "@volar/language-core"; | ||
export declare const fileLanguageIdProviderPlugin: LanguagePlugin; | ||
export declare function resolveFileLanguageId(path: string): string | undefined; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.fileLanguageIdProviderPlugin = void 0; | ||
exports.fileLanguageIdProviderPlugin = { | ||
getLanguageId(scriptId) { | ||
const ext = scriptId.split('.').pop(); | ||
switch (ext) { | ||
case 'js': return 'javascript'; | ||
case 'cjs': return 'javascript'; | ||
case 'mjs': return 'javascript'; | ||
case 'ts': return 'typescript'; | ||
case 'cts': return 'typescript'; | ||
case 'mts': return 'typescript'; | ||
case 'jsx': return 'javascriptreact'; | ||
case 'tsx': return 'typescriptreact'; | ||
case 'json': return 'json'; | ||
} | ||
}, | ||
}; | ||
exports.resolveFileLanguageId = void 0; | ||
function resolveFileLanguageId(path) { | ||
const ext = path.split('.').pop(); | ||
switch (ext) { | ||
case 'js': return 'javascript'; | ||
case 'cjs': return 'javascript'; | ||
case 'mjs': return 'javascript'; | ||
case 'ts': return 'typescript'; | ||
case 'cts': return 'typescript'; | ||
case 'mts': return 'typescript'; | ||
case 'jsx': return 'javascriptreact'; | ||
case 'tsx': return 'typescriptreact'; | ||
case 'json': return 'json'; | ||
} | ||
} | ||
exports.resolveFileLanguageId = resolveFileLanguageId; | ||
//# sourceMappingURL=common.js.map |
import { Language } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function decorateLanguageService(language: Language, languageService: ts.LanguageService): void; | ||
export declare function decorateLanguageService(language: Language<string>, languageService: ts.LanguageService): void; |
import type { Language } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function decorateLanguageServiceHost(ts: typeof import('typescript'), language: Language, languageServiceHost: ts.LanguageServiceHost): void; | ||
export declare function decorateLanguageServiceHost(ts: typeof import('typescript'), language: Language<string>, languageServiceHost: ts.LanguageServiceHost): void; | ||
export declare function searchExternalFiles(ts: typeof import('typescript'), project: ts.server.Project, exts: string[]): string[]; |
import type { Language } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function decorateProgram(language: Language, program: ts.Program): void; | ||
export declare function decorateProgram(language: Language<string>, program: ts.Program): void; |
import { LanguagePlugin } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[]): typeof import("typescript").createProgram; | ||
export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin<string>[]): typeof import("typescript").createProgram; |
@@ -33,3 +33,3 @@ "use strict"; | ||
function proxyCreateProgram(ts, original, getLanguagePlugins) { | ||
const sourceFileSnapshots = new Map(); | ||
const sourceFileSnapshots = new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames); | ||
const parsedSourceFiles = new WeakMap(); | ||
@@ -54,4 +54,8 @@ let lastOptions; | ||
...languagePlugins, | ||
common_1.fileLanguageIdProviderPlugin, | ||
], ts.sys.useCaseSensitiveFileNames, fileName => { | ||
{ | ||
getLanguageId(fileName) { | ||
return (0, common_1.resolveFileLanguageId)(fileName); | ||
}, | ||
}, | ||
], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => { | ||
if (!sourceFileSnapshots.has(fileName)) { | ||
@@ -58,0 +62,0 @@ const sourceFileText = originalHost.readFile(fileName); |
@@ -1,16 +0,17 @@ | ||
import { Language, CodeInformation, SourceMap, SourceScript } from '@volar/language-core'; | ||
import type { CodeInformation, SourceMap, SourceScript } from '@volar/language-core'; | ||
import { Language } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function transformCallHierarchyItem(language: Language, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem; | ||
export declare function transformDiagnostic<T extends ts.Diagnostic>(language: Language, diagnostic: T, isTsc: boolean): T | undefined; | ||
export declare function fillSourceFileText(language: Language, sourceFile: ts.SourceFile): void; | ||
export declare function transformFileTextChanges(language: Language, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined; | ||
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined; | ||
export declare function transformSpan(language: Language, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): { | ||
export declare function transformCallHierarchyItem(language: Language<string>, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem; | ||
export declare function transformDiagnostic<T extends ts.Diagnostic>(language: Language<string>, diagnostic: T, isTsc: boolean): T | undefined; | ||
export declare function fillSourceFileText(language: Language<string>, sourceFile: ts.SourceFile): void; | ||
export declare function transformFileTextChanges(language: Language<string>, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined; | ||
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language<string>, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined; | ||
export declare function transformSpan(language: Language<string>, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): { | ||
fileName: string; | ||
textSpan: ts.TextSpan; | ||
} | undefined; | ||
export declare function transformTextChange(sourceScript: SourceScript, map: SourceMap<CodeInformation>, textChange: ts.TextChange, filter: (data: CodeInformation) => boolean): ts.TextChange | undefined; | ||
export declare function transformTextSpan(sourceScript: SourceScript, map: SourceMap<CodeInformation>, textSpan: ts.TextSpan, filter: (data: CodeInformation) => boolean): ts.TextSpan | undefined; | ||
export declare function toSourceOffset(sourceScript: SourceScript, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined; | ||
export declare function toGeneratedOffset(sourceScript: SourceScript, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined; | ||
export declare function toGeneratedOffsets(sourceScript: SourceScript, map: SourceMap<CodeInformation>, position: number): Generator<readonly [number, import("@volar/language-core").Mapping<CodeInformation>], void, unknown>; | ||
export declare function transformTextChange(sourceScript: SourceScript<string>, map: SourceMap<CodeInformation>, textChange: ts.TextChange, filter: (data: CodeInformation) => boolean): ts.TextChange | undefined; | ||
export declare function transformTextSpan(sourceScript: SourceScript<string>, map: SourceMap<CodeInformation>, textSpan: ts.TextSpan, filter: (data: CodeInformation) => boolean): ts.TextSpan | undefined; | ||
export declare function toSourceOffset(sourceScript: SourceScript<string>, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined; | ||
export declare function toGeneratedOffset(sourceScript: SourceScript<string>, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined; | ||
export declare function toGeneratedOffsets(sourceScript: SourceScript<string>, map: SourceMap<CodeInformation>, position: number): Generator<readonly [number, import("@volar/language-core").Mapping<CodeInformation>], void, unknown>; |
import type { Language } from '@volar/language-core'; | ||
export declare function notEmpty<T>(value: T | null | undefined): value is T; | ||
export declare function getServiceScript(language: Language, fileName: string): readonly [import("@volar/language-core").ServiceScript, import("@volar/language-core").SourceScript, import("@volar/language-core").SourceMap<import("@volar/language-core").CodeInformation>] | readonly [undefined, undefined, undefined]; | ||
export declare function getServiceScript(language: Language<string>, fileName: string): readonly [import("@volar/language-core").TypeScriptServiceScript, import("@volar/language-core").SourceScript<string>, import("@volar/language-core").SourceMap<import("@volar/language-core").CodeInformation>] | readonly [undefined, undefined, undefined]; |
@@ -1,2 +0,9 @@ | ||
import { LanguagePlugin, Language, TypeScriptProjectHost } from '@volar/language-core'; | ||
export declare function createTypeScriptLanguage(ts: typeof import('typescript'), languagePlugins: LanguagePlugin[], projectHost: TypeScriptProjectHost): Language; | ||
import { Language, TypeScriptExtraServiceScript } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
import type { createSys } from './createSys'; | ||
export interface TypeScriptProjectHost extends Pick<ts.LanguageServiceHost, 'getLocalizedDiagnosticMessages' | 'getCurrentDirectory' | 'getCompilationSettings' | 'getProjectReferences' | 'getScriptFileNames' | 'getProjectVersion' | 'getScriptSnapshot'> { | ||
} | ||
export declare function createLanguageServiceHost<T>(ts: typeof import('typescript'), sys: ReturnType<typeof createSys> | ts.System, language: Language<T>, asScrpitId: (fileName: string) => T, projectHost: TypeScriptProjectHost): { | ||
languageServiceHost: ts.LanguageServiceHost; | ||
getExtraServiceScript: (fileName: string) => TypeScriptExtraServiceScript | undefined; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createTypeScriptLanguage = void 0; | ||
exports.createLanguageServiceHost = void 0; | ||
const language_core_1 = require("@volar/language-core"); | ||
const language_core_2 = require("@volar/language-core"); | ||
const path = require("path-browserify"); | ||
const resolveModuleName_1 = require("../resolveModuleName"); | ||
const common_1 = require("../common"); | ||
const scriptVersions = new Map(); | ||
const fsFileSnapshots = new Map(); | ||
function createTypeScriptLanguage(ts, languagePlugins, projectHost) { | ||
const language = (0, language_core_1.createLanguage)([ | ||
...languagePlugins, | ||
common_1.fileLanguageIdProviderPlugin, | ||
], projectHost.useCaseSensitiveFileNames, scriptId => { | ||
const fileName = projectHost.scriptIdToFileName(scriptId); | ||
// opened files | ||
let snapshot = projectHost.getScriptSnapshot(fileName); | ||
if (!snapshot) { | ||
// fs files | ||
const cache = fsFileSnapshots.get(fileName); | ||
const modifiedTime = projectHost.getModifiedTime?.(fileName)?.valueOf(); | ||
if (!cache || cache[0] !== modifiedTime) { | ||
if (projectHost.fileExists(fileName)) { | ||
const text = projectHost.readFile(fileName); | ||
const snapshot = text !== undefined ? ts.ScriptSnapshot.fromString(text) : undefined; | ||
fsFileSnapshots.set(fileName, [modifiedTime, snapshot]); | ||
function createLanguageServiceHost(ts, sys, language, asScrpitId, projectHost) { | ||
const scriptVersions = new language_core_1.FileMap(sys.useCaseSensitiveFileNames); | ||
let lastProjectVersion; | ||
let tsProjectVersion = 0; | ||
let tsFileRegistry = new language_core_1.FileMap(sys.useCaseSensitiveFileNames); | ||
let extraScriptRegistry = new language_core_1.FileMap(sys.useCaseSensitiveFileNames); | ||
let lastTsVirtualFileSnapshots = new Set(); | ||
let lastOtherVirtualFileSnapshots = new Set(); | ||
let languageServiceHost = { | ||
...sys, | ||
getCurrentDirectory() { | ||
return projectHost.getCurrentDirectory(); | ||
}, | ||
useCaseSensitiveFileNames() { | ||
return sys.useCaseSensitiveFileNames; | ||
}, | ||
getNewLine() { | ||
return sys.newLine; | ||
}, | ||
getTypeRootsVersion: () => { | ||
return 'version' in sys ? sys.version : -1; // TODO: only update for /node_modules changes? | ||
}, | ||
getDirectories(dirName) { | ||
return sys.getDirectories(dirName); | ||
}, | ||
readDirectory(dirName, extensions, excludes, includes, depth) { | ||
const exts = new Set(extensions); | ||
for (const languagePlugin of language.plugins) { | ||
for (const ext of languagePlugin.typescript?.extraFileExtensions ?? []) { | ||
exts.add('.' + ext.extension); | ||
} | ||
else { | ||
fsFileSnapshots.set(fileName, [modifiedTime, undefined]); | ||
} | ||
extensions = [...exts]; | ||
return sys.readDirectory(dirName, extensions, excludes, includes, depth); | ||
}, | ||
getCompilationSettings() { | ||
const options = projectHost.getCompilationSettings(); | ||
if (language.plugins.some(language => language.typescript?.extraFileExtensions.length)) { | ||
options.allowNonTsExtensions ??= true; | ||
if (!options.allowNonTsExtensions) { | ||
console.warn('`allowNonTsExtensions` must be `true`.'); | ||
} | ||
} | ||
snapshot = fsFileSnapshots.get(fileName)?.[1]; | ||
return options; | ||
}, | ||
getLocalizedDiagnosticMessages: projectHost.getLocalizedDiagnosticMessages, | ||
getProjectReferences: projectHost.getProjectReferences, | ||
getDefaultLibFileName: options => { | ||
try { | ||
return ts.getDefaultLibFilePath(options); | ||
} | ||
catch { | ||
// web | ||
return `/node_modules/typescript/lib/${ts.getDefaultLibFileName(options)}`; | ||
} | ||
}, | ||
readFile(fileName) { | ||
const snapshot = getScriptSnapshot(fileName); | ||
if (snapshot) { | ||
return snapshot.getText(0, snapshot.getLength()); | ||
} | ||
}, | ||
fileExists(fileName) { | ||
return getScriptVersion(fileName) !== ''; | ||
}, | ||
getProjectVersion() { | ||
sync(); | ||
return tsProjectVersion + ('version' in sys ? `:${sys.version}` : ''); | ||
}, | ||
getScriptFileNames() { | ||
sync(); | ||
return [...tsFileRegistry.keys()]; | ||
}, | ||
getScriptKind(fileName) { | ||
sync(); | ||
if (extraScriptRegistry.has(fileName)) { | ||
return extraScriptRegistry.get(fileName).scriptKind; | ||
} | ||
const sourceScript = language.scripts.get(asScrpitId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
return serviceScript.scriptKind; | ||
} | ||
} | ||
switch (path.extname(fileName)) { | ||
case '.js': | ||
case '.cjs': | ||
case '.mjs': | ||
return ts.ScriptKind.JS; | ||
case '.jsx': | ||
return ts.ScriptKind.JSX; | ||
case '.ts': | ||
case '.cts': | ||
case '.mts': | ||
return ts.ScriptKind.TS; | ||
case '.tsx': | ||
return ts.ScriptKind.TSX; | ||
case '.json': | ||
return ts.ScriptKind.JSON; | ||
default: | ||
return ts.ScriptKind.Unknown; | ||
} | ||
}, | ||
getScriptVersion, | ||
getScriptSnapshot, | ||
}; | ||
for (const plugin of language.plugins) { | ||
if (plugin.typescript?.resolveLanguageServiceHost) { | ||
languageServiceHost = plugin.typescript.resolveLanguageServiceHost(languageServiceHost); | ||
} | ||
if (snapshot) { | ||
language.scripts.set(scriptId, snapshot); | ||
} | ||
else { | ||
language.scripts.delete(scriptId); | ||
} | ||
}); | ||
let { languageServiceHost, getExtraScript } = createLanguageServiceHost(); | ||
for (const language of languagePlugins) { | ||
if (language.typescript?.resolveLanguageServiceHost) { | ||
languageServiceHost = language.typescript.resolveLanguageServiceHost(languageServiceHost); | ||
} | ||
} | ||
if (languagePlugins.some(language => language.typescript?.extraFileExtensions.length)) { | ||
if (language.plugins.some(language => language.typescript?.extraFileExtensions.length)) { | ||
// TODO: can this share between monorepo packages? | ||
const moduleCache = ts.createModuleResolutionCache(languageServiceHost.getCurrentDirectory(), languageServiceHost.useCaseSensitiveFileNames?.() ? s => s : s => s.toLowerCase(), languageServiceHost.getCompilationSettings()); | ||
const resolveModuleName = (0, resolveModuleName_1.createResolveModuleName)(ts, languageServiceHost, languagePlugins, fileName => language.scripts.get(projectHost.fileNameToScriptId(fileName))); | ||
let lastSysVersion = projectHost.getSystemVersion?.(); | ||
const resolveModuleName = (0, resolveModuleName_1.createResolveModuleName)(ts, languageServiceHost, language.plugins, fileName => language.scripts.get(asScrpitId(fileName))); | ||
let lastSysVersion = 'version' in sys ? sys.version : undefined; | ||
languageServiceHost.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, options, sourceFile) => { | ||
if (projectHost.getSystemVersion && lastSysVersion !== projectHost.getSystemVersion()) { | ||
lastSysVersion = projectHost.getSystemVersion(); | ||
if ('version' in sys && lastSysVersion !== sys.version) { | ||
lastSysVersion = sys.version; | ||
moduleCache.clear(); | ||
@@ -63,4 +134,4 @@ } | ||
languageServiceHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options) => { | ||
if (projectHost.getSystemVersion && lastSysVersion !== projectHost.getSystemVersion()) { | ||
lastSysVersion = projectHost.getSystemVersion(); | ||
if ('version' in sys && lastSysVersion !== sys.version) { | ||
lastSysVersion = sys.version; | ||
moduleCache.clear(); | ||
@@ -73,223 +144,112 @@ } | ||
} | ||
language.typescript = { | ||
projectHost, | ||
return { | ||
languageServiceHost, | ||
getExtraServiceScript: getExtraScript, | ||
getExtraServiceScript, | ||
}; | ||
return language; | ||
function createLanguageServiceHost() { | ||
let lastProjectVersion; | ||
let tsProjectVersion = 0; | ||
let tsFileRegistry = new language_core_1.FileMap(projectHost.useCaseSensitiveFileNames); | ||
let extraScriptRegistry = new language_core_1.FileMap(projectHost.useCaseSensitiveFileNames); | ||
let lastTsVirtualFileSnapshots = new Set(); | ||
let lastOtherVirtualFileSnapshots = new Set(); | ||
const languageServiceHost = { | ||
...projectHost, | ||
getCurrentDirectory: projectHost.getCurrentDirectory, | ||
getCompilationSettings() { | ||
const options = projectHost.getCompilationSettings(); | ||
if (languagePlugins.some(language => language.typescript?.extraFileExtensions.length)) { | ||
options.allowNonTsExtensions ??= true; | ||
if (!options.allowNonTsExtensions) { | ||
console.warn('`allowNonTsExtensions` must be `true`.'); | ||
} | ||
} | ||
return options; | ||
}, | ||
getLocalizedDiagnosticMessages: projectHost.getLocalizedDiagnosticMessages, | ||
getProjectReferences: projectHost.getProjectReferences, | ||
getDefaultLibFileName: options => { | ||
try { | ||
return ts.getDefaultLibFilePath(options); | ||
} | ||
catch { | ||
// web | ||
return `/node_modules/typescript/lib/${ts.getDefaultLibFileName(options)}`; | ||
} | ||
}, | ||
useCaseSensitiveFileNames() { | ||
return projectHost.useCaseSensitiveFileNames; | ||
}, | ||
getNewLine() { | ||
return projectHost.newLine; | ||
}, | ||
getTypeRootsVersion: () => { | ||
return projectHost.getSystemVersion?.() ?? -1; // TODO: only update for /node_modules changes? | ||
}, | ||
getDirectories(dirName) { | ||
return projectHost.getDirectories(dirName); | ||
}, | ||
readDirectory(dirName, extensions, excludes, includes, depth) { | ||
const exts = new Set(extensions); | ||
for (const languagePlugin of languagePlugins) { | ||
for (const ext of languagePlugin.typescript?.extraFileExtensions ?? []) { | ||
exts.add('.' + ext.extension); | ||
} | ||
} | ||
extensions = [...exts]; | ||
return projectHost.readDirectory(dirName, extensions, excludes, includes, depth); | ||
}, | ||
readFile(fileName) { | ||
const snapshot = getScriptSnapshot(fileName); | ||
if (snapshot) { | ||
return snapshot.getText(0, snapshot.getLength()); | ||
} | ||
}, | ||
fileExists(fileName) { | ||
return getScriptVersion(fileName) !== ''; | ||
}, | ||
getProjectVersion() { | ||
sync(); | ||
return tsProjectVersion + (projectHost.getSystemVersion ? `:${projectHost.getSystemVersion()}` : ''); | ||
}, | ||
getScriptFileNames() { | ||
sync(); | ||
return [...tsFileRegistry.keys()]; | ||
}, | ||
getScriptKind(fileName) { | ||
sync(); | ||
if (extraScriptRegistry.has(fileName)) { | ||
return extraScriptRegistry.get(fileName).scriptKind; | ||
} | ||
const sourceScript = language.scripts.get(projectHost.fileNameToScriptId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
return serviceScript.scriptKind; | ||
} | ||
} | ||
switch (path.extname(fileName)) { | ||
case '.js': | ||
case '.cjs': | ||
case '.mjs': | ||
return ts.ScriptKind.JS; | ||
case '.jsx': | ||
return ts.ScriptKind.JSX; | ||
case '.ts': | ||
case '.cts': | ||
case '.mts': | ||
return ts.ScriptKind.TS; | ||
case '.tsx': | ||
return ts.ScriptKind.TSX; | ||
case '.json': | ||
return ts.ScriptKind.JSON; | ||
default: | ||
return ts.ScriptKind.Unknown; | ||
} | ||
}, | ||
getScriptVersion, | ||
getScriptSnapshot, | ||
}; | ||
return { | ||
languageServiceHost, | ||
getExtraScript, | ||
}; | ||
function getExtraScript(fileName) { | ||
sync(); | ||
return extraScriptRegistry.get(fileName); | ||
function getExtraServiceScript(fileName) { | ||
sync(); | ||
return extraScriptRegistry.get(fileName); | ||
} | ||
function sync() { | ||
const newProjectVersion = projectHost.getProjectVersion?.(); | ||
const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion; | ||
if (!shouldUpdate) { | ||
return; | ||
} | ||
function sync() { | ||
const newProjectVersion = projectHost.getProjectVersion?.(); | ||
const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion; | ||
if (!shouldUpdate) { | ||
return; | ||
} | ||
lastProjectVersion = newProjectVersion; | ||
extraScriptRegistry.clear(); | ||
const newTsVirtualFileSnapshots = new Set(); | ||
const newOtherVirtualFileSnapshots = new Set(); | ||
const tsFileNamesSet = new Set(); | ||
for (const fileName of projectHost.getScriptFileNames()) { | ||
const sourceScript = language.scripts.get(projectHost.fileNameToScriptId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
newTsVirtualFileSnapshots.add(serviceScript.code.snapshot); | ||
tsFileNamesSet.add(fileName); | ||
} | ||
for (const extraServiceScript of sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts?.(fileName, sourceScript.generated.root) ?? []) { | ||
newTsVirtualFileSnapshots.add(extraServiceScript.code.snapshot); | ||
tsFileNamesSet.add(extraServiceScript.fileName); | ||
extraScriptRegistry.set(extraServiceScript.fileName, extraServiceScript); | ||
} | ||
for (const code of (0, language_core_2.forEachEmbeddedCode)(sourceScript.generated.root)) { | ||
newOtherVirtualFileSnapshots.add(code.snapshot); | ||
} | ||
} | ||
else { | ||
tsFileNamesSet.add(fileName); | ||
} | ||
} | ||
if (!setEquals(lastTsVirtualFileSnapshots, newTsVirtualFileSnapshots)) { | ||
tsProjectVersion++; | ||
} | ||
else if (setEquals(lastOtherVirtualFileSnapshots, newOtherVirtualFileSnapshots)) { | ||
// no any meta language files update, it mean project version was update by source files this time | ||
tsProjectVersion++; | ||
} | ||
lastTsVirtualFileSnapshots = newTsVirtualFileSnapshots; | ||
lastOtherVirtualFileSnapshots = newOtherVirtualFileSnapshots; | ||
tsFileRegistry.clear(); | ||
for (const fileName of tsFileNamesSet) { | ||
tsFileRegistry.set(fileName, true); | ||
} | ||
} | ||
function getScriptSnapshot(fileName) { | ||
sync(); | ||
if (extraScriptRegistry.has(fileName)) { | ||
return extraScriptRegistry.get(fileName).code.snapshot; | ||
} | ||
const sourceScript = language.scripts.get(projectHost.fileNameToScriptId(fileName)); | ||
lastProjectVersion = newProjectVersion; | ||
extraScriptRegistry.clear(); | ||
const newTsVirtualFileSnapshots = new Set(); | ||
const newOtherVirtualFileSnapshots = new Set(); | ||
const tsFileNamesSet = new Set(); | ||
for (const fileName of projectHost.getScriptFileNames()) { | ||
const sourceScript = language.scripts.get(asScrpitId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
return serviceScript.code.snapshot; | ||
newTsVirtualFileSnapshots.add(serviceScript.code.snapshot); | ||
tsFileNamesSet.add(fileName); | ||
} | ||
for (const extraServiceScript of sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts?.(fileName, sourceScript.generated.root) ?? []) { | ||
newTsVirtualFileSnapshots.add(extraServiceScript.code.snapshot); | ||
tsFileNamesSet.add(extraServiceScript.fileName); | ||
extraScriptRegistry.set(extraServiceScript.fileName, extraServiceScript); | ||
} | ||
for (const code of (0, language_core_1.forEachEmbeddedCode)(sourceScript.generated.root)) { | ||
newOtherVirtualFileSnapshots.add(code.snapshot); | ||
} | ||
} | ||
else if (sourceScript) { | ||
return sourceScript.snapshot; | ||
else { | ||
tsFileNamesSet.add(fileName); | ||
} | ||
} | ||
function getScriptVersion(fileName) { | ||
sync(); | ||
if (!scriptVersions.has(fileName)) { | ||
scriptVersions.set(fileName, { lastVersion: 0, map: new WeakMap() }); | ||
if (!setEquals(lastTsVirtualFileSnapshots, newTsVirtualFileSnapshots)) { | ||
tsProjectVersion++; | ||
} | ||
else if (setEquals(lastOtherVirtualFileSnapshots, newOtherVirtualFileSnapshots)) { | ||
// no any meta language files update, it mean project version was update by source files this time | ||
tsProjectVersion++; | ||
} | ||
lastTsVirtualFileSnapshots = newTsVirtualFileSnapshots; | ||
lastOtherVirtualFileSnapshots = newOtherVirtualFileSnapshots; | ||
tsFileRegistry.clear(); | ||
for (const fileName of tsFileNamesSet) { | ||
tsFileRegistry.set(fileName, true); | ||
} | ||
} | ||
function getScriptSnapshot(fileName) { | ||
sync(); | ||
if (extraScriptRegistry.has(fileName)) { | ||
return extraScriptRegistry.get(fileName).code.snapshot; | ||
} | ||
const sourceScript = language.scripts.get(asScrpitId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
return serviceScript.code.snapshot; | ||
} | ||
const version = scriptVersions.get(fileName); | ||
if (extraScriptRegistry.has(fileName)) { | ||
const snapshot = extraScriptRegistry.get(fileName).code.snapshot; | ||
if (!version.map.has(snapshot)) { | ||
version.map.set(snapshot, version.lastVersion++); | ||
} | ||
return version.map.get(snapshot).toString(); | ||
} | ||
else if (sourceScript) { | ||
return sourceScript.snapshot; | ||
} | ||
} | ||
function getScriptVersion(fileName) { | ||
sync(); | ||
if (!scriptVersions.has(fileName)) { | ||
scriptVersions.set(fileName, { lastVersion: 0, map: new WeakMap() }); | ||
} | ||
const version = scriptVersions.get(fileName); | ||
if (extraScriptRegistry.has(fileName)) { | ||
const snapshot = extraScriptRegistry.get(fileName).code.snapshot; | ||
if (!version.map.has(snapshot)) { | ||
version.map.set(snapshot, version.lastVersion++); | ||
} | ||
const sourceScript = language.scripts.get(projectHost.fileNameToScriptId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
if (!version.map.has(serviceScript.code.snapshot)) { | ||
version.map.set(serviceScript.code.snapshot, version.lastVersion++); | ||
} | ||
return version.map.get(serviceScript.code.snapshot).toString(); | ||
return version.map.get(snapshot).toString(); | ||
} | ||
const sourceScript = language.scripts.get(asScrpitId(fileName)); | ||
if (sourceScript?.generated) { | ||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root); | ||
if (serviceScript) { | ||
if (!version.map.has(serviceScript.code.snapshot)) { | ||
version.map.set(serviceScript.code.snapshot, version.lastVersion++); | ||
} | ||
return version.map.get(serviceScript.code.snapshot).toString(); | ||
} | ||
const isOpenedFile = !!projectHost.getScriptSnapshot(fileName); | ||
if (isOpenedFile) { | ||
const sourceScript = language.scripts.get(projectHost.fileNameToScriptId(fileName)); | ||
if (sourceScript && !sourceScript.generated) { | ||
if (!version.map.has(sourceScript.snapshot)) { | ||
version.map.set(sourceScript.snapshot, version.lastVersion++); | ||
} | ||
return version.map.get(sourceScript.snapshot).toString(); | ||
} | ||
const isOpenedFile = !!projectHost.getScriptSnapshot(fileName); | ||
if (isOpenedFile) { | ||
const sourceScript = language.scripts.get(asScrpitId(fileName)); | ||
if (sourceScript && !sourceScript.generated) { | ||
if (!version.map.has(sourceScript.snapshot)) { | ||
version.map.set(sourceScript.snapshot, version.lastVersion++); | ||
} | ||
return version.map.get(sourceScript.snapshot).toString(); | ||
} | ||
if (projectHost.fileExists(fileName)) { | ||
return projectHost.getModifiedTime?.(fileName)?.valueOf().toString() ?? '0'; | ||
} | ||
return ''; | ||
} | ||
if (sys.fileExists(fileName)) { | ||
return sys.getModifiedTime?.(fileName)?.valueOf().toString() ?? '0'; | ||
} | ||
return ''; | ||
} | ||
} | ||
exports.createTypeScriptLanguage = createTypeScriptLanguage; | ||
exports.createLanguageServiceHost = createLanguageServiceHost; | ||
function setEquals(a, b) { | ||
@@ -296,0 +256,0 @@ if (a.size !== b.size) { |
@@ -1,6 +0,10 @@ | ||
import type { ServiceEnvironment, Disposable } from '@volar/language-service'; | ||
import type { LanguageServiceEnvironment, Disposable } from '@volar/language-service'; | ||
import type * as ts from 'typescript'; | ||
export declare function createSys(ts: typeof import('typescript'), env: ServiceEnvironment, currentDirectory: string): ts.System & { | ||
import { URI } from 'vscode-uri'; | ||
export declare function createSys(sys: ts.System | undefined, env: LanguageServiceEnvironment, workspaceFolder: URI | undefined, uriConverter: { | ||
asUri(fileName: string): URI; | ||
asFileName(uri: URI): string; | ||
}): ts.System & { | ||
version: number; | ||
sync(): Promise<number>; | ||
} & Disposable; |
@@ -6,7 +6,7 @@ "use strict"; | ||
const utilities_1 = require("../typescript/utilities"); | ||
const vscode_uri_1 = require("vscode-uri"); | ||
let currentCwd = ''; | ||
function createSys(ts, env, currentDirectory) { | ||
function createSys(sys, env, workspaceFolder, uriConverter) { | ||
let version = 0; | ||
// sys is undefined in browser | ||
const sys = ts.sys; | ||
const currentDirectory = workspaceFolder ? uriConverter.asFileName(workspaceFolder) : ''; | ||
const caseSensitive = sys?.useCaseSensitiveFileNames ?? false; | ||
@@ -23,3 +23,4 @@ const root = { | ||
for (const change of changes) { | ||
const fileName = env.typescript.uriToFileName(change.uri); | ||
const changeUri = vscode_uri_1.URI.parse(change.uri); | ||
const fileName = uriConverter.asFileName(changeUri); | ||
const dirName = path.dirname(fileName); | ||
@@ -112,3 +113,3 @@ const baseName = path.basename(fileName); | ||
dir.exists = false; | ||
const result = env.fs?.stat(env.typescript.fileNameToUri(dirName)); | ||
const result = env.fs?.stat(uriConverter.asUri(dirName)); | ||
if (typeof result === 'object' && 'then' in result) { | ||
@@ -154,3 +155,3 @@ const promise = result; | ||
function handleStat(fileName, file) { | ||
const result = env.fs?.stat(env.typescript.fileNameToUri(fileName)); | ||
const result = env.fs?.stat(uriConverter.asUri(fileName)); | ||
if (typeof result === 'object' && 'then' in result) { | ||
@@ -226,3 +227,3 @@ const promise = result; | ||
file.requestedText = true; | ||
const uri = env.typescript.fileNameToUri(fileName); | ||
const uri = uriConverter.asUri(fileName); | ||
const result = env.fs?.readFile(uri, encoding); | ||
@@ -253,3 +254,3 @@ if (typeof result === 'object' && 'then' in result) { | ||
dir.requestedRead = true; | ||
const result = env.fs?.readDirectory(env.typescript.fileNameToUri(dirName || '.')); | ||
const result = env.fs?.readDirectory(uriConverter.asUri(dirName || '.')); | ||
if (typeof result === 'object' && 'then' in result) { | ||
@@ -276,3 +277,3 @@ const promise = result; | ||
if (fileType === 64) { | ||
const stat = env.fs?.stat(env.typescript.fileNameToUri(dirName + '/' + name)); | ||
const stat = env.fs?.stat(uriConverter.asUri(dirName + '/' + name)); | ||
if (typeof stat === 'object' && 'then' in stat) { | ||
@@ -279,0 +280,0 @@ const promise = stat; |
@@ -0,3 +1,3 @@ | ||
import { LanguagePlugin } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
import { LanguagePlugin } from '@volar/language-core'; | ||
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>): ts.server.PluginModuleFactory; | ||
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin<string>[]>): ts.server.PluginModuleFactory; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createAsyncLanguageServicePlugin = void 0; | ||
const language_core_1 = require("@volar/language-core"); | ||
const common_1 = require("../common"); | ||
const decorateLanguageService_1 = require("../node/decorateLanguageService"); | ||
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost"); | ||
const language_core_1 = require("@volar/language-core"); | ||
const createLanguageServicePlugin_1 = require("./createLanguageServicePlugin"); | ||
const common_1 = require("../common"); | ||
const externalFiles = new WeakMap(); | ||
@@ -59,4 +59,8 @@ const decoratedLanguageServices = new WeakSet(); | ||
...languagePlugins, | ||
common_1.fileLanguageIdProviderPlugin, | ||
], ts.sys.useCaseSensitiveFileNames, fileName => { | ||
{ | ||
getLanguageId(fileName) { | ||
return (0, common_1.resolveFileLanguageId)(fileName); | ||
}, | ||
}, | ||
], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => { | ||
const version = getScriptVersion(fileName); | ||
@@ -63,0 +67,0 @@ if (syncedScriptVersions.get(fileName) === version) { |
@@ -0,4 +1,4 @@ | ||
import { LanguagePlugin } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
import { LanguagePlugin } from '@volar/language-core'; | ||
export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin[]): ts.server.PluginModuleFactory; | ||
export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin<string>[]): ts.server.PluginModuleFactory; | ||
export declare function arrayItemsEqual(a: string[], b: string[]): boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.arrayItemsEqual = exports.createLanguageServicePlugin = void 0; | ||
const language_core_1 = require("@volar/language-core"); | ||
const common_1 = require("../common"); | ||
const decorateLanguageService_1 = require("../node/decorateLanguageService"); | ||
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost"); | ||
const language_core_1 = require("@volar/language-core"); | ||
const common_1 = require("../common"); | ||
const externalFiles = new WeakMap(); | ||
@@ -31,4 +31,8 @@ const projectExternalFileExtensions = new WeakMap(); | ||
...languagePlugins, | ||
common_1.fileLanguageIdProviderPlugin, | ||
], ts.sys.useCaseSensitiveFileNames, fileName => { | ||
{ | ||
getLanguageId(fileName) { | ||
return (0, common_1.resolveFileLanguageId)(fileName); | ||
}, | ||
}, | ||
], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => { | ||
const version = getScriptVersion(fileName); | ||
@@ -35,0 +39,0 @@ if (syncedScriptVersions.get(fileName) === version) { |
import type * as ts from 'typescript'; | ||
import type { LanguagePlugin } from '@volar/language-core'; | ||
export declare let getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[]; | ||
export declare let getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin<string>[]; | ||
export declare function runTsc(tscPath: string, extensions: string[], _getLanguagePlugins: typeof getLanguagePlugins): void; |
import type { LanguagePlugin, SourceScript } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function createResolveModuleName(ts: typeof import('typescript'), host: ts.ModuleResolutionHost, languagePlugins: LanguagePlugin<any>[], getSourceScript: (fileName: string) => SourceScript | undefined): (moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, cache?: ts.ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, resolutionMode?: ts.ResolutionMode) => ts.ResolvedModuleWithFailedLookupLocations; | ||
export declare function createResolveModuleName<T>(ts: typeof import('typescript'), host: ts.ModuleResolutionHost, languagePlugins: LanguagePlugin<any>[], getSourceScript: (fileName: string) => SourceScript<T> | undefined): (moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, cache?: ts.ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, resolutionMode?: ts.ResolutionMode) => ts.ResolvedModuleWithFailedLookupLocations; |
{ | ||
"name": "@volar/typescript", | ||
"version": "2.2.5", | ||
"version": "2.3.0-alpha.0", | ||
"license": "MIT", | ||
@@ -15,4 +15,5 @@ "files": [ | ||
"dependencies": { | ||
"@volar/language-core": "2.2.5", | ||
"path-browserify": "^1.0.1" | ||
"@volar/language-core": "2.3.0-alpha.0", | ||
"path-browserify": "^1.0.1", | ||
"vscode-uri": "^3.0.8" | ||
}, | ||
@@ -22,5 +23,5 @@ "devDependencies": { | ||
"@types/path-browserify": "latest", | ||
"@volar/language-service": "2.2.5" | ||
"@volar/language-service": "2.3.0-alpha.0" | ||
}, | ||
"gitHead": "ee4aaa9da58c4c942d6cb74f9028d19b7ef4465d" | ||
"gitHead": "f17c19f712651acde33cc2171a112e64db0b460e" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
180599
3
3870
2
+ Addedvscode-uri@^3.0.8
+ Added@volar/language-core@2.3.0-alpha.0(transitive)
+ Added@volar/source-map@2.3.0-alpha.0(transitive)
+ Addedvscode-uri@3.0.8(transitive)
- Removed@volar/language-core@2.2.5(transitive)
- Removed@volar/source-map@2.2.5(transitive)