first commit

This commit is contained in:
rafaeldpsilva
2025-12-10 12:32:12 +00:00
commit adbbf6bf50
3442 changed files with 2725681 additions and 0 deletions

21
web-app/node_modules/@volar/language-core/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present Johnson Chu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

9
web-app/node_modules/@volar/language-core/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
export { Mapping, SourceMap } from '@volar/source-map';
export * from './lib/editor';
export * from './lib/linkedCodeMap';
export * from './lib/types';
export * from './lib/utils';
import type { Language, LanguagePlugin, MapperFactory, SourceScript, VirtualCode } from './lib/types';
export declare const defaultMapperFactory: MapperFactory;
export declare function createLanguage<T>(plugins: LanguagePlugin<T>[], scriptRegistry: Map<T, SourceScript<T>>, sync: (id: T, includeFsFiles: boolean, shouldRegister: boolean) => void, onAssociationDirty?: (targetId: T) => void): Language<T>;
export declare function forEachEmbeddedCode(virtualCode: VirtualCode): Generator<VirtualCode>;

239
web-app/node_modules/@volar/language-core/index.js generated vendored Normal file
View File

@@ -0,0 +1,239 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultMapperFactory = exports.SourceMap = void 0;
exports.createLanguage = createLanguage;
exports.forEachEmbeddedCode = forEachEmbeddedCode;
var source_map_1 = require("@volar/source-map");
Object.defineProperty(exports, "SourceMap", { enumerable: true, get: function () { return source_map_1.SourceMap; } });
__exportStar(require("./lib/editor"), exports);
__exportStar(require("./lib/linkedCodeMap"), exports);
__exportStar(require("./lib/types"), exports);
__exportStar(require("./lib/utils"), exports);
const source_map_2 = require("@volar/source-map");
const linkedCodeMap_1 = require("./lib/linkedCodeMap");
const defaultMapperFactory = mappings => new source_map_2.SourceMap(mappings);
exports.defaultMapperFactory = defaultMapperFactory;
function createLanguage(plugins, scriptRegistry, sync, onAssociationDirty) {
const virtualCodeToSourceScriptMap = new WeakMap();
const virtualCodeToSourceMap = new WeakMap();
const virtualCodeToLinkedCodeMap = new WeakMap();
const language = {
mapperFactory: exports.defaultMapperFactory,
plugins,
scripts: {
fromVirtualCode(virtualCode) {
return virtualCodeToSourceScriptMap.get(virtualCode);
},
get(id, includeFsFiles = true, shouldRegister = false) {
sync(id, includeFsFiles, shouldRegister);
const result = scriptRegistry.get(id);
// The sync function provider may not always call the set function due to caching, so it is necessary to explicitly check isAssociationDirty.
if (result?.isAssociationDirty) {
this.set(id, result.snapshot, result.languageId);
}
return scriptRegistry.get(id);
},
set(id, snapshot, languageId, _plugins = plugins) {
if (!languageId) {
for (const plugin of plugins) {
languageId = plugin.getLanguageId?.(id);
if (languageId) {
break;
}
}
}
if (!languageId) {
console.warn(`languageId not found for ${id}`);
return;
}
let associatedOnly = false;
for (const plugin of plugins) {
if (plugin.isAssociatedFileOnly?.(id, languageId)) {
associatedOnly = true;
break;
}
}
if (scriptRegistry.has(id)) {
const sourceScript = scriptRegistry.get(id);
if (sourceScript.languageId !== languageId || sourceScript.associatedOnly !== associatedOnly) {
this.delete(id);
triggerTargetsDirty(sourceScript);
return this.set(id, snapshot, languageId);
}
else if (associatedOnly) {
if (sourceScript.snapshot !== snapshot) {
sourceScript.snapshot = snapshot;
triggerTargetsDirty(sourceScript);
}
}
else if (sourceScript.isAssociationDirty || sourceScript.snapshot !== snapshot) {
if (sourceScript.snapshot !== snapshot) {
sourceScript.snapshot = snapshot;
triggerTargetsDirty(sourceScript);
}
const codegenCtx = prepareCreateVirtualCode(sourceScript);
if (sourceScript.generated) {
const { updateVirtualCode, createVirtualCode } = sourceScript.generated.languagePlugin;
const newVirtualCode = updateVirtualCode
? updateVirtualCode(id, sourceScript.generated.root, snapshot, codegenCtx)
: createVirtualCode?.(id, languageId, snapshot, codegenCtx);
if (newVirtualCode) {
sourceScript.generated.root = newVirtualCode;
sourceScript.generated.embeddedCodes.clear();
for (const code of forEachEmbeddedCode(sourceScript.generated.root)) {
virtualCodeToSourceScriptMap.set(code, sourceScript);
sourceScript.generated.embeddedCodes.set(code.id, code);
}
return sourceScript;
}
else {
this.delete(id);
return;
}
}
}
else {
// not changed
return sourceScript;
}
}
else {
// created
const sourceScript = {
id: id,
languageId,
snapshot,
associatedIds: new Set(),
targetIds: new Set(),
associatedOnly
};
scriptRegistry.set(id, sourceScript);
if (associatedOnly) {
return sourceScript;
}
for (const languagePlugin of _plugins) {
const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot, prepareCreateVirtualCode(sourceScript));
if (virtualCode) {
sourceScript.generated = {
root: virtualCode,
languagePlugin,
embeddedCodes: new Map(),
};
for (const code of forEachEmbeddedCode(virtualCode)) {
virtualCodeToSourceScriptMap.set(code, sourceScript);
sourceScript.generated.embeddedCodes.set(code.id, code);
}
break;
}
}
return sourceScript;
}
},
delete(id) {
const sourceScript = scriptRegistry.get(id);
if (sourceScript) {
sourceScript.generated?.languagePlugin.disposeVirtualCode?.(id, sourceScript.generated.root);
scriptRegistry.delete(id);
triggerTargetsDirty(sourceScript);
}
},
},
maps: {
get(virtualCode, sourceScript) {
let mapCache = virtualCodeToSourceMap.get(virtualCode.snapshot);
if (!mapCache) {
virtualCodeToSourceMap.set(virtualCode.snapshot, mapCache = new WeakMap());
}
if (!mapCache.has(sourceScript.snapshot)) {
const mappings = virtualCode.associatedScriptMappings?.get(sourceScript.id) ?? virtualCode.mappings;
mapCache.set(sourceScript.snapshot, language.mapperFactory(mappings));
}
return mapCache.get(sourceScript.snapshot);
},
*forEach(virtualCode) {
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
yield [
sourceScript,
this.get(virtualCode, sourceScript),
];
if (virtualCode.associatedScriptMappings) {
for (const [relatedScriptId] of virtualCode.associatedScriptMappings) {
const relatedSourceScript = scriptRegistry.get(relatedScriptId);
if (relatedSourceScript) {
yield [
relatedSourceScript,
this.get(virtualCode, relatedSourceScript),
];
}
}
}
},
},
linkedCodeMaps: {
get(virtualCode) {
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
let mapCache = virtualCodeToLinkedCodeMap.get(virtualCode.snapshot);
if (mapCache?.[0] !== sourceScript.snapshot) {
virtualCodeToLinkedCodeMap.set(virtualCode.snapshot, mapCache = [
sourceScript.snapshot,
virtualCode.linkedCodeMappings
? new linkedCodeMap_1.LinkedCodeMap(virtualCode.linkedCodeMappings)
: undefined,
]);
}
return mapCache[1];
},
},
};
return language;
function triggerTargetsDirty(sourceScript) {
sourceScript.targetIds.forEach(id => {
const sourceScript = scriptRegistry.get(id);
if (sourceScript) {
sourceScript.isAssociationDirty = true;
onAssociationDirty?.(sourceScript.id);
}
});
}
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, true, true);
const relatedSourceScript = scriptRegistry.get(id);
if (relatedSourceScript) {
relatedSourceScript.targetIds.add(sourceScript.id);
sourceScript.associatedIds.add(relatedSourceScript.id);
}
return relatedSourceScript;
},
};
}
}
function* forEachEmbeddedCode(virtualCode) {
yield virtualCode;
if (virtualCode.embeddedCodes) {
for (const embeddedCode of virtualCode.embeddedCodes) {
yield* forEachEmbeddedCode(embeddedCode);
}
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,34 @@
import type { CodeInformation, Mapper } from './types';
export declare function isHoverEnabled(info: CodeInformation): boolean;
export declare function isInlayHintsEnabled(info: CodeInformation): boolean;
export declare function isCodeLensEnabled(info: CodeInformation): boolean;
export declare function isMonikerEnabled(info: CodeInformation): boolean;
export declare function isInlineValueEnabled(info: CodeInformation): boolean;
export declare function isSemanticTokensEnabled(info: CodeInformation): boolean;
export declare function isCallHierarchyEnabled(info: CodeInformation): boolean;
export declare function isTypeHierarchyEnabled(info: CodeInformation): boolean;
export declare function isRenameEnabled(info: CodeInformation): boolean;
export declare function isDefinitionEnabled(info: CodeInformation): boolean;
export declare function isTypeDefinitionEnabled(info: CodeInformation): boolean;
export declare function isReferencesEnabled(info: CodeInformation): boolean;
export declare function isImplementationEnabled(info: CodeInformation): boolean;
export declare function isHighlightEnabled(info: CodeInformation): boolean;
export declare function isSymbolsEnabled(info: CodeInformation): boolean;
export declare function isFoldingRangesEnabled(info: CodeInformation): boolean;
export declare function isSelectionRangesEnabled(info: CodeInformation): boolean;
export declare function isLinkedEditingEnabled(info: CodeInformation): boolean;
export declare function isColorEnabled(info: CodeInformation): boolean;
export declare function isDocumentLinkEnabled(info: CodeInformation): boolean;
export declare function isDiagnosticsEnabled(info: CodeInformation): boolean;
export declare function isCodeActionsEnabled(info: CodeInformation): boolean;
export declare function isFormattingEnabled(info: CodeInformation): boolean;
export declare function isCompletionEnabled(info: CodeInformation): boolean;
export declare function isAutoInsertEnabled(info: CodeInformation): boolean;
export declare function isSignatureHelpEnabled(info: CodeInformation): boolean;
export declare function shouldReportDiagnostics(info: CodeInformation, source: string | undefined, code: string | number | undefined): boolean;
export declare function resolveRenameNewName(newName: string, info: CodeInformation): string;
export declare function resolveRenameEditText(text: string, info: CodeInformation): string;
export declare function findOverlapCodeRange(start: number, end: number, map: Mapper, filter: (data: CodeInformation) => boolean): {
start: number;
end: number;
} | undefined;

182
web-app/node_modules/@volar/language-core/lib/editor.js generated vendored Normal file
View File

@@ -0,0 +1,182 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isHoverEnabled = isHoverEnabled;
exports.isInlayHintsEnabled = isInlayHintsEnabled;
exports.isCodeLensEnabled = isCodeLensEnabled;
exports.isMonikerEnabled = isMonikerEnabled;
exports.isInlineValueEnabled = isInlineValueEnabled;
exports.isSemanticTokensEnabled = isSemanticTokensEnabled;
exports.isCallHierarchyEnabled = isCallHierarchyEnabled;
exports.isTypeHierarchyEnabled = isTypeHierarchyEnabled;
exports.isRenameEnabled = isRenameEnabled;
exports.isDefinitionEnabled = isDefinitionEnabled;
exports.isTypeDefinitionEnabled = isTypeDefinitionEnabled;
exports.isReferencesEnabled = isReferencesEnabled;
exports.isImplementationEnabled = isImplementationEnabled;
exports.isHighlightEnabled = isHighlightEnabled;
exports.isSymbolsEnabled = isSymbolsEnabled;
exports.isFoldingRangesEnabled = isFoldingRangesEnabled;
exports.isSelectionRangesEnabled = isSelectionRangesEnabled;
exports.isLinkedEditingEnabled = isLinkedEditingEnabled;
exports.isColorEnabled = isColorEnabled;
exports.isDocumentLinkEnabled = isDocumentLinkEnabled;
exports.isDiagnosticsEnabled = isDiagnosticsEnabled;
exports.isCodeActionsEnabled = isCodeActionsEnabled;
exports.isFormattingEnabled = isFormattingEnabled;
exports.isCompletionEnabled = isCompletionEnabled;
exports.isAutoInsertEnabled = isAutoInsertEnabled;
exports.isSignatureHelpEnabled = isSignatureHelpEnabled;
exports.shouldReportDiagnostics = shouldReportDiagnostics;
exports.resolveRenameNewName = resolveRenameNewName;
exports.resolveRenameEditText = resolveRenameEditText;
exports.findOverlapCodeRange = findOverlapCodeRange;
function isHoverEnabled(info) {
return !!info.semantic;
}
function isInlayHintsEnabled(info) {
return !!info.semantic;
}
function isCodeLensEnabled(info) {
return !!info.semantic;
}
function isMonikerEnabled(info) {
return !!info.semantic;
}
function isInlineValueEnabled(info) {
return !!info.semantic;
}
function isSemanticTokensEnabled(info) {
return typeof info.semantic === 'object'
? info.semantic.shouldHighlight?.() ?? true
: !!info.semantic;
}
function isCallHierarchyEnabled(info) {
return !!info.navigation;
}
function isTypeHierarchyEnabled(info) {
return !!info.navigation;
}
function isRenameEnabled(info) {
return typeof info.navigation === 'object'
? info.navigation.shouldRename?.() ?? true
: !!info.navigation;
}
function isDefinitionEnabled(info) {
return !!info.navigation;
}
function isTypeDefinitionEnabled(info) {
return !!info.navigation;
}
function isReferencesEnabled(info) {
return !!info.navigation;
}
function isImplementationEnabled(info) {
return !!info.navigation;
}
function isHighlightEnabled(info) {
return !!info.navigation;
}
function isSymbolsEnabled(info) {
return !!info.structure;
}
function isFoldingRangesEnabled(info) {
return !!info.structure;
}
function isSelectionRangesEnabled(info) {
return !!info.structure;
}
function isLinkedEditingEnabled(info) {
return !!info.structure;
}
function isColorEnabled(info) {
return !!info.structure;
}
function isDocumentLinkEnabled(info) {
return !!info.structure;
}
function isDiagnosticsEnabled(info) {
return !!info.verification;
}
function isCodeActionsEnabled(info) {
return !!info.verification;
}
function isFormattingEnabled(info) {
return !!info.format;
}
function isCompletionEnabled(info) {
return !!info.completion;
}
function isAutoInsertEnabled(info) {
return !!info.completion;
}
function isSignatureHelpEnabled(info) {
return !!info.completion;
}
// should...
function shouldReportDiagnostics(info, source, code) {
return typeof info.verification === 'object'
? info.verification.shouldReport?.(source, code) ?? true
: !!info.verification;
}
// resolve...
function resolveRenameNewName(newName, info) {
return typeof info.navigation === 'object'
? info.navigation.resolveRenameNewName?.(newName) ?? newName
: newName;
}
function resolveRenameEditText(text, info) {
return typeof info.navigation === 'object'
? info.navigation.resolveRenameEditText?.(text) ?? text
: text;
}
function findOverlapCodeRange(start, end, map, filter) {
let mappedStart;
let mappedEnd;
for (const [mapped, mapping] of map.toGeneratedLocation(start)) {
if (filter(mapping.data)) {
mappedStart = mapped;
break;
}
}
for (const [mapped, mapping] of map.toGeneratedLocation(end)) {
if (filter(mapping.data)) {
mappedEnd = mapped;
break;
}
}
if (mappedStart === undefined || mappedEnd === undefined) {
for (const mapping of map.mappings) {
if (filter(mapping.data)) {
const mappingStart = mapping.sourceOffsets[0];
const mappingEnd = mapping.sourceOffsets[mapping.sourceOffsets.length - 1] + mapping.lengths[mapping.lengths.length - 1];
const overlap = getOverlapRange(start, end, mappingStart, mappingEnd);
if (overlap) {
const curMappedStart = (overlap.start - mappingStart) + mapping.generatedOffsets[0];
const lastGeneratedLength = (mapping.generatedLengths ?? mapping.lengths)[mapping.generatedOffsets.length - 1];
const curMappedEndOffset = Math.min(overlap.end - mapping.sourceOffsets[mapping.sourceOffsets.length - 1], lastGeneratedLength);
const curMappedEnd = mapping.generatedOffsets[mapping.generatedOffsets.length - 1] + curMappedEndOffset;
mappedStart = mappedStart === undefined ? curMappedStart : Math.min(mappedStart, curMappedStart);
mappedEnd = mappedEnd === undefined ? curMappedEnd : Math.max(mappedEnd, curMappedEnd);
}
}
}
}
if (mappedStart !== undefined && mappedEnd !== undefined) {
return {
start: mappedStart,
end: mappedEnd,
};
}
}
function getOverlapRange(range1Start, range1End, range2Start, range2End) {
const start = Math.max(range1Start, range2Start);
const end = Math.min(range1End, range2End);
if (start > end) {
return undefined;
}
return {
start,
end,
};
}
//# sourceMappingURL=editor.js.map

View File

@@ -0,0 +1,28 @@
import type { CodeInformation } from './types';
export declare function isHoverEnabled(info: CodeInformation): boolean;
export declare function isInlayHintsEnabled(info: CodeInformation): boolean;
export declare function isCodeLensEnabled(info: CodeInformation): boolean;
export declare function isMonikerEnabled(info: CodeInformation): boolean;
export declare function isInlineValueEnabled(info: CodeInformation): boolean;
export declare function isSemanticTokensEnabled(info: CodeInformation): boolean;
export declare function isCallHierarchyEnabled(info: CodeInformation): boolean;
export declare function isTypeHierarchyEnabled(info: CodeInformation): boolean;
export declare function isRenameEnabled(info: CodeInformation): boolean;
export declare function isDefinitionEnabled(info: CodeInformation): boolean;
export declare function isTypeDefinitionEnabled(info: CodeInformation): boolean;
export declare function isReferencesEnabled(info: CodeInformation): boolean;
export declare function isImplementationEnabled(info: CodeInformation): boolean;
export declare function isHighlightEnabled(info: CodeInformation): boolean;
export declare function isSymbolsEnabled(info: CodeInformation): boolean;
export declare function isFoldingRangesEnabled(info: CodeInformation): boolean;
export declare function isSelectionRangesEnabled(info: CodeInformation): boolean;
export declare function isLinkedEditingEnabled(info: CodeInformation): boolean;
export declare function isColorEnabled(info: CodeInformation): boolean;
export declare function isDocumentLinkEnabled(info: CodeInformation): boolean;
export declare function isDiagnosticsEnabled(info: CodeInformation): boolean;
export declare function isCodeActionsEnabled(info: CodeInformation): boolean;
export declare function isFormattingEnabled(info: CodeInformation): boolean;
export declare function isCompletionEnabled(info: CodeInformation): boolean;
export declare function isAutoInsertEnabled(info: CodeInformation): boolean;
export declare function isSignatureHelpEnabled(info: CodeInformation): boolean;
export declare function shouldReportDiagnostics(info: CodeInformation, source: string | undefined, code: string | number | undefined): boolean;

View File

@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isHoverEnabled = isHoverEnabled;
exports.isInlayHintsEnabled = isInlayHintsEnabled;
exports.isCodeLensEnabled = isCodeLensEnabled;
exports.isMonikerEnabled = isMonikerEnabled;
exports.isInlineValueEnabled = isInlineValueEnabled;
exports.isSemanticTokensEnabled = isSemanticTokensEnabled;
exports.isCallHierarchyEnabled = isCallHierarchyEnabled;
exports.isTypeHierarchyEnabled = isTypeHierarchyEnabled;
exports.isRenameEnabled = isRenameEnabled;
exports.isDefinitionEnabled = isDefinitionEnabled;
exports.isTypeDefinitionEnabled = isTypeDefinitionEnabled;
exports.isReferencesEnabled = isReferencesEnabled;
exports.isImplementationEnabled = isImplementationEnabled;
exports.isHighlightEnabled = isHighlightEnabled;
exports.isSymbolsEnabled = isSymbolsEnabled;
exports.isFoldingRangesEnabled = isFoldingRangesEnabled;
exports.isSelectionRangesEnabled = isSelectionRangesEnabled;
exports.isLinkedEditingEnabled = isLinkedEditingEnabled;
exports.isColorEnabled = isColorEnabled;
exports.isDocumentLinkEnabled = isDocumentLinkEnabled;
exports.isDiagnosticsEnabled = isDiagnosticsEnabled;
exports.isCodeActionsEnabled = isCodeActionsEnabled;
exports.isFormattingEnabled = isFormattingEnabled;
exports.isCompletionEnabled = isCompletionEnabled;
exports.isAutoInsertEnabled = isAutoInsertEnabled;
exports.isSignatureHelpEnabled = isSignatureHelpEnabled;
exports.shouldReportDiagnostics = shouldReportDiagnostics;
function isHoverEnabled(info) {
return !!info.semantic;
}
function isInlayHintsEnabled(info) {
return !!info.semantic;
}
function isCodeLensEnabled(info) {
return !!info.semantic;
}
function isMonikerEnabled(info) {
return !!info.semantic;
}
function isInlineValueEnabled(info) {
return !!info.semantic;
}
function isSemanticTokensEnabled(info) {
return typeof info.semantic === 'object'
? info.semantic.shouldHighlight?.() ?? true
: !!info.semantic;
}
function isCallHierarchyEnabled(info) {
return !!info.navigation;
}
function isTypeHierarchyEnabled(info) {
return !!info.navigation;
}
function isRenameEnabled(info) {
return typeof info.navigation === 'object'
? info.navigation.shouldRename?.() ?? true
: !!info.navigation;
}
function isDefinitionEnabled(info) {
return !!info.navigation;
}
function isTypeDefinitionEnabled(info) {
return !!info.navigation;
}
function isReferencesEnabled(info) {
return !!info.navigation;
}
function isImplementationEnabled(info) {
return !!info.navigation;
}
function isHighlightEnabled(info) {
return !!info.navigation;
}
function isSymbolsEnabled(info) {
return !!info.structure;
}
function isFoldingRangesEnabled(info) {
return !!info.structure;
}
function isSelectionRangesEnabled(info) {
return !!info.structure;
}
function isLinkedEditingEnabled(info) {
return !!info.structure;
}
function isColorEnabled(info) {
return !!info.structure;
}
function isDocumentLinkEnabled(info) {
return !!info.structure;
}
function isDiagnosticsEnabled(info) {
return !!info.verification;
}
function isCodeActionsEnabled(info) {
return !!info.verification;
}
function isFormattingEnabled(info) {
return !!info.format;
}
function isCompletionEnabled(info) {
return !!info.completion;
}
function isAutoInsertEnabled(info) {
return !!info.completion;
}
function isSignatureHelpEnabled(info) {
return !!info.completion;
}
// should...
function shouldReportDiagnostics(info, source, code) {
return typeof info.verification === 'object'
? info.verification.shouldReport?.(source, code) ?? true
: !!info.verification;
}
//# sourceMappingURL=editorFeatures.js.map

View File

@@ -0,0 +1,4 @@
import { SourceMap } from '@volar/source-map';
export declare class LinkedCodeMap extends SourceMap<any> {
getLinkedOffsets(start: number): Generator<number, void, unknown>;
}

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LinkedCodeMap = void 0;
const source_map_1 = require("@volar/source-map");
class LinkedCodeMap extends source_map_1.SourceMap {
*getLinkedOffsets(start) {
for (const mapped of this.toGeneratedLocation(start)) {
yield mapped[0];
}
for (const mapped of this.toSourceLocation(start)) {
yield mapped[0];
}
}
}
exports.LinkedCodeMap = LinkedCodeMap;
//# sourceMappingURL=linkedCodeMap.js.map

View File

@@ -0,0 +1,155 @@
import type { Mapping } from '@volar/source-map';
import type { LinkedCodeMap } from './linkedCodeMap';
export interface Mapper {
mappings: Mapping<CodeInformation>[];
toSourceRange(start: number, end: number, fallbackToAnyMatch: boolean, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, number, Mapping<CodeInformation>, Mapping<CodeInformation>]>;
toGeneratedRange(start: number, end: number, fallbackToAnyMatch: boolean, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, number, Mapping<CodeInformation>, Mapping<CodeInformation>]>;
toSourceLocation(generatedOffset: number, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, Mapping<CodeInformation>]>;
toGeneratedLocation(sourceOffset: number, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, Mapping<CodeInformation>]>;
}
export type MapperFactory = (mappings: Mapping<CodeInformation>[]) => Mapper;
export interface Language<T = unknown> {
mapperFactory: MapperFactory;
plugins: LanguagePlugin<T>[];
scripts: {
get(id: T, includeFsFiles?: boolean, shouldRegister?: boolean): SourceScript<T> | undefined;
set(id: T, snapshot: IScriptSnapshot, languageId?: string, plugins?: LanguagePlugin<T>[]): SourceScript<T> | undefined;
delete(id: T): void;
fromVirtualCode(virtualCode: VirtualCode): SourceScript<T>;
};
maps: {
get(virtualCode: VirtualCode, sourceScript: SourceScript<T>): Mapper;
forEach(virtualCode: VirtualCode): Generator<[sourceScript: SourceScript<T>, map: Mapper]>;
};
linkedCodeMaps: {
get(virtualCode: VirtualCode): LinkedCodeMap | undefined;
};
}
export interface SourceScript<T = unknown> {
id: T;
languageId: string;
snapshot: IScriptSnapshot;
targetIds: Set<T>;
associatedIds: Set<T>;
associatedOnly: boolean;
isAssociationDirty?: boolean;
generated?: {
root: VirtualCode;
languagePlugin: LanguagePlugin<T>;
embeddedCodes: Map<string, VirtualCode>;
};
}
export type CodeMapping = Mapping<CodeInformation>;
export interface VirtualCode {
id: string;
languageId: string;
snapshot: IScriptSnapshot;
mappings: CodeMapping[];
associatedScriptMappings?: Map<unknown, CodeMapping[]>;
embeddedCodes?: VirtualCode[];
linkedCodeMappings?: Mapping[];
}
/**
* CodeInformation is a configuration object attached to each CodeMapping (between source code and generated code,
* e.g. between the template code in a .vue file and the type-checkable TS code generated from it) that
* determines what code/language features are expected to be available for the mapping.
*
* Due to the dynamic nature of code generation and the fact that, for example, things like Code Actions
* and auto-complete shouldn't be triggerable on certain "in-between" regions of generated code, we need
* a way to shut off certain features in certain regions, while leaving them enabled in others.
*/
export interface CodeInformation {
/** virtual code is expected to support verification, where verification includes:
*
* - diagnostics (syntactic, semantic, and others, such as those generated by the TypeScript language service on generated TS code)
* - code actions (refactorings, quick fixes,etc.)
*/
verification?: boolean | {
/**
* when present, `shouldReport` callback is invoked to determine whether a diagnostic
* raised in the generated code should be propagated back to the original source code.
* Note that when this callback is present, diagnostic processing (e.g. typechecking) will
* still be performed, but the results will not be reported back to the original source code. */
shouldReport?(source: string | undefined, code: string | number | undefined): boolean;
};
/** virtual code is expected to support assisted completion */
completion?: boolean | {
isAdditional?: boolean;
onlyImport?: boolean;
};
/** virtual code is expected correctly reflect semantic of the source code. Specifically this controls the following langauge features:
*
* - hover
* - inlay hints
* - code lens
* - semantic tokens
* - others
*
* Note that semantic diagnostics (e.g. TS type-checking) are covered by the `verification` property above.
*/
semantic?: boolean | {
shouldHighlight?(): boolean;
};
/** virtual code is expected correctly reflect reference relationships of the source code */
navigation?: boolean | {
shouldRename?(): boolean;
resolveRenameNewName?(newName: string): string;
resolveRenameEditText?(newText: string): string;
};
/** virtual code is expected correctly reflect the structural information of the source code */
structure?: boolean;
/** virtual code is expected correctly reflect the format information of the source code */
format?: boolean;
}
export interface LanguagePlugin<T = unknown, K extends VirtualCode = VirtualCode> {
/**
* 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.
*/
getLanguageId(scriptId: T): string | undefined;
/**
* Generate a virtual code.
*/
createVirtualCode?(scriptId: T, languageId: string, snapshot: IScriptSnapshot, ctx: CodegenContext<T>): K | undefined;
/**
* Incremental update a virtual code. If not provide, call createVirtualCode again.
*/
updateVirtualCode?(scriptId: T, virtualCode: K, newSnapshot: IScriptSnapshot, ctx: CodegenContext<T>): K | undefined;
/**
* Cleanup a virtual code.
*/
disposeVirtualCode?(scriptId: T, virtualCode: K): void;
/**
* Some file types should not be parsed or processed as TypeScript files,
* as they are used only as sources for generated files.
*
* This functionality is required only in TS plugin mode.
*/
isAssociatedFileOnly?(scriptId: T, languageId: string): boolean;
}
export interface CodegenContext<T = unknown> {
getAssociatedScript(scriptId: T): SourceScript<T> | undefined;
}
export interface IScriptSnapshot {
/** Gets a portion of the script snapshot specified by [start, end). */
getText(start: number, end: number): string;
/** Gets the length of this script snapshot. */
getLength(): number;
/**
* Gets the TextChangeRange that describe how the text changed between this text and
* an older version. This information is used by the incremental parser to determine
* what sections of the script need to be re-parsed. 'undefined' can be returned if the
* change range cannot be determined. However, in that case, incremental parsing will
* not happen and the entire document will be re - parsed.
*/
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined;
/** Releases all resources held by this script snapshot */
dispose?(): void;
}
export interface TextChangeRange {
span: TextSpan;
newLength: number;
}
export interface TextSpan {
start: number;
length: number;
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1,12 @@
export declare class FileMap<T> extends Map<string, T> {
private caseSensitive;
private originalFileNames;
constructor(caseSensitive: boolean);
keys(): IterableIterator<string>;
get(key: string): T | undefined;
has(key: string): boolean;
set(key: string, value: T): this;
delete(key: string): boolean;
clear(): void;
normalizeId(id: string): string;
}

36
web-app/node_modules/@volar/language-core/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileMap = void 0;
class FileMap extends Map {
constructor(caseSensitive) {
super();
this.caseSensitive = caseSensitive;
this.originalFileNames = new Map();
}
keys() {
return this.originalFileNames.values();
}
get(key) {
return super.get(this.normalizeId(key));
}
has(key) {
return super.has(this.normalizeId(key));
}
set(key, value) {
this.originalFileNames.set(this.normalizeId(key), key);
return super.set(this.normalizeId(key), value);
}
delete(key) {
this.originalFileNames.delete(this.normalizeId(key));
return super.delete(this.normalizeId(key));
}
clear() {
this.originalFileNames.clear();
return super.clear();
}
normalizeId(id) {
return this.caseSensitive ? id : id.toLowerCase();
}
}
exports.FileMap = FileMap;
//# sourceMappingURL=utils.js.map

18
web-app/node_modules/@volar/language-core/package.json generated vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "@volar/language-core",
"version": "2.4.15",
"license": "MIT",
"files": [
"**/*.js",
"**/*.d.ts"
],
"repository": {
"type": "git",
"url": "https://github.com/volarjs/volar.js.git",
"directory": "packages/language-core"
},
"dependencies": {
"@volar/source-map": "2.4.15"
},
"gitHead": "adcdcbc801b284cce3239fec231c7f4cebfd8688"
}

21
web-app/node_modules/@volar/source-map/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present Johnson Chu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
web-app/node_modules/@volar/source-map/README.md generated vendored Normal file
View File

@@ -0,0 +1,53 @@
# @volar/source-map
Provides functionality related to source maps.
## API
### This package exports a `SourceMap` class with the following methods:
Params:
- `fallbackToAnyMatch`(default: false): allow the start and end offsets to come from different mappings.
- `filter?: (data: Data) => boolean)`(default: undefined): according to mapping: Mapping<MyDataType>.data, filter out offsets that do not meet the custom conditions.
Methods:
- `toSourceRange(generatedStart: number, generatedEnd: number, fallbackToAnyMatch: boolean, filter?: (data: Data) => boolean)`: Returns all source start and end offsets for the given generated start and end offsets.
- `toGeneratedRange(sourceStart: number, sourceEnd: number, fallbackToAnyMatch: boolean, filter?: (data: Data) => boolean) `: Returns all generated start and end offsets for the given source start and end offsets.
- `toSourceLocation(generatedOffset: number, filter?: (data: Data) => boolean)`: Returns all source offsets for a given generated offset.
- `toGeneratedLocation(sourceOffset: number, filter?: (data: Data) => boolean)`: Returns all generated offsets for a given source offset.
## Data Structures
### `Mapping`
The `Mapping` is a tuple that represents a mapping in the source map. It consists of the following elements:
- `source`: A string representing the source file. This can be `undefined`.
- `sourceOffsets`: Offsets in the source code.
- `generatedOffsets`: Offsets in the generated code.
- `data`: The data associated with this mapping. The type of this data is generic and can be specified when creating a `SourceMap` instance.
Here is an example of a `Mapping`:
```ts
let mapping: Mapping<MyDataType> = {
source: '.../sourceFile.ts',
sourceOffsets: [10],
generatedOffsets: [30],
lengths: [10],
data: myData,
};
```
In this example, `myData` is of type `MyDataType`, which is the type specified for the SourceMap instance.
Remember to replace `MyDataType` and `myData` with actual types and data that are relevant to your project.
## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.

2
web-app/node_modules/@volar/source-map/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from './lib/sourceMap';
export * from './lib/translateOffset';

19
web-app/node_modules/@volar/source-map/index.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./lib/sourceMap"), exports);
__exportStar(require("./lib/translateOffset"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,5 @@
export declare function binarySearch(values: number[], searchValue: number): {
low: number;
high: number;
match: number | undefined;
};

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.binarySearch = binarySearch;
function binarySearch(values, searchValue) {
let low = 0;
let high = values.length - 1;
let match;
while (low <= high) {
const mid = Math.floor((low + high) / 2);
const midValue = values[mid];
if (midValue < searchValue) {
low = mid + 1;
}
else if (midValue > searchValue) {
high = mid - 1;
}
else {
low = mid;
high = mid;
match = mid;
break;
}
}
const finalLow = Math.max(Math.min(low, high, values.length - 1), 0);
const finalHigh = Math.min(Math.max(low, high, 0), values.length - 1);
return { low: finalLow, high: finalHigh, match };
}
//# sourceMappingURL=binarySearch.js.map

View File

@@ -0,0 +1,23 @@
type CodeRangeKey = 'sourceOffsets' | 'generatedOffsets';
export interface Mapping<Data = unknown> {
sourceOffsets: number[];
generatedOffsets: number[];
lengths: number[];
generatedLengths?: number[];
data: Data;
}
export declare class SourceMap<Data = unknown> {
readonly mappings: Mapping<Data>[];
private sourceCodeOffsetsMemo;
private generatedCodeOffsetsMemo;
constructor(mappings: Mapping<Data>[]);
toSourceRange(generatedStart: number, generatedEnd: number, fallbackToAnyMatch: boolean, filter?: (data: Data) => boolean): Generator<[mappedStart: number, mappedEnd: number, startMapping: Mapping<Data>, endMapping: Mapping<Data>], any, unknown>;
toGeneratedRange(sourceStart: number, sourceEnd: number, fallbackToAnyMatch: boolean, filter?: (data: Data) => boolean): Generator<[mappedStart: number, mappedEnd: number, startMapping: Mapping<Data>, endMapping: Mapping<Data>], any, unknown>;
toSourceLocation(generatedOffset: number, filter?: (data: Data) => boolean): Generator<readonly [number, Mapping<Data>], void, unknown>;
toGeneratedLocation(sourceOffset: number, filter?: (data: Data) => boolean): Generator<readonly [number, Mapping<Data>], void, unknown>;
findMatchingOffsets(offset: number, fromRange: CodeRangeKey, filter?: (data: Data) => boolean): Generator<readonly [number, Mapping<Data>], void, unknown>;
findMatchingStartEnd(start: number, end: number, fallbackToAnyMatch: boolean, fromRange: CodeRangeKey, filter?: (data: Data) => boolean): Generator<[mappedStart: number, mappedEnd: number, startMapping: Mapping<Data>, endMapping: Mapping<Data>]>;
private getMemoBasedOnRange;
private createMemo;
}
export {};

105
web-app/node_modules/@volar/source-map/lib/sourceMap.js generated vendored Normal file
View File

@@ -0,0 +1,105 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SourceMap = void 0;
const binarySearch_1 = require("./binarySearch");
const translateOffset_1 = require("./translateOffset");
class SourceMap {
constructor(mappings) {
this.mappings = mappings;
}
toSourceRange(generatedStart, generatedEnd, fallbackToAnyMatch, filter) {
return this.findMatchingStartEnd(generatedStart, generatedEnd, fallbackToAnyMatch, 'generatedOffsets', filter);
}
toGeneratedRange(sourceStart, sourceEnd, fallbackToAnyMatch, filter) {
return this.findMatchingStartEnd(sourceStart, sourceEnd, fallbackToAnyMatch, 'sourceOffsets', filter);
}
toSourceLocation(generatedOffset, filter) {
return this.findMatchingOffsets(generatedOffset, 'generatedOffsets', filter);
}
toGeneratedLocation(sourceOffset, filter) {
return this.findMatchingOffsets(sourceOffset, 'sourceOffsets', filter);
}
*findMatchingOffsets(offset, fromRange, filter) {
const memo = this.getMemoBasedOnRange(fromRange);
if (memo.offsets.length === 0) {
return;
}
const { low: start, high: end } = (0, binarySearch_1.binarySearch)(memo.offsets, offset);
const skip = new Set();
const toRange = fromRange == 'sourceOffsets' ? 'generatedOffsets' : 'sourceOffsets';
for (let i = start; i <= end; i++) {
for (const mapping of memo.mappings[i]) {
if (skip.has(mapping)) {
continue;
}
skip.add(mapping);
if (filter && !filter(mapping.data)) {
continue;
}
const mapped = (0, translateOffset_1.translateOffset)(offset, mapping[fromRange], mapping[toRange], getLengths(mapping, fromRange), getLengths(mapping, toRange));
if (mapped !== undefined) {
yield [mapped, mapping];
}
}
}
}
*findMatchingStartEnd(start, end, fallbackToAnyMatch, fromRange, filter) {
const toRange = fromRange == 'sourceOffsets' ? 'generatedOffsets' : 'sourceOffsets';
const mappedStarts = [];
let hadMatch = false;
for (const [mappedStart, mapping] of this.findMatchingOffsets(start, fromRange)) {
if (filter && !filter(mapping.data)) {
continue;
}
mappedStarts.push([mappedStart, mapping]);
const mappedEnd = (0, translateOffset_1.translateOffset)(end, mapping[fromRange], mapping[toRange], getLengths(mapping, fromRange), getLengths(mapping, toRange));
if (mappedEnd !== undefined) {
hadMatch = true;
yield [mappedStart, mappedEnd, mapping, mapping];
}
}
if (!hadMatch && fallbackToAnyMatch) {
for (const [mappedStart, mappingStart] of mappedStarts) {
for (const [mappedEnd, mappingEnd] of this.findMatchingOffsets(end, fromRange)) {
if (filter && !filter(mappingEnd.data) || mappedEnd < mappedStart) {
continue;
}
yield [mappedStart, mappedEnd, mappingStart, mappingEnd];
break;
}
;
}
}
}
getMemoBasedOnRange(fromRange) {
return fromRange === 'sourceOffsets'
? this.sourceCodeOffsetsMemo ??= this.createMemo('sourceOffsets')
: this.generatedCodeOffsetsMemo ??= this.createMemo('generatedOffsets');
}
createMemo(key) {
const offsetsSet = new Set();
for (const mapping of this.mappings) {
for (let i = 0; i < mapping[key].length; i++) {
offsetsSet.add(mapping[key][i]);
offsetsSet.add(mapping[key][i] + getLengths(mapping, key)[i]);
}
}
const offsets = [...offsetsSet].sort((a, b) => a - b);
const mappings = offsets.map(() => new Set());
for (const mapping of this.mappings) {
for (let i = 0; i < mapping[key].length; i++) {
const startIndex = (0, binarySearch_1.binarySearch)(offsets, mapping[key][i]).match;
const endIndex = (0, binarySearch_1.binarySearch)(offsets, mapping[key][i] + getLengths(mapping, key)[i]).match;
for (let i = startIndex; i <= endIndex; i++) {
mappings[i].add(mapping);
}
}
}
return { offsets, mappings };
}
}
exports.SourceMap = SourceMap;
function getLengths(mapping, key) {
return key == 'sourceOffsets' ? mapping.lengths : mapping.generatedLengths ?? mapping.lengths;
}
//# sourceMappingURL=sourceMap.js.map

View File

@@ -0,0 +1 @@
export declare function translateOffset(start: number, fromOffsets: number[], toOffsets: number[], fromLengths: number[], toLengths?: number[]): number | undefined;

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.translateOffset = translateOffset;
let warned = false;
function translateOffset(start, fromOffsets, toOffsets, fromLengths, toLengths = fromLengths) {
const isSorted = fromOffsets.every((value, index) => index === 0 || fromOffsets[index - 1] <= value);
if (!isSorted) {
for (let i = 0; i < fromOffsets.length; i++) {
const fromOffset = fromOffsets[i];
const fromLength = fromLengths[i];
if (start >= fromOffset && start <= fromOffset + fromLength) {
const toLength = toLengths[i];
const toOffset = toOffsets[i];
let rangeOffset = Math.min(start - fromOffset, toLength);
return toOffset + rangeOffset;
}
}
if (!warned) {
warned = true;
console.warn('fromOffsets should be sorted in ascending order');
}
}
let low = 0;
let high = fromOffsets.length - 1;
while (low <= high) {
const mid = Math.floor((low + high) / 2);
const fromOffset = fromOffsets[mid];
const fromLength = fromLengths[mid];
if (start >= fromOffset && start <= fromOffset + fromLength) {
const toLength = toLengths[mid];
const toOffset = toOffsets[mid];
let rangeOffset = Math.min(start - fromOffset, toLength);
return toOffset + rangeOffset;
}
else if (start < fromOffset) {
high = mid - 1;
}
else {
low = mid + 1;
}
}
}
//# sourceMappingURL=translateOffset.js.map

15
web-app/node_modules/@volar/source-map/package.json generated vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "@volar/source-map",
"version": "2.4.15",
"license": "MIT",
"files": [
"**/*.js",
"**/*.d.ts"
],
"repository": {
"type": "git",
"url": "https://github.com/volarjs/volar.js.git",
"directory": "packages/source-map"
},
"gitHead": "adcdcbc801b284cce3239fec231c7f4cebfd8688"
}

21
web-app/node_modules/@volar/typescript/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present Johnson Chu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

60
web-app/node_modules/@volar/typescript/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,60 @@
export * from './lib/common';
export * from './lib/node/proxyLanguageService';
export * from './lib/node/decorateLanguageServiceHost';
export * from './lib/node/decorateProgram';
export * from './lib/node/proxyCreateProgram';
export * from './lib/protocol/createProject';
export * from './lib/protocol/createSys';
import type { VirtualCode } from '@volar/language-core';
import type * as ts from 'typescript';
import { URI } from 'vscode-uri';
declare module '@volar/language-service' {
interface ProjectContext {
typescript?: {
configFileName: string | undefined;
sys: ts.System & {
version?: number;
sync?(): Promise<number>;
};
languageServiceHost: ts.LanguageServiceHost;
getExtraServiceScript(fileName: string): TypeScriptExtraServiceScript | undefined;
uriConverter: {
asUri(fileName: string): URI;
asFileName(uri: URI): string;
};
};
}
}
declare module '@volar/language-core' {
interface LanguagePlugin {
typescript?: TypeScriptGenericOptions & TypeScriptNonTSPluginOptions;
}
}
/**
* The following options available to all situations.
*/
interface TypeScriptGenericOptions {
extraFileExtensions: ts.FileExtensionInfo[];
resolveHiddenExtensions?: boolean;
getServiceScript(root: VirtualCode): TypeScriptServiceScript | undefined;
}
/**
* The following options will not be available in TS plugin.
*/
interface TypeScriptNonTSPluginOptions {
getExtraServiceScripts?(fileName: string, root: VirtualCode): TypeScriptExtraServiceScript[];
/**
* @deprecated Remove in 2.5.0
*/
resolveLanguageServiceHost?(host: ts.LanguageServiceHost): ts.LanguageServiceHost;
}
export interface TypeScriptServiceScript {
code: VirtualCode;
extension: '.ts' | '.js' | '.mts' | '.mjs' | '.cjs' | '.cts' | '.d.ts' | string;
scriptKind: ts.ScriptKind;
/** See #188 */
preventLeadingOffset?: boolean;
}
export interface TypeScriptExtraServiceScript extends TypeScriptServiceScript {
fileName: string;
}

24
web-app/node_modules/@volar/typescript/index.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./lib/common"), exports);
__exportStar(require("./lib/node/proxyLanguageService"), exports);
__exportStar(require("./lib/node/decorateLanguageServiceHost"), exports);
__exportStar(require("./lib/node/decorateProgram"), exports);
__exportStar(require("./lib/node/proxyCreateProgram"), exports);
__exportStar(require("./lib/protocol/createProject"), exports);
__exportStar(require("./lib/protocol/createSys"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
export declare function resolveFileLanguageId(path: string): string | undefined;

18
web-app/node_modules/@volar/typescript/lib/common.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveFileLanguageId = resolveFileLanguageId;
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';
}
}
//# sourceMappingURL=common.js.map

View File

@@ -0,0 +1,4 @@
import type { Language } from '@volar/language-core';
import type * as ts from 'typescript';
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[];

View File

@@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decorateLanguageServiceHost = decorateLanguageServiceHost;
exports.searchExternalFiles = searchExternalFiles;
const resolveModuleName_1 = require("../resolveModuleName");
function decorateLanguageServiceHost(ts, language, languageServiceHost) {
const pluginExtensions = language.plugins
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
.flat();
const scripts = new Map();
const crashFileNames = new Set();
const readDirectory = languageServiceHost.readDirectory?.bind(languageServiceHost);
const resolveModuleNameLiterals = languageServiceHost.resolveModuleNameLiterals?.bind(languageServiceHost);
const resolveModuleNames = languageServiceHost.resolveModuleNames?.bind(languageServiceHost);
const getScriptSnapshot = languageServiceHost.getScriptSnapshot.bind(languageServiceHost);
const getScriptKind = languageServiceHost.getScriptKind?.bind(languageServiceHost);
// path completion
if (readDirectory) {
languageServiceHost.readDirectory = (path, extensions, exclude, include, depth) => {
if (extensions) {
for (const ext of pluginExtensions) {
if (!extensions.includes(ext)) {
extensions = [...extensions, ext];
}
}
}
return readDirectory(path, extensions, exclude, include, depth);
};
}
if (pluginExtensions.length) {
const resolveModuleName = (0, resolveModuleName_1.createResolveModuleName)(ts, ts.sys.getFileSize, languageServiceHost, language.plugins, fileName => language.scripts.get(fileName));
const getCanonicalFileName = languageServiceHost.useCaseSensitiveFileNames?.()
? (fileName) => fileName
: (fileName) => fileName.toLowerCase();
const moduleResolutionCache = ts.createModuleResolutionCache(languageServiceHost.getCurrentDirectory(), getCanonicalFileName, languageServiceHost.getCompilationSettings());
if (resolveModuleNameLiterals) {
languageServiceHost.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, options, ...rest) => {
if (moduleLiterals.every(name => !pluginExtensions.some(ext => name.text.endsWith(ext)))) {
return resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options, ...rest);
}
return moduleLiterals.map(moduleLiteral => {
return resolveModuleName(moduleLiteral.text, containingFile, options, moduleResolutionCache, redirectedReference);
});
};
}
if (resolveModuleNames) {
languageServiceHost.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, options, containingSourceFile) => {
if (moduleNames.every(name => !pluginExtensions.some(ext => name.endsWith(ext)))) {
return resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, options, containingSourceFile);
}
return moduleNames.map(moduleName => {
return resolveModuleName(moduleName, containingFile, options, moduleResolutionCache, redirectedReference).resolvedModule;
});
};
}
}
languageServiceHost.getScriptSnapshot = fileName => {
const virtualScript = updateVirtualScript(fileName, true);
if (virtualScript) {
return virtualScript.snapshot;
}
return getScriptSnapshot(fileName);
};
if (getScriptKind) {
languageServiceHost.getScriptKind = fileName => {
const virtualScript = updateVirtualScript(fileName, false);
if (virtualScript) {
return virtualScript.scriptKind;
}
return getScriptKind(fileName);
};
}
function updateVirtualScript(fileName, shouldRegister) {
if (crashFileNames.has(fileName)) {
return;
}
let version;
try {
version = languageServiceHost.getScriptVersion(fileName);
}
catch {
// fix https://github.com/vuejs/language-tools/issues/4278
crashFileNames.add(fileName);
}
if (version === undefined) {
// somehow getScriptVersion returns undefined
return;
}
let script = scripts.get(fileName);
if (!script || script[0] !== version) {
script = [version];
const sourceScript = language.scripts.get(fileName, undefined, shouldRegister);
if (sourceScript?.generated) {
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
if (serviceScript) {
if (serviceScript.preventLeadingOffset) {
script[1] = {
extension: serviceScript.extension,
scriptKind: serviceScript.scriptKind,
snapshot: serviceScript.code.snapshot,
};
}
else {
const sourceContents = sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength());
const virtualContents = sourceContents.split('\n').map(line => ' '.repeat(line.length)).join('\n')
+ serviceScript.code.snapshot.getText(0, serviceScript.code.snapshot.getLength());
script[1] = {
extension: serviceScript.extension,
scriptKind: serviceScript.scriptKind,
snapshot: ts.ScriptSnapshot.fromString(virtualContents),
};
}
}
if (sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts) {
console.warn('getExtraServiceScripts() is not available in TS plugin.');
}
}
scripts.set(fileName, script);
}
return script[1];
}
}
function searchExternalFiles(ts, project, exts) {
if (project.projectKind !== ts.server.ProjectKind.Configured) {
return [];
}
const configFile = project.getProjectName();
const config = ts.readJsonConfigFile(configFile, project.readFile.bind(project));
const parseHost = {
useCaseSensitiveFileNames: project.useCaseSensitiveFileNames(),
fileExists: project.fileExists.bind(project),
readFile: project.readFile.bind(project),
readDirectory: (...args) => {
args[1] = exts;
return project.readDirectory(...args);
},
};
const parsed = ts.parseJsonSourceFileConfigFileContent(config, parseHost, project.getCurrentDirectory());
return parsed.fileNames;
}
//# sourceMappingURL=decorateLanguageServiceHost.js.map

