版博士V2.0程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

381 rivejä
12 KiB

  1. "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/ts.ts
  2. var _promises = require('fs/promises');
  3. var _fs = require('fs');
  4. var _path = require('path'); var _path2 = _interopRequireDefault(_path);
  5. var _common = require('@vue-macros/common');
  6. var _types = require('@babel/types');
  7. var tsFileCache = {};
  8. async function getTSFile(filePath) {
  9. if (tsFileCache[filePath])
  10. return tsFileCache[filePath];
  11. const content = await _promises.readFile.call(void 0, filePath, "utf-8");
  12. const { code, lang } = _common.getFileCodeAndLang.call(void 0, content, filePath);
  13. const program = _common.babelParse.call(void 0, code, lang);
  14. return tsFileCache[filePath] = {
  15. filePath,
  16. content,
  17. ast: program.body
  18. };
  19. }
  20. function isTSDeclaration(node) {
  21. return _types.isDeclaration.call(void 0, node) && node.type.startsWith("TS");
  22. }
  23. function mergeTSProperties(a, b) {
  24. return {
  25. callSignatures: [...a.callSignatures, ...b.callSignatures],
  26. constructSignatures: [...a.constructSignatures, ...b.constructSignatures],
  27. methods: { ...a.methods, ...b.methods },
  28. properties: { ...a.properties, ...b.properties }
  29. };
  30. }
  31. async function resolveTSProperties({
  32. type,
  33. scope
  34. }) {
  35. switch (type.type) {
  36. case "TSInterfaceBody":
  37. return resolveTypeElements(scope, type.body);
  38. case "TSTypeLiteral":
  39. return resolveTypeElements(scope, type.members);
  40. case "TSInterfaceDeclaration": {
  41. let properties = resolveTypeElements(scope, type.body.body);
  42. if (type.extends) {
  43. const resolvedExtends = (await Promise.all(
  44. type.extends.map(
  45. (node) => node.expression.type === "Identifier" ? resolveTSReferencedType({
  46. scope,
  47. type: node.expression
  48. }) : void 0
  49. )
  50. )).filter(filterValidExtends);
  51. if (resolvedExtends.length > 0) {
  52. const ext = (await Promise.all(
  53. resolvedExtends.map((resolved) => resolveTSProperties(resolved))
  54. )).reduceRight((acc, curr) => mergeTSProperties(acc, curr));
  55. properties = mergeTSProperties(ext, properties);
  56. }
  57. }
  58. return properties;
  59. }
  60. case "TSIntersectionType": {
  61. let properties = {
  62. callSignatures: [],
  63. constructSignatures: [],
  64. methods: {},
  65. properties: {}
  66. };
  67. for (const subType of type.types) {
  68. const resolved = await resolveTSReferencedType({
  69. scope,
  70. type: subType
  71. });
  72. if (!filterValidExtends(resolved))
  73. continue;
  74. properties = mergeTSProperties(
  75. properties,
  76. await resolveTSProperties(resolved)
  77. );
  78. }
  79. return properties;
  80. }
  81. case "TSMappedType": {
  82. const properties = {
  83. callSignatures: [],
  84. constructSignatures: [],
  85. methods: {},
  86. properties: {}
  87. };
  88. if (!type.typeParameter.constraint)
  89. return properties;
  90. const constraint = await resolveTSReferencedType({
  91. type: type.typeParameter.constraint,
  92. scope
  93. });
  94. if (!(constraint == null ? void 0 : constraint.type))
  95. return properties;
  96. const types = constraint.type.type === "TSUnionType" ? constraint.type.types : [constraint.type];
  97. for (const subType of types) {
  98. if (subType.type !== "TSLiteralType")
  99. continue;
  100. const literal = subType.literal;
  101. if (!_common.isStaticExpression.call(void 0, literal))
  102. continue;
  103. const key = _common.resolveLiteral.call(void 0,
  104. literal
  105. );
  106. if (!key)
  107. continue;
  108. properties.properties[String(key)] = {
  109. value: type.typeAnnotation ? { scope, type: type.typeAnnotation } : null,
  110. optional: type.optional === "+" || type.optional === true,
  111. signature: { type, scope }
  112. };
  113. }
  114. return properties;
  115. }
  116. case "TSFunctionType": {
  117. const properties = {
  118. callSignatures: [{ type, scope }],
  119. constructSignatures: [],
  120. methods: {},
  121. properties: {}
  122. };
  123. return properties;
  124. }
  125. default:
  126. throw new Error(`unknown node: ${type == null ? void 0 : type.type}`);
  127. }
  128. function filterValidExtends(node) {
  129. return !isTSExports(node) && [
  130. "TSInterfaceDeclaration",
  131. "TSTypeLiteral",
  132. "TSIntersectionType"
  133. ].includes(node == null ? void 0 : node.type.type);
  134. }
  135. }
  136. function resolveTypeElements(scope, elements) {
  137. var _a;
  138. const properties = {
  139. callSignatures: [],
  140. constructSignatures: [],
  141. methods: {},
  142. properties: {}
  143. };
  144. const tryGetKey = (element) => {
  145. try {
  146. return _common.resolveObjectKey.call(void 0, element.key, element.computed, false);
  147. } catch (e) {
  148. }
  149. };
  150. for (const element of elements) {
  151. switch (element.type) {
  152. case "TSCallSignatureDeclaration":
  153. properties.callSignatures.push({ scope, type: element });
  154. break;
  155. case "TSConstructSignatureDeclaration":
  156. properties.constructSignatures.push({ scope, type: element });
  157. break;
  158. case "TSMethodSignature": {
  159. const key = tryGetKey(element);
  160. if (!key)
  161. continue;
  162. if (properties.properties[key])
  163. continue;
  164. if (!properties.methods[key])
  165. properties.methods[key] = [];
  166. if (element.typeAnnotation) {
  167. properties.methods[key].push({ scope, type: element });
  168. }
  169. break;
  170. }
  171. case "TSPropertySignature": {
  172. const key = tryGetKey(element);
  173. if (!key)
  174. continue;
  175. if (!properties.properties[key] && !properties.methods[key]) {
  176. const type = (_a = element.typeAnnotation) == null ? void 0 : _a.typeAnnotation;
  177. properties.properties[key] = {
  178. value: type ? { type, scope } : null,
  179. optional: !!element.optional,
  180. signature: { type: element, scope }
  181. };
  182. }
  183. break;
  184. }
  185. case "TSIndexSignature":
  186. break;
  187. }
  188. }
  189. return properties;
  190. }
  191. async function resolveTSReferencedType(ref, stacks = []) {
  192. var _a;
  193. const { scope, type } = ref;
  194. if (stacks.some((stack) => stack.scope === scope && stack.type === type)) {
  195. return ref;
  196. }
  197. stacks.push(ref);
  198. if (type.type === "TSTypeAliasDeclaration" || type.type === "TSParenthesizedType") {
  199. return resolveTSReferencedType({ scope, type: type.typeAnnotation }, stacks);
  200. }
  201. let refNames;
  202. if (type.type === "Identifier") {
  203. refNames = [type.name];
  204. } else if (type.type === "TSTypeReference") {
  205. if (type.typeName.type === "Identifier") {
  206. refNames = [type.typeName.name];
  207. } else {
  208. refNames = resolveTSEntityName(type.typeName).map((id) => id.name);
  209. }
  210. } else if (type.type === "TSModuleDeclaration" && type.body.type === "TSModuleBlock") {
  211. return resolveTSExports({ type: type.body, scope });
  212. } else {
  213. return { scope, type };
  214. }
  215. const [refName, ...restNames] = refNames;
  216. const { body, file } = resolveTSScope(scope);
  217. for (let node of body) {
  218. if (node.type === "ImportDeclaration") {
  219. const specifier = node.specifiers.find(
  220. (specifier2) => specifier2.type === "ImportSpecifier" && specifier2.imported.type === "Identifier" && specifier2.imported.name === refName || specifier2.type === "ImportNamespaceSpecifier" && specifier2.local.name === refName
  221. );
  222. if (!specifier)
  223. continue;
  224. const resolved = await resolveTSFileId(node.source.value, file.filePath);
  225. if (!resolved)
  226. continue;
  227. const exports = await resolveTSExports(await getTSFile(resolved));
  228. let type2 = exports;
  229. for (const name of specifier.type === "ImportSpecifier" ? refNames : restNames) {
  230. type2 = type2 == null ? void 0 : type2[name];
  231. }
  232. return type2;
  233. }
  234. if (node.type === "ExportNamedDeclaration" && node.declaration)
  235. node = node.declaration;
  236. if (isTSDeclaration(node)) {
  237. if (((_a = node.id) == null ? void 0 : _a.type) !== "Identifier")
  238. continue;
  239. if (node.id.name !== refName)
  240. continue;
  241. const resolved = await resolveTSReferencedType(
  242. { scope, type: node },
  243. stacks
  244. );
  245. if (!resolved)
  246. return;
  247. if (restNames.length === 0) {
  248. return resolved;
  249. } else {
  250. let exports = resolved;
  251. for (const name of restNames) {
  252. exports = exports[name];
  253. }
  254. return exports;
  255. }
  256. }
  257. }
  258. if (type.type === "TSTypeReference")
  259. return { scope, type };
  260. }
  261. function resolveTSScope(scope) {
  262. const isFile = "ast" in scope;
  263. const file = isFile ? scope : resolveTSScope(scope.scope).file;
  264. const body = isFile ? scope.ast : scope.type.body;
  265. return {
  266. isFile,
  267. file,
  268. body
  269. };
  270. }
  271. function resolveTSEntityName(node) {
  272. if (node.type === "Identifier")
  273. return [node];
  274. else {
  275. return [...resolveTSEntityName(node.left), node.right];
  276. }
  277. }
  278. var exportsSymbol = Symbol("exports");
  279. var tsFileExportsCache = /* @__PURE__ */ new Map();
  280. function isTSExports(val) {
  281. return !!val && typeof val === "object" && exportsSymbol in val;
  282. }
  283. async function resolveTSExports(scope) {
  284. var _a;
  285. if (tsFileExportsCache.has(scope))
  286. return tsFileExportsCache.get(scope);
  287. const exports = {
  288. [exportsSymbol]: true
  289. };
  290. tsFileExportsCache.set(scope, exports);
  291. const { body, file } = resolveTSScope(scope);
  292. for (const stmt of body) {
  293. if (stmt.type === "ExportDefaultDeclaration") {
  294. } else if (stmt.type === "ExportAllDeclaration") {
  295. const resolved = await resolveTSFileId(stmt.source.value, file.filePath);
  296. if (!resolved)
  297. continue;
  298. const sourceExports = await resolveTSExports(await getTSFile(resolved));
  299. Object.assign(exports, sourceExports);
  300. } else if (stmt.type === "ExportNamedDeclaration") {
  301. let sourceExports;
  302. if (stmt.source) {
  303. const resolved = await resolveTSFileId(stmt.source.value, file.filePath);
  304. if (!resolved)
  305. continue;
  306. sourceExports = await resolveTSExports(await getTSFile(resolved));
  307. }
  308. for (const specifier of stmt.specifiers) {
  309. if (specifier.type === "ExportDefaultSpecifier") {
  310. continue;
  311. }
  312. if (specifier.type === "ExportNamespaceSpecifier") {
  313. exports[specifier.exported.name] = sourceExports;
  314. } else {
  315. const exportedName = specifier.exported.type === "Identifier" ? specifier.exported.name : specifier.exported.value;
  316. if (stmt.source) {
  317. exports[exportedName] = sourceExports[specifier.local.name];
  318. } else {
  319. exports[exportedName] = await resolveTSReferencedType({
  320. scope,
  321. type: specifier.local
  322. });
  323. }
  324. }
  325. }
  326. if (isTSDeclaration(stmt.declaration)) {
  327. const decl = stmt.declaration;
  328. if (((_a = decl.id) == null ? void 0 : _a.type) === "Identifier") {
  329. const exportedName = decl.id.name;
  330. exports[exportedName] = await resolveTSReferencedType({
  331. scope,
  332. type: decl
  333. });
  334. }
  335. }
  336. }
  337. }
  338. return exports;
  339. }
  340. var resolveTSFileIdImpl = resolveTSFileIdNode;
  341. function resolveTSFileId(id, importer) {
  342. return resolveTSFileIdImpl(id, importer);
  343. }
  344. function resolveTSFileIdNode(id, importer) {
  345. function tryResolve(id2, importer2) {
  346. const filePath = _path2.default.resolve(importer2, "..", id2);
  347. if (!_fs.existsSync.call(void 0, filePath))
  348. return;
  349. return filePath;
  350. }
  351. return tryResolve(id, importer) || tryResolve(`${id}.ts`, importer) || tryResolve(`${id}.d.ts`, importer) || tryResolve(`${id}/index`, importer) || tryResolve(`${id}/index.ts`, importer) || tryResolve(`${id}/index.d.ts`, importer);
  352. }
  353. function setResolveTSFileIdImpl(impl) {
  354. resolveTSFileIdImpl = impl;
  355. }
  356. exports.tsFileCache = tsFileCache; exports.getTSFile = getTSFile; exports.isTSDeclaration = isTSDeclaration; exports.mergeTSProperties = mergeTSProperties; exports.resolveTSProperties = resolveTSProperties; exports.resolveTypeElements = resolveTypeElements; exports.resolveTSReferencedType = resolveTSReferencedType; exports.resolveTSScope = resolveTSScope; exports.resolveTSEntityName = resolveTSEntityName; exports.exportsSymbol = exportsSymbol; exports.tsFileExportsCache = tsFileExportsCache; exports.isTSExports = isTSExports; exports.resolveTSExports = resolveTSExports; exports.resolveTSFileId = resolveTSFileId; exports.resolveTSFileIdNode = resolveTSFileIdNode; exports.setResolveTSFileIdImpl = setResolveTSFileIdImpl;