@volar/language-core 1.11.0 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- export * from './lib/virtualFiles';
2
- export * from './lib/languageContext';
3
- export * from './lib/sourceMaps';
1
+ export * from './lib/editorFeatures';
2
+ export * from './lib/fileProvider';
3
+ export * from './lib/linkedCodeMap';
4
4
  export * from './lib/types';
5
- //# sourceMappingURL=index.d.ts.map
5
+ export * from './lib/utils';
6
+ export * from '@volar/source-map';
7
+ export declare function resolveCommonLanguageId(fileNameOrUri: string): string;
package/index.js CHANGED
@@ -14,8 +14,28 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./lib/virtualFiles"), exports);
18
- __exportStar(require("./lib/languageContext"), exports);
19
- __exportStar(require("./lib/sourceMaps"), exports);
17
+ exports.resolveCommonLanguageId = void 0;
18
+ __exportStar(require("./lib/editorFeatures"), exports);
19
+ __exportStar(require("./lib/fileProvider"), exports);
20
+ __exportStar(require("./lib/linkedCodeMap"), exports);
20
21
  __exportStar(require("./lib/types"), exports);
22
+ __exportStar(require("./lib/utils"), exports);
23
+ __exportStar(require("@volar/source-map"), exports);
24
+ function resolveCommonLanguageId(fileNameOrUri) {
25
+ const ext = fileNameOrUri.split('.').pop();
26
+ switch (ext) {
27
+ case 'js': return 'javascript';
28
+ case 'cjs': return 'javascript';
29
+ case 'mjs': return 'javascript';
30
+ case 'ts': return 'typescript';
31
+ case 'cts': return 'typescript';
32
+ case 'mts': return 'typescript';
33
+ case 'jsx': return 'javascriptreact';
34
+ case 'tsx': return 'typescriptreact';
35
+ case 'pug': return 'jade';
36
+ case 'md': return 'markdown';
37
+ }
38
+ return ext;
39
+ }
40
+ exports.resolveCommonLanguageId = resolveCommonLanguageId;
21
41
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,27 @@
1
+ import type { CodeInformation } from './types';
2
+ export declare function isHoverEnabled(info: CodeInformation): boolean;
3
+ export declare function isInlayHintsEnabled(info: CodeInformation): boolean;
4
+ export declare function isCodeLensEnabled(info: CodeInformation): boolean;
5
+ export declare function isSemanticTokensEnabled(info: CodeInformation): boolean;
6
+ export declare function isCallHierarchyEnabled(info: CodeInformation): boolean;
7
+ export declare function isRenameEnabled(info: CodeInformation): boolean;
8
+ export declare function isDefinitionEnabled(info: CodeInformation): boolean;
9
+ export declare function isTypeDefinitionEnabled(info: CodeInformation): boolean;
10
+ export declare function isReferencesEnabled(info: CodeInformation): boolean;
11
+ export declare function isImplementationEnabled(info: CodeInformation): boolean;
12
+ export declare function isHighlightEnabled(info: CodeInformation): boolean;
13
+ export declare function isSymbolsEnabled(info: CodeInformation): boolean;
14
+ export declare function isFoldingRangesEnabled(info: CodeInformation): boolean;
15
+ export declare function isSelectionRangesEnabled(info: CodeInformation): boolean;
16
+ export declare function isLinkedEditingEnabled(info: CodeInformation): boolean;
17
+ export declare function isColorEnabled(info: CodeInformation): boolean;
18
+ export declare function isDocumentLinkEnabled(info: CodeInformation): boolean;
19
+ export declare function isDiagnosticsEnabled(info: CodeInformation): boolean;
20
+ export declare function isCodeActionsEnabled(info: CodeInformation): boolean;
21
+ export declare function isFormattingEnabled(info: CodeInformation): boolean;
22
+ export declare function isCompletionEnabled(info: CodeInformation): boolean;
23
+ export declare function isAutoInsertEnabled(info: CodeInformation): boolean;
24
+ export declare function isSignatureHelpEnabled(info: CodeInformation): boolean;
25
+ export declare function shouldReportDiagnostics(info: CodeInformation): boolean;
26
+ export declare function resolveRenameNewName(newName: string, info: CodeInformation): string;
27
+ export declare function resolveRenameEditText(text: string, info: CodeInformation): string;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveRenameEditText = exports.resolveRenameNewName = exports.shouldReportDiagnostics = exports.isSignatureHelpEnabled = exports.isAutoInsertEnabled = exports.isCompletionEnabled = exports.isFormattingEnabled = exports.isCodeActionsEnabled = exports.isDiagnosticsEnabled = exports.isDocumentLinkEnabled = exports.isColorEnabled = exports.isLinkedEditingEnabled = exports.isSelectionRangesEnabled = exports.isFoldingRangesEnabled = exports.isSymbolsEnabled = exports.isHighlightEnabled = exports.isImplementationEnabled = exports.isReferencesEnabled = exports.isTypeDefinitionEnabled = exports.isDefinitionEnabled = exports.isRenameEnabled = exports.isCallHierarchyEnabled = exports.isSemanticTokensEnabled = exports.isCodeLensEnabled = exports.isInlayHintsEnabled = exports.isHoverEnabled = void 0;
4
+ function isHoverEnabled(info) {
5
+ return !!info.semantic;
6
+ }
7
+ exports.isHoverEnabled = isHoverEnabled;
8
+ function isInlayHintsEnabled(info) {
9
+ return !!info.semantic;
10
+ }
11
+ exports.isInlayHintsEnabled = isInlayHintsEnabled;
12
+ function isCodeLensEnabled(info) {
13
+ return !!info.semantic;
14
+ }
15
+ exports.isCodeLensEnabled = isCodeLensEnabled;
16
+ function isSemanticTokensEnabled(info) {
17
+ return typeof info.semantic === 'object'
18
+ ? info.semantic.shouldHighlight?.() ?? true
19
+ : info.semantic;
20
+ }
21
+ exports.isSemanticTokensEnabled = isSemanticTokensEnabled;
22
+ function isCallHierarchyEnabled(info) {
23
+ return !!info.navigation;
24
+ }
25
+ exports.isCallHierarchyEnabled = isCallHierarchyEnabled;
26
+ function isRenameEnabled(info) {
27
+ return !!info.navigation;
28
+ }
29
+ exports.isRenameEnabled = isRenameEnabled;
30
+ function isDefinitionEnabled(info) {
31
+ return !!info.navigation;
32
+ }
33
+ exports.isDefinitionEnabled = isDefinitionEnabled;
34
+ function isTypeDefinitionEnabled(info) {
35
+ return !!info.navigation;
36
+ }
37
+ exports.isTypeDefinitionEnabled = isTypeDefinitionEnabled;
38
+ function isReferencesEnabled(info) {
39
+ return !!info.navigation;
40
+ }
41
+ exports.isReferencesEnabled = isReferencesEnabled;
42
+ function isImplementationEnabled(info) {
43
+ return !!info.navigation;
44
+ }
45
+ exports.isImplementationEnabled = isImplementationEnabled;
46
+ function isHighlightEnabled(info) {
47
+ return !!info.navigation;
48
+ }
49
+ exports.isHighlightEnabled = isHighlightEnabled;
50
+ function isSymbolsEnabled(info) {
51
+ return info.structure;
52
+ }
53
+ exports.isSymbolsEnabled = isSymbolsEnabled;
54
+ function isFoldingRangesEnabled(info) {
55
+ return info.structure;
56
+ }
57
+ exports.isFoldingRangesEnabled = isFoldingRangesEnabled;
58
+ function isSelectionRangesEnabled(info) {
59
+ return info.structure;
60
+ }
61
+ exports.isSelectionRangesEnabled = isSelectionRangesEnabled;
62
+ function isLinkedEditingEnabled(info) {
63
+ return info.structure;
64
+ }
65
+ exports.isLinkedEditingEnabled = isLinkedEditingEnabled;
66
+ function isColorEnabled(info) {
67
+ return info.structure;
68
+ }
69
+ exports.isColorEnabled = isColorEnabled;
70
+ function isDocumentLinkEnabled(info) {
71
+ return info.structure;
72
+ }
73
+ exports.isDocumentLinkEnabled = isDocumentLinkEnabled;
74
+ function isDiagnosticsEnabled(info) {
75
+ return !!info.verification;
76
+ }
77
+ exports.isDiagnosticsEnabled = isDiagnosticsEnabled;
78
+ function isCodeActionsEnabled(info) {
79
+ return !!info.verification;
80
+ }
81
+ exports.isCodeActionsEnabled = isCodeActionsEnabled;
82
+ function isFormattingEnabled(info) {
83
+ return info.format;
84
+ }
85
+ exports.isFormattingEnabled = isFormattingEnabled;
86
+ function isCompletionEnabled(info) {
87
+ return !!info.completion;
88
+ }
89
+ exports.isCompletionEnabled = isCompletionEnabled;
90
+ function isAutoInsertEnabled(info) {
91
+ return !!info.completion;
92
+ }
93
+ exports.isAutoInsertEnabled = isAutoInsertEnabled;
94
+ function isSignatureHelpEnabled(info) {
95
+ return !!info.completion;
96
+ }
97
+ exports.isSignatureHelpEnabled = isSignatureHelpEnabled;
98
+ // should...
99
+ function shouldReportDiagnostics(info) {
100
+ return typeof info.verification === 'object'
101
+ ? info.verification.shouldReport?.() ?? true
102
+ : info.verification;
103
+ }
104
+ exports.shouldReportDiagnostics = shouldReportDiagnostics;
105
+ // resolve...
106
+ function resolveRenameNewName(newName, info) {
107
+ return typeof info.navigation === 'object'
108
+ ? info.navigation.resolveRenameNewName?.(newName) ?? newName
109
+ : newName;
110
+ }
111
+ exports.resolveRenameNewName = resolveRenameNewName;
112
+ function resolveRenameEditText(text, info) {
113
+ return typeof info.navigation === 'object'
114
+ ? info.navigation.resolveRenameEditText?.(text) ?? text
115
+ : text;
116
+ }
117
+ exports.resolveRenameEditText = resolveRenameEditText;
118
+ //# sourceMappingURL=editorFeatures.js.map
@@ -0,0 +1,15 @@
1
+ import { SourceMap } from '@volar/source-map';
2
+ import type * as ts from 'typescript/lib/tsserverlibrary';
3
+ import { LinkedCodeMap } from './linkedCodeMap';
4
+ import type { CodeInformation, LanguagePlugin, SourceFile, VirtualFile } from './types';
5
+ export type FileProvider = ReturnType<typeof createFileProvider>;
6
+ export declare function createFileProvider(languages: LanguagePlugin[], caseSensitive: boolean, sync: (sourceFileId: string) => void): {
7
+ updateSourceFile(id: string, snapshot: ts.IScriptSnapshot, languageId: string): SourceFile;
8
+ deleteSourceFile(id: string): void;
9
+ getLinkedCodeMap(file: VirtualFile): LinkedCodeMap | undefined;
10
+ getMaps(virtualFile: VirtualFile): Map<string, [ts.IScriptSnapshot, SourceMap<CodeInformation>]>;
11
+ getSourceFile(id: string): SourceFile | undefined;
12
+ getVirtualFile(id: string): [VirtualFile, SourceFile] | readonly [undefined, undefined];
13
+ };
14
+ export declare function updateVirtualFileMaps(virtualFile: VirtualFile, getSourceSnapshot: (sourceUri: string | undefined) => [string, ts.IScriptSnapshot] | undefined, map?: Map<string, [ts.IScriptSnapshot, SourceMap<CodeInformation>]>): Map<string, [ts.IScriptSnapshot, SourceMap<CodeInformation>]>;
15
+ export declare function forEachEmbeddedFile(file: VirtualFile): Generator<VirtualFile>;
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.forEachEmbeddedFile = exports.updateVirtualFileMaps = exports.createFileProvider = void 0;
4
+ const source_map_1 = require("@volar/source-map");
5
+ const linkedCodeMap_1 = require("./linkedCodeMap");
6
+ const utils_1 = require("./utils");
7
+ function createFileProvider(languages, caseSensitive, sync) {
8
+ const sourceFileRegistry = new utils_1.FileMap(caseSensitive);
9
+ const virtualFileRegistry = new utils_1.FileMap(caseSensitive);
10
+ const virtualFileToMaps = new WeakMap();
11
+ const virtualFileToLinkedCodeMap = new WeakMap();
12
+ return {
13
+ updateSourceFile(id, snapshot, languageId) {
14
+ const value = sourceFileRegistry.get(id);
15
+ if (value) {
16
+ if (value.languageId !== languageId) {
17
+ // languageId changed
18
+ this.deleteSourceFile(id);
19
+ return this.updateSourceFile(id, snapshot, languageId);
20
+ }
21
+ else if (value.snapshot !== snapshot) {
22
+ // updated
23
+ value.snapshot = snapshot;
24
+ if (value.virtualFile) {
25
+ disposeVirtualFiles(value);
26
+ value.virtualFile[1].updateVirtualFile(value.virtualFile[0], snapshot);
27
+ updateVirtualFiles(value);
28
+ }
29
+ return value;
30
+ }
31
+ else {
32
+ // not changed
33
+ return value;
34
+ }
35
+ }
36
+ for (const language of languages) {
37
+ const virtualFile = language.createVirtualFile(id, languageId, snapshot);
38
+ if (virtualFile) {
39
+ // created
40
+ const source = {
41
+ id,
42
+ languageId,
43
+ snapshot,
44
+ virtualFile: [virtualFile, language],
45
+ };
46
+ sourceFileRegistry.set(id, source);
47
+ updateVirtualFiles(source);
48
+ return source;
49
+ }
50
+ }
51
+ const source = { id: id, languageId, snapshot };
52
+ sourceFileRegistry.set(id, source);
53
+ return source;
54
+ },
55
+ deleteSourceFile(id) {
56
+ const value = sourceFileRegistry.get(id);
57
+ if (value) {
58
+ if (value.virtualFile) {
59
+ value.virtualFile[1].disposeVirtualFile?.(value.virtualFile[0]);
60
+ }
61
+ sourceFileRegistry.delete(id); // deleted
62
+ disposeVirtualFiles(value);
63
+ }
64
+ },
65
+ getLinkedCodeMap(file) {
66
+ if (!virtualFileToLinkedCodeMap.has(file.snapshot)) {
67
+ virtualFileToLinkedCodeMap.set(file.snapshot, file.linkedNavigationMappings ? new linkedCodeMap_1.LinkedCodeMap(file.linkedNavigationMappings) : undefined);
68
+ }
69
+ return virtualFileToLinkedCodeMap.get(file.snapshot);
70
+ },
71
+ getMaps(virtualFile) {
72
+ if (!virtualFileToMaps.has(virtualFile.snapshot)) {
73
+ virtualFileToMaps.set(virtualFile.snapshot, new Map());
74
+ }
75
+ updateVirtualFileMaps(virtualFile, sourceId => {
76
+ if (sourceId) {
77
+ const sourceFile = sourceFileRegistry.get(sourceId);
78
+ return [sourceId, sourceFile.snapshot];
79
+ }
80
+ else {
81
+ const sourceFile = virtualFileRegistry.get(virtualFile.id)[1];
82
+ return [sourceFile.id, sourceFile.snapshot];
83
+ }
84
+ }, virtualFileToMaps.get(virtualFile.snapshot));
85
+ return virtualFileToMaps.get(virtualFile.snapshot);
86
+ },
87
+ getSourceFile(id) {
88
+ sync(id);
89
+ return sourceFileRegistry.get(id);
90
+ },
91
+ getVirtualFile(id) {
92
+ let sourceAndVirtual = virtualFileRegistry.get(id);
93
+ if (sourceAndVirtual) {
94
+ sync(sourceAndVirtual[1].id);
95
+ sourceAndVirtual = virtualFileRegistry.get(id);
96
+ if (sourceAndVirtual) {
97
+ return sourceAndVirtual;
98
+ }
99
+ }
100
+ return [undefined, undefined];
101
+ },
102
+ };
103
+ function disposeVirtualFiles(source) {
104
+ if (source.virtualFile) {
105
+ for (const file of forEachEmbeddedFile(source.virtualFile[0])) {
106
+ virtualFileRegistry.delete(file.id);
107
+ }
108
+ }
109
+ }
110
+ function updateVirtualFiles(source) {
111
+ if (source.virtualFile) {
112
+ for (const file of forEachEmbeddedFile(source.virtualFile[0])) {
113
+ virtualFileRegistry.set(file.id, [file, source]);
114
+ }
115
+ }
116
+ }
117
+ }
118
+ exports.createFileProvider = createFileProvider;
119
+ function updateVirtualFileMaps(virtualFile, getSourceSnapshot, map = new Map()) {
120
+ const sources = new Set();
121
+ for (const mapping of virtualFile.mappings) {
122
+ if (sources.has(mapping.source))
123
+ continue;
124
+ sources.add(mapping.source);
125
+ const source = getSourceSnapshot(mapping.source);
126
+ if (!source)
127
+ continue;
128
+ if (!map.has(source[0]) || map.get(source[0])[0] !== source[1]) {
129
+ map.set(source[0], [source[1], new source_map_1.SourceMap(virtualFile.mappings.filter(mapping2 => mapping2.source === mapping.source))]);
130
+ }
131
+ }
132
+ return map;
133
+ }
134
+ exports.updateVirtualFileMaps = updateVirtualFileMaps;
135
+ function* forEachEmbeddedFile(file) {
136
+ yield file;
137
+ for (const embeddedFile of file.embeddedFiles) {
138
+ yield* forEachEmbeddedFile(embeddedFile);
139
+ }
140
+ }
141
+ exports.forEachEmbeddedFile = forEachEmbeddedFile;
142
+ //# sourceMappingURL=fileProvider.js.map
@@ -0,0 +1,4 @@
1
+ import { SourceMap } from '@volar/source-map';
2
+ export declare class LinkedCodeMap extends SourceMap {
3
+ getLinkedOffsets(start: number): Generator<number, void, unknown>;
4
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LinkedCodeMap = void 0;
4
+ const source_map_1 = require("@volar/source-map");
5
+ class LinkedCodeMap extends source_map_1.SourceMap {
6
+ *getLinkedOffsets(start) {
7
+ for (const mapped of this.getGeneratedOffsets(start)) {
8
+ yield mapped[0];
9
+ }
10
+ for (const mapped of this.getSourceOffsets(start)) {
11
+ yield mapped[0];
12
+ }
13
+ }
14
+ }
15
+ exports.LinkedCodeMap = LinkedCodeMap;
16
+ //# sourceMappingURL=linkedCodeMap.js.map
package/lib/types.d.ts CHANGED
@@ -1,76 +1,75 @@
1
- import { Mapping, Stack } from '@volar/source-map';
1
+ import type { Mapping, Stack } from '@volar/source-map';
2
2
  import type * as ts from 'typescript/lib/tsserverlibrary';
3
- export interface FileCapabilities {
4
- diagnostic?: boolean;
5
- foldingRange?: boolean;
6
- documentFormatting?: boolean;
7
- documentSymbol?: boolean;
8
- codeAction?: boolean;
9
- inlayHint?: boolean;
3
+ import type { FileProvider } from './fileProvider';
4
+ export interface SourceFile extends BaseFile {
5
+ virtualFile?: [VirtualFile, LanguagePlugin];
10
6
  }
11
- export interface FileRangeCapabilities {
12
- hover?: boolean;
13
- references?: boolean;
14
- definition?: boolean;
15
- rename?: boolean | {
16
- normalize?(newName: string): string;
17
- apply?(newName: string): string;
7
+ export interface VirtualFile extends BaseFile {
8
+ mappings: Mapping<CodeInformation>[];
9
+ embeddedFiles: VirtualFile[];
10
+ typescript?: {
11
+ scriptKind: ts.ScriptKind;
18
12
  };
19
- completion?: boolean | {
20
- additional?: boolean;
21
- autoImportOnly?: boolean;
13
+ codegenStacks?: Stack[];
14
+ linkedNavigationMappings?: Mapping[];
15
+ }
16
+ export interface CodeInformation {
17
+ /** virtual code is expected to support verification */
18
+ verification: boolean | {
19
+ shouldReport?(): boolean;
22
20
  };
23
- diagnostic?: boolean | {
24
- shouldReport(): boolean;
21
+ /** virtual code is expected to support assisted completion */
22
+ completion: boolean | {
23
+ isAdditional?: boolean;
24
+ onlyImport?: boolean;
25
25
  };
26
- semanticTokens?: boolean;
27
- referencesCodeLens?: boolean;
28
- displayWithLink?: boolean;
29
- }
30
- export interface MirrorBehaviorCapabilities {
31
- references?: boolean;
32
- definition?: boolean;
33
- rename?: boolean;
34
- }
35
- export declare namespace FileCapabilities {
36
- const full: FileCapabilities;
37
- }
38
- export declare namespace FileRangeCapabilities {
39
- const full: FileRangeCapabilities;
40
- }
41
- export declare namespace MirrorBehaviorCapabilities {
42
- const full: MirrorBehaviorCapabilities;
43
- }
44
- export declare enum FileKind {
45
- TextFile = 0,
46
- TypeScriptHostFile = 1
26
+ /** virtual code is expected correctly reflect semantic of the source code */
27
+ semantic: boolean | {
28
+ shouldHighlight?(): boolean;
29
+ };
30
+ /** virtual code is expected correctly reflect reference relationships of the source code */
31
+ navigation: boolean | {
32
+ shouldRename?(): boolean;
33
+ resolveRenameNewName?(newName: string): string;
34
+ resolveRenameEditText?(newText: string): string;
35
+ };
36
+ /** virtual code is expected correctly reflect the structural information of the source code */
37
+ structure: boolean;
38
+ /** virtual code is expected correctly reflect the format information of the source code */
39
+ format: boolean;
47
40
  }
48
- export interface VirtualFile {
49
- fileName: string;
41
+ export interface BaseFile {
42
+ /**
43
+ * for language-server, kit, monaco, this is uri
44
+ *
45
+ * for typescript server plugin, tsc, this is fileName
46
+ */
47
+ id: string;
48
+ languageId: string;
50
49
  snapshot: ts.IScriptSnapshot;
51
- kind: FileKind;
52
- capabilities: FileCapabilities;
53
- mappings: Mapping<FileRangeCapabilities>[];
54
- codegenStacks: Stack[];
55
- mirrorBehaviorMappings?: Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[];
56
- embeddedFiles: VirtualFile[];
57
50
  }
58
- export interface Language<T extends VirtualFile = VirtualFile> {
59
- resolveHost?(host: TypeScriptLanguageHost): TypeScriptLanguageHost;
60
- createVirtualFile(fileName: string, snapshot: ts.IScriptSnapshot, languageId: string | undefined): T | undefined;
51
+ export interface LanguagePlugin<T extends VirtualFile = VirtualFile> {
52
+ createVirtualFile(id: string, languageId: string, snapshot: ts.IScriptSnapshot): T | undefined;
61
53
  updateVirtualFile(virtualFile: T, snapshot: ts.IScriptSnapshot): void;
62
- deleteVirtualFile?(virtualFile: T): void;
54
+ disposeVirtualFile?(virtualFile: T): void;
55
+ typescript?: {
56
+ resolveSourceFileName(tsFileName: string): string | undefined;
57
+ resolveModuleName?(path: string, impliedNodeFormat?: ts.ResolutionMode): string | undefined;
58
+ resolveLanguageServiceHost?(host: ts.LanguageServiceHost): ts.LanguageServiceHost;
59
+ };
63
60
  }
64
- interface LanguageHost {
65
- workspacePath: string;
66
- rootPath: string;
67
- getProjectVersion(): string;
68
- getScriptFileNames(): string[];
69
- getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined;
70
- getLanguageId?(fileName: string): string | undefined;
61
+ export interface Language {
62
+ files: FileProvider;
63
+ typescript?: {
64
+ configFileName: string | undefined;
65
+ sys: ts.System;
66
+ projectHost: TypeScriptProjectHost;
67
+ languageServiceHost: ts.LanguageServiceHost;
68
+ synchronizeFileSystem?(): Promise<number>;
69
+ };
71
70
  }
72
- export interface TypeScriptLanguageHost extends LanguageHost, Pick<ts.LanguageServiceHost, 'getCancellationToken' | 'getLocalizedDiagnosticMessages' | 'getCompilationSettings' | 'getProjectReferences'> {
73
- resolveModuleName?(path: string, impliedNodeFormat?: ts.ResolutionMode): string;
71
+ export interface TypeScriptProjectHost extends Pick<ts.LanguageServiceHost, 'getLocalizedDiagnosticMessages' | 'getCompilationSettings' | 'getProjectReferences' | 'getCurrentDirectory' | 'getScriptFileNames' | 'getProjectVersion' | 'getScriptSnapshot' | 'getCancellationToken'> {
72
+ getFileId(fileName: string): string;
73
+ getFileName(fileId: string): string;
74
+ getLanguageId(id: string): string;
74
75
  }
75
- export {};
76
- //# sourceMappingURL=types.d.ts.map
package/lib/types.js CHANGED
@@ -1,40 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FileKind = exports.MirrorBehaviorCapabilities = exports.FileRangeCapabilities = exports.FileCapabilities = void 0;
4
- var FileCapabilities;
5
- (function (FileCapabilities) {
6
- FileCapabilities.full = {
7
- diagnostic: true,
8
- foldingRange: true,
9
- documentFormatting: true,
10
- documentSymbol: true,
11
- codeAction: true,
12
- inlayHint: true,
13
- };
14
- })(FileCapabilities || (exports.FileCapabilities = FileCapabilities = {}));
15
- var FileRangeCapabilities;
16
- (function (FileRangeCapabilities) {
17
- FileRangeCapabilities.full = {
18
- hover: true,
19
- references: true,
20
- definition: true,
21
- rename: true,
22
- completion: true,
23
- diagnostic: true,
24
- semanticTokens: true,
25
- };
26
- })(FileRangeCapabilities || (exports.FileRangeCapabilities = FileRangeCapabilities = {}));
27
- var MirrorBehaviorCapabilities;
28
- (function (MirrorBehaviorCapabilities) {
29
- MirrorBehaviorCapabilities.full = {
30
- references: true,
31
- definition: true,
32
- rename: true,
33
- };
34
- })(MirrorBehaviorCapabilities || (exports.MirrorBehaviorCapabilities = MirrorBehaviorCapabilities = {}));
35
- var FileKind;
36
- (function (FileKind) {
37
- FileKind[FileKind["TextFile"] = 0] = "TextFile";
38
- FileKind[FileKind["TypeScriptHostFile"] = 1] = "TypeScriptHostFile";
39
- })(FileKind || (exports.FileKind = FileKind = {}));
40
3
  //# sourceMappingURL=types.js.map
package/lib/utils.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export declare class FileMap<T> extends Map<string, T> {
2
+ private caseSensitive;
3
+ private originalFileNames;
4
+ constructor(caseSensitive: boolean);
5
+ keys(): IterableIterator<string>;
6
+ get(key: string): T | undefined;
7
+ has(key: string): boolean;
8
+ set(key: string, value: T): this;
9
+ delete(key: string): boolean;
10
+ clear(): void;
11
+ normalizeId(id: string): string;
12
+ }
package/lib/utils.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileMap = void 0;
4
+ class FileMap extends Map {
5
+ constructor(caseSensitive) {
6
+ super();
7
+ this.caseSensitive = caseSensitive;
8
+ this.originalFileNames = new Map();
9
+ }
10
+ keys() {
11
+ return this.originalFileNames.values();
12
+ }
13
+ get(key) {
14
+ return super.get(this.normalizeId(key));
15
+ }
16
+ has(key) {
17
+ return super.has(this.normalizeId(key));
18
+ }
19
+ set(key, value) {
20
+ this.originalFileNames.set(this.normalizeId(key), key);
21
+ return super.set(this.normalizeId(key), value);
22
+ }
23
+ delete(key) {
24
+ this.originalFileNames.delete(this.normalizeId(key));
25
+ return super.delete(this.normalizeId(key));
26
+ }
27
+ clear() {
28
+ this.originalFileNames.clear();
29
+ return super.clear();
30
+ }
31
+ normalizeId(id) {
32
+ return this.caseSensitive ? id : id.toLowerCase();
33
+ }
34
+ }
35
+ exports.FileMap = FileMap;
36
+ //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volar/language-core",
3
- "version": "1.11.0",
3
+ "version": "2.0.0-alpha.0",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,7 +12,7 @@
12
12
  "directory": "packages/language-core"
13
13
  },
14
14
  "dependencies": {
15
- "@volar/source-map": "1.11.0"
15
+ "@volar/source-map": "2.0.0-alpha.0"
16
16
  },
17
- "gitHead": "e3f563cbbf4cc03c058f5df38df0498034e5feb5"
17
+ "gitHead": "6a6be45a3b7983148d90541e7c68ef84c9155a7a"
18
18
  }
@@ -1,9 +0,0 @@
1
- import { createVirtualFiles } from './virtualFiles';
2
- import { Language, TypeScriptLanguageHost } from './types';
3
- export interface LanguageContext {
4
- rawHost: TypeScriptLanguageHost;
5
- host: TypeScriptLanguageHost;
6
- virtualFiles: ReturnType<typeof createVirtualFiles>;
7
- }
8
- export declare function createLanguageContext(rawHost: TypeScriptLanguageHost, languages: Language<any>[]): LanguageContext;
9
- //# sourceMappingURL=languageContext.d.ts.map
@@ -1,67 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLanguageContext = void 0;
4
- const virtualFiles_1 = require("./virtualFiles");
5
- function createLanguageContext(rawHost, languages) {
6
- let host = rawHost;
7
- let lastRootFiles = new Map();
8
- let lastProjectVersion;
9
- const virtualFiles = (0, virtualFiles_1.createVirtualFiles)(languages);
10
- for (const language of languages.reverse()) {
11
- if (language.resolveHost) {
12
- const pastHost = host;
13
- let proxyHost = language.resolveHost(host);
14
- if (proxyHost === pastHost) {
15
- console.warn(`[volar] language.resolveHost() should not return the same host instance.`);
16
- proxyHost = { ...proxyHost };
17
- }
18
- host = new Proxy(proxyHost, {
19
- get(target, p) {
20
- if (p in target) {
21
- return target[p];
22
- }
23
- return pastHost[p];
24
- }
25
- });
26
- }
27
- }
28
- return {
29
- rawHost,
30
- host,
31
- virtualFiles: new Proxy(virtualFiles, {
32
- get: (target, property) => {
33
- syncVirtualFiles();
34
- return target[property];
35
- },
36
- }),
37
- };
38
- function syncVirtualFiles() {
39
- const newProjectVersion = host.getProjectVersion();
40
- const shouldUpdate = newProjectVersion !== lastProjectVersion;
41
- if (!shouldUpdate)
42
- return;
43
- const nowRootFiles = new Map();
44
- const remainRootFiles = new Set(lastRootFiles.keys());
45
- for (const rootFileName of host.getScriptFileNames()) {
46
- nowRootFiles.set(rootFileName, host.getScriptSnapshot(rootFileName));
47
- }
48
- for (const [fileName, snapshot] of nowRootFiles) {
49
- remainRootFiles.delete(fileName);
50
- if (lastRootFiles.get(fileName) !== nowRootFiles.get(fileName)) {
51
- if (snapshot) {
52
- virtualFiles.updateSource(fileName, snapshot, host.getLanguageId?.(fileName));
53
- }
54
- else {
55
- virtualFiles.deleteSource(fileName);
56
- }
57
- }
58
- }
59
- for (const fileName of remainRootFiles) {
60
- virtualFiles.deleteSource(fileName);
61
- }
62
- lastRootFiles = nowRootFiles;
63
- lastProjectVersion = newProjectVersion;
64
- }
65
- }
66
- exports.createLanguageContext = createLanguageContext;
67
- //# sourceMappingURL=languageContext.js.map
@@ -1,6 +0,0 @@
1
- import * as SourceMaps from '@volar/source-map';
2
- import { MirrorBehaviorCapabilities } from './types';
3
- export declare class MirrorMap extends SourceMaps.SourceMap<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]> {
4
- findMirrorOffsets(start: number): Generator<readonly [number, MirrorBehaviorCapabilities], void, unknown>;
5
- }
6
- //# sourceMappingURL=sourceMaps.d.ts.map
package/lib/sourceMaps.js DELETED
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MirrorMap = void 0;
4
- const SourceMaps = require("@volar/source-map");
5
- class MirrorMap extends SourceMaps.SourceMap {
6
- *findMirrorOffsets(start) {
7
- for (const mapped of this.toGeneratedOffsets(start)) {
8
- yield [mapped[0], mapped[1].data[1]];
9
- }
10
- for (const mapped of this.toSourceOffsets(start)) {
11
- yield [mapped[0], mapped[1].data[0]];
12
- }
13
- }
14
- }
15
- exports.MirrorMap = MirrorMap;
16
- //# sourceMappingURL=sourceMaps.js.map
@@ -1,26 +0,0 @@
1
- import { SourceMap } from '@volar/source-map';
2
- import type * as ts from 'typescript/lib/tsserverlibrary';
3
- import { MirrorMap } from './sourceMaps';
4
- import type { FileRangeCapabilities, Language, VirtualFile } from './types';
5
- export type VirtualFiles = ReturnType<typeof createVirtualFiles>;
6
- export interface Source {
7
- fileName: string;
8
- languageId: string | undefined;
9
- snapshot: ts.IScriptSnapshot;
10
- root: VirtualFile;
11
- language: Language;
12
- }
13
- export declare function createVirtualFiles(languages: Language[]): {
14
- allSources(): Source[];
15
- updateSource(fileName: string, snapshot: ts.IScriptSnapshot, languageId: string | undefined): VirtualFile | undefined;
16
- deleteSource(fileName: string): void;
17
- getSource(fileName: string): Source | undefined;
18
- hasSource: (fileName: string) => boolean;
19
- getMirrorMap: (file: VirtualFile) => MirrorMap | undefined;
20
- getMaps: (virtualFile: VirtualFile) => Map<string, [ts.IScriptSnapshot, SourceMap<FileRangeCapabilities>]>;
21
- hasVirtualFile(fileName: string): boolean;
22
- getVirtualFile(fileName: string): readonly [VirtualFile, Source] | readonly [undefined, undefined];
23
- };
24
- export declare function updateVirtualFileMaps(virtualFile: VirtualFile, getSourceSnapshot: (source: string | undefined) => [string, ts.IScriptSnapshot] | undefined, map?: Map<string, [ts.IScriptSnapshot, SourceMap<FileRangeCapabilities>]>): Map<string, [ts.IScriptSnapshot, SourceMap<FileRangeCapabilities>]>;
25
- export declare function forEachEmbeddedFile(file: VirtualFile, cb: (embedded: VirtualFile) => void): void;
26
- //# sourceMappingURL=virtualFiles.d.ts.map
@@ -1,129 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.forEachEmbeddedFile = exports.updateVirtualFileMaps = exports.createVirtualFiles = void 0;
4
- const source_map_1 = require("@volar/source-map");
5
- const sourceMaps_1 = require("./sourceMaps");
6
- function createVirtualFiles(languages) {
7
- const sourceFiles = new Map();
8
- const virtualFiles = new Map();
9
- const virtualFileMaps = new WeakMap();
10
- const virtualFileToMirrorMap = new WeakMap();
11
- return {
12
- allSources() {
13
- return Array.from(sourceFiles.values());
14
- },
15
- updateSource(fileName, snapshot, languageId) {
16
- const key = normalizePath(fileName);
17
- const value = sourceFiles.get(key);
18
- if (value) {
19
- if (value.languageId !== languageId) {
20
- // languageId changed
21
- this.deleteSource(fileName);
22
- return this.updateSource(fileName, snapshot, languageId);
23
- }
24
- else {
25
- value.snapshot = snapshot;
26
- deleteVirtualFiles(value);
27
- value.language.updateVirtualFile(value.root, snapshot);
28
- updateVirtualFiles(value);
29
- return value.root; // updated
30
- }
31
- }
32
- for (const language of languages) {
33
- const virtualFile = language.createVirtualFile(fileName, snapshot, languageId);
34
- if (virtualFile) {
35
- const source = { fileName, languageId, snapshot, root: virtualFile, language };
36
- sourceFiles.set(key, source);
37
- updateVirtualFiles(source);
38
- return virtualFile; // created
39
- }
40
- }
41
- },
42
- deleteSource(fileName) {
43
- const key = normalizePath(fileName);
44
- const value = sourceFiles.get(key);
45
- if (value) {
46
- value.language.deleteVirtualFile?.(value.root);
47
- sourceFiles.delete(key); // deleted
48
- deleteVirtualFiles(value);
49
- }
50
- },
51
- getSource(fileName) {
52
- const key = normalizePath(fileName);
53
- return sourceFiles.get(key);
54
- },
55
- hasSource: (fileName) => sourceFiles.has(normalizePath(fileName)),
56
- getMirrorMap: getMirrorMap,
57
- getMaps: getMapsByVirtualFile,
58
- hasVirtualFile(fileName) {
59
- return !!virtualFiles.get(normalizePath(fileName));
60
- },
61
- getVirtualFile(fileName) {
62
- const sourceAndVirtual = virtualFiles.get(normalizePath(fileName));
63
- if (sourceAndVirtual) {
64
- return [sourceAndVirtual.virtualFile, sourceAndVirtual.source];
65
- }
66
- return [undefined, undefined];
67
- },
68
- };
69
- function deleteVirtualFiles(source) {
70
- forEachEmbeddedFile(source.root, file => {
71
- virtualFiles.delete(normalizePath(file.fileName));
72
- });
73
- }
74
- function updateVirtualFiles(source) {
75
- forEachEmbeddedFile(source.root, file => {
76
- virtualFiles.set(normalizePath(file.fileName), { virtualFile: file, source });
77
- });
78
- }
79
- function getMapsByVirtualFile(virtualFile) {
80
- if (!virtualFileMaps.has(virtualFile.snapshot)) {
81
- virtualFileMaps.set(virtualFile.snapshot, new Map());
82
- }
83
- updateVirtualFileMaps(virtualFile, sourceFileName => {
84
- if (sourceFileName) {
85
- const source = sourceFiles.get(normalizePath(sourceFileName));
86
- return [sourceFileName, source.snapshot];
87
- }
88
- else {
89
- const source = virtualFiles.get(normalizePath(virtualFile.fileName)).source;
90
- return [source.fileName, source.snapshot];
91
- }
92
- }, virtualFileMaps.get(virtualFile.snapshot));
93
- return virtualFileMaps.get(virtualFile.snapshot);
94
- }
95
- function getMirrorMap(file) {
96
- if (!virtualFileToMirrorMap.has(file.snapshot)) {
97
- virtualFileToMirrorMap.set(file.snapshot, file.mirrorBehaviorMappings ? new sourceMaps_1.MirrorMap(file.mirrorBehaviorMappings) : undefined);
98
- }
99
- return virtualFileToMirrorMap.get(file.snapshot);
100
- }
101
- }
102
- exports.createVirtualFiles = createVirtualFiles;
103
- function updateVirtualFileMaps(virtualFile, getSourceSnapshot, map = new Map()) {
104
- const sources = new Set();
105
- for (const mapping of virtualFile.mappings) {
106
- if (sources.has(mapping.source))
107
- continue;
108
- sources.add(mapping.source);
109
- const source = getSourceSnapshot(mapping.source);
110
- if (!source)
111
- continue;
112
- if (!map.has(source[0]) || map.get(source[0])[0] !== source[1]) {
113
- map.set(source[0], [source[1], new source_map_1.SourceMap(virtualFile.mappings.filter(mapping2 => mapping2.source === mapping.source))]);
114
- }
115
- }
116
- return map;
117
- }
118
- exports.updateVirtualFileMaps = updateVirtualFileMaps;
119
- function forEachEmbeddedFile(file, cb) {
120
- cb(file);
121
- for (const embeddedFile of file.embeddedFiles) {
122
- forEachEmbeddedFile(embeddedFile, cb);
123
- }
124
- }
125
- exports.forEachEmbeddedFile = forEachEmbeddedFile;
126
- function normalizePath(fileName) {
127
- return fileName.replace(/\\/g, '/').toLowerCase();
128
- }
129
- //# sourceMappingURL=virtualFiles.js.map