View File

@@ -0,0 +1,3 @@
import type { Language } from '@volar/language-core';
import type * as ts from 'typescript';
export declare function decorateProgram(language: Language<string>, program: ts.Program): void;

View File

@@ -0,0 +1,85 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decorateProgram = decorateProgram;
const transform_1 = require("./transform");
const utils_1 = require("./utils");
function decorateProgram(language, program) {
const emit = program.emit;
// for tsc --noEmit
const getSyntacticDiagnostics = program.getSyntacticDiagnostics;
const getSemanticDiagnostics = program.getSemanticDiagnostics;
const getGlobalDiagnostics = program.getGlobalDiagnostics;
const getSourceFileByPath = program.getSourceFileByPath;
// for tsc --noEmit --watch
// @ts-ignore
const getBindAndCheckDiagnostics = program.getBindAndCheckDiagnostics;
program.emit = (...args) => {
const result = emit(...args);
return {
...result,
diagnostics: result.diagnostics
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d),
};
};
program.getSyntacticDiagnostics = (sourceFile, cancellationToken) => {
if (!sourceFile) {
return getSyntacticDiagnostics(undefined, cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d);
}
else {
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
return getSyntacticDiagnostics(actualSourceFile, cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d)
.filter(d => !serviceScript || !d.file || language.scripts.get(d.file.fileName) === sourceScript);
}
};
program.getSemanticDiagnostics = (sourceFile, cancellationToken) => {
if (!sourceFile) {
return getSemanticDiagnostics(undefined, cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d);
}
else {
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
return getSemanticDiagnostics(actualSourceFile, cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d)
.filter(d => !serviceScript || !d.file || language.scripts.get(d.file.fileName) === sourceScript);
}
};
program.getGlobalDiagnostics = cancellationToken => {
return getGlobalDiagnostics(cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d);
};
// @ts-ignore
program.getBindAndCheckDiagnostics = (sourceFile, cancellationToken) => {
if (!sourceFile) {
return getBindAndCheckDiagnostics(undefined, cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d);
}
else {
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
return getBindAndCheckDiagnostics(actualSourceFile, cancellationToken)
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
.filter(d => !!d)
.filter(d => !serviceScript || language.scripts.get(d.file.fileName) === sourceScript);
}
};
// fix https://github.com/vuejs/language-tools/issues/4099 with `incremental`
program.getSourceFileByPath = path => {
const sourceFile = getSourceFileByPath(path);
if (sourceFile) {
(0, transform_1.fillSourceFileText)(language, sourceFile);
}
return sourceFile;
};
}
//# sourceMappingURL=decorateProgram.js.map

