@volar/language-core
Advanced tools
Comparing version 2.3.0-alpha.5 to 2.3.0-alpha.6
@@ -8,2 +8,2 @@ export * from '@volar/source-map'; | ||
export declare function createLanguage<T>(plugins: LanguagePlugin<T>[], scriptRegistry: Map<T, SourceScript<T>>, sync: (id: T) => void): Language<T>; | ||
export declare function forEachEmbeddedCode(virtualCode: VirtualCode): Generator<VirtualCode>; | ||
export declare function forEachEmbeddedCode<T>(virtualCode: VirtualCode<T>): Generator<VirtualCode<T>>; |
85
index.js
@@ -59,10 +59,11 @@ "use strict"; | ||
} | ||
else if (sourceScript.snapshot !== snapshot) { | ||
else if (sourceScript.isAssociationDirty || sourceScript.snapshot !== snapshot) { | ||
// snapshot updated | ||
sourceScript.snapshot = snapshot; | ||
const codegenCtx = prepareCreateVirtualCode(sourceScript); | ||
if (sourceScript.generated) { | ||
const { updateVirtualCode, createVirtualCode } = sourceScript.generated.languagePlugin; | ||
const newVirtualCode = updateVirtualCode | ||
? updateVirtualCode(id, sourceScript.generated.root, snapshot) | ||
: createVirtualCode?.(id, languageId, snapshot); | ||
? updateVirtualCode(id, sourceScript.generated.root, snapshot, codegenCtx) | ||
: createVirtualCode?.(id, languageId, snapshot, codegenCtx); | ||
if (newVirtualCode) { | ||
@@ -82,2 +83,3 @@ sourceScript.generated.root = newVirtualCode; | ||
} | ||
triggerTargetsDirty(sourceScript); | ||
} | ||
@@ -91,6 +93,12 @@ else { | ||
// created | ||
const sourceScript = { id, languageId, snapshot }; | ||
const sourceScript = { | ||
id: id, | ||
languageId, | ||
snapshot, | ||
associatedIds: new Set(), | ||
targetIds: new Set(), | ||
}; | ||
scriptRegistry.set(id, sourceScript); | ||
for (const languagePlugin of _plugins) { | ||
const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot); | ||
const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot, prepareCreateVirtualCode(sourceScript)); | ||
if (virtualCode) { | ||
@@ -113,8 +121,7 @@ sourceScript.generated = { | ||
delete(id) { | ||
const value = scriptRegistry.get(id); | ||
if (value) { | ||
if (value.generated) { | ||
value.generated.languagePlugin.disposeVirtualCode?.(id, value.generated.root); | ||
} | ||
const sourceScript = scriptRegistry.get(id); | ||
if (sourceScript) { | ||
sourceScript.generated?.languagePlugin.disposeVirtualCode?.(id, sourceScript.generated.root); | ||
scriptRegistry.delete(id); | ||
triggerTargetsDirty(sourceScript); | ||
} | ||
@@ -125,14 +132,28 @@ }, | ||
get(virtualCode) { | ||
for (const map of this.forEach(virtualCode)) { | ||
return map[2]; | ||
} | ||
throw `no map found for ${virtualCode.id}`; | ||
}, | ||
*forEach(virtualCode) { | ||
let mapCache = virtualCodeToSourceMap.get(virtualCode.snapshot); | ||
if (!mapCache) { | ||
virtualCodeToSourceMap.set(virtualCode.snapshot, mapCache = new WeakMap()); | ||
} | ||
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode); | ||
let mapCache = virtualCodeToSourceMap.get(virtualCode.snapshot); | ||
if (mapCache?.[0] !== sourceScript.snapshot) { | ||
if (virtualCode.mappings.some(mapping => mapping.source)) { | ||
throw 'not implemented'; | ||
if (!mapCache.has(sourceScript.snapshot)) { | ||
mapCache.set(sourceScript.snapshot, new source_map_1.SourceMap(virtualCode.mappings)); | ||
} | ||
yield [sourceScript.id, sourceScript.snapshot, mapCache.get(sourceScript.snapshot)]; | ||
if (virtualCode.associatedScriptMappings) { | ||
for (const [relatedScriptId, relatedMappings] of virtualCode.associatedScriptMappings) { | ||
const relatedSourceScript = scriptRegistry.get(relatedScriptId); | ||
if (relatedSourceScript) { | ||
if (!mapCache.has(relatedSourceScript.snapshot)) { | ||
mapCache.set(relatedSourceScript.snapshot, new source_map_1.SourceMap(relatedMappings)); | ||
} | ||
yield [relatedSourceScript.id, relatedSourceScript.snapshot, mapCache.get(relatedSourceScript.snapshot)]; | ||
} | ||
} | ||
virtualCodeToSourceMap.set(virtualCode.snapshot, mapCache = [ | ||
sourceScript.snapshot, | ||
new source_map_1.SourceMap(virtualCode.mappings), | ||
]); | ||
} | ||
return mapCache[1]; | ||
}, | ||
@@ -156,2 +177,28 @@ }, | ||
}; | ||
function triggerTargetsDirty(sourceScript) { | ||
sourceScript.targetIds.forEach(id => { | ||
const sourceScript = scriptRegistry.get(id); | ||
if (sourceScript) { | ||
sourceScript.isAssociationDirty = true; | ||
} | ||
}); | ||
} | ||
function prepareCreateVirtualCode(sourceScript) { | ||
for (const id of sourceScript.associatedIds) { | ||
scriptRegistry.get(id)?.targetIds.delete(sourceScript.id); | ||
} | ||
sourceScript.associatedIds.clear(); | ||
sourceScript.isAssociationDirty = false; | ||
return { | ||
getAssociatedScript(id) { | ||
sync(id); | ||
const relatedSourceScript = scriptRegistry.get(id); | ||
if (relatedSourceScript) { | ||
relatedSourceScript.targetIds.add(sourceScript.id); | ||
sourceScript.associatedIds.add(relatedSourceScript.id); | ||
} | ||
return relatedSourceScript; | ||
}, | ||
}; | ||
} | ||
} | ||
@@ -158,0 +205,0 @@ exports.createLanguage = createLanguage; |
import { SourceMap } from '@volar/source-map'; | ||
export declare class LinkedCodeMap extends SourceMap { | ||
export declare class LinkedCodeMap extends SourceMap<any> { | ||
getLinkedOffsets(start: number): Generator<number, void, unknown>; | ||
} |
import type { Mapping, SourceMap } from '@volar/source-map'; | ||
import type * as ts from 'typescript'; | ||
import type { LinkedCodeMap } from './linkedCodeMap'; | ||
export interface Language<T> { | ||
export interface Language<T = unknown> { | ||
plugins: LanguagePlugin<T>[]; | ||
@@ -10,9 +10,10 @@ scripts: { | ||
delete(id: T): void; | ||
fromVirtualCode(virtualCode: VirtualCode): SourceScript<T>; | ||
fromVirtualCode(virtualCode: VirtualCode<T>): SourceScript<T>; | ||
}; | ||
maps: { | ||
get(virtualCode: VirtualCode): SourceMap<CodeInformation>; | ||
get(virtualCode: VirtualCode<T>): SourceMap<CodeInformation>; | ||
forEach(virtualCode: VirtualCode<T>): Generator<[id: T, snapshot: ts.IScriptSnapshot, map: SourceMap<CodeInformation>]>; | ||
}; | ||
linkedCodeMaps: { | ||
get(virtualCode: VirtualCode): LinkedCodeMap | undefined; | ||
get(virtualCode: VirtualCode<T>): LinkedCodeMap | undefined; | ||
}; | ||
@@ -26,3 +27,3 @@ typescript?: { | ||
languageServiceHost: ts.LanguageServiceHost; | ||
getExtraServiceScript(fileName: string): TypeScriptExtraServiceScript | undefined; | ||
getExtraServiceScript(fileName: string): TypeScriptExtraServiceScript<T> | undefined; | ||
asScriptId(fileName: string): T; | ||
@@ -32,14 +33,17 @@ asFileName(scriptId: T): string; | ||
} | ||
export interface SourceScript<T> { | ||
export interface SourceScript<T = unknown> { | ||
id: T; | ||
languageId: string; | ||
snapshot: ts.IScriptSnapshot; | ||
targetIds: Set<T>; | ||
associatedIds: Set<T>; | ||
isAssociationDirty?: boolean; | ||
generated?: { | ||
root: VirtualCode; | ||
root: VirtualCode<T>; | ||
languagePlugin: LanguagePlugin<T>; | ||
embeddedCodes: Map<string, VirtualCode>; | ||
embeddedCodes: Map<string, VirtualCode<T>>; | ||
}; | ||
} | ||
export type CodeMapping = Mapping<CodeInformation>; | ||
export interface VirtualCode { | ||
export interface VirtualCode<T = unknown> { | ||
id: string; | ||
@@ -49,3 +53,4 @@ languageId: string; | ||
mappings: CodeMapping[]; | ||
embeddedCodes?: VirtualCode[]; | ||
associatedScriptMappings?: Map<T, CodeMapping[]>; | ||
embeddedCodes?: VirtualCode<T>[]; | ||
linkedCodeMappings?: Mapping[]; | ||
@@ -78,11 +83,13 @@ } | ||
} | ||
export interface TypeScriptServiceScript { | ||
code: VirtualCode; | ||
export interface TypeScriptServiceScript<T = unknown> { | ||
code: VirtualCode<T>; | ||
extension: '.ts' | '.js' | '.mts' | '.mjs' | '.cjs' | '.cts' | '.d.ts' | string; | ||
scriptKind: ts.ScriptKind; | ||
/** See #188 */ | ||
preventLeadingOffset?: boolean; | ||
} | ||
export interface TypeScriptExtraServiceScript extends TypeScriptServiceScript { | ||
export interface TypeScriptExtraServiceScript<T = unknown> extends TypeScriptServiceScript<T> { | ||
fileName: string; | ||
} | ||
export interface LanguagePlugin<T, K extends VirtualCode = VirtualCode> { | ||
export interface LanguagePlugin<T = unknown, K extends VirtualCode<T> = VirtualCode<T>> { | ||
/** | ||
@@ -95,7 +102,7 @@ * For files that are not opened in the IDE, the language ID will not be synchronized to the language server, so a hook is needed to parse the language ID of files that are known extension but not opened in the IDE. | ||
*/ | ||
createVirtualCode?(scriptId: T, languageId: string, snapshot: ts.IScriptSnapshot): K | undefined; | ||
createVirtualCode?(scriptId: T, languageId: string, snapshot: ts.IScriptSnapshot, ctx: CodegenContext<T>): K | undefined; | ||
/** | ||
* Incremental update a virtual code. If not provide, call createVirtualCode again. | ||
*/ | ||
updateVirtualCode?(scriptId: T, virtualCode: K, newSnapshot: ts.IScriptSnapshot): K | undefined; | ||
updateVirtualCode?(scriptId: T, virtualCode: K, newSnapshot: ts.IScriptSnapshot, ctx: CodegenContext<T>): K | undefined; | ||
/** | ||
@@ -105,11 +112,14 @@ * Cleanup a virtual code. | ||
disposeVirtualCode?(scriptId: T, virtualCode: K): void; | ||
typescript?: TypeScriptGenericOptions<K> & TypeScriptNonTSPluginOptions<K>; | ||
typescript?: TypeScriptGenericOptions<T, K> & TypeScriptNonTSPluginOptions<T, K>; | ||
} | ||
export interface CodegenContext<T = unknown> { | ||
getAssociatedScript(scriptId: T): SourceScript<T> | undefined; | ||
} | ||
/** | ||
* The following options available to all situations. | ||
*/ | ||
interface TypeScriptGenericOptions<T> { | ||
interface TypeScriptGenericOptions<T, K> { | ||
extraFileExtensions: ts.FileExtensionInfo[]; | ||
resolveHiddenExtensions?: boolean; | ||
getServiceScript(rootVirtualCode: T): TypeScriptServiceScript | undefined; | ||
getServiceScript(root: K): TypeScriptServiceScript<T> | undefined; | ||
} | ||
@@ -119,6 +129,6 @@ /** | ||
*/ | ||
interface TypeScriptNonTSPluginOptions<T> { | ||
getExtraServiceScripts?(fileName: string, rootVirtualCode: T): TypeScriptExtraServiceScript[]; | ||
interface TypeScriptNonTSPluginOptions<T, K> { | ||
getExtraServiceScripts?(fileName: string, rootVirtualCode: K): TypeScriptExtraServiceScript<T>[]; | ||
resolveLanguageServiceHost?(host: ts.LanguageServiceHost): ts.LanguageServiceHost; | ||
} | ||
export {}; |
{ | ||
"name": "@volar/language-core", | ||
"version": "2.3.0-alpha.5", | ||
"version": "2.3.0-alpha.6", | ||
"license": "MIT", | ||
@@ -15,5 +15,5 @@ "files": [ | ||
"dependencies": { | ||
"@volar/source-map": "2.3.0-alpha.5" | ||
"@volar/source-map": "2.3.0-alpha.6" | ||
}, | ||
"gitHead": "c3f6867de39095913ceaa2256ad35a9ca1a90487" | ||
"gitHead": "f3103e86be8d80cb36f66be4c054ef9a255c29b1" | ||
} |
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
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
25626
558
+ Added@volar/source-map@2.3.0-alpha.6(transitive)
- Removed@volar/source-map@2.3.0-alpha.5(transitive)