@volar/typescript 2.4.10 → 2.4.11

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.
@@ -55,7 +55,7 @@ function decorateLanguageServiceHost(ts, language, languageServiceHost) {
55
55
  }
56
56
  }
57
57
  languageServiceHost.getScriptSnapshot = fileName => {
58
- const virtualScript = updateVirtualScript(fileName);
58
+ const virtualScript = updateVirtualScript(fileName, true);
59
59
  if (virtualScript) {
60
60
  return virtualScript.snapshot;
61
61
  }
@@ -63,14 +63,14 @@ function decorateLanguageServiceHost(ts, language, languageServiceHost) {
63
63
  };
64
64
  if (getScriptKind) {
65
65
  languageServiceHost.getScriptKind = fileName => {
66
- const virtualScript = updateVirtualScript(fileName);
66
+ const virtualScript = updateVirtualScript(fileName, false);
67
67
  if (virtualScript) {
68
68
  return virtualScript.scriptKind;
69
69
  }
70
70
  return getScriptKind(fileName);
71
71
  };
72
72
  }
73
- function updateVirtualScript(fileName) {
73
+ function updateVirtualScript(fileName, shouldRegister) {
74
74
  if (crashFileNames.has(fileName)) {
75
75
  return;
76
76
  }
@@ -89,7 +89,7 @@ function decorateLanguageServiceHost(ts, language, languageServiceHost) {
89
89
  let script = scripts.get(fileName);
90
90
  if (!script || script[0] !== version) {
91
91
  script = [version];
92
- const sourceScript = language.scripts.get(fileName);
92
+ const sourceScript = language.scripts.get(fileName, undefined, shouldRegister);
93
93
  if (sourceScript?.generated) {
94
94
  const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
95
95
  if (serviceScript) {
@@ -22,14 +22,24 @@ function createAsyncLanguageServicePlugin(extensions, getScriptKindForExtraExten
22
22
  const getProjectVersion = info.languageServiceHost.getProjectVersion?.bind(info.languageServiceHost);
23
23
  let initialized = false;
24
24
  info.languageServiceHost.getScriptSnapshot = fileName => {
25
- if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
26
- return emptySnapshot;
25
+ if (!initialized) {
26
+ if (extensions.some(ext => fileName.endsWith(ext))) {
27
+ return emptySnapshot;
28
+ }
29
+ if (getScriptInfo(fileName)?.isScriptOpen()) {
30
+ return emptySnapshot;
31
+ }
27
32
  }
28
33
  return getScriptSnapshot(fileName);
29
34
  };
30
35
  info.languageServiceHost.getScriptVersion = fileName => {
31
- if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
32
- return 'initializing...';
36
+ if (!initialized) {
37
+ if (extensions.some(ext => fileName.endsWith(ext))) {
38
+ return 'initializing...';
39
+ }
40
+ if (getScriptInfo(fileName)?.isScriptOpen()) {
41
+ return getScriptVersion(fileName) + ',initializing...';
42
+ }
33
43
  }
34
44
  return getScriptVersion(fileName);
35
45
  };
@@ -62,33 +72,44 @@ function createAsyncLanguageServicePlugin(extensions, getScriptKindForExtraExten
62
72
  const language = (0, language_core_1.createLanguage)([
63
73
  ...languagePlugins,
64
74
  { getLanguageId: common_1.resolveFileLanguageId },
65
- ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => {
66
- try { // getSnapshot could be crashed if the file is too large
67
- let snapshot = info.project.getScriptInfo(fileName)?.getSnapshot();
75
+ ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), (fileName, _, shouldRegister) => {
76
+ let snapshot;
77
+ if (shouldRegister) {
78
+ // We need to trigger registration of the script file with the project, see #250
79
+ snapshot = getScriptSnapshot(fileName);
80
+ }
81
+ else {
82
+ snapshot = getScriptInfo(fileName)?.getSnapshot();
68
83
  if (!snapshot) {
69
84
  // trigger projectService.getOrCreateScriptInfoNotOpenedByClient
70
85
  info.project.getScriptVersion(fileName);
71
- snapshot = info.project.getScriptInfo(fileName)?.getSnapshot();
72
- }
73
- if (snapshot) {
74
- language.scripts.set(fileName, snapshot);
75
- }
76
- else {
77
- language.scripts.delete(fileName);
86
+ snapshot = getScriptInfo(fileName)?.getSnapshot();
78
87
  }
79
88
  }
80
- catch { }
89
+ if (snapshot) {
90
+ language.scripts.set(fileName, snapshot);
91
+ }
92
+ else {
93
+ language.scripts.delete(fileName);
94
+ }
81
95
  });
82
96
  initialize(language);
83
97
  (0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost);
84
98
  setup?.(language);
99
+ initialized = true;
85
100
  if ('markAsDirty' in info.project && typeof info.project.markAsDirty === 'function') {
86
101
  info.project.markAsDirty();
87
102
  }
88
- initialized = true;
89
103
  });
90
104
  }
91
105
  return info.languageService;
106
+ function getScriptInfo(fileName) {
107
+ // getSnapshot could be crashed if the file is too large
108
+ try {
109
+ return info.project.getScriptInfo(fileName);
110
+ }
111
+ catch { }
112
+ }
92
113
  },
93
114
  getExternalFiles(project, updateLevel = 0) {
94
115
  if (updateLevel >= 1
@@ -25,25 +25,30 @@ function createLanguageServicePlugin(create) {
25
25
  .map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
26
26
  .flat();
27
27
  exports.projectExternalFileExtensions.set(info.project, extensions);
28
+ const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
28
29
  const language = (0, language_core_1.createLanguage)([
29
30
  ...languagePlugins,
30
31
  { getLanguageId: common_1.resolveFileLanguageId },
31
- ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => {
32
- try { // getSnapshot could be crashed if the file is too large
33
- let snapshot = info.project.getScriptInfo(fileName)?.getSnapshot();
32
+ ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), (fileName, _, shouldRegister) => {
33
+ let snapshot;
34
+ if (shouldRegister) {
35
+ // We need to trigger registration of the script file with the project, see #250
36
+ snapshot = getScriptSnapshot(fileName);
37
+ }
38
+ else {
39
+ snapshot = getScriptInfo(fileName)?.getSnapshot();
34
40
  if (!snapshot) {
35
41
  // trigger projectService.getOrCreateScriptInfoNotOpenedByClient
36
42
  info.project.getScriptVersion(fileName);
37
- snapshot = info.project.getScriptInfo(fileName)?.getSnapshot();
38
- }
39
- if (snapshot) {
40
- language.scripts.set(fileName, snapshot);
41
- }
42
- else {
43
- language.scripts.delete(fileName);
43
+ snapshot = getScriptInfo(fileName)?.getSnapshot();
44
44
  }
45
45
  }
46
- catch { }
46
+ if (snapshot) {
47
+ language.scripts.set(fileName, snapshot);
48
+ }
49
+ else {
50
+ language.scripts.delete(fileName);
51
+ }
47
52
  });
48
53
  const { proxy, initialize } = (0, proxyLanguageService_1.createProxyLanguageService)(info.languageService);
49
54
  info.languageService = proxy;
@@ -52,6 +57,13 @@ function createLanguageServicePlugin(create) {
52
57
  setup?.(language);
53
58
  }
54
59
  return info.languageService;
60
+ function getScriptInfo(fileName) {
61
+ // getSnapshot could be crashed if the file is too large
62
+ try {
63
+ return info.project.getScriptInfo(fileName);
64
+ }
65
+ catch { }
66
+ }
55
67
  },
56
68
  getExternalFiles(project, updateLevel = 0) {
57
69
  if (updateLevel >= 1
@@ -7,7 +7,7 @@ export declare let getLanguagePlugins: (ts: typeof import('typescript'), options
7
7
  export declare function runTsc(tscPath: string, options: string[] | {
8
8
  extraSupportedExtensions: string[];
9
9
  extraExtensionsToRemove: string[];
10
- }, _getLanguagePlugins: typeof getLanguagePlugins): void;
10
+ }, _getLanguagePlugins: typeof getLanguagePlugins, typescriptObject?: string): void;
11
11
  /**
12
12
  * Replaces the code of typescript to add support for additional extensions and language plugins.
13
13
  *
@@ -16,6 +16,7 @@ export declare function runTsc(tscPath: string, options: string[] | {
16
16
  * @param extraSupportedExtensions - An array of additional supported extensions.
17
17
  * @param extraExtensionsToRemove - An array of extensions to remove.
18
18
  * @param getLanguagePluginsFile - The file to get language plugins from.
19
+ * @param typescriptObject - The object to use as typescript.
19
20
  * @returns The modified typescript code.
20
21
  */
21
- export declare function transformTscContent(tsc: string, proxyApiPath: string, extraSupportedExtensions: string[], extraExtensionsToRemove: string[], getLanguagePluginsFile?: string): string;
22
+ export declare function transformTscContent(tsc: string, proxyApiPath: string, extraSupportedExtensions: string[], extraExtensionsToRemove: string[], getLanguagePluginsFile?: string, typescriptObject?: string): string;
@@ -4,26 +4,41 @@ exports.getLanguagePlugins = void 0;
4
4
  exports.runTsc = runTsc;
5
5
  exports.transformTscContent = transformTscContent;
6
6
  const fs = require("fs");
7
+ const path = require("path");
7
8
  let getLanguagePlugins = () => [];
8
9
  exports.getLanguagePlugins = getLanguagePlugins;
9
- function runTsc(tscPath, options, _getLanguagePlugins) {
10
+ function runTsc(tscPath, options, _getLanguagePlugins, typescriptObject) {
10
11
  exports.getLanguagePlugins = _getLanguagePlugins;
12
+ let extraSupportedExtensions;
13
+ let extraExtensionsToRemove;
14
+ if (Array.isArray(options)) {
15
+ extraSupportedExtensions = options;
16
+ extraExtensionsToRemove = [];
17
+ }
18
+ else {
19
+ extraSupportedExtensions = options.extraSupportedExtensions;
20
+ extraExtensionsToRemove = options.extraExtensionsToRemove;
21
+ }
11
22
  const proxyApiPath = require.resolve('../node/proxyCreateProgram');
12
23
  const readFileSync = fs.readFileSync;
13
24
  fs.readFileSync = (...args) => {
14
25
  if (args[0] === tscPath) {
15
26
  let tsc = readFileSync(...args);
16
- let extraSupportedExtensions;
17
- let extraExtensionsToRemove;
18
- if (Array.isArray(options)) {
19
- extraSupportedExtensions = options;
20
- extraExtensionsToRemove = [];
27
+ try {
28
+ return transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, __filename, typescriptObject);
21
29
  }
22
- else {
23
- extraSupportedExtensions = options.extraSupportedExtensions;
24
- extraExtensionsToRemove = options.extraExtensionsToRemove;
30
+ catch {
31
+ // Support the tsc shim used in Typescript v5.7 and up
32
+ const requireRegex = /module\.exports\s*=\s*require\((?:"|')(?<path>\.\/\w+\.js)(?:"|')\)/;
33
+ const requirePath = requireRegex.exec(tsc)?.groups?.path;
34
+ if (requirePath) {
35
+ tsc = readFileSync(path.join(path.dirname(tscPath), requirePath), 'utf8');
36
+ return transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, __filename, typescriptObject);
37
+ }
38
+ else {
39
+ throw new Error('Failed to locate tsc module path from shim');
40
+ }
25
41
  }
26
- return transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove);
27
42
  }
28
43
  return readFileSync(...args);
29
44
  };
@@ -43,9 +58,10 @@ function runTsc(tscPath, options, _getLanguagePlugins) {
43
58
  * @param extraSupportedExtensions - An array of additional supported extensions.
44
59
  * @param extraExtensionsToRemove - An array of extensions to remove.
45
60
  * @param getLanguagePluginsFile - The file to get language plugins from.
61
+ * @param typescriptObject - The object to use as typescript.
46
62
  * @returns The modified typescript code.
47
63
  */
48
- function transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, getLanguagePluginsFile = __filename) {
64
+ function transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraExtensionsToRemove, getLanguagePluginsFile = __filename, typescriptObject = `new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } )`) {
49
65
  const neededPatchExtenstions = extraSupportedExtensions.filter(ext => !extraExtensionsToRemove.includes(ext));
50
66
  // Add allow extensions
51
67
  if (extraSupportedExtensions.length) {
@@ -71,7 +87,7 @@ function transformTscContent(tsc, proxyApiPath, extraSupportedExtensions, extraE
71
87
  // proxy createProgram
72
88
  tsc = replace(tsc, /function createProgram\(.+\) {/, s => `var createProgram = require(${JSON.stringify(proxyApiPath)}).proxyCreateProgram(`
73
89
  + [
74
- `new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } )`,
90
+ typescriptObject,
75
91
  `_createProgram`,
76
92
  `require(${JSON.stringify(getLanguagePluginsFile)}).getLanguagePlugins`,
77
93
  ].join(', ')
@@ -84,7 +100,7 @@ function replace(text, ...[search, replace]) {
84
100
  text = text.replace(search, replace);
85
101
  const after = text;
86
102
  if (after === before) {
87
- throw 'Search string not found: ' + JSON.stringify(search.toString());
103
+ throw new Error('Failed to replace: ' + search);
88
104
  }
89
105
  return after;
90
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volar/typescript",
3
- "version": "2.4.10",
3
+ "version": "2.4.11",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,14 +12,14 @@
12
12
  "directory": "packages/typescript"
13
13
  },
14
14
  "dependencies": {
15
- "@volar/language-core": "2.4.10",
15
+ "@volar/language-core": "2.4.11",
16
16
  "path-browserify": "^1.0.1",
17
17
  "vscode-uri": "^3.0.8"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@types/node": "latest",
21
21
  "@types/path-browserify": "latest",
22
- "@volar/language-service": "2.4.10"
22
+ "@volar/language-service": "2.4.11"
23
23
  },
24
- "gitHead": "03d1e8b07e1e64921b76b635c7064d7b4fcf63b5"
24
+ "gitHead": "42ccae005cc8516e07ad38f4d7730cab9b723340"
25
25
  }