View File

@@ -0,0 +1,2 @@
import type * as ts from 'typescript';
export declare function dedupeDocumentSpans<T extends ts.DocumentSpan>(items: T[]): T[];

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.dedupeDocumentSpans = dedupeDocumentSpans;
function dedupeDocumentSpans(items) {
return dedupe(items, item => [
item.fileName,
item.textSpan.start,
item.textSpan.length,
].join(':'));
}
function dedupe(items, getKey) {
const map = new Map();
for (const item of items.reverse()) {
map.set(getKey(item), item);
}
return [...map.values()];
}
//# sourceMappingURL=dedupe.js.map

View File

@@ -0,0 +1,6 @@
import { Language, LanguagePlugin } from '@volar/language-core';
import type * as ts from 'typescript';
export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], create: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin<string>[] | {
languagePlugins: LanguagePlugin<string>[];
setup?(language: Language<string>): void;
}): typeof import("typescript").createProgram;

View File

@@ -0,0 +1,183 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.proxyCreateProgram = proxyCreateProgram;
const language_core_1 = require("@volar/language-core");
const resolveModuleName_1 = require("../resolveModuleName");
const decorateProgram_1 = require("./decorateProgram");
const common_1 = require("../common");
const arrayEqual = (a, b) => {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
};
const objectEqual = (a, b) => {
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) {
return false;
}
for (const key of keysA) {
if (a[key] !== b[key]) {
return false;
}
}
return true;
};
function proxyCreateProgram(ts, original, create) {
const sourceFileSnapshots = new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames);
const parsedSourceFiles = new WeakMap();
let lastOptions;
let languagePlugins;
let language;
let moduleResolutionCache;
return new Proxy(original, {
apply: (target, thisArg, args) => {
const options = args[0];
assert(!!options.host, '!!options.host');
if (!lastOptions
|| !languagePlugins
|| !language
|| !arrayEqual(options.rootNames, lastOptions.rootNames)
|| !objectEqual(options.options, lastOptions.options)) {
moduleResolutionCache = ts.createModuleResolutionCache(options.host.getCurrentDirectory(), options.host.getCanonicalFileName, options.options);
lastOptions = options;
const created = create(ts, options);
if (Array.isArray(created)) {
languagePlugins = created;
}
else {
languagePlugins = created.languagePlugins;
}
language = (0, language_core_1.createLanguage)([
...languagePlugins,
{ getLanguageId: common_1.resolveFileLanguageId },
], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), (fileName, includeFsFiles) => {
if (includeFsFiles && !sourceFileSnapshots.has(fileName)) {
const sourceFileText = originalHost.readFile(fileName);
if (sourceFileText !== undefined) {
sourceFileSnapshots.set(fileName, [undefined, {
getChangeRange() {
return undefined;
},
getLength() {
return sourceFileText.length;
},
getText(start, end) {
return sourceFileText.substring(start, end);
},
}]);
}
else {
sourceFileSnapshots.set(fileName, [undefined, undefined]);
}
}
const snapshot = sourceFileSnapshots.get(fileName)?.[1];
if (snapshot) {
language.scripts.set(fileName, snapshot);
}
else {
language.scripts.delete(fileName);
}
});
if ('setup' in created) {
created.setup?.(language);
}
}
const originalHost = options.host;
const extensions = languagePlugins
.map(plugin => plugin.typescript?.extraFileExtensions.map(({ extension }) => `.${extension}`) ?? [])
.flat();
options.host = { ...originalHost };
options.host.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
const originalSourceFile = originalHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
if (!sourceFileSnapshots.has(fileName)
|| sourceFileSnapshots.get(fileName)?.[0] !== originalSourceFile) {
if (originalSourceFile) {
sourceFileSnapshots.set(fileName, [originalSourceFile, {
getChangeRange() {
return undefined;
},
getLength() {
return originalSourceFile.text.length;
},
getText(start, end) {
return originalSourceFile.text.substring(start, end);
},
}]);
}
else {
sourceFileSnapshots.set(fileName, [undefined, undefined]);
}
}
if (!originalSourceFile) {
return;
}
if (!parsedSourceFiles.has(originalSourceFile)) {
const sourceScript = language.scripts.get(fileName);
assert(!!sourceScript, '!!sourceScript');
parsedSourceFiles.set(originalSourceFile, undefined);
if (sourceScript.generated?.languagePlugin.typescript) {
const { getServiceScript, getExtraServiceScripts } = sourceScript.generated.languagePlugin.typescript;
const serviceScript = getServiceScript(sourceScript.generated.root);
if (serviceScript) {
let virtualContents;
if (!serviceScript.preventLeadingOffset) {
virtualContents = originalSourceFile.text.split('\n').map(line => ' '.repeat(line.length)).join('\n')
+ serviceScript.code.snapshot.getText(0, serviceScript.code.snapshot.getLength());
}
else {
virtualContents = serviceScript.code.snapshot.getText(0, serviceScript.code.snapshot.getLength());
}
const parsedSourceFile = ts.createSourceFile(fileName, virtualContents, languageVersionOrOptions, undefined, serviceScript.scriptKind);
// @ts-expect-error
parsedSourceFile.version = originalSourceFile.version;
parsedSourceFiles.set(originalSourceFile, parsedSourceFile);
}
if (getExtraServiceScripts) {
console.warn('getExtraServiceScripts() is not available in this use case.');
}
}
}
return parsedSourceFiles.get(originalSourceFile) ?? originalSourceFile;
};
if (extensions.length) {
options.options.allowArbitraryExtensions = true;
const resolveModuleName = (0, resolveModuleName_1.createResolveModuleName)(ts, ts.sys.getFileSize, originalHost, language.plugins, fileName => language.scripts.get(fileName));
const resolveModuleNameLiterals = originalHost.resolveModuleNameLiterals;
const resolveModuleNames = originalHost.resolveModuleNames;
options.host.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, compilerOptions, ...rest) => {
if (resolveModuleNameLiterals && moduleLiterals.every(name => !extensions.some(ext => name.text.endsWith(ext)))) {
return resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, compilerOptions, ...rest);
}
return moduleLiterals.map(moduleLiteral => {
return resolveModuleName(moduleLiteral.text, containingFile, compilerOptions, moduleResolutionCache, redirectedReference);
});
};
options.host.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions, containingSourceFile) => {
if (resolveModuleNames && moduleNames.every(name => !extensions.some(ext => name.endsWith(ext)))) {
return resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions, containingSourceFile);
}
return moduleNames.map(moduleName => {
return resolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionCache, redirectedReference).resolvedModule;
});
};
}
const program = Reflect.apply(target, thisArg, args);
(0, decorateProgram_1.decorateProgram)(language, program);
return program;
},
});
}
function assert(condition, message) {
if (!condition) {
console.error(message);
throw new Error(message);
}
}
//# sourceMappingURL=proxyCreateProgram.js.map

View File

@@ -0,0 +1,18 @@
import { Language } from '@volar/language-core';
import type * as ts from 'typescript';
/**
* Creates and returns a Proxy around the base TypeScript LanguageService.
*
* This is used by the Volar TypeScript Plugin (which can be created by `createLanguageServicePlugin`
* and `createAsyncLanguageServicePlugin`) as an adapter layer between the TypeScript Language Service
* plugin API (see https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin)
* and a Volar `Language`.
*
* Once the `initialize` method is called, the proxy will begin intercepting requests and
* enhancing the default behavior of the LanguageService with enhancements based on
* the Volar `Language` that has been passed to `initialize`.
*/
export declare function createProxyLanguageService(languageService: ts.LanguageService): {
initialize(language: Language<string>): void;
proxy: ts.LanguageService;
};

View File

