index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __exportStar = (this && this.__exportStar) || function(m, exports) {
  14. for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
  15. };
  16. Object.defineProperty(exports, "__esModule", { value: true });
  17. exports.defaultMapperFactory = exports.SourceMap = void 0;
  18. exports.createLanguage = createLanguage;
  19. exports.forEachEmbeddedCode = forEachEmbeddedCode;
  20. var source_map_1 = require("@volar/source-map");
  21. Object.defineProperty(exports, "SourceMap", { enumerable: true, get: function () { return source_map_1.SourceMap; } });
  22. __exportStar(require("./lib/editor"), exports);
  23. __exportStar(require("./lib/linkedCodeMap"), exports);
  24. __exportStar(require("./lib/types"), exports);
  25. __exportStar(require("./lib/utils"), exports);
  26. const source_map_2 = require("@volar/source-map");
  27. const linkedCodeMap_1 = require("./lib/linkedCodeMap");
  28. const defaultMapperFactory = mappings => new source_map_2.SourceMap(mappings);
  29. exports.defaultMapperFactory = defaultMapperFactory;
  30. function createLanguage(plugins, scriptRegistry, sync, onAssociationDirty) {
  31. const virtualCodeToSourceScriptMap = new WeakMap();
  32. const virtualCodeToSourceMap = new WeakMap();
  33. const virtualCodeToLinkedCodeMap = new WeakMap();
  34. const language = {
  35. mapperFactory: exports.defaultMapperFactory,
  36. plugins,
  37. scripts: {
  38. fromVirtualCode(virtualCode) {
  39. return virtualCodeToSourceScriptMap.get(virtualCode);
  40. },
  41. get(id, includeFsFiles = true, shouldRegister = false) {
  42. sync(id, includeFsFiles, shouldRegister);
  43. const result = scriptRegistry.get(id);
  44. // The sync function provider may not always call the set function due to caching, so it is necessary to explicitly check isAssociationDirty.
  45. if (result?.isAssociationDirty) {
  46. this.set(id, result.snapshot, result.languageId);
  47. }
  48. return scriptRegistry.get(id);
  49. },
  50. set(id, snapshot, languageId, _plugins = plugins) {
  51. if (!languageId) {
  52. for (const plugin of plugins) {
  53. languageId = plugin.getLanguageId?.(id);
  54. if (languageId) {
  55. break;
  56. }
  57. }
  58. }
  59. if (!languageId) {
  60. console.warn(`languageId not found for ${id}`);
  61. return;
  62. }
  63. let associatedOnly = false;
  64. for (const plugin of plugins) {
  65. if (plugin.isAssociatedFileOnly?.(id, languageId)) {
  66. associatedOnly = true;
  67. break;
  68. }
  69. }
  70. if (scriptRegistry.has(id)) {
  71. const sourceScript = scriptRegistry.get(id);
  72. if (sourceScript.languageId !== languageId || sourceScript.associatedOnly !== associatedOnly) {
  73. this.delete(id);
  74. triggerTargetsDirty(sourceScript);
  75. return this.set(id, snapshot, languageId);
  76. }
  77. else if (associatedOnly) {
  78. if (sourceScript.snapshot !== snapshot) {
  79. sourceScript.snapshot = snapshot;
  80. triggerTargetsDirty(sourceScript);
  81. }
  82. }
  83. else if (sourceScript.isAssociationDirty || sourceScript.snapshot !== snapshot) {
  84. if (sourceScript.snapshot !== snapshot) {
  85. sourceScript.snapshot = snapshot;
  86. triggerTargetsDirty(sourceScript);
  87. }
  88. const codegenCtx = prepareCreateVirtualCode(sourceScript);
  89. if (sourceScript.generated) {
  90. const { updateVirtualCode, createVirtualCode } = sourceScript.generated.languagePlugin;
  91. const newVirtualCode = updateVirtualCode
  92. ? updateVirtualCode(id, sourceScript.generated.root, snapshot, codegenCtx)
  93. : createVirtualCode?.(id, languageId, snapshot, codegenCtx);
  94. if (newVirtualCode) {
  95. sourceScript.generated.root = newVirtualCode;
  96. sourceScript.generated.embeddedCodes.clear();
  97. for (const code of forEachEmbeddedCode(sourceScript.generated.root)) {
  98. virtualCodeToSourceScriptMap.set(code, sourceScript);
  99. sourceScript.generated.embeddedCodes.set(code.id, code);
  100. }
  101. return sourceScript;
  102. }
  103. else {
  104. this.delete(id);
  105. return;
  106. }
  107. }
  108. }
  109. else {
  110. // not changed
  111. return sourceScript;
  112. }
  113. }
  114. else {
  115. // created
  116. const sourceScript = {
  117. id: id,
  118. languageId,
  119. snapshot,
  120. associatedIds: new Set(),
  121. targetIds: new Set(),
  122. associatedOnly
  123. };
  124. scriptRegistry.set(id, sourceScript);
  125. if (associatedOnly) {
  126. return sourceScript;
  127. }
  128. for (const languagePlugin of _plugins) {
  129. const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot, prepareCreateVirtualCode(sourceScript));
  130. if (virtualCode) {
  131. sourceScript.generated = {
  132. root: virtualCode,
  133. languagePlugin,
  134. embeddedCodes: new Map(),
  135. };
  136. for (const code of forEachEmbeddedCode(virtualCode)) {
  137. virtualCodeToSourceScriptMap.set(code, sourceScript);
  138. sourceScript.generated.embeddedCodes.set(code.id, code);
  139. }
  140. break;
  141. }
  142. }
  143. return sourceScript;
  144. }
  145. },
  146. delete(id) {
  147. const sourceScript = scriptRegistry.get(id);
  148. if (sourceScript) {
  149. sourceScript.generated?.languagePlugin.disposeVirtualCode?.(id, sourceScript.generated.root);
  150. scriptRegistry.delete(id);
  151. triggerTargetsDirty(sourceScript);
  152. }
  153. },
  154. },
  155. maps: {
  156. get(virtualCode, sourceScript) {
  157. let mapCache = virtualCodeToSourceMap.get(virtualCode.snapshot);
  158. if (!mapCache) {
  159. virtualCodeToSourceMap.set(virtualCode.snapshot, mapCache = new WeakMap());
  160. }
  161. if (!mapCache.has(sourceScript.snapshot)) {
  162. const mappings = virtualCode.associatedScriptMappings?.get(sourceScript.id) ?? virtualCode.mappings;
  163. mapCache.set(sourceScript.snapshot, language.mapperFactory(mappings));
  164. }
  165. return mapCache.get(sourceScript.snapshot);
  166. },
  167. *forEach(virtualCode) {
  168. const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
  169. yield [
  170. sourceScript,
  171. this.get(virtualCode, sourceScript),
  172. ];
  173. if (virtualCode.associatedScriptMappings) {
  174. for (const [relatedScriptId] of virtualCode.associatedScriptMappings) {
  175. const relatedSourceScript = scriptRegistry.get(relatedScriptId);
  176. if (relatedSourceScript) {
  177. yield [
  178. relatedSourceScript,
  179. this.get(virtualCode, relatedSourceScript),
  180. ];
  181. }
  182. }
  183. }
  184. },
  185. },
  186. linkedCodeMaps: {
  187. get(virtualCode) {
  188. const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
  189. let mapCache = virtualCodeToLinkedCodeMap.get(virtualCode.snapshot);
  190. if (mapCache?.[0] !== sourceScript.snapshot) {
  191. virtualCodeToLinkedCodeMap.set(virtualCode.snapshot, mapCache = [
  192. sourceScript.snapshot,
  193. virtualCode.linkedCodeMappings
  194. ? new linkedCodeMap_1.LinkedCodeMap(virtualCode.linkedCodeMappings)
  195. : undefined,
  196. ]);
  197. }
  198. return mapCache[1];
  199. },
  200. },
  201. };
  202. return language;
  203. function triggerTargetsDirty(sourceScript) {
  204. sourceScript.targetIds.forEach(id => {
  205. const sourceScript = scriptRegistry.get(id);
  206. if (sourceScript) {
  207. sourceScript.isAssociationDirty = true;
  208. onAssociationDirty?.(sourceScript.id);
  209. }
  210. });
  211. }
  212. function prepareCreateVirtualCode(sourceScript) {
  213. for (const id of sourceScript.associatedIds) {
  214. scriptRegistry.get(id)?.targetIds.delete(sourceScript.id);
  215. }
  216. sourceScript.associatedIds.clear();
  217. sourceScript.isAssociationDirty = false;
  218. return {
  219. getAssociatedScript(id) {
  220. sync(id, true, true);
  221. const relatedSourceScript = scriptRegistry.get(id);
  222. if (relatedSourceScript) {
  223. relatedSourceScript.targetIds.add(sourceScript.id);
  224. sourceScript.associatedIds.add(relatedSourceScript.id);
  225. }
  226. return relatedSourceScript;
  227. },
  228. };
  229. }
  230. }
  231. function* forEachEmbeddedCode(virtualCode) {
  232. yield virtualCode;
  233. if (virtualCode.embeddedCodes) {
  234. for (const embeddedCode of virtualCode.embeddedCodes) {
  235. yield* forEachEmbeddedCode(embeddedCode);
  236. }
  237. }
  238. }
  239. //# sourceMappingURL=index.js.map