@@ -0,0 +1,930 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createProxyLanguageService = createProxyLanguageService;
const language_core_1 = require("@volar/language-core");
const dedupe_1 = require("./dedupe");
const transform_1 = require("./transform");
const utils_1 = require("./utils");
const windowsPathReg = /\\/g;
/**
* Creates and returns a Proxy around the base TypeScript LanguageService.
*
* This is used by the Volar TypeScript Plugin (which can be created by `createLanguageServicePlugin`
* and `createAsyncLanguageServicePlugin`) as an adapter layer between the TypeScript Language Service
* plugin API (see https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin)
* and a Volar `Language`.
*
* Once the `initialize` method is called, the proxy will begin intercepting requests and
* enhancing the default behavior of the LanguageService with enhancements based on
* the Volar `Language` that has been passed to `initialize`.
*/
function createProxyLanguageService(languageService) {
const proxyCache = new Map();
let getProxyMethod;
return {
initialize(language) {
getProxyMethod = (target, p) => {
switch (p) {
case 'getNavigationTree': return getNavigationTree(language, target[p]);
case 'getOutliningSpans': return getOutliningSpans(language, target[p]);
case 'getFormattingEditsForDocument': return getFormattingEditsForDocument(language, target[p]);
case 'getFormattingEditsForRange': return getFormattingEditsForRange(language, target[p]);
case 'getFormattingEditsAfterKeystroke': return getFormattingEditsAfterKeystroke(language, target[p]);
case 'getEditsForFileRename': return getEditsForFileRename(language, target[p]);
case 'getLinkedEditingRangeAtPosition': return getLinkedEditingRangeAtPosition(language, target[p]);
case 'prepareCallHierarchy': return prepareCallHierarchy(language, target[p]);
case 'provideCallHierarchyIncomingCalls': return provideCallHierarchyIncomingCalls(language, target[p]);
case 'provideCallHierarchyOutgoingCalls': return provideCallHierarchyOutgoingCalls(language, target[p]);
case 'organizeImports': return organizeImports(language, target[p]);
case 'getQuickInfoAtPosition': return getQuickInfoAtPosition(language, target[p]);
case 'getSignatureHelpItems': return getSignatureHelpItems(language, target[p]);
case 'getDocumentHighlights': return getDocumentHighlights(language, target[p]);
case 'getApplicableRefactors': return getApplicableRefactors(language, target[p]);
case 'getEditsForRefactor': return getEditsForRefactor(language, target[p]);
case 'getCombinedCodeFix': return getCombinedCodeFix(language, target[p]);
case 'getRenameInfo': return getRenameInfo(language, target[p]);
case 'getCodeFixesAtPosition': return getCodeFixesAtPosition(language, target[p]);
case 'getEncodedSemanticClassifications': return getEncodedSemanticClassifications(language, target[p]);
case 'getSyntacticDiagnostics': return getSyntacticDiagnostics(language, languageService, target[p]);
case 'getSemanticDiagnostics': return getSemanticDiagnostics(language, languageService, target[p]);
case 'getSuggestionDiagnostics': return getSuggestionDiagnostics(language, languageService, target[p]);
case 'getDefinitionAndBoundSpan': return getDefinitionAndBoundSpan(language, target[p]);
case 'findReferences': return findReferences(language, target[p]);
case 'getDefinitionAtPosition': return getDefinitionAtPosition(language, target[p]);
case 'getTypeDefinitionAtPosition': return getTypeDefinitionAtPosition(language, target[p]);
case 'getImplementationAtPosition': return getImplementationAtPosition(language, target[p]);
case 'findRenameLocations': return findRenameLocations(language, target[p]);
case 'getReferencesAtPosition': return getReferencesAtPosition(language, target[p]);
case 'getCompletionsAtPosition': return getCompletionsAtPosition(language, target[p]);
case 'getCompletionEntryDetails': return getCompletionEntryDetails(language, target[p]);
case 'provideInlayHints': return provideInlayHints(language, target[p]);
case 'getFileReferences': return getFileReferences(language, target[p]);
case 'getNavigateToItems': return getNavigateToItems(language, target[p]);
}
};
},
proxy: new Proxy(languageService, {
get(target, p, receiver) {
if (getProxyMethod) {
if (!proxyCache.has(p)) {
proxyCache.set(p, getProxyMethod(target, p));
}
const proxyMethod = proxyCache.get(p);
if (proxyMethod) {
return proxyMethod;
}
}
return Reflect.get(target, p, receiver);
},
set(target, p, value, receiver) {
return Reflect.set(target, p, value, receiver);
},
}),
};
}
// ignored methods
function getNavigationTree(language, getNavigationTree) {
return filePath => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript] = (0, utils_1.getServiceScript)(language, fileName);
if (serviceScript || targetScript?.associatedOnly) {
const tree = getNavigationTree(targetScript.id);
tree.childItems = undefined;
return tree;
}
else {
return getNavigationTree(fileName);
}
};
}
function getOutliningSpans(language, getOutliningSpans) {
return filePath => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript] = (0, utils_1.getServiceScript)(language, fileName);
if (serviceScript || targetScript?.associatedOnly) {
return [];
}
else {
return getOutliningSpans(fileName);
}
};
}
// proxy methods
function getFormattingEditsForDocument(language, getFormattingEditsForDocument) {
return (filePath, options) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const map = language.maps.get(serviceScript.code, targetScript);
if (!map.mappings.some(mapping => (0, language_core_1.isFormattingEnabled)(mapping.data))) {
return [];
}
const edits = getFormattingEditsForDocument(targetScript.id, options);
return edits
.map(edit => (0, transform_1.transformTextChange)(sourceScript, language, serviceScript, edit, false, language_core_1.isFormattingEnabled)?.[1])
.filter(edit => !!edit);
}
else {
return getFormattingEditsForDocument(fileName, options);
}
};
}
function getFormattingEditsForRange(language, getFormattingEditsForRange) {
return (filePath, start, end, options) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const generatedRange = (0, transform_1.toGeneratedRange)(language, serviceScript, sourceScript, start, end, language_core_1.isFormattingEnabled);
if (generatedRange !== undefined) {
const edits = getFormattingEditsForRange(targetScript.id, generatedRange[0], generatedRange[1], options);
return edits
.map(edit => (0, transform_1.transformTextChange)(sourceScript, language, serviceScript, edit, false, language_core_1.isFormattingEnabled)?.[1])
.filter(edit => !!edit);
}
return [];
}
else {
return getFormattingEditsForRange(fileName, start, end, options);
}
};
}
function getFormattingEditsAfterKeystroke(language, getFormattingEditsAfterKeystroke) {
return (filePath, position, key, options) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isFormattingEnabled);
if (generatePosition !== undefined) {
const edits = getFormattingEditsAfterKeystroke(targetScript.id, generatePosition, key, options);
return edits
.map(edit => (0, transform_1.transformTextChange)(sourceScript, language, serviceScript, edit, false, language_core_1.isFormattingEnabled)?.[1])
.filter(edit => !!edit);
}
return [];
}
else {
return getFormattingEditsAfterKeystroke(fileName, position, key, options);
}
};
}
function getEditsForFileRename(language, getEditsForFileRename) {
return (oldFilePath, newFilePath, formatOptions, preferences) => {
const edits = getEditsForFileRename(oldFilePath, newFilePath, formatOptions, preferences);
return (0, transform_1.transformFileTextChanges)(language, edits, false, language_core_1.isRenameEnabled);
};
}
function getLinkedEditingRangeAtPosition(language, getLinkedEditingRangeAtPosition) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isLinkedEditingEnabled);
if (generatePosition !== undefined) {
const info = getLinkedEditingRangeAtPosition(targetScript.id, generatePosition);
if (info) {
return {
ranges: info.ranges
.map(span => (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, span, false, language_core_1.isLinkedEditingEnabled)?.[1])
.filter(span => !!span),
wordPattern: info.wordPattern,
};
}
}
}
else {
return getLinkedEditingRangeAtPosition(fileName, position);
}
};
}
function prepareCallHierarchy(language, prepareCallHierarchy) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isCallHierarchyEnabled);
if (generatePosition !== undefined) {
const item = prepareCallHierarchy(targetScript.id, generatePosition);
if (Array.isArray(item)) {
return item.map(item => (0, transform_1.transformCallHierarchyItem)(language, item, true, language_core_1.isCallHierarchyEnabled));
}
else if (item) {
return (0, transform_1.transformCallHierarchyItem)(language, item, true, language_core_1.isCallHierarchyEnabled);
}
}
}
else {
return prepareCallHierarchy(fileName, position);
}
};
}
function provideCallHierarchyIncomingCalls(language, provideCallHierarchyIncomingCalls) {
return (filePath, position) => {
let calls = [];
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isCallHierarchyEnabled);
if (generatePosition !== undefined) {
calls = provideCallHierarchyIncomingCalls(targetScript.id, generatePosition);
}
}
else {
calls = provideCallHierarchyIncomingCalls(fileName, position);
}
return calls
.map(call => {
const from = (0, transform_1.transformCallHierarchyItem)(language, call.from, true, language_core_1.isCallHierarchyEnabled);
const fromSpans = call.fromSpans
.map(span => (0, transform_1.transformSpan)(language, call.from.file, span, true, language_core_1.isCallHierarchyEnabled)?.textSpan)
.filter(span => !!span);
return {
from,
fromSpans,
};
});
};
}
function provideCallHierarchyOutgoingCalls(language, provideCallHierarchyOutgoingCalls) {
return (filePath, position) => {
let calls = [];
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isCallHierarchyEnabled);
if (generatePosition !== undefined) {
calls = provideCallHierarchyOutgoingCalls(targetScript.id, generatePosition);
}
}
else {
calls = provideCallHierarchyOutgoingCalls(fileName, position);
}
return calls
.map(call => {
const to = (0, transform_1.transformCallHierarchyItem)(language, call.to, true, language_core_1.isCallHierarchyEnabled);
const fromSpans = call.fromSpans
.map(span => serviceScript
? (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, span, true, language_core_1.isCallHierarchyEnabled)?.[1]
: span)
.filter(span => !!span);
return {
to,
fromSpans,
};
});
};
}
function organizeImports(language, organizeImports) {
return (args, formatOptions, preferences) => {
const unresolved = organizeImports(args, formatOptions, preferences);
return (0, transform_1.transformFileTextChanges)(language, unresolved, false, language_core_1.isCodeActionsEnabled);
};
}
function getQuickInfoAtPosition(language, getQuickInfoAtPosition) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
const infos = [];
for (const [generatePosition] of (0, transform_1.toGeneratedOffsets)(language, serviceScript, sourceScript, position, language_core_1.isHoverEnabled)) {
const info = getQuickInfoAtPosition(targetScript.id, generatePosition);
if (info) {
const textSpan = (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, info.textSpan, true, language_core_1.isHoverEnabled)?.[1];
if (textSpan) {
infos.push({
...info,
textSpan: textSpan,
});
}
}
}
if (infos.length === 1) {
return infos[0];
}
else if (infos.length >= 2) {
const combine = { ...infos[0] };
combine.displayParts = combine.displayParts?.slice();
combine.documentation = combine.documentation?.slice();
combine.tags = combine.tags?.slice();
const displayPartsStrs = new Set([displayPartsToString(infos[0].displayParts)]);
const documentationStrs = new Set([displayPartsToString(infos[0].documentation)]);
const tagsStrs = new Set();
for (const tag of infos[0].tags ?? []) {
tagsStrs.add(tag.name + '__volar__' + displayPartsToString(tag.text));
}
for (let i = 1; i < infos.length; i++) {
const { displayParts, documentation, tags } = infos[i];
if (displayParts?.length && !displayPartsStrs.has(displayPartsToString(displayParts))) {
displayPartsStrs.add(displayPartsToString(displayParts));
combine.displayParts ??= [];
combine.displayParts.push({ ...displayParts[0], text: '\n\n' + displayParts[0].text });
combine.displayParts.push(...displayParts.slice(1));
}
if (documentation?.length && !documentationStrs.has(displayPartsToString(documentation))) {
documentationStrs.add(displayPartsToString(documentation));
combine.documentation ??= [];
combine.documentation.push({ ...documentation[0], text: '\n\n' + documentation[0].text });
combine.documentation.push(...documentation.slice(1));
}
for (const tag of tags ?? []) {
if (!tagsStrs.has(tag.name + '__volar__' + displayPartsToString(tag.text))) {
tagsStrs.add(tag.name + '__volar__' + displayPartsToString(tag.text));
combine.tags ??= [];
combine.tags.push(tag);
}
}
}
return combine;
}
}
else {
return getQuickInfoAtPosition(fileName, position);
}
};
}
function getSignatureHelpItems(language, getSignatureHelpItems) {
return (filePath, position, options) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isSignatureHelpEnabled);
if (generatePosition !== undefined) {
const result = getSignatureHelpItems(targetScript.id, generatePosition, options);
if (result) {
const applicableSpan = (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, result.applicableSpan, true, language_core_1.isSignatureHelpEnabled)?.[1];
if (applicableSpan) {
return {
...result,
applicableSpan,
};
}
}
}
}
else {
return getSignatureHelpItems(fileName, position, options);
}
};
}
function getDocumentHighlights(language, getDocumentHighlights) {
return (filePath, position, filesToSearch) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isHighlightEnabled, (fileName, position) => getDocumentHighlights(fileName, position, filesToSearch), function* (result) {
for (const ref of result) {
for (const reference of ref.highlightSpans) {
yield [reference.fileName ?? ref.fileName, reference.textSpan.start];
}
}
});
const resolved = unresolved
.flat()
.map(highlights => {
return {
...highlights,
highlightSpans: highlights.highlightSpans
.map(span => {
const { textSpan } = (0, transform_1.transformSpan)(language, span.fileName ?? highlights.fileName, span.textSpan, false, language_core_1.isHighlightEnabled) ?? {};
if (textSpan) {
return {
...span,
contextSpan: (0, transform_1.transformSpan)(language, span.fileName ?? highlights.fileName, span.contextSpan, false, language_core_1.isHighlightEnabled)?.textSpan,
textSpan,
};
}
})
.filter(span => !!span),
};
});
return resolved;
};
}
function getApplicableRefactors(language, getApplicableRefactors) {
return (filePath, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
if (typeof positionOrRange === 'number') {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, positionOrRange, language_core_1.isCodeActionsEnabled);
if (generatePosition !== undefined) {
return getApplicableRefactors(targetScript.id, generatePosition, preferences, triggerReason, kind, includeInteractiveActions);
}
}
else {
for (const [generatedStart, generatedEnd] of (0, transform_1.toGeneratedRanges)(language, serviceScript, sourceScript, positionOrRange.pos, positionOrRange.end, language_core_1.isCodeActionsEnabled)) {
return getApplicableRefactors(targetScript.id, { pos: generatedStart, end: generatedEnd }, preferences, triggerReason, kind, includeInteractiveActions);
}
}
return [];
}
else {
return getApplicableRefactors(fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions);
}
};
}
function getEditsForRefactor(language, getEditsForRefactor) {
return (filePath, formatOptions, positionOrRange, refactorName, actionName, preferences, interactiveRefactorArguments) => {
let edits;
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
if (typeof positionOrRange === 'number') {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, positionOrRange, language_core_1.isCodeActionsEnabled);
if (generatePosition !== undefined) {
edits = getEditsForRefactor(targetScript.id, formatOptions, generatePosition, refactorName, actionName, preferences, interactiveRefactorArguments);
}
}
else {
for (const [generatedStart, generatedEnd] of (0, transform_1.toGeneratedRanges)(language, serviceScript, sourceScript, positionOrRange.pos, positionOrRange.end, language_core_1.isCodeActionsEnabled)) {
edits = getEditsForRefactor(targetScript.id, formatOptions, { pos: generatedStart, end: generatedEnd }, refactorName, actionName, preferences, interactiveRefactorArguments);
}
}
}
else {
edits = getEditsForRefactor(fileName, formatOptions, positionOrRange, refactorName, actionName, preferences, interactiveRefactorArguments);
}
if (edits) {
edits.edits = (0, transform_1.transformFileTextChanges)(language, edits.edits, false, language_core_1.isCodeActionsEnabled);
return edits;
}
};
}
function getCombinedCodeFix(language, getCombinedCodeFix) {
return (...args) => {
const codeActions = getCombinedCodeFix(...args);
codeActions.changes = (0, transform_1.transformFileTextChanges)(language, codeActions.changes, false, language_core_1.isCodeActionsEnabled);
return codeActions;
};
}
function getRenameInfo(language, getRenameInfo) {
return (filePath, position, options) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return {
canRename: false,
localizedErrorMessage: "Cannot rename"
};
}
if (serviceScript) {
let failed;
for (const [generateOffset] of (0, transform_1.toGeneratedOffsets)(language, serviceScript, sourceScript, position, language_core_1.isRenameEnabled)) {
const info = getRenameInfo(targetScript.id, generateOffset, options);
if (info.canRename) {
const span = (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, info.triggerSpan, false, language_core_1.isRenameEnabled)?.[1];
if (span) {
info.triggerSpan = span;
return info;
}
}
else {
failed = info;
}
}
if (failed) {
return failed;
}
return {
canRename: false,
localizedErrorMessage: 'Failed to get rename locations',
};
}
else {
return getRenameInfo(fileName, position, options);
}
};
}
function getCodeFixesAtPosition(language, getCodeFixesAtPosition) {
return (filePath, start, end, errorCodes, formatOptions, preferences) => {
let fixes = [];
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const generateRange = (0, transform_1.toGeneratedRange)(language, serviceScript, sourceScript, start, end, language_core_1.isCodeActionsEnabled);
if (generateRange !== undefined) {
fixes = getCodeFixesAtPosition(targetScript.id, generateRange[0], generateRange[1], errorCodes, formatOptions, preferences);
}
}
else {
fixes = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
}
fixes = fixes.map(fix => {
fix.changes = (0, transform_1.transformFileTextChanges)(language, fix.changes, false, language_core_1.isCodeActionsEnabled);
return fix;
});
return fixes;
};
}
function getEncodedSemanticClassifications(language, getEncodedSemanticClassifications) {
return (filePath, span, format) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return {
spans: [],
endOfLineState: 0
};
}
if (serviceScript) {
const map = language.maps.get(serviceScript.code, targetScript);
const mapped = (0, language_core_1.findOverlapCodeRange)(span.start, span.start + span.length, map, language_core_1.isSemanticTokensEnabled);
if (!mapped) {
return {
spans: [],
endOfLineState: 0
};
}
const mappingOffset = (0, transform_1.getMappingOffset)(language, serviceScript);
const start = mapped.start + mappingOffset;
const end = mapped.end + mappingOffset;
const result = getEncodedSemanticClassifications(targetScript.id, { start, length: end - start }, format);
const spans = [];
for (let i = 0; i < result.spans.length; i += 3) {
for (const [_, sourceStart, sourceEnd] of (0, transform_1.toSourceRanges)(sourceScript, language, serviceScript, result.spans[i], result.spans[i] + result.spans[i + 1], false, language_core_1.isSemanticTokensEnabled)) {
spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
break;
}
}
result.spans = spans;
return result;
}
else {
return getEncodedSemanticClassifications(fileName, span, format);
}
};
}
function getSyntacticDiagnostics(language, languageService, getSyntacticDiagnostics) {
return filePath => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
return getSyntacticDiagnostics(targetScript?.id ?? fileName)
.map(d => (0, transform_1.transformDiagnostic)(language, d, languageService.getProgram(), false))
.filter(d => !!d)
.filter(d => !serviceScript || language.scripts.get(d.file.fileName) === sourceScript);
};
}
function getSemanticDiagnostics(language, languageService, getSemanticDiagnostics) {
return filePath => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
return getSemanticDiagnostics(targetScript?.id ?? fileName)
.map(d => (0, transform_1.transformDiagnostic)(language, d, languageService.getProgram(), false))
.filter(d => !!d)
.filter(d => !serviceScript || !d.file || language.scripts.get(d.file.fileName) === sourceScript);
};
}
function getSuggestionDiagnostics(language, languageService, getSuggestionDiagnostics) {
return filePath => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
return getSuggestionDiagnostics(targetScript?.id ?? fileName)
.map(d => (0, transform_1.transformDiagnostic)(language, d, languageService.getProgram(), false))
.filter(d => !!d)
.filter(d => !serviceScript || !d.file || language.scripts.get(d.file.fileName) === sourceScript);
};
}
function getDefinitionAndBoundSpan(language, getDefinitionAndBoundSpan) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isDefinitionEnabled, (fileName, position) => getDefinitionAndBoundSpan(fileName, position), function* (result) {
for (const ref of result.definitions ?? []) {
yield [ref.fileName, ref.textSpan.start];
}
});
const textSpan = unresolved
.map(s => (0, transform_1.transformSpan)(language, fileName, s.textSpan, true, language_core_1.isDefinitionEnabled)?.textSpan)
.filter(s => !!s)[0];
if (!textSpan) {
return;
}
const definitions = unresolved
.map(s => s.definitions
?.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
.filter(s => !!s)
?? [])
.flat();
return {
textSpan,
definitions: (0, dedupe_1.dedupeDocumentSpans)(definitions),
};
};
}
function findReferences(language, findReferences) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isReferencesEnabled, (fileName, position) => findReferences(fileName, position), function* (result) {
for (const ref of result) {
for (const reference of ref.references) {
yield [reference.fileName, reference.textSpan.start];
}
}
});
const resolved = unresolved
.flat()
.map(symbol => {
const definition = (0, transform_1.transformDocumentSpan)(language, symbol.definition, true, language_core_1.isDefinitionEnabled, true);
return {
definition,
references: symbol.references
.map(r => (0, transform_1.transformDocumentSpan)(language, r, true, language_core_1.isReferencesEnabled))
.filter(r => !!r),
};
});
return resolved;
};
}
function getDefinitionAtPosition(language, getDefinitionAtPosition) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isDefinitionEnabled, (fileName, position) => getDefinitionAtPosition(fileName, position), function* (result) {
for (const ref of result) {
yield [ref.fileName, ref.textSpan.start];
}
});
const resolved = unresolved
.flat()
.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function getTypeDefinitionAtPosition(language, getTypeDefinitionAtPosition) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isTypeDefinitionEnabled, (fileName, position) => getTypeDefinitionAtPosition(fileName, position), function* (result) {
for (const ref of result) {
yield [ref.fileName, ref.textSpan.start];
}
});
const resolved = unresolved
.flat()
.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isTypeDefinitionEnabled))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function getImplementationAtPosition(language, getImplementationAtPosition) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isImplementationEnabled, (fileName, position) => getImplementationAtPosition(fileName, position), function* (result) {
for (const ref of result) {
yield [ref.fileName, ref.textSpan.start];
}
});
const resolved = unresolved
.flat()
.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isImplementationEnabled))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function findRenameLocations(language, findRenameLocations) {
return (filePath, position, findInStrings, findInComments, preferences) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isRenameEnabled, (fileName, position) => findRenameLocations(fileName, position, findInStrings, findInComments, preferences), function* (result) {
for (const ref of result) {
yield [ref.fileName, ref.textSpan.start];
}
});
const resolved = unresolved
.flat()
.map(s => (0, transform_1.transformDocumentSpan)(language, s, false, language_core_1.isRenameEnabled))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function getReferencesAtPosition(language, getReferencesAtPosition) {
return (filePath, position) => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = linkedCodeFeatureWorker(language, fileName, position, language_core_1.isReferencesEnabled, (fileName, position) => getReferencesAtPosition(fileName, position), function* (result) {
for (const ref of result) {
yield [ref.fileName, ref.textSpan.start];
}
});
const resolved = unresolved
.flat()
.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isReferencesEnabled))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function getCompletionsAtPosition(language, getCompletionsAtPosition) {
return (filePath, position, options, formattingSettings) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
let mainResult;
const additionalResults = [];
for (const [generatedOffset, mapping] of (0, transform_1.toGeneratedOffsets)(language, serviceScript, sourceScript, position, language_core_1.isCompletionEnabled)) {
const isAdditional = typeof mapping.data.completion === 'object' && mapping.data.completion.isAdditional;
if (!isAdditional && mainResult?.entries.length) {
continue;
}
const result = getCompletionsAtPosition(targetScript.id, generatedOffset, options, formattingSettings);
if (!result) {
continue;
}
if (typeof mapping.data.completion === 'object' && mapping.data.completion.onlyImport) {
result.entries = result.entries.filter(entry => !!entry.sourceDisplay);
}
for (const entry of result.entries) {
entry.replacementSpan = entry.replacementSpan && (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, entry.replacementSpan, false, language_core_1.isCompletionEnabled)?.[1];
}
result.optionalReplacementSpan = result.optionalReplacementSpan
&& (0, transform_1.transformTextSpan)(sourceScript, language, serviceScript, result.optionalReplacementSpan, false, language_core_1.isCompletionEnabled)?.[1];
if (isAdditional) {
additionalResults.push(result);
}
else {
mainResult = result;
}
}
const results = additionalResults;
if (mainResult) {
results.unshift(mainResult);
}
if (results.length) {
return {
...results[0],
entries: results
.map(additionalResult => additionalResult.entries)
.flat(),
};
}
}
else {
return getCompletionsAtPosition(fileName, position, options, formattingSettings);
}
};
}
function getCompletionEntryDetails(language, getCompletionEntryDetails) {
return (filePath, position, entryName, formatOptions, source, preferences, data) => {
let details;
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return undefined;
}
if (serviceScript) {
const generatePosition = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isCompletionEnabled);
if (generatePosition !== undefined) {
details = getCompletionEntryDetails(targetScript.id, generatePosition, entryName, formatOptions, source, preferences, data);
}
}
else {
return getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
}
if (details?.codeActions) {
for (const codeAction of details.codeActions) {
codeAction.changes = (0, transform_1.transformFileTextChanges)(language, codeAction.changes, false, language_core_1.isCompletionEnabled);
}
}
return details;
};
}
function provideInlayHints(language, provideInlayHints) {
return (filePath, span, preferences) => {
const fileName = filePath.replace(windowsPathReg, '/');
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (targetScript?.associatedOnly) {
return [];
}
if (serviceScript) {
const map = language.maps.get(serviceScript.code, sourceScript);
const mapped = (0, language_core_1.findOverlapCodeRange)(span.start, span.start + span.length, map, language_core_1.isSemanticTokensEnabled);
if (!mapped) {
return [];
}
const mappingOffset = (0, transform_1.getMappingOffset)(language, serviceScript);
const start = mapped.start + mappingOffset;
const end = mapped.end + mappingOffset;
const result = provideInlayHints(targetScript.id, { start, length: end - start }, preferences);
const hints = [];
for (const hint of result) {
const sourcePosition = (0, transform_1.toSourceOffset)(sourceScript, language, serviceScript, hint.position, language_core_1.isInlayHintsEnabled);
if (sourcePosition !== undefined) {
hints.push({
...hint,
position: sourcePosition[1],
});
}
}
return hints;
}
else {
return provideInlayHints(fileName, span, preferences);
}
};
}
function getFileReferences(language, getFileReferences) {
return filePath => {
const fileName = filePath.replace(windowsPathReg, '/');
const unresolved = getFileReferences(fileName);
const resolved = unresolved
.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isReferencesEnabled))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function getNavigateToItems(language, getNavigateToItems) {
return (...args) => {
const unresolved = getNavigateToItems(...args);
const resolved = unresolved
.map(s => (0, transform_1.transformDocumentSpan)(language, s, true, language_core_1.isReferencesEnabled))
.filter(s => !!s);
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
};
}
function linkedCodeFeatureWorker(language, fileName, position, filter, worker, getLinkedCodes) {
const results = [];
const processedFilePositions = new Set();
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (serviceScript) {
for (const [generatedOffset] of (0, transform_1.toGeneratedOffsets)(language, serviceScript, sourceScript, position, filter)) {
process(targetScript.id, generatedOffset);
}
}
else {
process(fileName, position);
}
return results;
function process(fileName, position) {
if (processedFilePositions.has(fileName + ':' + position)) {
return;
}
processedFilePositions.add(fileName + ':' + position);
const result = worker(fileName, position);
if (!result) {
return;
}
results.push(result);
for (const ref of getLinkedCodes(result)) {
processedFilePositions.add(ref[0] + ':' + ref[1]);
const [serviceScript] = (0, utils_1.getServiceScript)(language, ref[0]);
if (!serviceScript) {
continue;
}
const linkedCodeMap = language.linkedCodeMaps.get(serviceScript.code);
if (!linkedCodeMap) {
continue;
}
const mappingOffset = (0, transform_1.getMappingOffset)(language, serviceScript);
for (const linkedCodeOffset of linkedCodeMap.getLinkedOffsets(ref[1] - mappingOffset)) {
process(ref[0], linkedCodeOffset + mappingOffset);
}
}
}
}
function displayPartsToString(displayParts) {
if (displayParts) {
return displayParts.map(displayPart => displayPart.text).join('');
}
return '';
}
//# sourceMappingURL=proxyLanguageService.js.map

View File

@@ -0,0 +1,29 @@
import type { CodeInformation, SourceScript } from '@volar/language-core';
import { Language } from '@volar/language-core';
import type * as ts from 'typescript';
import type { TypeScriptServiceScript } from '../..';
/**
* This file contains a number of facilities for transforming `ts.Diagnostic`s returned
* from the base TypeScript LanguageService, which reference locations in generated
* TS code (e.g. the TypeScript codegen'd from the script portion of a .vue file) into locations
* in the script portion of the .vue file.
*/
export declare function transformCallHierarchyItem(language: Language<string>, item: ts.CallHierarchyItem, fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
export declare function transformDiagnostic<T extends ts.Diagnostic>(language: Language<string>, diagnostic: T, program: ts.Program | undefined, isTsc: boolean): T | undefined;
export declare function fillSourceFileText(language: Language<string>, sourceFile: ts.SourceFile): void;
export declare function transformFileTextChanges(language: Language<string>, changes: readonly ts.FileTextChanges[], fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean): ts.FileTextChanges[];
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language<string>, documentSpan: T, fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
export declare function transformSpan(language: Language<string>, fileName: string | undefined, textSpan: ts.TextSpan | undefined, fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean): {
fileName: string;
textSpan: ts.TextSpan;
} | undefined;
export declare function transformTextChange(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, textChange: ts.TextChange, fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean): [string, ts.TextChange] | undefined;
export declare function transformTextSpan(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, textSpan: ts.TextSpan, fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean): [string, ts.TextSpan] | undefined;
export declare function toSourceOffset(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, position: number, filter: (data: CodeInformation) => boolean): [fileName: string, offset: number] | undefined;
export declare function toSourceRanges(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, start: number, end: number, fallbackToAnyMatch: boolean, filter: (data: CodeInformation) => boolean): Generator<[fileName: string, start: number, end: number]>;
export declare function toSourceOffsets(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, position: number, filter: (data: CodeInformation) => boolean): Generator<[fileName: string, offset: number]>;
export declare function toGeneratedRange(language: Language, serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>, start: number, end: number, filter: (data: CodeInformation) => boolean): readonly [number, number] | undefined;
export declare function toGeneratedRanges(language: Language, serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>, start: number, end: number, filter: (data: CodeInformation) => boolean): Generator<readonly [number, number], void, unknown>;
export declare function toGeneratedOffset(language: Language, serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
export declare function toGeneratedOffsets(language: Language, serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>, position: number, filter: (data: CodeInformation) => boolean): Generator<readonly [number, import("@volar/language-core").Mapping<CodeInformation>], void, unknown>;
export declare function getMappingOffset(language: Language, serviceScript: TypeScriptServiceScript): number;

View File

@@ -0,0 +1,268 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformCallHierarchyItem = transformCallHierarchyItem;
exports.transformDiagnostic = transformDiagnostic;
exports.fillSourceFileText = fillSourceFileText;
exports.transformFileTextChanges = transformFileTextChanges;
exports.transformDocumentSpan = transformDocumentSpan;
exports.transformSpan = transformSpan;
exports.transformTextChange = transformTextChange;
exports.transformTextSpan = transformTextSpan;
exports.toSourceOffset = toSourceOffset;
exports.toSourceRanges = toSourceRanges;
exports.toSourceOffsets = toSourceOffsets;
exports.toGeneratedRange = toGeneratedRange;
exports.toGeneratedRanges = toGeneratedRanges;
exports.toGeneratedOffset = toGeneratedOffset;
exports.toGeneratedOffsets = toGeneratedOffsets;
exports.getMappingOffset = getMappingOffset;
const language_core_1 = require("@volar/language-core");
const utils_1 = require("./utils");
const transformedDiagnostics = new WeakMap();
const transformedSourceFile = new WeakSet();
/**
* This file contains a number of facilities for transforming `ts.Diagnostic`s returned
* from the base TypeScript LanguageService, which reference locations in generated
* TS code (e.g. the TypeScript codegen'd from the script portion of a .vue file) into locations
* in the script portion of the .vue file.
*/
function transformCallHierarchyItem(language, item, fallbackToAnyMatch, filter) {
const span = transformSpan(language, item.file, item.span, fallbackToAnyMatch, filter);
const selectionSpan = transformSpan(language, item.file, item.selectionSpan, fallbackToAnyMatch, filter);
return {
...item,
file: span?.fileName ?? item.file,
span: span?.textSpan ?? { start: 0, length: 0 },
selectionSpan: selectionSpan?.textSpan ?? { start: 0, length: 0 },
};
}
function transformDiagnostic(language, diagnostic, program, isTsc) {
if (!transformedDiagnostics.has(diagnostic)) {
transformedDiagnostics.set(diagnostic, undefined);
const { relatedInformation } = diagnostic;
if (relatedInformation) {
diagnostic.relatedInformation = relatedInformation
.map(d => transformDiagnostic(language, d, program, isTsc))
.filter(d => !!d);
}
if (diagnostic.file !== undefined
&& diagnostic.start !== undefined
&& diagnostic.length !== undefined) {
const [serviceScript] = (0, utils_1.getServiceScript)(language, diagnostic.file.fileName);
if (serviceScript) {
const [sourceSpanFileName, sourceSpan] = transformTextSpan(undefined, language, serviceScript, {
start: diagnostic.start,
length: diagnostic.length
}, true, data => (0, language_core_1.shouldReportDiagnostics)(data, String(diagnostic.source), String(diagnostic.code))) ?? [];
const actualDiagnosticFile = sourceSpanFileName
? diagnostic.file.fileName === sourceSpanFileName
? diagnostic.file
: program?.getSourceFile(sourceSpanFileName)
: undefined;
if (sourceSpan && actualDiagnosticFile) {
if (isTsc) {
fillSourceFileText(language, diagnostic.file);
}
transformedDiagnostics.set(diagnostic, {
...diagnostic,
file: actualDiagnosticFile,
start: sourceSpan.start,
length: sourceSpan.length,
});
}
}
else {
transformedDiagnostics.set(diagnostic, diagnostic);
}
}
else {
transformedDiagnostics.set(diagnostic, diagnostic);
}
}
return transformedDiagnostics.get(diagnostic);
}
// fix https://github.com/vuejs/language-tools/issues/4099 without `incremental`
function fillSourceFileText(language, sourceFile) {
if (transformedSourceFile.has(sourceFile)) {
return;
}
transformedSourceFile.add(sourceFile);
const [serviceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
if (serviceScript && !serviceScript.preventLeadingOffset) {
const sourceScript = language.scripts.fromVirtualCode(serviceScript.code);
sourceFile.text = sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength())
+ sourceFile.text.substring(sourceScript.snapshot.getLength());
}
}
function transformFileTextChanges(language, changes, fallbackToAnyMatch, filter) {
const changesPerFile = {};
const newFiles = new Set();
for (const fileChanges of changes) {
const [_, source] = (0, utils_1.getServiceScript)(language, fileChanges.fileName);
if (source) {
fileChanges.textChanges.forEach(c => {
const { fileName, textSpan } = transformSpan(language, fileChanges.fileName, c.span, fallbackToAnyMatch, filter) ?? {};
if (fileName && textSpan) {
(changesPerFile[fileName] ?? (changesPerFile[fileName] = [])).push({ ...c, span: textSpan });
}
});
}
else {
const list = (changesPerFile[fileChanges.fileName] ?? (changesPerFile[fileChanges.fileName] = []));
fileChanges.textChanges.forEach(c => {
list.push(c);
});
if (fileChanges.isNewFile) {
newFiles.add(fileChanges.fileName);
}
}
}
const result = [];
for (const fileName in changesPerFile) {
result.push({
fileName,
isNewFile: newFiles.has(fileName),
textChanges: changesPerFile[fileName]
});
}
return result;
}
function transformDocumentSpan(language, documentSpan, fallbackToAnyMatch, filter, shouldFallback) {
let textSpan = transformSpan(language, documentSpan.fileName, documentSpan.textSpan, fallbackToAnyMatch, filter);
if (!textSpan && shouldFallback) {
textSpan = {
fileName: documentSpan.fileName,
textSpan: { start: 0, length: 0 },
};
}
if (!textSpan) {
return;
}
const contextSpan = transformSpan(language, documentSpan.fileName, documentSpan.contextSpan, fallbackToAnyMatch, filter);
const originalTextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalTextSpan, fallbackToAnyMatch, filter);
const originalContextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalContextSpan, fallbackToAnyMatch, filter);
return {
...documentSpan,
fileName: textSpan.fileName,
textSpan: textSpan.textSpan,
contextSpan: contextSpan?.textSpan,
originalFileName: originalTextSpan?.fileName,
originalTextSpan: originalTextSpan?.textSpan,
originalContextSpan: originalContextSpan?.textSpan,
};
}
function transformSpan(language, fileName, textSpan, fallbackToAnyMatch, filter) {
if (!fileName || !textSpan) {
return;
}
const [serviceScript] = (0, utils_1.getServiceScript)(language, fileName);
if (serviceScript) {
const [sourceSpanFileName, sourceSpan] = transformTextSpan(undefined, language, serviceScript, textSpan, fallbackToAnyMatch, filter) ?? [];
if (sourceSpan && sourceSpanFileName) {
return {
fileName: sourceSpanFileName,
textSpan: sourceSpan,
};
}
}
else {
return {
fileName,
textSpan,
};
}
}
function transformTextChange(sourceScript, language, serviceScript, textChange, fallbackToAnyMatch, filter) {
const [sourceSpanFileName, sourceSpan] = transformTextSpan(sourceScript, language, serviceScript, textChange.span, fallbackToAnyMatch, filter) ?? [];
if (sourceSpan && sourceSpanFileName) {
return [sourceSpanFileName, {
newText: textChange.newText,
span: sourceSpan,
}];
}
return undefined;
}
function transformTextSpan(sourceScript, language, serviceScript, textSpan, fallbackToAnyMatch, filter) {
const start = textSpan.start;
const end = textSpan.start + textSpan.length;
for (const [fileName, sourceStart, sourceEnd] of toSourceRanges(sourceScript, language, serviceScript, start, end, fallbackToAnyMatch, filter)) {
return [fileName, {
start: sourceStart,
length: sourceEnd - sourceStart,
}];
}
}
function toSourceOffset(sourceScript, language, serviceScript, position, filter) {
for (const source of toSourceOffsets(sourceScript, language, serviceScript, position, filter)) {
return source;
}
}
function* toSourceRanges(sourceScript, language, serviceScript, start, end, fallbackToAnyMatch, filter) {
if (sourceScript) {
const map = language.maps.get(serviceScript.code, sourceScript);
for (const [sourceStart, sourceEnd] of map.toSourceRange(start - getMappingOffset(language, serviceScript), end - getMappingOffset(language, serviceScript), fallbackToAnyMatch, filter)) {
yield [sourceScript.id, sourceStart, sourceEnd];
}
}
else {
for (const [sourceScript, map] of language.maps.forEach(serviceScript.code)) {
for (const [sourceStart, sourceEnd] of map.toSourceRange(start - getMappingOffset(language, serviceScript), end - getMappingOffset(language, serviceScript), fallbackToAnyMatch, filter)) {
yield [sourceScript.id, sourceStart, sourceEnd];
}
}
}
}
function* toSourceOffsets(sourceScript, language, serviceScript, position, filter) {
if (sourceScript) {
const map = language.maps.get(serviceScript.code, sourceScript);
for (const [sourceOffset, mapping] of map.toSourceLocation(position - getMappingOffset(language, serviceScript))) {
if (filter(mapping.data)) {
yield [sourceScript.id, sourceOffset];
}
}
}
else {
for (const [sourceScript, map] of language.maps.forEach(serviceScript.code)) {
for (const [sourceOffset, mapping] of map.toSourceLocation(position - getMappingOffset(language, serviceScript))) {
if (filter(mapping.data)) {
yield [sourceScript.id, sourceOffset];
}
}
}
}
}
function toGeneratedRange(language, serviceScript, sourceScript, start, end, filter) {
for (const result of toGeneratedRanges(language, serviceScript, sourceScript, start, end, filter)) {
return result;
}
}
function* toGeneratedRanges(language, serviceScript, sourceScript, start, end, filter) {
const map = language.maps.get(serviceScript.code, sourceScript);
for (const [generateStart, generateEnd] of map.toGeneratedRange(start, end, true, filter)) {
yield [
generateStart + getMappingOffset(language, serviceScript),
generateEnd + getMappingOffset(language, serviceScript),
];
}
}
function toGeneratedOffset(language, serviceScript, sourceScript, position, filter) {
for (const [generateOffset] of toGeneratedOffsets(language, serviceScript, sourceScript, position, filter)) {
return generateOffset;
}
}
function* toGeneratedOffsets(language, serviceScript, sourceScript, position, filter) {
const map = language.maps.get(serviceScript.code, sourceScript);
for (const [generateOffset, mapping] of map.toGeneratedLocation(position)) {
if (filter(mapping.data)) {
yield [generateOffset + getMappingOffset(language, serviceScript), mapping];
}
}
}
function getMappingOffset(language, serviceScript) {
if (serviceScript.preventLeadingOffset) {
return 0;
}
const sourceScript = language.scripts.fromVirtualCode(serviceScript.code);
return sourceScript.snapshot.getLength();
}
//# sourceMappingURL=transform.js.map

View File

@@ -0,0 +1,3 @@
import type { Language, SourceScript } from '@volar/language-core';
import type { TypeScriptServiceScript } from '../..';
export declare function getServiceScript(language: Language<string>, fileName: string): [serviceScript: TypeScriptServiceScript, targetScript: SourceScript<string>, sourceScript: SourceScript<string>] | [serviceScript: undefined, sourceScript: SourceScript<string>, sourceScript: SourceScript<string>] | [serviceScript: undefined, sourceScript: undefined, targetScript: undefined];

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getServiceScript = getServiceScript;
function getServiceScript(language, fileName) {
const sourceScript = language.scripts.get(fileName);
if (sourceScript?.targetIds.size) {
for (const targetId of sourceScript.targetIds) {
const targetScript = language.scripts.get(targetId);
if (targetScript?.generated) {
const serviceScript = targetScript.generated.languagePlugin.typescript?.getServiceScript(targetScript.generated.root);
if (serviceScript) {
return [serviceScript, targetScript, sourceScript];
}
}
}
}
if (sourceScript?.associatedOnly) {
return [undefined, sourceScript, sourceScript];
}
if (sourceScript?.generated) {
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
if (serviceScript) {
return [serviceScript, sourceScript, sourceScript];
}
}
return [undefined, undefined, undefined];
}
//# sourceMappingURL=utils.js.map

View File

@@ -0,0 +1,18 @@
import { Language } from '@volar/language-core';
import type * as ts from 'typescript';
import type { TypeScriptExtraServiceScript } from '../..';
import type { createSys } from './createSys';
export interface TypeScriptProjectHost extends Pick<ts.LanguageServiceHost, 'getLocalizedDiagnosticMessages' | 'getCurrentDirectory' | 'getCompilationSettings' | 'getProjectReferences' | 'getScriptFileNames' | 'getProjectVersion'> {
}
declare module 'typescript' {
interface LanguageServiceHost {
/**
* @internal
*/
getModuleResolutionCache?(): ts.ModuleResolutionCache;
}
}
export declare function createLanguageServiceHost<T>(ts: typeof import('typescript'), sys: ReturnType<typeof createSys> | ts.System, language: Language<T>, asScriptId: (fileName: string) => T, projectHost: TypeScriptProjectHost): {
languageServiceHost: ts.LanguageServiceHost;
getExtraServiceScript: (fileName: string) => TypeScriptExtraServiceScript | undefined;
};

View File

@@ -0,0 +1,275 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLanguageServiceHost = createLanguageServiceHost;
const language_core_1 = require("@volar/language-core");
const path = require("path-browserify");
const resolveModuleName_1 = require("../resolveModuleName");
function createLanguageServiceHost(ts, sys, language, asScriptId, 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 tsFileDirRegistry = 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);
}
}
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`.');
}
}
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());
}
},
directoryExists(directoryName) {
sync();
if (tsFileDirRegistry.has(directoryName)) {
return true;
}
return sys.directoryExists(directoryName);
},
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(asScriptId(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 (language.plugins.some(plugin => plugin.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, sys.getFileSize, languageServiceHost, language.plugins, fileName => language.scripts.get(asScriptId(fileName)));
let lastSysVersion = 'version' in sys ? sys.version : undefined;
languageServiceHost.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, options, sourceFile) => {
if ('version' in sys && lastSysVersion !== sys.version) {
lastSysVersion = sys.version;
moduleCache.clear();
}
return moduleLiterals.map(moduleLiteral => {
return resolveModuleName(moduleLiteral.text, containingFile, options, moduleCache, redirectedReference, sourceFile.impliedNodeFormat);
});
};
languageServiceHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options) => {
if ('version' in sys && lastSysVersion !== sys.version) {
lastSysVersion = sys.version;
moduleCache.clear();
}
return moduleNames.map(moduleName => {
return resolveModuleName(moduleName, containingFile, options, moduleCache, redirectedReference).resolvedModule;
});
};
languageServiceHost.getModuleResolutionCache = () => moduleCache;
}
return {
languageServiceHost,
getExtraServiceScript,
};
function getExtraServiceScript(fileName) {
sync();
return extraScriptRegistry.get(fileName);
}
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(asScriptId(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_1.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();
tsFileDirRegistry.clear();
for (const fileName of tsFileNamesSet) {
tsFileRegistry.set(fileName, true);
const parts = fileName.split('/');
for (let i = 1; i < parts.length; i++) {
const dirName = parts.slice(0, i).join('/');
tsFileDirRegistry.set(dirName, true);
}
}
}
function getScriptSnapshot(fileName) {
sync();
if (extraScriptRegistry.has(fileName)) {
return extraScriptRegistry.get(fileName).code.snapshot;
}
const sourceScript = language.scripts.get(asScriptId(fileName));
if (sourceScript?.generated) {
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
if (serviceScript) {
return serviceScript.code.snapshot;
}
}
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++);
}
return version.map.get(snapshot).toString();
}
const sourceScript = language.scripts.get(asScriptId(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 openedFile = language.scripts.get(asScriptId(fileName), false);
if (openedFile && !openedFile.generated) {
if (!version.map.has(openedFile.snapshot)) {
version.map.set(openedFile.snapshot, version.lastVersion++);
}
return version.map.get(openedFile.snapshot).toString();
}
if (sys.fileExists(fileName)) {
return sys.getModifiedTime?.(fileName)?.valueOf().toString() ?? '0';
}
return '';
}
}
function setEquals(a, b) {
if (a.size !== b.size) {
return false;
}
for (const item of a) {
if (!b.has(item)) {
return false;
}
}
return true;
}
//# sourceMappingURL=createProject.js.map

View File

@@ -0,0 +1,10 @@
import type { LanguageServiceEnvironment, Disposable } from '@volar/language-service';
import type * as ts from 'typescript';
import { URI } from 'vscode-uri';
export declare function createSys(sys: ts.System | undefined, env: Pick<LanguageServiceEnvironment, 'onDidChangeWatchedFiles' | 'fs'>, getCurrentDirectory: () => string, uriConverter: {
asUri(fileName: string): URI;
asFileName(uri: URI): string;
}): ts.System & {
version: number;
sync(): Promise<number>;
} & Disposable;

View File

@@ -0,0 +1,372 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSys = createSys;
const path = require("path-browserify");
const utilities_1 = require("../typescript/utilities");
const vscode_uri_1 = require("vscode-uri");
let currentCwd = '';
function createSys(sys, env, getCurrentDirectory, uriConverter) {
let version = 0;
const caseSensitive = sys?.useCaseSensitiveFileNames ?? false;
const root = {
name: '',
dirs: new Map(),
files: new Map(),
requestedRead: false,
};
const promises = new Set();
const fileWatcher = env.onDidChangeWatchedFiles?.(({ changes }) => {
version++;
for (const change of changes) {
const changeUri = vscode_uri_1.URI.parse(change.uri);
const fileName = uriConverter.asFileName(changeUri);
const dirName = path.dirname(fileName);
const baseName = path.basename(fileName);
const fileExists = change.type === 1
|| change.type === 2;
const dir = getDir(dirName, fileExists);
dir.files.set(normalizeFileId(baseName), fileExists ? {
name: baseName,
stat: {
type: 1,
ctime: Date.now(),
mtime: Date.now(),
size: -1,
},
requestedStat: false,
requestedText: false,
} : {
name: baseName,
stat: undefined,
text: undefined,
requestedStat: true,
requestedText: true,
});
}
});
return {
dispose() {
fileWatcher?.dispose();
},
args: sys?.args ?? [],
newLine: sys?.newLine ?? '\n',
useCaseSensitiveFileNames: caseSensitive,
realpath: sys?.realpath,
write: sys?.write ?? (() => { }),
writeFile: sys?.writeFile ?? (() => { }),
createDirectory: sys?.createDirectory ?? (() => { }),
exit: sys?.exit ?? (() => { }),
getExecutingFilePath: sys?.getExecutingFilePath ?? (() => getCurrentDirectory + '/__fake__.js'),
getCurrentDirectory,
getModifiedTime,
readFile,
readDirectory,
getDirectories,
resolvePath,
fileExists,
directoryExists,
get version() {
return version;
},
async sync() {
while (promises.size) {
await Promise.all(promises);
}
return version;
},
};
function resolvePath(fsPath) {
if (sys) {
const currentDirectory = getCurrentDirectory();
if (currentCwd !== currentDirectory) {
currentCwd = currentDirectory;
// https://github.com/vuejs/language-tools/issues/2039
// https://github.com/vuejs/language-tools/issues/2234
if (sys.directoryExists(currentDirectory)) {
// https://github.com/vuejs/language-tools/issues/2480
try {
// @ts-ignore
process.chdir(currentDirectory);
}
catch { }
}
}
return sys.resolvePath(fsPath).replace(/\\/g, '/');
}
return path.resolve(fsPath).replace(/\\/g, '/');
}
function readFile(fileName, encoding) {
fileName = resolvePath(fileName);
const dirPath = path.dirname(fileName);
const dir = getDir(dirPath);
const name = path.basename(fileName);
readFileWorker(fileName, encoding, dir);
return dir.files.get(normalizeFileId(name))?.text;
}
function directoryExists(dirName) {
dirName = resolvePath(dirName);
const dir = getDir(dirName);
if (dir.exists === undefined) {
dir.exists = false;
const result = env.fs?.stat(uriConverter.asUri(dirName));
if (typeof result === 'object' && 'then' in result) {
const promise = result;
promises.add(promise);
result.then(result => {
promises.delete(promise);
dir.exists = result?.type === 2;
if (dir.exists) {
version++;
}
});
}
else {
dir.exists = result?.type === 2;
}
}
return dir.exists;
}
function getModifiedTime(fileName) {
fileName = resolvePath(fileName);
const file = getFile(fileName);
if (!file.requestedStat) {
file.requestedStat = true;
handleStat(fileName, file);
}
return file.stat ? new Date(file.stat.mtime) : new Date(0);
}
function fileExists(fileName) {
fileName = resolvePath(fileName);
const file = getFile(fileName);
const exists = () => file.text !== undefined || file.stat?.type === 1;
if (exists()) {
return true;
}
if (!file.requestedStat) {
file.requestedStat = true;
handleStat(fileName, file);
}
return exists();
}
function handleStat(fileName, file) {
const result = env.fs?.stat(uriConverter.asUri(fileName));
if (typeof result === 'object' && 'then' in result) {
const promise = result;
promises.add(promise);
result.then(result => {
promises.delete(promise);
if (file.stat?.type !== result?.type || file.stat?.mtime !== result?.mtime) {
version++;
}
file.stat = result;
});
}
else {
file.stat = result;
}
}
function getFile(fileName) {
fileName = resolvePath(fileName);
const dirPath = path.dirname(fileName);
const baseName = path.basename(fileName);
const dir = getDir(dirPath);
let file = dir.files.get(normalizeFileId(baseName));
if (!file) {
dir.files.set(normalizeFileId(baseName), file = {
name: baseName,
requestedStat: false,
requestedText: false,
});
}
return file;
}
// for import path completion
function getDirectories(dirName) {
dirName = resolvePath(dirName);
readDirectoryWorker(dirName);
const dir = getDir(dirName);
return [...dir.dirs.values()]
.filter(dir => dir.exists)
.map(dir => dir.name);
}
function readDirectory(dirName, extensions, excludes, includes, depth) {
dirName = resolvePath(dirName);
const currentDirectory = getCurrentDirectory();
const matches = (0, utilities_1.matchFiles)(dirName, extensions, excludes, includes, caseSensitive, currentDirectory, depth, dirPath => {
dirPath = resolvePath(dirPath);
readDirectoryWorker(dirPath);
const dir = getDir(dirPath);
return {
files: [...dir.files.values()]
.filter(file => file.stat?.type === 1)
.map(file => file.name),
directories: [...dir.dirs.values()]
.filter(dir => dir.exists)
.map(dir => dir.name),
};
}, sys?.realpath ? (path => sys.realpath(path)) : (path => path));
return [...new Set(matches)];
}
function readFileWorker(fileName, encoding, dir) {
const name = path.basename(fileName);
let file = dir.files.get(normalizeFileId(name));
if (!file) {
dir.files.set(normalizeFileId(name), file = {
name,
requestedStat: false,
requestedText: false,
});
}
if (file.requestedText) {
return;
}
file.requestedText = true;
const uri = uriConverter.asUri(fileName);
const result = env.fs?.readFile(uri, encoding);
if (typeof result === 'object' && 'then' in result) {
const promise = result;
promises.add(promise);
result.then(result => {
promises.delete(promise);
if (result !== undefined) {
file.text = result;
if (file.stat) {
file.stat.mtime++;
}
version++;
}
});
}
else if (result !== undefined) {
file.text = result;
}
}
function readDirectoryWorker(dirName) {
const dir = getDir(dirName);
if (dir.requestedRead) {
return;
}
dir.requestedRead = true;
const result = env.fs?.readDirectory(uriConverter.asUri(dirName || '.'));
if (typeof result === 'object' && 'then' in result) {
const promise = result;
promises.add(promise);
result.then(result => {
promises.delete(promise);
if (onReadDirectoryResult(dirName, dir, result)) {
version++;
}
});
}
else {
onReadDirectoryResult(dirName, dir, result ?? []);
}
}
function onReadDirectoryResult(dirName, dir, result) {
// See https://github.com/microsoft/TypeScript/blob/e1a9290051a3b0cbdfbadc3adbcc155a4641522a/src/compiler/sys.ts#L1853-L1857
result = result.filter(([name]) => name !== '.' && name !== '..');
let updated = false;
for (const [name, _fileType] of result) {
let fileType = _fileType;
if (fileType === 64) {
const stat = env.fs?.stat(uriConverter.asUri(dirName + '/' + name));
if (typeof stat === 'object' && 'then' in stat) {
const promise = stat;
promises.add(promise);
stat.then(stat => {
promises.delete(promise);
if (stat?.type === 1) {
let file = dir.files.get(normalizeFileId(name));
if (!file) {
dir.files.set(normalizeFileId(name), file = {
name,
requestedStat: false,
requestedText: false,
});
}
if (stat.type !== file.stat?.type || stat.mtime !== file.stat?.mtime) {
version++;
}
file.stat = stat;
file.requestedStat = true;
}
else if (stat?.type === 2) {
const childDir = getDirFromDir(dir, name);
if (!childDir.exists) {
childDir.exists = true;
version++;
}
}
});
}
else if (stat) {
fileType = stat.type;
}
}
if (fileType === 1) {
let file = dir.files.get(normalizeFileId(name));
if (!file) {
dir.files.set(normalizeFileId(name), file = {
name,
requestedStat: false,
requestedText: false,
});
}
if (!file.stat) {
file.stat = {
type: 1,
mtime: 0,
ctime: 0,
size: 0,
};
updated = true;
}
}
else if (fileType === 2) {
const childDir = getDirFromDir(dir, name);
if (!childDir.exists) {
childDir.exists = true;
updated = true;
}
}
}
return updated;
}
function getDir(dirName, markExists = false) {
const dirNames = [];
let currentDirPath = dirName;
let currentDirName = path.basename(currentDirPath);
let lastDirPath;
while (lastDirPath !== currentDirPath) {
lastDirPath = currentDirPath;
dirNames.push(currentDirName);
currentDirPath = path.dirname(currentDirPath);
currentDirName = path.basename(currentDirPath);
}
let currentDir = root;
for (let i = dirNames.length - 1; i >= 0; i--) {
const nextDirName = dirNames[i];
currentDir = getDirFromDir(currentDir, nextDirName);
if (markExists && !currentDir.exists) {
currentDir.exists = true;
version++;
}
}
return currentDir;
}
function getDirFromDir(dir, name) {
let target = dir.dirs.get(normalizeFileId(name));
if (!target) {
dir.dirs.set(normalizeFileId(name), target = {
name,
dirs: new Map(),
files: new Map(),
});
}
return target;
}
function normalizeFileId(fileName) {
return caseSensitive ? fileName : fileName.toLowerCase();
}
}
//# sourceMappingURL=createSys.js.map

View File

@@ -0,0 +1,22 @@
import type * as ts from 'typescript';
import type { createPluginCallbackAsync } from './languageServicePluginCommon';
/**
* Creates and returns a TS Service Plugin that supports async initialization.
* Essentially, this functions the same as `createLanguageServicePlugin`, but supports
* use cases in which the plugin callback must be async. For example in mdx-analyzer
* and Glint, this async variant is required because Glint + mdx-analyzer are written
* in ESM and get transpiled to CJS, which requires usage of `await import()` to load
* the necessary dependencies and fully initialize the plugin.
*
* To handle the period of time in which the plugin is initializing, this async
* variant stubs a number of methods on the LanguageServiceHost to handle the uninitialized state.
*
* Additionally, this async variant requires a few extra args pertaining to
* file extensions intended to be handled by the TS Plugin. In the synchronous variant,
* these can be synchronously inferred from elsewhere but for the async variant, they
* need to be passed in.
*
* See https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin for
* more information.
*/
export declare function createAsyncLanguageServicePlugin(extensions: string[], getScriptKindForExtraExtensions: ts.ScriptKind | ((fileName: string) => ts.ScriptKind), createPluginCallbackAsync: createPluginCallbackAsync): ts.server.PluginModuleFactory;

View File

@@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAsyncLanguageServicePlugin = createAsyncLanguageServicePlugin;
const proxyLanguageService_1 = require("../node/proxyLanguageService");
const languageServicePluginCommon_1 = require("./languageServicePluginCommon");
/**
* Creates and returns a TS Service Plugin that supports async initialization.
* Essentially, this functions the same as `createLanguageServicePlugin`, but supports
* use cases in which the plugin callback must be async. For example in mdx-analyzer
* and Glint, this async variant is required because Glint + mdx-analyzer are written
* in ESM and get transpiled to CJS, which requires usage of `await import()` to load
* the necessary dependencies and fully initialize the plugin.
*
* To handle the period of time in which the plugin is initializing, this async
* variant stubs a number of methods on the LanguageServiceHost to handle the uninitialized state.
*
* Additionally, this async variant requires a few extra args pertaining to
* file extensions intended to be handled by the TS Plugin. In the synchronous variant,
* these can be synchronously inferred from elsewhere but for the async variant, they
* need to be passed in.
*
* See https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin for
* more information.
*/
function createAsyncLanguageServicePlugin(extensions, getScriptKindForExtraExtensions, createPluginCallbackAsync) {
return modules => {
const { typescript: ts } = modules;
const pluginModule = {
create(info) {
if (!(0, languageServicePluginCommon_1.isHasAlreadyDecoratedLanguageService)(info)) {
const state = decorateWithAsyncInitializationHandling(ts, info, extensions, getScriptKindForExtraExtensions);
const { proxy, initialize } = (0, proxyLanguageService_1.createProxyLanguageService)(info.languageService);
info.languageService = proxy;
createPluginCallbackAsync(ts, info).then(createPluginResult => {
(0, languageServicePluginCommon_1.createLanguageCommon)(createPluginResult, ts, info, initialize);
state.initialized = true;
if ('markAsDirty' in info.project && typeof info.project.markAsDirty === 'function') {
// This is an attempt to mark the project as dirty so that in case the IDE/tsserver
// already finished a first pass of generating diagnostics (or other things), another
// pass will be triggered which should hopefully make use of this now-initialized plugin.
info.project.markAsDirty();
}
});
}
return info.languageService;
},
getExternalFiles: (0, languageServicePluginCommon_1.makeGetExternalFiles)(ts),
};
return pluginModule;
};
}
function decorateWithAsyncInitializationHandling(ts, info, extensions, getScriptKindForExtraExtensions) {
const emptySnapshot = ts.ScriptSnapshot.fromString('');
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
const getScriptKind = info.languageServiceHost.getScriptKind?.bind(info.languageServiceHost);
const getProjectVersion = info.languageServiceHost.getProjectVersion?.bind(info.languageServiceHost);
const getScriptInfo = (0, languageServicePluginCommon_1.makeGetScriptInfoWithLargeFileFailsafe)(info);
const state = { initialized: false };
info.languageServiceHost.getScriptSnapshot = fileName => {
if (!state.initialized) {
if (extensions.some(ext => fileName.endsWith(ext))) {
return emptySnapshot;
}
if (getScriptInfo(fileName)?.isScriptOpen()) {
return emptySnapshot;
}
}
return getScriptSnapshot(fileName);
};
info.languageServiceHost.getScriptVersion = fileName => {
if (!state.initialized) {
if (extensions.some(ext => fileName.endsWith(ext))) {
return 'initializing...';
}
if (getScriptInfo(fileName)?.isScriptOpen()) {
return getScriptVersion(fileName) + ',initializing...';
}
}
return getScriptVersion(fileName);
};
if (getScriptKind) {
info.languageServiceHost.getScriptKind = fileName => {
if (!state.initialized && extensions.some(ext => fileName.endsWith(ext))) {
// bypass upstream bug https://github.com/microsoft/TypeScript/issues/57631
// TODO: check if the bug is fixed in 5.5
if (typeof getScriptKindForExtraExtensions === 'function') {
return getScriptKindForExtraExtensions(fileName);
}
else {
return getScriptKindForExtraExtensions;
}
}
return getScriptKind(fileName);
};
}
if (getProjectVersion) {
info.languageServiceHost.getProjectVersion = () => {
if (!state.initialized) {
return getProjectVersion() + ',initializing...';
}
return getProjectVersion();
};
}
return state;
}
//# sourceMappingURL=createAsyncLanguageServicePlugin.js.map

View File

@@ -0,0 +1,9 @@
import type * as ts from 'typescript';
import type { createPluginCallbackSync } from './languageServicePluginCommon';
/**
* Creates and returns a TS Service Plugin using Volar primitives.
*
* See https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin for
* more information.
*/
export declare function createLanguageServicePlugin(createPluginCallback: createPluginCallbackSync): ts.server.PluginModuleFactory;

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLanguageServicePlugin = createLanguageServicePlugin;
const proxyLanguageService_1 = require("../node/proxyLanguageService");
const languageServicePluginCommon_1 = require("./languageServicePluginCommon");
/**
* Creates and returns a TS Service Plugin using Volar primitives.
*
* See https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin for
* more information.
*/
function createLanguageServicePlugin(createPluginCallback) {
return modules => {
const { typescript: ts } = modules;
const pluginModule = {
create(info) {
if (!(0, languageServicePluginCommon_1.isHasAlreadyDecoratedLanguageService)(info)) {
const createPluginResult = createPluginCallback(ts, info);
const extensions = createPluginResult.languagePlugins
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
.flat();
// TODO: this logic does not seem to appear in the async variant
// (createAsyncLanguageServicePlugin)... bug?
languageServicePluginCommon_1.projectExternalFileExtensions.set(info.project, extensions);
const { proxy, initialize } = (0, proxyLanguageService_1.createProxyLanguageService)(info.languageService);
info.languageService = proxy;
(0, languageServicePluginCommon_1.createLanguageCommon)(createPluginResult, ts, info, initialize);
}
return info.languageService;
},
getExternalFiles: (0, languageServicePluginCommon_1.makeGetExternalFiles)(ts),
};
return pluginModule;
};
}
//# sourceMappingURL=createLanguageServicePlugin.js.map

View File

@@ -0,0 +1,24 @@
import { Language, LanguagePlugin } from '@volar/language-core/lib/types';
import type * as ts from 'typescript';
export declare const externalFiles: WeakMap<ts.server.Project, string[]>;
export declare const projectExternalFileExtensions: WeakMap<ts.server.Project, string[]>;
export declare const decoratedLanguageServices: WeakSet<ts.LanguageService>;
export declare const decoratedLanguageServiceHosts: WeakSet<ts.LanguageServiceHost>;
/**
* Wrap `getScriptInfo` to handle large files that may crash the language service.
*
* Introduced to fix issues with converting `relatedInformation` (in Diagnostics)
* when working with large files.
*
* https://github.com/volarjs/volar.js/commit/e242709a91e9d2919dc4fa59278dd266fd11e7a3
*/
export declare function makeGetScriptInfoWithLargeFileFailsafe(info: ts.server.PluginCreateInfo): (fileName: string) => ts.server.ScriptInfo | undefined;
export declare function createLanguageCommon(createPluginResult: createPluginCallbackReturnValue, ts: typeof import('typescript'), info: ts.server.PluginCreateInfo, initializeProxiedLanguageService: (language: Language<string>) => void): void;
export declare const makeGetExternalFiles: (ts: typeof import("typescript")) => (project: ts.server.Project, updateLevel?: number) => string[];
export type createPluginCallbackReturnValue = {
languagePlugins: LanguagePlugin<string>[];
setup?: (language: Language<string>) => void;
};
export type createPluginCallbackSync = (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => createPluginCallbackReturnValue;
export type createPluginCallbackAsync = (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<createPluginCallbackReturnValue>;
export declare function isHasAlreadyDecoratedLanguageService(info: ts.server.PluginCreateInfo): boolean;

View File

@@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeGetExternalFiles = exports.decoratedLanguageServiceHosts = exports.decoratedLanguageServices = exports.projectExternalFileExtensions = exports.externalFiles = void 0;
exports.makeGetScriptInfoWithLargeFileFailsafe = makeGetScriptInfoWithLargeFileFailsafe;
exports.createLanguageCommon = createLanguageCommon;
exports.isHasAlreadyDecoratedLanguageService = isHasAlreadyDecoratedLanguageService;
const language_core_1 = require("@volar/language-core");
const common_1 = require("../common");
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost");
exports.externalFiles = new WeakMap();
exports.projectExternalFileExtensions = new WeakMap();
exports.decoratedLanguageServices = new WeakSet();
exports.decoratedLanguageServiceHosts = new WeakSet();
/**
* Wrap `getScriptInfo` to handle large files that may crash the language service.
*
* Introduced to fix issues with converting `relatedInformation` (in Diagnostics)
* when working with large files.
*
* https://github.com/volarjs/volar.js/commit/e242709a91e9d2919dc4fa59278dd266fd11e7a3
*/
function makeGetScriptInfoWithLargeFileFailsafe(info) {
return (fileName) => {
// getSnapshot could be crashed if the file is too large
try {
return info.project.getScriptInfo(fileName);
}
catch { }
};
}
function createLanguageCommon(createPluginResult, ts, info, initializeProxiedLanguageService) {
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
const getScriptInfo = makeGetScriptInfoWithLargeFileFailsafe(info);
const language = (0, language_core_1.createLanguage)([
...createPluginResult.languagePlugins,
{ getLanguageId: common_1.resolveFileLanguageId },
], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), (fileName, _, shouldRegister) => {
let snapshot;
if (shouldRegister) {
// We need to trigger registration of the script file with the project, see #250
snapshot = getScriptSnapshot(fileName);
}
else {
snapshot = getScriptInfo(fileName)?.getSnapshot();
if (!snapshot) {
// trigger projectService.getOrCreateScriptInfoNotOpenedByClient
info.project.getScriptVersion(fileName);
snapshot = getScriptInfo(fileName)?.getSnapshot();
}
}
if (snapshot) {
language.scripts.set(fileName, snapshot);
}
else {
language.scripts.delete(fileName);
}
}, targetFileName => {
// https://github.com/JetBrains/intellij-plugins/blob/6435723ad88fa296b41144162ebe3b8513f4949b/Angular/src-js/angular-service/src/ngCommands.ts#L88
info.session.change({
file: targetFileName,
line: 1,
offset: 1,
endLine: 1,
endOffset: 1,
insertString: '',
});
});
initializeProxiedLanguageService(language);
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost);
createPluginResult.setup?.(language);
}
const makeGetExternalFiles = (ts) => (project, updateLevel = 0) => {
if (updateLevel >= 1
|| !exports.externalFiles.has(project)) {
const oldFiles = exports.externalFiles.get(project);
const extensions = exports.projectExternalFileExtensions.get(project);
const newFiles = extensions?.length ? (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions) : [];
exports.externalFiles.set(project, newFiles);
if (oldFiles && !arrayItemsEqual(oldFiles, newFiles)) {
project.refreshDiagnostics();
}
}
return exports.externalFiles.get(project);
};
exports.makeGetExternalFiles = makeGetExternalFiles;
function arrayItemsEqual(a, b) {
if (a.length !== b.length) {
return false;
}
const set = new Set(a);
for (const file of b) {
if (!set.has(file)) {
return false;
}
}
return true;
}
function isHasAlreadyDecoratedLanguageService(info) {
if (exports.decoratedLanguageServices.has(info.languageService)
|| exports.decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
return true;
}
else {
exports.decoratedLanguageServices.add(info.languageService);
exports.decoratedLanguageServiceHosts.add(info.languageServiceHost);
return false;
}
}
//# sourceMappingURL=languageServicePluginCommon.js.map

View File

@@ -0,0 +1,22 @@
import type * as ts from 'typescript';
import type { Language, LanguagePlugin } from '@volar/language-core';
export declare let getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin<string>[] | {
languagePlugins: LanguagePlugin<string>[];
setup?(language: Language<string>): void;
};
export declare function runTsc(tscPath: string, options: string[] | {
extraSupportedExtensions: string[];
extraExtensionsToRemove: string[];
}, _getLanguagePlugins: typeof getLanguagePlugins, typescriptObject?: string): void;
/**
* Replaces the code of typescript to add support for additional extensions and language plugins.
*
* @param tsc - The original code of typescript.
* @param proxyApiPath - The path to the proxy API.
* @param extraSupportedExtensions - An array of additional supported extensions.
* @param extraExtensionsToRemove - An array of extensions to remove.
* @param getLanguagePluginsFile - The file to get language plugins from.
* @param typescriptObject - The object to use as typescript.
* @returns The modified typescript code.
*/
export declare function transformTscContent(tsc: string, proxyApiPath: string, extraSupportedExtensions: string[], extraExtensionsToRemove: string[], getLanguagePluginsFile?: string, typescriptObject?: string): string;

View File

@@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLanguagePlugins = void 0;
exports.runTsc = runTsc;
exports.transformTscContent = transformTscContent;
const fs = require("fs");
const path = require("path");
let getLanguagePlugins = () => [];
exports.getLanguagePlugins = getLanguagePlugins;
function runTsc(tscPath, options, _getLanguagePlugins, typescriptObject) {
exports.getLanguagePlugins = _getLanguagePlugins;
let extraSupportedExtensions;
let extraExtensionsToRemove;
if (Array.isArray(options)) {
extraSupportedExtensions = options;
extraExtensionsToRemove = [];
}
else {
extraSupportedExtensions = options.extraSupportedExtensions;
extraExtensionsToRemove = options.extraExtensionsToRemove;
}
const proxyApiPath = require.resolve('../node/proxyCreateProgram');
const readFileSync = fs.readFileSync;
fs.readFileSync = (...args) => {
if (args[0] === tscPath) {
let tsc = readFileSync(...args);
try {
return transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, __filename, typescriptObject);
}
catch {
// Support the tsc shim used in Typescript v5.7 and up
const requireRegex = /module\.exports\s*=\s*require\((?:"|')(?<path>\.\/\w+\.js)(?:"|')\)/;
const requirePath = requireRegex.exec(tsc)?.groups?.path;
if (requirePath) {
tsc = readFileSync(path.join(path.dirname(tscPath), requirePath), 'utf8');
return transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, __filename, typescriptObject);
}
else {
throw new Error('Failed to locate tsc module path from shim');
}
}
}
return readFileSync(...args);
};
try {
require(tscPath);
}
finally {
fs.readFileSync = readFileSync;
delete require.cache[tscPath];
}
}
/**
* Replaces the code of typescript to add support for additional extensions and language plugins.
*
* @param tsc - The original code of typescript.
* @param proxyApiPath - The path to the proxy API.
* @param extraSupportedExtensions - An array of additional supported extensions.
* @param extraExtensionsToRemove - An array of extensions to remove.
* @param getLanguagePluginsFile - The file to get language plugins from.
* @param typescriptObject - The object to use as typescript.
* @returns The modified typescript code.
*/
function transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, getLanguagePluginsFile = __filename, typescriptObject = `new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } )`) {
const neededPatchExtenstions = extraSupportedExtensions.filter(ext => !extraExtensionsToRemove.includes(ext));
// Add allow extensions
if (extraSupportedExtensions.length) {
const extsText = extraSupportedExtensions.map(ext => `"${ext}"`).join(', ');
tsc = replace(tsc, /supportedTSExtensions = .*(?=;)/, s => s + `.map((group, i) => i === 0 ? group.splice(0, 0, ${extsText}) && group : group)`);
tsc = replace(tsc, /supportedJSExtensions = .*(?=;)/, s => s + `.map((group, i) => i === 0 ? group.splice(0, 0, ${extsText}) && group : group)`);
tsc = replace(tsc, /allSupportedExtensions = .*(?=;)/, s => s + `.map((group, i) => i === 0 ? group.splice(0, 0, ${extsText}) && group : group)`);
}
// Use to emit basename.xxx to basename.d.ts instead of basename.xxx.d.ts
if (extraExtensionsToRemove.length) {
const extsText = extraExtensionsToRemove.map(ext => `"${ext}"`).join(', ');
tsc = replace(tsc, /extensionsToRemove = .*(?=;)/, s => s + `.concat([${extsText}])`);
}
// Support for basename.xxx to basename.xxx.d.ts
if (neededPatchExtenstions.length) {
const extsText = neededPatchExtenstions.map(ext => `"${ext}"`).join(', ');
tsc = replace(tsc, /function changeExtension\(/, s => `function changeExtension(path, newExtension) {
return [${extsText}].some(ext => path.endsWith(ext))
? path + newExtension
: _changeExtension(path, newExtension)
}\n` + s.replace('changeExtension', '_changeExtension'));
}
// proxy createProgram
tsc = replace(tsc, /function createProgram\(.+\) {/, s => `var createProgram = require(${JSON.stringify(proxyApiPath)}).proxyCreateProgram(`
+ [
typescriptObject,
`_createProgram`,
`require(${JSON.stringify(getLanguagePluginsFile)}).getLanguagePlugins`,
].join(', ')
+ `);\n`
+ s.replace('createProgram', '_createProgram'));
return tsc;
}
function replace(text, ...[search, replace]) {
const before = text;
text = text.replace(search, replace);
const after = text;
if (after === before) {
throw new Error('Failed to replace: ' + search);
}
return after;
}
//# sourceMappingURL=runTsc.js.map

View File

@@ -0,0 +1,3 @@
import type { LanguagePlugin, SourceScript } from '@volar/language-core';
import type * as ts from 'typescript';
export declare function createResolveModuleName<T>(ts: typeof import('typescript'), getFileSize: ((fileName: string) => number) | undefined, 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;

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createResolveModuleName = createResolveModuleName;
function createResolveModuleName(ts, getFileSize, host, languagePlugins, getSourceScript) {
const toSourceFileInfo = new Map();
const moduleResolutionHost = {
readFile: host.readFile.bind(host),
directoryExists: host.directoryExists?.bind(host),
realpath: host.realpath?.bind(host),
getCurrentDirectory: host.getCurrentDirectory?.bind(host),
getDirectories: host.getDirectories?.bind(host),
useCaseSensitiveFileNames: typeof host.useCaseSensitiveFileNames === 'function'
? host.useCaseSensitiveFileNames.bind(host)
: host.useCaseSensitiveFileNames,
fileExists(fileName) {
for (const { typescript } of languagePlugins) {
if (!typescript) {
continue;
}
for (const { extension } of typescript.extraFileExtensions) {
if (fileName.endsWith(`.d.${extension}.ts`)) {
const sourceFileName = fileName.slice(0, -`.d.${extension}.ts`.length) + `.${extension}`;
if (fileExists(sourceFileName)) {
const sourceScript = getSourceScript(sourceFileName);
if (sourceScript?.generated) {
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
if (serviceScript) {
const dtsPath = sourceFileName + '.d.ts';
if ((serviceScript.extension === '.js' || serviceScript.extension === '.jsx') && fileExists(dtsPath)) {
toSourceFileInfo.set(fileName, {
sourceFileName: dtsPath,
extension: '.ts',
});
}
else {
toSourceFileInfo.set(fileName, {
sourceFileName,
extension: serviceScript.extension,
});
}
return true;
}
}
}
}
}
if (typescript.resolveHiddenExtensions && fileName.endsWith(`.d.ts`)) {
for (const { extension } of typescript.extraFileExtensions) {
const sourceFileName = fileName.slice(0, -`.d.ts`.length) + `.${extension}`;
if (fileExists(sourceFileName)) {
const sourceScript = getSourceScript(sourceFileName);
if (sourceScript?.generated) {
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
if (serviceScript) {
toSourceFileInfo.set(fileName, {
sourceFileName,
extension: serviceScript.extension,
});
return true;
}
}
}
}
}
}
return host.fileExists(fileName);
},
};
return (moduleName, containingFile, compilerOptions, cache, redirectedReference, resolutionMode) => {
const result = ts.resolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, cache, redirectedReference, resolutionMode);
if (result.resolvedModule) {
const sourceFileInfo = toSourceFileInfo.get(result.resolvedModule.resolvedFileName);
if (sourceFileInfo) {
result.resolvedModule.resolvedFileName = sourceFileInfo.sourceFileName;
result.resolvedModule.extension = sourceFileInfo.extension;
}
}
toSourceFileInfo.clear();
return result;
};
// fix https://github.com/vuejs/language-tools/issues/3332
function fileExists(fileName) {
if (host.fileExists(fileName)) {
const fileSize = getFileSize?.(fileName) ?? host.readFile(fileName)?.length ?? 0;
return fileSize < 4 * 1024 * 1024;
}
return false;
}
}
//# sourceMappingURL=resolveModuleName.js.map

View File

@@ -0,0 +1,83 @@
import { Comparer, Comparison, SortedReadonlyArray } from "./corePublic";
/**
* Iterates through `array` by index and performs the callback on each element of array until the callback
* returns a falsey value, then returns false.
* If no such value is found, the callback is applied to each element of array and `true` is returned.
*/
export declare function every<T>(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean;
/** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */
export declare function findIndex<T>(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): number;
export declare function indexOfAnyCharCode(text: string, charCodes: readonly number[], start?: number): number;
export declare function map<T, U>(array: readonly T[], f: (x: T, i: number) => U): U[];
export declare function map<T, U>(array: readonly T[] | undefined, f: (x: T, i: number) => U): U[] | undefined;
/**
* Flattens an array containing a mix of array or non-array elements.
*
* @param array The array to flatten.
*/
export declare function flatten<T>(array: T[][] | readonly (T | readonly T[] | undefined)[]): T[];
/**
* Maps an array. If the mapped value is an array, it is spread into the result.
*
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
export declare function flatMap<T, U>(array: readonly T[] | undefined, mapfn: (x: T, i: number) => U | readonly U[] | undefined): readonly U[];
export declare function some<T>(array: readonly T[] | undefined): array is readonly T[];
export declare function some<T>(array: readonly T[] | undefined, predicate: (value: T) => boolean): boolean;
/**
* Returns a new sorted array.
*/
export declare function sort<T>(array: readonly T[], comparer?: Comparer<T>): SortedReadonlyArray<T>;
/**
* Returns the last element of an array if non-empty, `undefined` otherwise.
*/
export declare function lastOrUndefined<T>(array: readonly T[] | undefined): T | undefined;
export declare function last<T>(array: readonly T[]): T;
/**
* Compare the equality of two strings using a case-sensitive ordinal comparison.
*
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point after applying `toUpperCase` to each string. We always map both
* strings to their upper-case form as some unicode characters do not properly round-trip to
* lowercase (such as `ẞ` (German sharp capital s)).
*/
export declare function equateStringsCaseInsensitive(a: string, b: string): boolean;
/**
* Compare the equality of two strings using a case-sensitive ordinal comparison.
*
* Case-sensitive comparisons compare both strings one code-point at a time using the
* integer value of each code-point.
*/
export declare function equateStringsCaseSensitive(a: string, b: string): boolean;
/**
* Compare two strings using a case-insensitive ordinal comparison.
*
* Ordinal comparisons are based on the difference between the unicode code points of both
* strings. Characters with multiple unicode representations are considered unequal. Ordinal
* comparisons provide predictable ordering, but place "a" after "B".
*
* Case-insensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point after applying `toUpperCase` to each string. We always map both
* strings to their upper-case form as some unicode characters do not properly round-trip to
* lowercase (such as `ẞ` (German sharp capital s)).
*/
declare function compareStringsCaseInsensitive(a: string, b: string): Comparison;
/**
* Compare two strings using a case-sensitive ordinal comparison.
*
* Ordinal comparisons are based on the difference between the unicode code points of both
* strings. Characters with multiple unicode representations are considered unequal. Ordinal
* comparisons provide predictable ordering, but place "a" after "B".
*
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point.
*/
export declare function compareStringsCaseSensitive(a: string | undefined, b: string | undefined): Comparison;
export declare function getStringComparer(ignoreCase?: boolean): typeof compareStringsCaseInsensitive;
export declare function endsWith(str: string, suffix: string): boolean;
export declare function stringContains(str: string, substring: string): boolean;
type GetCanonicalFileName = (fileName: string) => string;
export declare function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): GetCanonicalFileName;
export declare function startsWith(str: string, prefix: string): boolean;
export {};

View File

@@ -0,0 +1,327 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.every = every;
exports.findIndex = findIndex;
exports.indexOfAnyCharCode = indexOfAnyCharCode;
exports.map = map;
exports.flatten = flatten;
exports.flatMap = flatMap;
exports.some = some;
exports.sort = sort;
exports.lastOrUndefined = lastOrUndefined;
exports.last = last;
exports.equateStringsCaseInsensitive = equateStringsCaseInsensitive;
exports.equateStringsCaseSensitive = equateStringsCaseSensitive;
exports.compareStringsCaseSensitive = compareStringsCaseSensitive;
exports.getStringComparer = getStringComparer;
exports.endsWith = endsWith;
exports.stringContains = stringContains;
exports.createGetCanonicalFileName = createGetCanonicalFileName;
exports.startsWith = startsWith;
const emptyArray = [];
/**
* Iterates through `array` by index and performs the callback on each element of array until the callback
* returns a falsey value, then returns false.
* If no such value is found, the callback is applied to each element of array and `true` is returned.
*/
function every(array, callback) {
if (array) {
for (let i = 0; i < array.length; i++) {
if (!callback(array[i], i)) {
return false;
}
}
}
return true;
}
/** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */
function findIndex(array, predicate, startIndex) {
if (array === undefined) {
return -1;
}
for (let i = startIndex ?? 0; i < array.length; i++) {
if (predicate(array[i], i)) {
return i;
}
}
return -1;
}
function contains(array, value, equalityComparer = equateValues) {
if (array) {
for (const v of array) {
if (equalityComparer(v, value)) {
return true;
}
}
}
return false;
}
function indexOfAnyCharCode(text, charCodes, start) {
for (let i = start || 0; i < text.length; i++) {
if (contains(charCodes, text.charCodeAt(i))) {
return i;
}
}
return -1;
}
function map(array, f) {
let result;
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
result.push(f(array[i], i));
}
}
return result;
}
/**
* Flattens an array containing a mix of array or non-array elements.
*
* @param array The array to flatten.
*/
function flatten(array) {
const result = [];
for (const v of array) {
if (v) {
if (isArray(v)) {
addRange(result, v);
}
else {
result.push(v);
}
}
}
return result;
}
/**
* Maps an array. If the mapped value is an array, it is spread into the result.
*
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
function flatMap(array, mapfn) {
let result;
if (array) {
for (let i = 0; i < array.length; i++) {
const v = mapfn(array[i], i);
if (v) {
if (isArray(v)) {
result = addRange(result, v);
}
else {
result = append(result, v);
}
}
}
}
return result || emptyArray;
}
function some(array, predicate) {
if (array) {
if (predicate) {
for (const v of array) {
if (predicate(v)) {
return true;
}
}
}
else {
return array.length > 0;
}
}
return false;
}
// function append<T>(to: T[] | undefined, value: T): T[];
// function append<T>(to: T[] | undefined, value: T | undefined): T[] | undefined;
// function append<T>(to: Push<T>, value: T | undefined): void;
function append(to, value) {
if (value === undefined) {
return to;
}
if (to === undefined) {
return [value];
}
to.push(value);
return to;
}
/**
* Gets the actual offset into an array for a relative offset. Negative offsets indicate a
* position offset from the end of the array.
*/
function toOffset(array, offset) {
return offset < 0 ? array.length + offset : offset;
}
function addRange(to, from, start, end) {
if (from === undefined || from.length === 0) {
return to;
}
if (to === undefined) {
return from.slice(start, end);
}
start = start === undefined ? 0 : toOffset(from, start);
end = end === undefined ? from.length : toOffset(from, end);
for (let i = start; i < end && i < from.length; i++) {
if (from[i] !== undefined) {
to.push(from[i]);
}
}
return to;
}
/**
* Returns a new sorted array.
*/
function sort(array, comparer) {
return (array.length === 0 ? array : array.slice().sort(comparer));
}
/**
* Returns the last element of an array if non-empty, `undefined` otherwise.
*/
function lastOrUndefined(array) {
return array === undefined || array.length === 0 ? undefined : array[array.length - 1];
}
function last(array) {
// Debug.assert(array.length !== 0);
return array[array.length - 1];
}
/**
* Tests whether a value is an array.
*/
function isArray(value) {
return Array.isArray ? Array.isArray(value) : value instanceof Array;
}
/** Returns its argument. */
function identity(x) {
return x;
}
/** Returns lower case string */
function toLowerCase(x) {
return x.toLowerCase();
}
// We convert the file names to lower case as key for file name on case insensitive file system
// While doing so we need to handle special characters (eg \u0130) to ensure that we dont convert
// it to lower case, fileName with its lowercase form can exist along side it.
// Handle special characters and make those case sensitive instead
//
// |-#--|-Unicode--|-Char code-|-Desc-------------------------------------------------------------------|
// | 1. | i | 105 | Ascii i |
// | 2. | I | 73 | Ascii I |
// |-------- Special characters ------------------------------------------------------------------------|
// | 3. | \u0130 | 304 | Upper case I with dot above |
// | 4. | i,\u0307 | 105,775 | i, followed by 775: Lower case of (3rd item) |
// | 5. | I,\u0307 | 73,775 | I, followed by 775: Upper case of (4th item), lower case is (4th item) |
// | 6. | \u0131 | 305 | Lower case i without dot, upper case is I (2nd item) |
// | 7. | \u00DF | 223 | Lower case sharp s |
//
// Because item 3 is special where in its lowercase character has its own
// upper case form we cant convert its case.
// Rest special characters are either already in lower case format or
// they have corresponding upper case character so they dont need special handling
//
// But to avoid having to do string building for most common cases, also ignore
// a-z, 0-9, \u0131, \u00DF, \, /, ., : and space
const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g;
/**
* Case insensitive file systems have descripencies in how they handle some characters (eg. turkish Upper case I with dot on top - \u0130)
* This function is used in places where we want to make file name as a key on these systems
* It is possible on mac to be able to refer to file name with I with dot on top as a fileName with its lower case form
* But on windows we cannot. Windows can have fileName with I with dot on top next to its lower case and they can not each be referred with the lowercase forms
* Technically we would want this function to be platform sepcific as well but
* our api has till now only taken caseSensitive as the only input and just for some characters we dont want to update API and ensure all customers use those api
* We could use upper case and we would still need to deal with the descripencies but
* we want to continue using lower case since in most cases filenames are lowercasewe and wont need any case changes and avoid having to store another string for the key
* So for this function purpose, we go ahead and assume character I with dot on top it as case sensitive since its very unlikely to use lower case form of that special character
*/
function toFileNameLowerCase(x) {
return fileNameLowerCaseRegExp.test(x) ?
x.replace(fileNameLowerCaseRegExp, toLowerCase) :
x;
}
function equateValues(a, b) {
return a === b;
}
/**
* Compare the equality of two strings using a case-sensitive ordinal comparison.
*
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point after applying `toUpperCase` to each string. We always map both
* strings to their upper-case form as some unicode characters do not properly round-trip to
* lowercase (such as `ẞ` (German sharp capital s)).
*/
function equateStringsCaseInsensitive(a, b) {
return a === b
|| a !== undefined
&& b !== undefined
&& a.toUpperCase() === b.toUpperCase();
}
/**
* Compare the equality of two strings using a case-sensitive ordinal comparison.
*
* Case-sensitive comparisons compare both strings one code-point at a time using the
* integer value of each code-point.
*/
function equateStringsCaseSensitive(a, b) {
return equateValues(a, b);
}
function compareComparableValues(a, b) {
return a === b ? 0 /* Comparison.EqualTo */ :
a === undefined ? -1 /* Comparison.LessThan */ :
b === undefined ? 1 /* Comparison.GreaterThan */ :
a < b ? -1 /* Comparison.LessThan */ :
1 /* Comparison.GreaterThan */;
}
/**
* Compare two strings using a case-insensitive ordinal comparison.
*
* Ordinal comparisons are based on the difference between the unicode code points of both
* strings. Characters with multiple unicode representations are considered unequal. Ordinal
* comparisons provide predictable ordering, but place "a" after "B".
*
* Case-insensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point after applying `toUpperCase` to each string. We always map both
* strings to their upper-case form as some unicode characters do not properly round-trip to
* lowercase (such as `ẞ` (German sharp capital s)).
*/
function compareStringsCaseInsensitive(a, b) {
if (a === b) {
return 0 /* Comparison.EqualTo */;
}
if (a === undefined) {
return -1 /* Comparison.LessThan */;
}
if (b === undefined) {
return 1 /* Comparison.GreaterThan */;
}
a = a.toUpperCase();
b = b.toUpperCase();
return a < b ? -1 /* Comparison.LessThan */ : a > b ? 1 /* Comparison.GreaterThan */ : 0 /* Comparison.EqualTo */;
}
/**
* Compare two strings using a case-sensitive ordinal comparison.
*
* Ordinal comparisons are based on the difference between the unicode code points of both
* strings. Characters with multiple unicode representations are considered unequal. Ordinal
* comparisons provide predictable ordering, but place "a" after "B".
*
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point.
*/
function compareStringsCaseSensitive(a, b) {
return compareComparableValues(a, b);
}
function getStringComparer(ignoreCase) {
return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
}
function endsWith(str, suffix) {
const expectedPos = str.length - suffix.length;
return expectedPos >= 0 && str.indexOf(suffix, expectedPos) === expectedPos;
}
function stringContains(str, substring) {
return str.indexOf(substring) !== -1;
}
function createGetCanonicalFileName(useCaseSensitiveFileNames) {
return useCaseSensitiveFileNames ? identity : toFileNameLowerCase;
}
function startsWith(str, prefix) {
return str.lastIndexOf(prefix, 0) === 0;
}
//# sourceMappingURL=core.js.map

View File

@@ -0,0 +1,91 @@
export declare const versionMajorMinor = "4.9";
/** The version of the TypeScript compiler release */
export declare const version: string;
/**
* Type of objects whose values are all of the same type.
* The `in` and `for-in` operators can *not* be safely used,
* since `Object.prototype` may be modified by outside code.
*/
export interface MapLike<T> {
[index: string]: T;
}
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
" __sortedArrayBrand": any;
}
export interface SortedArray<T> extends Array<T> {
" __sortedArrayBrand": any;
}
/** Common read methods for ES6 Map/Set. */
export interface ReadonlyCollection<K> {
readonly size: number;
has(key: K): boolean;
keys(): Iterator<K>;
}
/** Common write methods for ES6 Map/Set. */
export interface Collection<K> extends ReadonlyCollection<K> {
delete(key: K): boolean;
clear(): void;
}
/** ES6 Map interface, only read methods included. */
export interface ReadonlyESMap<K, V> extends ReadonlyCollection<K> {
get(key: K): V | undefined;
values(): Iterator<V>;
entries(): Iterator<[K, V]>;
forEach(action: (value: V, key: K) => void): void;
}
/**
* ES6 Map interface, only read methods included.
*/
export interface ReadonlyMap<T> extends ReadonlyESMap<string, T> {
}
/** ES6 Map interface. */
export interface ESMap<K, V> extends ReadonlyESMap<K, V>, Collection<K> {
set(key: K, value: V): this;
}
/**
* ES6 Map interface.
*/
export interface Map<T> extends ESMap<string, T> {
}
export interface MapConstructor {
new <K, V>(iterable?: readonly (readonly [K, V])[] | ReadonlyESMap<K, V>): ESMap<K, V>;
}
/** ES6 Set interface, only read methods included. */
export interface ReadonlySet<T> extends ReadonlyCollection<T> {
has(value: T): boolean;
values(): Iterator<T>;
entries(): Iterator<[T, T]>;
forEach(action: (value: T, key: T) => void): void;
}
/** ES6 Set interface. */
export interface Set<T> extends ReadonlySet<T>, Collection<T> {
add(value: T): this;
delete(value: T): boolean;
}
export interface SetConstructor {
new <T>(iterable?: readonly T[] | ReadonlySet<T>): Set<T>;
}
/** ES6 Iterator type. */
export interface Iterator<T> {
next(): {
value: T;
done?: false;
} | {
value: void;
done: true;
};
}
/** Array that is only intended to be pushed to, never read. */
export interface Push<T> {
push(...values: T[]): void;
readonly length: number;
}
export type EqualityComparer<T> = (a: T, b: T) => boolean;
export type Comparer<T> = (a: T, b: T) => Comparison;
export declare const enum Comparison {
LessThan = -1,
EqualTo = 0,
GreaterThan = 1
}
export declare const Map: MapConstructor;
export declare const Set: SetConstructor;

View File

@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Set = exports.Map = exports.version = exports.versionMajorMinor = void 0;
// WARNING: The script `configurePrerelease.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configurePrerelease` too.
exports.versionMajorMinor = "4.9";
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
exports.version = `${exports.versionMajorMinor}.0-dev`;
/* @internal */
var NativeCollections;
(function (NativeCollections) {
const globals = typeof globalThis !== "undefined" ? globalThis :
// @ts-ignore node global
typeof global !== "undefined" ? global :
typeof self !== "undefined" ? self :
undefined;
/**
* Returns the native Map implementation if it is available and compatible (i.e. supports iteration).
*/
function tryGetNativeMap() {
// Internet Explorer's Map doesn't support iteration, so don't use it.
const gMap = globals?.Map;
// eslint-disable-next-line local/no-in-operator
const constructor = typeof gMap !== "undefined" && "entries" in gMap.prototype && new gMap([[0, 0]]).size === 1 ? gMap : undefined;
if (!constructor) {
throw new Error("No compatible Map implementation found.");
}
return constructor;
}
NativeCollections.tryGetNativeMap = tryGetNativeMap;
/**
* Returns the native Set implementation if it is available and compatible (i.e. supports iteration).
*/
function tryGetNativeSet() {
// Internet Explorer's Set doesn't support iteration, so don't use it.
const gSet = globals?.Set;
// eslint-disable-next-line local/no-in-operator
const constructor = typeof gSet !== "undefined" && "entries" in gSet.prototype && new gSet([0]).size === 1 ? gSet : undefined;
if (!constructor) {
throw new Error("No compatible Set implementation found.");
}
return constructor;
}
NativeCollections.tryGetNativeSet = tryGetNativeSet;
})(NativeCollections || (NativeCollections = {}));
/* @internal */
exports.Map = NativeCollections.tryGetNativeMap();
/* @internal */
exports.Set = NativeCollections.tryGetNativeSet();
//# sourceMappingURL=corePublic.js.map

View File

@@ -0,0 +1,112 @@
import { Path } from "./types";
/**
* Internally, we represent paths as strings with '/' as the directory separator.
* When we make system calls (eg: LanguageServiceHost.getDirectory()),
* we expect the host to correctly handle paths in our specified format.
*/
export declare const directorySeparator = "/";
/**
* Determines whether a path is an absolute disk path (e.g. starts with `/`, or a dos path
* like `c:`, `c:\` or `c:/`).
*/
export declare function isRootedDiskPath(path: string): boolean;
export declare function hasExtension(fileName: string): boolean;
export declare function fileExtensionIsOneOf(path: string, extensions: readonly string[]): boolean;
/**
* Returns the path except for its basename. Semantics align with NodeJS's `path.dirname`
* except that we support URLs as well.
*
* ```ts
* // POSIX
* getDirectoryPath("/path/to/file.ext") === "/path/to"
* getDirectoryPath("/path/to/") === "/path"
* getDirectoryPath("/") === "/"
* // DOS
* getDirectoryPath("c:/path/to/file.ext") === "c:/path/to"
* getDirectoryPath("c:/path/to/") === "c:/path"
* getDirectoryPath("c:/") === "c:/"
* getDirectoryPath("c:") === "c:"
* // URL
* getDirectoryPath("http://typescriptlang.org/path/to/file.ext") === "http://typescriptlang.org/path/to"
* getDirectoryPath("http://typescriptlang.org/path/to") === "http://typescriptlang.org/path"
* getDirectoryPath("http://typescriptlang.org/") === "http://typescriptlang.org/"
* getDirectoryPath("http://typescriptlang.org") === "http://typescriptlang.org"
* ```
*/
export declare function getDirectoryPath(path: Path): Path;
/**
* Returns the path except for its basename. Semantics align with NodeJS's `path.dirname`
* except that we support URLs as well.
*
* ```ts
* // POSIX
* getDirectoryPath("/path/to/file.ext") === "/path/to"
* getDirectoryPath("/path/to/") === "/path"
* getDirectoryPath("/") === "/"
* // DOS
* getDirectoryPath("c:/path/to/file.ext") === "c:/path/to"
* getDirectoryPath("c:/path/to/") === "c:/path"
* getDirectoryPath("c:/") === "c:/"
* getDirectoryPath("c:") === "c:"
* // URL
* getDirectoryPath("http://typescriptlang.org/path/to/file.ext") === "http://typescriptlang.org/path/to"
* getDirectoryPath("http://typescriptlang.org/path/to") === "http://typescriptlang.org/path"
* getDirectoryPath("http://typescriptlang.org/") === "http://typescriptlang.org/"
* getDirectoryPath("http://typescriptlang.org") === "http://typescriptlang.org"
* getDirectoryPath("file://server/path/to/file.ext") === "file://server/path/to"
* getDirectoryPath("file://server/path/to") === "file://server/path"
* getDirectoryPath("file://server/") === "file://server/"
* getDirectoryPath("file://server") === "file://server"
* getDirectoryPath("file:///path/to/file.ext") === "file:///path/to"
* getDirectoryPath("file:///path/to") === "file:///path"
* getDirectoryPath("file:///") === "file:///"
* getDirectoryPath("file://") === "file://"
* ```
*/
export declare function getDirectoryPath(path: string): string;
/**
* Combines paths. If a path is absolute, it replaces any previous path. Relative paths are not simplified.
*
* ```ts
* // Non-rooted
* combinePaths("path", "to", "file.ext") === "path/to/file.ext"
* combinePaths("path", "dir", "..", "to", "file.ext") === "path/dir/../to/file.ext"
* // POSIX
* combinePaths("/path", "to", "file.ext") === "/path/to/file.ext"
* combinePaths("/path", "/to", "file.ext") === "/to/file.ext"
* // DOS
* combinePaths("c:/path", "to", "file.ext") === "c:/path/to/file.ext"
* combinePaths("c:/path", "c:/to", "file.ext") === "c:/to/file.ext"
* // URL
* combinePaths("file:///path", "to", "file.ext") === "file:///path/to/file.ext"
* combinePaths("file:///path", "file:///to", "file.ext") === "file:///to/file.ext"
* ```
*/
export declare function combinePaths(path: string, ...paths: (string | undefined)[]): string;
/**
* Parse a path into an array containing a root component (at index 0) and zero or more path
* components (at indices > 0). The result is normalized.
* If the path is relative, the root component is `""`.
* If the path is absolute, the root component includes the first path separator (`/`).
*
* ```ts
* getNormalizedPathComponents("to/dir/../file.ext", "/path/") === ["/", "path", "to", "file.ext"]
* ```
*/
export declare function getNormalizedPathComponents(path: string, currentDirectory: string | undefined): string[];
export declare function normalizePath(path: string): string;
/**
* Removes a trailing directory separator from a path, if it does not already have one.
*
* ```ts
* removeTrailingDirectorySeparator("/path/to/file.ext") === "/path/to/file.ext"
* removeTrailingDirectorySeparator("/path/to/file.ext/") === "/path/to/file.ext"
* ```
*/
export declare function removeTrailingDirectorySeparator(path: Path): Path;
export declare function removeTrailingDirectorySeparator(path: string): string;
/**
* Determines whether a `parent` path contains a `child` path using the provide case sensitivity.
*/
export declare function containsPath(parent: string, child: string, ignoreCase?: boolean): boolean;
export declare function containsPath(parent: string, child: string, currentDirectory: string, ignoreCase?: boolean): boolean;

View File

@@ -0,0 +1,438 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.directorySeparator = void 0;
exports.isRootedDiskPath = isRootedDiskPath;
exports.hasExtension = hasExtension;
exports.fileExtensionIsOneOf = fileExtensionIsOneOf;
exports.getDirectoryPath = getDirectoryPath;
exports.combinePaths = combinePaths;
exports.getNormalizedPathComponents = getNormalizedPathComponents;
exports.normalizePath = normalizePath;
exports.removeTrailingDirectorySeparator = removeTrailingDirectorySeparator;
exports.containsPath = containsPath;
const core_1 = require("./core");
/**
* Internally, we represent paths as strings with '/' as the directory separator.
* When we make system calls (eg: LanguageServiceHost.getDirectory()),
* we expect the host to correctly handle paths in our specified format.
*/
exports.directorySeparator = "/";
const altDirectorySeparator = "\\";
const urlSchemeSeparator = "://";
const backslashRegExp = /\\/g;
//// Path Tests
/**
* Determines whether a charCode corresponds to `/` or `\`.
*/
function isAnyDirectorySeparator(charCode) {
return charCode === 47 /* CharacterCodes.slash */ || charCode === 92 /* CharacterCodes.backslash */;
}
/**
* Determines whether a path is an absolute disk path (e.g. starts with `/`, or a dos path
* like `c:`, `c:\` or `c:/`).
*/
function isRootedDiskPath(path) {
return getEncodedRootLength(path) > 0;
}
function hasExtension(fileName) {
return (0, core_1.stringContains)(getBaseFileName(fileName), ".");
}
function fileExtensionIs(path, extension) {
return path.length > extension.length && (0, core_1.endsWith)(path, extension);
}
function fileExtensionIsOneOf(path, extensions) {
for (const extension of extensions) {
if (fileExtensionIs(path, extension)) {
return true;
}
}
return false;
}
/**
* Determines whether a path has a trailing separator (`/` or `\\`).
*/
function hasTrailingDirectorySeparator(path) {
return path.length > 0 && isAnyDirectorySeparator(path.charCodeAt(path.length - 1));
}
//// Path Parsing
function isVolumeCharacter(charCode) {
return (charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
(charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */);
}
function getFileUrlVolumeSeparatorEnd(url, start) {
const ch0 = url.charCodeAt(start);
if (ch0 === 58 /* CharacterCodes.colon */) {
return start + 1;
}
if (ch0 === 37 /* CharacterCodes.percent */ && url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
const ch2 = url.charCodeAt(start + 2);
if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */) {
return start + 3;
}
}
return -1;
}
/**
* Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files").
* If the root is part of a URL, the twos-complement of the root length is returned.
*/
function getEncodedRootLength(path) {
if (!path) {
return 0;
}
const ch0 = path.charCodeAt(0);
// POSIX or UNC
if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
if (path.charCodeAt(1) !== ch0) {
return 1; // POSIX: "/" (or non-normalized "\")
}
const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? exports.directorySeparator : altDirectorySeparator, 2);
if (p1 < 0) {
return path.length; // UNC: "//server" or "\\server"
}
return p1 + 1; // UNC: "//server/" or "\\server\"
}
// DOS
if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
const ch2 = path.charCodeAt(2);
if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */) {
return 3; // DOS: "c:/" or "c:\"
}
if (path.length === 2) {
return 2; // DOS: "c:" (but not "c:d")
}
}
// URL
const schemeEnd = path.indexOf(urlSchemeSeparator);
if (schemeEnd !== -1) {
const authorityStart = schemeEnd + urlSchemeSeparator.length;
const authorityEnd = path.indexOf(exports.directorySeparator, authorityStart);
if (authorityEnd !== -1) { // URL: "file:///", "file://server/", "file://server/path"
// For local "file" URLs, include the leading DOS volume (if present).
// Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
// special case interpreted as "the machine from which the URL is being interpreted".
const scheme = path.slice(0, schemeEnd);
const authority = path.slice(authorityStart, authorityEnd);
if (scheme === "file" && (authority === "" || authority === "localhost") &&
isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
if (volumeSeparatorEnd !== -1) {
if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
// URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
return ~(volumeSeparatorEnd + 1);
}
if (volumeSeparatorEnd === path.length) {
// URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
// but not "file:///c:d" or "file:///c%3ad"
return ~volumeSeparatorEnd;
}
}
}
return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
}
return ~path.length; // URL: "file://server", "http://server"
}
// relative
return 0;
}
/**
* Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files").
*
* For example:
* ```ts
* getRootLength("a") === 0 // ""
* getRootLength("/") === 1 // "/"
* getRootLength("c:") === 2 // "c:"
* getRootLength("c:d") === 0 // ""
* getRootLength("c:/") === 3 // "c:/"
* getRootLength("c:\\") === 3 // "c:\\"
* getRootLength("//server") === 7 // "//server"
* getRootLength("//server/share") === 8 // "//server/"
* getRootLength("\\\\server") === 7 // "\\\\server"
* getRootLength("\\\\server\\share") === 8 // "\\\\server\\"
* getRootLength("file:///path") === 8 // "file:///"
* getRootLength("file:///c:") === 10 // "file:///c:"
* getRootLength("file:///c:d") === 8 // "file:///"
* getRootLength("file:///c:/path") === 11 // "file:///c:/"
* getRootLength("file://server") === 13 // "file://server"
* getRootLength("file://server/path") === 14 // "file://server/"
* getRootLength("http://server") === 13 // "http://server"
* getRootLength("http://server/path") === 14 // "http://server/"
* ```
*/
function getRootLength(path) {
const rootLength = getEncodedRootLength(path);
return rootLength < 0 ? ~rootLength : rootLength;
}
function getDirectoryPath(path) {
path = normalizeSlashes(path);
// If the path provided is itself the root, then return it.
const rootLength = getRootLength(path);
if (rootLength === path.length) {
return path;
}
// return the leading portion of the path up to the last (non-terminal) directory separator
// but not including any trailing directory separator.
path = removeTrailingDirectorySeparator(path);
return path.slice(0, Math.max(rootLength, path.lastIndexOf(exports.directorySeparator)));
}
function getBaseFileName(path, extensions, ignoreCase) {
path = normalizeSlashes(path);
// if the path provided is itself the root, then it has not file name.
const rootLength = getRootLength(path);
if (rootLength === path.length) {
return "";
}
// return the trailing portion of the path starting after the last (non-terminal) directory
// separator but not including any trailing directory separator.
path = removeTrailingDirectorySeparator(path);
const name = path.slice(Math.max(getRootLength(path), path.lastIndexOf(exports.directorySeparator) + 1));
const extension = extensions !== undefined && ignoreCase !== undefined ? getAnyExtensionFromPath(name, extensions, ignoreCase) : undefined;
return extension ? name.slice(0, name.length - extension.length) : name;
}
function tryGetExtensionFromPath(path, extension, stringEqualityComparer) {
if (!(0, core_1.startsWith)(extension, ".")) {
extension = "." + extension;
}
if (path.length >= extension.length && path.charCodeAt(path.length - extension.length) === 46 /* CharacterCodes.dot */) {
const pathExtension = path.slice(path.length - extension.length);
if (stringEqualityComparer(pathExtension, extension)) {
return pathExtension;
}
}
}
function getAnyExtensionFromPathWorker(path, extensions, stringEqualityComparer) {
if (typeof extensions === "string") {
return tryGetExtensionFromPath(path, extensions, stringEqualityComparer) || "";
}
for (const extension of extensions) {
const result = tryGetExtensionFromPath(path, extension, stringEqualityComparer);
if (result) {
return result;
}
}
return "";
}
function getAnyExtensionFromPath(path, extensions, ignoreCase) {
// Retrieves any string from the final "." onwards from a base file name.
// Unlike extensionFromPath, which throws an exception on unrecognized extensions.
if (extensions) {
return getAnyExtensionFromPathWorker(removeTrailingDirectorySeparator(path), extensions, ignoreCase ? core_1.equateStringsCaseInsensitive : core_1.equateStringsCaseSensitive);
}
const baseFileName = getBaseFileName(path);
const extensionIndex = baseFileName.lastIndexOf(".");
if (extensionIndex >= 0) {
return baseFileName.substring(extensionIndex);
}
return "";
}
function pathComponents(path, rootLength) {
const root = path.substring(0, rootLength);
const rest = path.substring(rootLength).split(exports.directorySeparator);
if (rest.length && !(0, core_1.lastOrUndefined)(rest)) {
rest.pop();
}
return [root, ...rest];
}
/**
* Parse a path into an array containing a root component (at index 0) and zero or more path
* components (at indices > 0). The result is not normalized.
* If the path is relative, the root component is `""`.
* If the path is absolute, the root component includes the first path separator (`/`).
*
* ```ts
* // POSIX
* getPathComponents("/path/to/file.ext") === ["/", "path", "to", "file.ext"]
* getPathComponents("/path/to/") === ["/", "path", "to"]
* getPathComponents("/") === ["/"]
* // DOS
* getPathComponents("c:/path/to/file.ext") === ["c:/", "path", "to", "file.ext"]
* getPathComponents("c:/path/to/") === ["c:/", "path", "to"]
* getPathComponents("c:/") === ["c:/"]
* getPathComponents("c:") === ["c:"]
* // URL
* getPathComponents("http://typescriptlang.org/path/to/file.ext") === ["http://typescriptlang.org/", "path", "to", "file.ext"]
* getPathComponents("http://typescriptlang.org/path/to/") === ["http://typescriptlang.org/", "path", "to"]
* getPathComponents("http://typescriptlang.org/") === ["http://typescriptlang.org/"]
* getPathComponents("http://typescriptlang.org") === ["http://typescriptlang.org"]
* getPathComponents("file://server/path/to/file.ext") === ["file://server/", "path", "to", "file.ext"]
* getPathComponents("file://server/path/to/") === ["file://server/", "path", "to"]
* getPathComponents("file://server/") === ["file://server/"]
* getPathComponents("file://server") === ["file://server"]
* getPathComponents("file:///path/to/file.ext") === ["file:///", "path", "to", "file.ext"]
* getPathComponents("file:///path/to/") === ["file:///", "path", "to"]
* getPathComponents("file:///") === ["file:///"]
* getPathComponents("file://") === ["file://"]
*/
function getPathComponents(path, currentDirectory = "") {
path = combinePaths(currentDirectory, path);
return pathComponents(path, getRootLength(path));
}
//// Path Formatting
/**
* Formats a parsed path consisting of a root component (at index 0) and zero or more path
* segments (at indices > 0).
*
* ```ts
* getPathFromPathComponents(["/", "path", "to", "file.ext"]) === "/path/to/file.ext"
* ```
*/
function getPathFromPathComponents(pathComponents) {
if (pathComponents.length === 0) {
return "";
}
const root = pathComponents[0] && ensureTrailingDirectorySeparator(pathComponents[0]);
return root + pathComponents.slice(1).join(exports.directorySeparator);
}
//// Path Normalization
/**
* Normalize path separators, converting `\` into `/`.
*/
function normalizeSlashes(path) {
return path.indexOf("\\") !== -1
? path.replace(backslashRegExp, exports.directorySeparator)
: path;
}
/**
* Reduce an array of path components to a more simplified path by navigating any
* `"."` or `".."` entries in the path.
*/
function reducePathComponents(components) {
if (!(0, core_1.some)(components)) {
return [];
}
const reduced = [components[0]];
for (let i = 1; i < components.length; i++) {
const component = components[i];
if (!component) {
continue;
}
if (component === ".") {
continue;
}
if (component === "..") {
if (reduced.length > 1) {
if (reduced[reduced.length - 1] !== "..") {
reduced.pop();
continue;
}
}
else if (reduced[0]) {
continue;
}
}
reduced.push(component);
}
return reduced;
}
/**
* Combines paths. If a path is absolute, it replaces any previous path. Relative paths are not simplified.
*
* ```ts
* // Non-rooted
* combinePaths("path", "to", "file.ext") === "path/to/file.ext"
* combinePaths("path", "dir", "..", "to", "file.ext") === "path/dir/../to/file.ext"
* // POSIX
* combinePaths("/path", "to", "file.ext") === "/path/to/file.ext"
* combinePaths("/path", "/to", "file.ext") === "/to/file.ext"
* // DOS
* combinePaths("c:/path", "to", "file.ext") === "c:/path/to/file.ext"
* combinePaths("c:/path", "c:/to", "file.ext") === "c:/to/file.ext"
* // URL
* combinePaths("file:///path", "to", "file.ext") === "file:///path/to/file.ext"
* combinePaths("file:///path", "file:///to", "file.ext") === "file:///to/file.ext"
* ```
*/
function combinePaths(path, ...paths) {
if (path) {
path = normalizeSlashes(path);
}
for (let relativePath of paths) {
if (!relativePath) {
continue;
}
relativePath = normalizeSlashes(relativePath);
if (!path || getRootLength(relativePath) !== 0) {
path = relativePath;
}
else {
path = ensureTrailingDirectorySeparator(path) + relativePath;
}
}
return path;
}
/**
* Parse a path into an array containing a root component (at index 0) and zero or more path
* components (at indices > 0). The result is normalized.
* If the path is relative, the root component is `""`.
* If the path is absolute, the root component includes the first path separator (`/`).
*
* ```ts
* getNormalizedPathComponents("to/dir/../file.ext", "/path/") === ["/", "path", "to", "file.ext"]
* ```
*/
function getNormalizedPathComponents(path, currentDirectory) {
return reducePathComponents(getPathComponents(path, currentDirectory));
}
function normalizePath(path) {
path = normalizeSlashes(path);
// Most paths don't require normalization
if (!relativePathSegmentRegExp.test(path)) {
return path;
}
// Some paths only require cleanup of `/./` or leading `./`
const simplified = path.replace(/\/\.\//g, "/").replace(/^\.\//, "");
if (simplified !== path) {
path = simplified;
if (!relativePathSegmentRegExp.test(path)) {
return path;
}
}
// Other paths require full normalization
const normalized = getPathFromPathComponents(reducePathComponents(getPathComponents(path)));
return normalized && hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalized) : normalized;
}
function removeTrailingDirectorySeparator(path) {
if (hasTrailingDirectorySeparator(path)) {
return path.substr(0, path.length - 1);
}
return path;
}
function ensureTrailingDirectorySeparator(path) {
if (!hasTrailingDirectorySeparator(path)) {
return path + exports.directorySeparator;
}
return path;
}
//// Path Comparisons
// check path for these segments: '', '.'. '..'
const relativePathSegmentRegExp = /(?:\/\/)|(?:^|\/)\.\.?(?:$|\/)/;
function containsPath(parent, child, currentDirectory, ignoreCase) {
if (typeof currentDirectory === "string") {
parent = combinePaths(currentDirectory, parent);
child = combinePaths(currentDirectory, child);
}
else if (typeof currentDirectory === "boolean") {
ignoreCase = currentDirectory;
}
if (parent === undefined || child === undefined) {
return false;
}
if (parent === child) {
return true;
}
const parentComponents = reducePathComponents(getPathComponents(parent));
const childComponents = reducePathComponents(getPathComponents(child));
if (childComponents.length < parentComponents.length) {
return false;
}
const componentEqualityComparer = ignoreCase ? core_1.equateStringsCaseInsensitive : core_1.equateStringsCaseSensitive;
for (let i = 0; i < parentComponents.length; i++) {
const equalityComparer = i === 0 ? core_1.equateStringsCaseInsensitive : componentEqualityComparer;
if (!equalityComparer(parentComponents[i], childComponents[i])) {
return false;
}
}
return true;
}
//# sourceMappingURL=path.js.map

View File

@@ -0,0 +1,129 @@
export type Path = string & {
__pathBrand: any;
};
export declare const enum CharacterCodes {
nullCharacter = 0,
maxAsciiCharacter = 127,
lineFeed = 10,// \n
carriageReturn = 13,// \r
lineSeparator = 8232,
paragraphSeparator = 8233,
nextLine = 133,
space = 32,// " "
nonBreakingSpace = 160,//
enQuad = 8192,
emQuad = 8193,
enSpace = 8194,
emSpace = 8195,
threePerEmSpace = 8196,
fourPerEmSpace = 8197,
sixPerEmSpace = 8198,
figureSpace = 8199,
punctuationSpace = 8200,
thinSpace = 8201,
hairSpace = 8202,
zeroWidthSpace = 8203,
narrowNoBreakSpace = 8239,
ideographicSpace = 12288,
mathematicalSpace = 8287,
ogham = 5760,
_ = 95,
$ = 36,
_0 = 48,
_1 = 49,
_2 = 50,
_3 = 51,
_4 = 52,
_5 = 53,
_6 = 54,
_7 = 55,
_8 = 56,
_9 = 57,
a = 97,
b = 98,
c = 99,
d = 100,
e = 101,
f = 102,
g = 103,
h = 104,
i = 105,
j = 106,
k = 107,
l = 108,
m = 109,
n = 110,
o = 111,
p = 112,
q = 113,
r = 114,
s = 115,
t = 116,
u = 117,
v = 118,
w = 119,
x = 120,
y = 121,
z = 122,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
ampersand = 38,// &
asterisk = 42,// *
at = 64,// @
backslash = 92,// \
backtick = 96,// `
bar = 124,// |
caret = 94,// ^
closeBrace = 125,// }
closeBracket = 93,// ]
closeParen = 41,// )
colon = 58,// :
comma = 44,// ,
dot = 46,// .
doubleQuote = 34,// "
equals = 61,// =
exclamation = 33,// !
greaterThan = 62,// >
hash = 35,// #
lessThan = 60,// <
minus = 45,// -
openBrace = 123,// {
openBracket = 91,// [
openParen = 40,// (
percent = 37,// %
plus = 43,// +
question = 63,// ?
semicolon = 59,// ;
singleQuote = 39,// '
slash = 47,// /
tilde = 126,// ~
backspace = 8,// \b
formFeed = 12,// \f
byteOrderMark = 65279,
tab = 9,// \t
verticalTab = 11
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1,7 @@
interface FileSystemEntries {
readonly files: readonly string[];
readonly directories: readonly string[];
}
/** @param path directory of the tsconfig.json */
export declare function matchFiles(path: string, extensions: readonly string[] | undefined, excludes: readonly string[] | undefined, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries, realpath: (path: string) => string): string[];
export {};

View File

@@ -0,0 +1,252 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.matchFiles = matchFiles;
const core_1 = require("./core");
const path_1 = require("./path");
// KLUDGE: Don't assume one 'node_modules' links to another. More likely a single directory inside the node_modules is the symlink.
// ALso, don't assume that an `@foo` directory is linked. More likely the contents of that are linked.
// Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
// It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future
// proof.
const reservedCharacterPattern = /[^\w\s\/]/g;
const wildcardCharCodes = [42 /* CharacterCodes.asterisk */, 63 /* CharacterCodes.question */];
const commonPackageFolders = ["node_modules", "bower_components", "jspm_packages"];
const implicitExcludePathRegexPattern = `(?!(${commonPackageFolders.join("|")})(/|$))`;
const filesMatcher = {
/**
* Matches any single directory segment unless it is the last segment and a .min.js file
* Breakdown:
* [^./] # matches everything up to the first . character (excluding directory separators)
* (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension
*/
singleAsteriskRegexFragment: "([^./]|(\\.(?!min\\.js$))?)*",
/**
* Regex for the ** wildcard. Matches any number of subdirectories. When used for including
* files or directories, does not match subdirectories that start with a . character
*/
doubleAsteriskRegexFragment: `(/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`,
replaceWildcardCharacter: match => replaceWildcardCharacter(match, filesMatcher.singleAsteriskRegexFragment)
};
const directoriesMatcher = {
singleAsteriskRegexFragment: "[^/]*",
/**
* Regex for the ** wildcard. Matches any number of subdirectories. When used for including
* files or directories, does not match subdirectories that start with a . character
*/
doubleAsteriskRegexFragment: `(/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`,
replaceWildcardCharacter: match => replaceWildcardCharacter(match, directoriesMatcher.singleAsteriskRegexFragment)
};
const excludeMatcher = {
singleAsteriskRegexFragment: "[^/]*",
doubleAsteriskRegexFragment: "(/.+?)?",
replaceWildcardCharacter: match => replaceWildcardCharacter(match, excludeMatcher.singleAsteriskRegexFragment)
};
const wildcardMatchers = {
files: filesMatcher,
directories: directoriesMatcher,
exclude: excludeMatcher
};
function getRegularExpressionForWildcard(specs, basePath, usage) {
const patterns = getRegularExpressionsForWildcards(specs, basePath, usage);
if (!patterns || !patterns.length) {
return undefined;
}
const pattern = patterns.map(pattern => `(${pattern})`).join("|");
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
const terminator = usage === "exclude" ? "($|/)" : "$";
return `^(${pattern})${terminator}`;
}
function getRegularExpressionsForWildcards(specs, basePath, usage) {
if (specs === undefined || specs.length === 0) {
return undefined;
}
return (0, core_1.flatMap)(specs, spec => spec && getSubPatternFromSpec(spec, basePath, usage, wildcardMatchers[usage]));
}
/**
* An "includes" path "foo" is implicitly a glob "foo/** /*" (without the space) if its last component has no extension,
* and does not contain any glob characters itself.
*/
function isImplicitGlob(lastPathComponent) {
return !/[.*?]/.test(lastPathComponent);
}
function getSubPatternFromSpec(spec, basePath, usage, { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter }) {
let subpattern = "";
let hasWrittenComponent = false;
const components = (0, path_1.getNormalizedPathComponents)(spec, basePath);
const lastComponent = (0, core_1.last)(components);
if (usage !== "exclude" && lastComponent === "**") {
return undefined;
}
// getNormalizedPathComponents includes the separator for the root component.
// We need to remove to create our regex correctly.
components[0] = (0, path_1.removeTrailingDirectorySeparator)(components[0]);
if (isImplicitGlob(lastComponent)) {
components.push("**", "*");
}
let optionalCount = 0;
for (let component of components) {
if (component === "**") {
subpattern += doubleAsteriskRegexFragment;
}
else {
if (usage === "directories") {
subpattern += "(";
optionalCount++;
}
if (hasWrittenComponent) {
subpattern += path_1.directorySeparator;
}
if (usage !== "exclude") {
let componentPattern = "";
// The * and ? wildcards should not match directories or files that start with . if they
// appear first in a component. Dotted directories and files can be included explicitly
// like so: **/.*/.*
if (component.charCodeAt(0) === 42 /* CharacterCodes.asterisk */) {
componentPattern += "([^./]" + singleAsteriskRegexFragment + ")?";
component = component.substr(1);
}
else if (component.charCodeAt(0) === 63 /* CharacterCodes.question */) {
componentPattern += "[^./]";
component = component.substr(1);
}
componentPattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
// Patterns should not include subfolders like node_modules unless they are
// explicitly included as part of the path.
//
// As an optimization, if the component pattern is the same as the component,
// then there definitely were no wildcard characters and we do not need to
// add the exclusion pattern.
if (componentPattern !== component) {
subpattern += implicitExcludePathRegexPattern;
}
subpattern += componentPattern;
}
else {
subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
}
}
hasWrittenComponent = true;
}
while (optionalCount > 0) {
subpattern += ")?";
optionalCount--;
}
return subpattern;
}
function replaceWildcardCharacter(match, singleAsteriskRegexFragment) {
return match === "*" ? singleAsteriskRegexFragment : match === "?" ? "[^/]" : "\\" + match;
}
/** @param path directory of the tsconfig.json */
function getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory) {
path = (0, path_1.normalizePath)(path);
currentDirectory = (0, path_1.normalizePath)(currentDirectory);
const absolutePath = (0, path_1.combinePaths)(currentDirectory, path);
return {
includeFilePatterns: (0, core_1.map)(getRegularExpressionsForWildcards(includes, absolutePath, "files"), pattern => `^${pattern}$`),
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
basePaths: getBasePaths(path, includes, useCaseSensitiveFileNames)
};
}
function getRegexFromPattern(pattern, useCaseSensitiveFileNames) {
return new RegExp(pattern, useCaseSensitiveFileNames ? "" : "i");
}
/** @param path directory of the tsconfig.json */
function matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries, realpath) {
path = (0, path_1.normalizePath)(path);
currentDirectory = (0, path_1.normalizePath)(currentDirectory);
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
const includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(pattern => getRegexFromPattern(pattern, useCaseSensitiveFileNames));
const includeDirectoryRegex = patterns.includeDirectoryPattern && getRegexFromPattern(patterns.includeDirectoryPattern, useCaseSensitiveFileNames);
const excludeRegex = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, useCaseSensitiveFileNames);
// Associate an array of results with each include regex. This keeps results in order of the "include" order.
// If there are no "includes", then just put everything in results[0].
const results = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
const visited = new Map();
const toCanonical = (0, core_1.createGetCanonicalFileName)(useCaseSensitiveFileNames);
for (const basePath of patterns.basePaths) {
visitDirectory(basePath, (0, path_1.combinePaths)(currentDirectory, basePath), depth);
}
return (0, core_1.flatten)(results);
function visitDirectory(path, absolutePath, depth) {
const canonicalPath = toCanonical(realpath(absolutePath));
if (visited.has(canonicalPath)) {
return;
}
visited.set(canonicalPath, true);
const { files, directories } = getFileSystemEntries(path);
for (const current of (0, core_1.sort)(files, core_1.compareStringsCaseSensitive)) {
const name = (0, path_1.combinePaths)(path, current);
const absoluteName = (0, path_1.combinePaths)(absolutePath, current);
if (extensions && !(0, path_1.fileExtensionIsOneOf)(name, extensions)) {
continue;
}
if (excludeRegex && excludeRegex.test(absoluteName)) {
continue;
}
if (!includeFileRegexes) {
results[0].push(name);
}
else {
const includeIndex = (0, core_1.findIndex)(includeFileRegexes, re => re.test(absoluteName));
if (includeIndex !== -1) {
results[includeIndex].push(name);
}
}
}
if (depth !== undefined) {
depth--;
if (depth === 0) {
return;
}
}
for (const current of (0, core_1.sort)(directories, core_1.compareStringsCaseSensitive)) {
const name = (0, path_1.combinePaths)(path, current);
const absoluteName = (0, path_1.combinePaths)(absolutePath, current);
if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) &&
(!excludeRegex || !excludeRegex.test(absoluteName))) {
visitDirectory(name, absoluteName, depth);
}
}
}
}
/**
* Computes the unique non-wildcard base paths amongst the provided include patterns.
*/
function getBasePaths(path, includes, useCaseSensitiveFileNames) {
// Storage for our results in the form of literal paths (e.g. the paths as written by the user).
const basePaths = [path];
if (includes) {
// Storage for literal base paths amongst the include patterns.
const includeBasePaths = [];
for (const include of includes) {
// We also need to check the relative paths by converting them to absolute and normalizing
// in case they escape the base path (e.g "..\somedirectory")
const absolute = (0, path_1.isRootedDiskPath)(include) ? include : (0, path_1.normalizePath)((0, path_1.combinePaths)(path, include));
// Append the literal and canonical candidate base paths.
includeBasePaths.push(getIncludeBasePath(absolute));
}
// Sort the offsets array using either the literal or canonical path representations.
includeBasePaths.sort((0, core_1.getStringComparer)(!useCaseSensitiveFileNames));
// Iterate over each include base path and include unique base paths that are not a
// subpath of an existing base path
for (const includeBasePath of includeBasePaths) {
if ((0, core_1.every)(basePaths, basePath => !(0, path_1.containsPath)(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) {
basePaths.push(includeBasePath);
}
}
}
return basePaths;
}
function getIncludeBasePath(absolute) {
const wildcardOffset = (0, core_1.indexOfAnyCharCode)(absolute, wildcardCharCodes);
if (wildcardOffset < 0) {
// No "*" or "?" in the path
return !(0, path_1.hasExtension)(absolute)
? absolute
: (0, path_1.removeTrailingDirectorySeparator)((0, path_1.getDirectoryPath)(absolute));
}
return absolute.substring(0, absolute.lastIndexOf(path_1.directorySeparator, wildcardOffset));
}
//# sourceMappingURL=utilities.js.map

25
web-app/node_modules/@volar/typescript/package.json generated vendored Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "@volar/typescript",
"version": "2.4.15",
"license": "MIT",
"files": [
"**/*.js",
"**/*.d.ts"
],
"repository": {
"type": "git",
"url": "https://github.com/volarjs/volar.js.git",
"directory": "packages/typescript"
},
"dependencies": {
"@volar/language-core": "2.4.15",
"path-browserify": "^1.0.1",
"vscode-uri": "^3.0.8"
},
"devDependencies": {
"@types/node": "latest",
"@types/path-browserify": "latest",
"@volar/language-service": "2.4.15"
},
"gitHead": "adcdcbc801b284cce3239fec231c7f4cebfd8688"
}