code.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.resolvePlatformIndex = exports.resolvePlatformIndexFilename = exports.resolveRootInterface = exports.resolveRootIndex = exports.genComponentsCode = exports.genProxyCode = void 0;
  7. const fs_1 = __importDefault(require("fs"));
  8. const path_1 = __importDefault(require("path"));
  9. const shared_1 = require("@vue/shared");
  10. const utils_1 = require("./utils");
  11. const shared_2 = require("./shared");
  12. const stacktrace_1 = require("./stacktrace");
  13. async function genProxyCode(module, options) {
  14. const { name, is_uni_modules, format, moduleName, moduleType } = options;
  15. options.inputDir = options.inputDir || process.env.UNI_INPUT_DIR;
  16. if (!options.meta) {
  17. options.meta = { exports: {}, types: {} };
  18. }
  19. options.types = await parseInterfaceTypes(module, options);
  20. options.meta.types = parseMetaTypes(options.types);
  21. const decls = await parseModuleDecls(module, options);
  22. return `
  23. const { registerUTSInterface, initUTSProxyClass, initUTSProxyFunction, initUTSPackageName, initUTSIndexClassName, initUTSClassName } = uni
  24. const name = '${name}'
  25. const moduleName = '${moduleName || ''}'
  26. const moduleType = '${moduleType || ''}'
  27. const errMsg = \`${utils_1.ERR_MSG_PLACEHOLDER}\`
  28. const is_uni_modules = ${is_uni_modules}
  29. const pkg = /*#__PURE__*/ initUTSPackageName(name, is_uni_modules)
  30. const cls = /*#__PURE__*/ initUTSIndexClassName(name, is_uni_modules)
  31. ${format === "cjs" /* FORMATS.CJS */
  32. ? `
  33. const exports = { __esModule: true }
  34. `
  35. : ''}
  36. ${genComponentsCode(format, options.androidComponents || {}, options.iosComponents || {})}
  37. ${genModuleCode(decls, format, options.pluginRelativeDir, options.meta)}
  38. `;
  39. }
  40. exports.genProxyCode = genProxyCode;
  41. function parseMetaTypes(types) {
  42. let res = {};
  43. types.class.forEach((n) => {
  44. res[n] = 'class';
  45. });
  46. Object.keys(types.fn).forEach((n) => {
  47. res[n] = 'function';
  48. });
  49. Object.keys(types.interface).forEach((n) => {
  50. res[n] = 'interface';
  51. });
  52. return res;
  53. }
  54. function genComponentsCode(format = "es" /* FORMATS.ES */, androidComponents, iosComponents) {
  55. const codes = [];
  56. Object.keys(Object.assign({}, androidComponents, iosComponents)).forEach((name) => {
  57. if (format === "cjs" /* FORMATS.CJS */) {
  58. codes.push(`exports.${(0, shared_1.capitalize)((0, shared_1.camelize)(name))}Component = {}`);
  59. }
  60. else {
  61. codes.push(`export const ${(0, shared_1.capitalize)((0, shared_1.camelize)(name))}Component = {}`);
  62. }
  63. });
  64. return codes.join('\n');
  65. }
  66. exports.genComponentsCode = genComponentsCode;
  67. function resolveRootIndex(module, options) {
  68. const filename = path_1.default.resolve(module, options.is_uni_modules ? 'utssdk' : '', `index${options.extname}`);
  69. return fs_1.default.existsSync(filename) && filename;
  70. }
  71. exports.resolveRootIndex = resolveRootIndex;
  72. function resolveRootInterface(module, options) {
  73. const filename = path_1.default.resolve(module, options.is_uni_modules ? 'utssdk' : '', `interface${options.extname}`);
  74. return fs_1.default.existsSync(filename) && filename;
  75. }
  76. exports.resolveRootInterface = resolveRootInterface;
  77. function resolvePlatformIndexFilename(platform, module, options) {
  78. return path_1.default.resolve(module, options.is_uni_modules ? 'utssdk' : '', platform, `index${options.extname}`);
  79. }
  80. exports.resolvePlatformIndexFilename = resolvePlatformIndexFilename;
  81. function resolvePlatformIndex(platform, module, options) {
  82. const filename = resolvePlatformIndexFilename(platform, module, options);
  83. return fs_1.default.existsSync(filename) && filename;
  84. }
  85. exports.resolvePlatformIndex = resolvePlatformIndex;
  86. function exportDefaultCode(format) {
  87. return format === "es" /* FORMATS.ES */
  88. ? 'export default /*#__PURE__*/ '
  89. : 'exports.default = ';
  90. }
  91. function exportVarCode(format, kind) {
  92. if (format === "es" /* FORMATS.ES */) {
  93. return `export ${kind} `;
  94. }
  95. return `exports.`;
  96. }
  97. function isClassReturnOptions(value) {
  98. return ((0, shared_1.isPlainObject)(value) &&
  99. value.type === 'interface' &&
  100. (0, shared_1.isString)(value.options));
  101. }
  102. function genClassOptionsCode(options) {
  103. return JSON.stringify(options, (key, value) => {
  104. if (key === 'return' && isClassReturnOptions(value)) {
  105. return { type: 'interface', options: `${value.options}Options` };
  106. }
  107. return value;
  108. });
  109. }
  110. function genModuleCode(decls, format = "es" /* FORMATS.ES */, pluginRelativeDir, meta) {
  111. const codes = [];
  112. const exportDefault = exportDefaultCode(format);
  113. const exportConst = exportVarCode(format, 'const');
  114. decls.forEach((decl) => {
  115. if (decl.type === 'InterfaceDeclaration') {
  116. meta.exports[decl.cls] = 'interface';
  117. codes.push(`registerUTSInterface('${decl.cls}Options',Object.assign({ moduleName, moduleType, errMsg, package: pkg, class: initUTSClassName(name, '${decl.cls}ByJsProxy', is_uni_modules) }, ${genClassOptionsCode(decl.options)} ))`);
  118. }
  119. else if (decl.type === 'Class') {
  120. meta.exports[decl.cls] = decl.isVar ? 'var' : 'class';
  121. if (decl.isDefault) {
  122. codes.push(`${exportDefault}initUTSProxyClass(Object.assign({ moduleName, moduleType, errMsg, package: pkg, class: initUTSClassName(name, '${decl.cls}ByJs', is_uni_modules) }, ${genClassOptionsCode(decl.options)} ))`);
  123. }
  124. else {
  125. codes.push(`${exportConst}${decl.cls} = /*#__PURE__*/ initUTSProxyClass(Object.assign({ moduleName, moduleType, errMsg, package: pkg, class: initUTSClassName(name, '${decl.cls}ByJs', is_uni_modules) }, ${genClassOptionsCode(decl.options)} ))`);
  126. }
  127. }
  128. else if (decl.type === 'FunctionDeclaration') {
  129. meta.exports[decl.method] = decl.isVar ? 'var' : 'function';
  130. const returnOptions = decl.return
  131. ? { type: decl.return.type, options: decl.return.options + 'Options' }
  132. : '';
  133. if (decl.isDefault) {
  134. codes.push(`${exportDefault}initUTSProxyFunction(${decl.async}, { moduleName, moduleType, errMsg, main: true, package: pkg, class: cls, name: '${decl.method}ByJs', params: ${JSON.stringify(decl.params)}, return: ${JSON.stringify(returnOptions)}})`);
  135. }
  136. else {
  137. codes.push(`${exportConst}${decl.method} = /*#__PURE__*/ initUTSProxyFunction(${decl.async}, { moduleName, moduleType, errMsg, main: true, package: pkg, class: cls, name: '${decl.method}ByJs', params: ${JSON.stringify(decl.params)}, return: ${JSON.stringify(returnOptions)}})`);
  138. }
  139. }
  140. else if (decl.type === 'VariableDeclaration') {
  141. decl.declarations.forEach((d) => {
  142. meta.exports[d.id.value] = 'var';
  143. });
  144. if (format === "es" /* FORMATS.ES */) {
  145. codes.push(`export ${decl.kind} ${decl.declarations
  146. .map((d) => `${d.id.value} = ${genInitCode(d.init)}`)
  147. .join(', ')}`);
  148. }
  149. else if (format === "cjs" /* FORMATS.CJS */) {
  150. codes.push(`${decl.kind} ${decl.declarations
  151. .map((d) => `${d.id.value} = ${genInitCode(d.init)}`)
  152. .join(', ')}`);
  153. const exportVar = exportVarCode(format, decl.kind);
  154. decl.declarations.forEach((d) => {
  155. const name = d.id.value;
  156. codes.push(`${exportVar}${name} = ${name}`);
  157. });
  158. }
  159. }
  160. });
  161. if (format === "cjs" /* FORMATS.CJS */) {
  162. codes.push(`uni.registerUTSPlugin('${(0, shared_2.normalizePath)(pluginRelativeDir)}', exports)`);
  163. }
  164. return codes.join(`\n`);
  165. }
  166. /**
  167. * 解析接口文件中定义的类型信息
  168. * @param module
  169. * @param options
  170. * @returns
  171. */
  172. async function parseInterfaceTypes(module, options) {
  173. const interfaceFilename = resolveRootInterface(module, options);
  174. if (!interfaceFilename) {
  175. return {
  176. interface: {},
  177. class: [],
  178. fn: {},
  179. };
  180. }
  181. // 懒加载 uts 编译器
  182. // eslint-disable-next-line no-restricted-globals
  183. const { parse } = require('@dcloudio/uts');
  184. let ast = null;
  185. try {
  186. ast = await parse(fs_1.default.readFileSync(interfaceFilename, 'utf8'), {
  187. filename: (0, utils_1.relative)(interfaceFilename, options.inputDir),
  188. noColor: !(0, utils_1.isColorSupported)(),
  189. });
  190. }
  191. catch (e) {
  192. console.error((0, stacktrace_1.parseUTSSyntaxError)(e, options.inputDir));
  193. }
  194. return parseAstTypes(ast, true);
  195. }
  196. function parseAstTypes(ast, isInterface) {
  197. const interfaceTypes = {};
  198. const classTypes = [];
  199. const fnTypes = {};
  200. const exportNamed = [];
  201. if (ast) {
  202. if (isInterface) {
  203. ast.body.filter((node) => {
  204. if (node.type === 'ExportNamedDeclaration') {
  205. node.specifiers.forEach((s) => {
  206. if (s.type === 'ExportSpecifier') {
  207. if (s.exported) {
  208. if (s.exported.type === 'Identifier') {
  209. exportNamed.push(s.exported.value);
  210. }
  211. }
  212. else {
  213. exportNamed.push(s.orig.value);
  214. }
  215. }
  216. });
  217. }
  218. });
  219. }
  220. ast.body.filter((node) => {
  221. if (node.type === 'ExportDeclaration') {
  222. if (node.declaration.type === 'TsTypeAliasDeclaration') {
  223. parseTypes(node.declaration, classTypes, fnTypes);
  224. }
  225. else if (node.declaration.type === 'TsInterfaceDeclaration') {
  226. interfaceTypes[node.declaration.id.value] = {
  227. returned: false,
  228. decl: node.declaration,
  229. };
  230. }
  231. }
  232. else if (node.type === 'TsTypeAliasDeclaration') {
  233. if (!isInterface || exportNamed.includes(node.id.value)) {
  234. parseTypes(node, classTypes, fnTypes);
  235. }
  236. }
  237. else if (node.type === 'TsInterfaceDeclaration') {
  238. interfaceTypes[node.id.value] = {
  239. returned: false,
  240. decl: node,
  241. };
  242. }
  243. });
  244. }
  245. return {
  246. interface: interfaceTypes,
  247. class: classTypes,
  248. fn: fnTypes,
  249. };
  250. }
  251. function parseTypes(decl, classTypes, fnTypes) {
  252. switch (decl.typeAnnotation.type) {
  253. // export type ShowLoading = ()=>void
  254. case 'TsFunctionType':
  255. const params = createParams(decl.typeAnnotation.params);
  256. if (params.length) {
  257. fnTypes[decl.id.value] = params;
  258. }
  259. else {
  260. fnTypes[decl.id.value] = [];
  261. }
  262. break;
  263. // export type ShowLoadingOptions = {}
  264. case 'TsTypeLiteral':
  265. classTypes.push(decl.id.value);
  266. }
  267. }
  268. function createParams(tsParams) {
  269. const params = [];
  270. tsParams.forEach((pat) => {
  271. if (pat.type === 'Identifier') {
  272. params.push({
  273. type: 'Parameter',
  274. pat,
  275. span: {},
  276. });
  277. }
  278. });
  279. return params;
  280. }
  281. async function parseModuleDecls(module, options) {
  282. // 优先合并 ios + android,如果没有,查找根目录 index.uts
  283. const iosDecls = await parseFile(resolvePlatformIndex('app-ios', module, options), options);
  284. const androidDecls = await parseFile(resolvePlatformIndex('app-android', module, options), options);
  285. // 优先使用 app-ios,因为 app-ios 平台函数类型需要正确的参数列表
  286. const decls = mergeDecls(androidDecls, iosDecls);
  287. // 如果没有平台特有,查找 root index.uts
  288. if (!decls.length) {
  289. return await parseFile(resolveRootIndex(module, options), options);
  290. }
  291. return decls;
  292. }
  293. function mergeDecls(from, to) {
  294. from.forEach((item) => {
  295. if (item.type === 'InterfaceDeclaration') {
  296. if (!to.find((toItem) => toItem.type === 'InterfaceDeclaration' && toItem.cls === item.cls)) {
  297. to.push(item);
  298. }
  299. }
  300. else if (item.type === 'Class') {
  301. if (!to.find((toItem) => toItem.type === 'Class' &&
  302. toItem.cls === item.cls &&
  303. toItem.isDefault === item.isDefault)) {
  304. to.push(item);
  305. }
  306. }
  307. else if (item.type === 'FunctionDeclaration') {
  308. if (!to.find((toItem) => toItem.type === 'FunctionDeclaration' &&
  309. toItem.method === item.method &&
  310. toItem.isDefault === item.isDefault)) {
  311. to.push(item);
  312. }
  313. }
  314. else if (item.type === 'VariableDeclaration' &&
  315. item.declarations.length === 1) {
  316. if (!to.find((toItem) => {
  317. if (toItem.type === 'VariableDeclaration' &&
  318. toItem.declarations.length === 1) {
  319. const toDecl = toItem.declarations[0].id;
  320. const decl = item.declarations[0].id;
  321. return (toDecl.type === 'Identifier' &&
  322. decl.type === 'Identifier' &&
  323. toDecl.value === decl.value);
  324. }
  325. return false;
  326. })) {
  327. to.push(item);
  328. }
  329. }
  330. });
  331. return to;
  332. }
  333. async function parseFile(filename, options) {
  334. if (filename) {
  335. return parseCode(fs_1.default.readFileSync(filename, 'utf8'), options.namespace, options.types, filename, options.inputDir);
  336. }
  337. return [];
  338. }
  339. async function parseCode(code, namespace, types, filename, inputDir) {
  340. // 懒加载 uts 编译器
  341. // eslint-disable-next-line no-restricted-globals
  342. const { parse } = require('@dcloudio/uts');
  343. try {
  344. const ast = await parse(code, {
  345. filename: (0, utils_1.relative)(filename, inputDir),
  346. noColor: !(0, utils_1.isColorSupported)(),
  347. });
  348. return parseAst(ast, (0, utils_1.createResolveTypeReferenceName)(namespace, ast, types.class), types);
  349. }
  350. catch (e) {
  351. console.error((0, stacktrace_1.parseUTSSyntaxError)(e, inputDir));
  352. }
  353. return [];
  354. }
  355. function mergeAstTypes(to, from) {
  356. if (from.class.length) {
  357. to.class = [...new Set(...[...to.class, ...from.class])];
  358. }
  359. if (Object.keys(from.fn).length) {
  360. for (const name in from.fn) {
  361. if (!(0, shared_1.hasOwn)(to.fn, name)) {
  362. to.fn[name] = from.fn[name];
  363. }
  364. }
  365. }
  366. if (Object.keys(from.interface).length) {
  367. for (const name in from.interface) {
  368. if (!(0, shared_1.hasOwn)(to.interface, name)) {
  369. to.interface[name] = from.interface[name];
  370. }
  371. }
  372. }
  373. }
  374. function parseAst(ast, resolveTypeReferenceName, types) {
  375. const decls = [];
  376. mergeAstTypes(types, parseAstTypes(ast, false));
  377. ast.body.forEach((item) => {
  378. if (item.type === 'ExportDeclaration') {
  379. const decl = item.declaration;
  380. switch (decl.type) {
  381. case 'FunctionDeclaration':
  382. decls.push(genFunctionDeclaration(types, decl, resolveTypeReferenceName, false));
  383. break;
  384. case 'ClassDeclaration':
  385. decls.push(genClassDeclaration(types, decl, resolveTypeReferenceName, false));
  386. break;
  387. case 'VariableDeclaration':
  388. const varDecl = genVariableDeclaration(types, decl, resolveTypeReferenceName);
  389. if (varDecl) {
  390. decls.push(varDecl);
  391. }
  392. break;
  393. }
  394. }
  395. else if (item.type === 'ExportDefaultDeclaration') {
  396. const decl = item.decl;
  397. if (decl.type === 'ClassExpression') {
  398. if (decl.identifier) {
  399. // export default class test{}
  400. decls.push(genClassDeclaration(types, decl, resolveTypeReferenceName, true));
  401. }
  402. }
  403. else if (decl.type === 'FunctionExpression') {
  404. if (decl.identifier) {
  405. decls.push(genFunctionDeclaration(types, decl, resolveTypeReferenceName, true));
  406. }
  407. }
  408. }
  409. });
  410. const interfaces = [];
  411. Object.keys(types.interface).forEach((name) => {
  412. const options = types.interface[name];
  413. if (options.returned) {
  414. interfaces.push(genInterfaceDeclaration(types, options.decl, resolveTypeReferenceName));
  415. }
  416. });
  417. return [...interfaces, ...decls];
  418. }
  419. function isReturnPromise(anno) {
  420. if (!anno) {
  421. return false;
  422. }
  423. const { typeAnnotation } = anno;
  424. return (typeAnnotation.type === 'TsTypeReference' &&
  425. typeAnnotation.typeName.type === 'Identifier' &&
  426. typeAnnotation.typeName.value === 'Promise');
  427. }
  428. function genProxyFunction(method, async, params, ret = '', isDefault = false, isVar = false) {
  429. return {
  430. type: 'FunctionDeclaration',
  431. method,
  432. async,
  433. params,
  434. return: ret ? { type: 'interface', options: ret } : undefined,
  435. isDefault,
  436. isVar,
  437. };
  438. }
  439. function genProxyClass(cls, options, isDefault = false, isVar = false) {
  440. return { type: 'Class', cls, options, isDefault, isVar };
  441. }
  442. function resolveIdentifierDefaultValue(ident) {
  443. if (ident.type === 'NullLiteral') {
  444. return 'UTSNull';
  445. }
  446. else if (ident.type === 'StringLiteral' ||
  447. ident.type === 'NumericLiteral' ||
  448. ident.type === 'BooleanLiteral') {
  449. return ident.value;
  450. }
  451. return null;
  452. }
  453. function resolveType(types, typeAnnotation, resolveTypeReferenceName) {
  454. if (typeAnnotation.type === 'TsKeywordType') {
  455. return typeAnnotation.kind;
  456. }
  457. else if (typeAnnotation.type === 'TsFunctionType') {
  458. return 'UTSCallback';
  459. }
  460. else if (typeAnnotation.type === 'TsTypeReference' &&
  461. typeAnnotation.typeName.type === 'Identifier') {
  462. if ((0, shared_1.hasOwn)(types.fn, typeAnnotation.typeName.value)) {
  463. return 'UTSCallback';
  464. }
  465. return resolveTypeReferenceName(typeAnnotation.typeName.value);
  466. }
  467. else if (typeAnnotation.type === 'TsParenthesizedType') {
  468. return resolveType(types, typeAnnotation.typeAnnotation, resolveTypeReferenceName);
  469. }
  470. else if (typeAnnotation.type === 'TsUnionType') {
  471. for (const type of typeAnnotation.types) {
  472. if (type.type === 'TsKeywordType') {
  473. continue;
  474. }
  475. return resolveType(types, type, resolveTypeReferenceName);
  476. }
  477. }
  478. return '';
  479. }
  480. function resolveIdentifierType(types, ident, resolveTypeReferenceName) {
  481. if (ident.typeAnnotation) {
  482. return resolveType(types, ident.typeAnnotation.typeAnnotation, resolveTypeReferenceName);
  483. }
  484. return '';
  485. }
  486. function resolveFunctionParams(types, params, resolveTypeReferenceName) {
  487. const result = [];
  488. params.forEach(({ pat }) => {
  489. if (pat.type === 'Identifier') {
  490. result.push({
  491. name: pat.value,
  492. type: resolveIdentifierType(types, pat, resolveTypeReferenceName),
  493. });
  494. }
  495. else if (pat.type === 'AssignmentPattern') {
  496. if (pat.left.type === 'Identifier') {
  497. const param = {
  498. name: pat.left.value,
  499. type: resolveIdentifierType(types, pat.left, resolveTypeReferenceName),
  500. };
  501. const defaultValue = resolveIdentifierDefaultValue(pat.right);
  502. if (defaultValue !== null) {
  503. param.default = defaultValue;
  504. }
  505. result.push(param);
  506. }
  507. }
  508. else {
  509. result.push({ name: '', type: '' });
  510. }
  511. });
  512. return result;
  513. }
  514. function parseReturnInterface(types, returnType) {
  515. switch (returnType.type) {
  516. case 'TsTypeReference':
  517. if (returnType.typeName.type === 'Identifier') {
  518. if ((0, shared_1.hasOwn)(types.interface, returnType.typeName.value)) {
  519. types.interface[returnType.typeName.value].returned = true;
  520. return returnType.typeName.value;
  521. }
  522. }
  523. break;
  524. case 'TsUnionType':
  525. for (const type of returnType.types) {
  526. if (type.type === 'TsKeywordType') {
  527. continue;
  528. }
  529. return parseReturnInterface(types, type);
  530. }
  531. break;
  532. case 'TsParenthesizedType':
  533. return parseReturnInterface(types, returnType.typeAnnotation);
  534. }
  535. return '';
  536. }
  537. function genFunctionDeclaration(types, decl, resolveTypeReferenceName, isDefault = false, isVar = false) {
  538. return genProxyFunction(decl.identifier.value, decl.async || isReturnPromise(decl.returnType), resolveFunctionParams(types, decl.params, resolveTypeReferenceName), decl.returnType
  539. ? parseReturnInterface(types, decl.returnType.typeAnnotation)
  540. : '', isDefault, isVar);
  541. }
  542. function genInterfaceDeclaration(types, decl, resolveTypeReferenceName) {
  543. const cls = decl.id.value;
  544. const methods = {};
  545. const props = [];
  546. decl.body.body.forEach((item) => {
  547. if (item.type === 'TsMethodSignature') {
  548. if (item.key.type === 'Identifier') {
  549. let returnOptions = {};
  550. if (item.typeAnn) {
  551. let returnInterface = parseReturnInterface(types, item.typeAnn.typeAnnotation);
  552. if (returnInterface) {
  553. returnOptions = {
  554. type: 'interface',
  555. options: returnInterface,
  556. };
  557. }
  558. }
  559. const name = item.key.value;
  560. const value = {
  561. async: isReturnPromise(item.typeAnn),
  562. params: resolveFunctionParams(types, tsParamsToParams(item.params), resolveTypeReferenceName),
  563. return: returnOptions,
  564. };
  565. methods[name + 'ByJs'] = value;
  566. }
  567. }
  568. else if (item.type === 'TsPropertySignature') {
  569. if (item.key.type === 'Identifier') {
  570. props.push(item.key.value);
  571. }
  572. }
  573. });
  574. return {
  575. type: 'InterfaceDeclaration',
  576. cls,
  577. options: {
  578. methods,
  579. props,
  580. },
  581. };
  582. }
  583. function tsParamsToParams(tsParams) {
  584. const params = [];
  585. tsParams.forEach((p) => {
  586. if (p.type === 'Identifier') {
  587. params.push({
  588. type: 'Parameter',
  589. pat: p,
  590. span: {},
  591. });
  592. }
  593. });
  594. return params;
  595. }
  596. function genClassDeclaration(types, decl, resolveTypeReferenceName, isDefault = false) {
  597. const cls = decl.identifier.value;
  598. const constructor = { params: [] };
  599. const methods = {};
  600. const staticMethods = {};
  601. const props = [];
  602. const staticProps = [];
  603. decl.body.forEach((item) => {
  604. if (item.type === 'Constructor') {
  605. constructor.params = resolveFunctionParams(types, item.params, resolveTypeReferenceName);
  606. }
  607. else if (item.type === 'ClassMethod') {
  608. if (item.key.type === 'Identifier') {
  609. let returnOptions = {};
  610. if (item.function.returnType) {
  611. let returnInterface = parseReturnInterface(types, item.function.returnType.typeAnnotation);
  612. if (returnInterface) {
  613. returnOptions = {
  614. type: 'interface',
  615. options: returnInterface,
  616. };
  617. }
  618. }
  619. const name = item.key.value;
  620. const value = {
  621. async: item.function.async || isReturnPromise(item.function.returnType),
  622. params: resolveFunctionParams(types, item.function.params, resolveTypeReferenceName),
  623. returnOptions,
  624. };
  625. if (item.isStatic) {
  626. staticMethods[name + 'ByJs'] = value;
  627. }
  628. else {
  629. methods[name + 'ByJs'] = value;
  630. }
  631. }
  632. }
  633. else if (item.type === 'ClassProperty') {
  634. if (item.key.type === 'Identifier') {
  635. if (item.isStatic) {
  636. staticProps.push(item.key.value);
  637. }
  638. else {
  639. props.push(item.key.value);
  640. }
  641. }
  642. }
  643. });
  644. return genProxyClass(cls, { constructor, methods, staticMethods, props, staticProps }, isDefault);
  645. }
  646. function genInitCode(expr) {
  647. switch (expr.type) {
  648. case 'BooleanLiteral':
  649. return expr.value + '';
  650. case 'NumericLiteral':
  651. return expr.value + '';
  652. case 'StringLiteral':
  653. return expr.value;
  654. }
  655. return '';
  656. }
  657. function genVariableDeclaration(types, decl, resolveTypeReferenceName) {
  658. // 目前仅支持 const 的 boolean,number,string
  659. const lits = ['BooleanLiteral', 'NumericLiteral', 'StringLiteral'];
  660. if (decl.kind === 'const' &&
  661. !decl.declarations.find((d) => {
  662. if (d.id.type !== 'Identifier') {
  663. return true;
  664. }
  665. if (!d.init) {
  666. return true;
  667. }
  668. const type = d.init.type;
  669. if (!lits.includes(type)) {
  670. return true;
  671. }
  672. return false;
  673. })) {
  674. return decl;
  675. }
  676. if (decl.declarations.length === 1) {
  677. // 识别是否是定义的 function,如:export const showToast:ShowToast = ()=>{}
  678. const { id, init } = decl.declarations[0];
  679. if (id.type === 'Identifier' &&
  680. init &&
  681. (init.type === 'ArrowFunctionExpression' ||
  682. init.type === 'FunctionExpression')) {
  683. // 根据类型信息查找参数列表
  684. let params;
  685. const typeAnn = id.typeAnnotation;
  686. if (typeAnn && typeAnn.typeAnnotation.type === 'TsTypeReference') {
  687. const { typeName } = typeAnn.typeAnnotation;
  688. if (typeName.type === 'Identifier') {
  689. const value = types.fn[typeName.value];
  690. if ((0, shared_1.isArray)(value)) {
  691. params = value;
  692. }
  693. }
  694. }
  695. return genFunctionDeclaration(types, createFunctionDeclaration(id.value, init, params), resolveTypeReferenceName, false, true);
  696. }
  697. }
  698. }
  699. // function createBindingIdentifier(name: string, typeAnnotation?: TsTypeAnnotation): BindingIdentifier {
  700. // return {
  701. // type: 'Identifier',
  702. // value: name,
  703. // optional: false,
  704. // span: {} as Span,
  705. // typeAnnotation
  706. // }
  707. // }
  708. function createIdentifier(name) {
  709. return {
  710. type: 'Identifier',
  711. value: name,
  712. optional: false,
  713. span: {},
  714. };
  715. }
  716. function createFunctionDeclaration(name, func, params) {
  717. if (!params) {
  718. if (func.type === 'FunctionExpression') {
  719. params = func.params;
  720. }
  721. else if (func.type === 'ArrowFunctionExpression') {
  722. params = [];
  723. func.params.forEach((p) => {
  724. if (p.type === 'Identifier') {
  725. params.push({
  726. type: 'Parameter',
  727. pat: p,
  728. span: {},
  729. });
  730. }
  731. });
  732. }
  733. }
  734. return {
  735. type: 'FunctionDeclaration',
  736. identifier: createIdentifier(name),
  737. declare: false,
  738. params: params,
  739. generator: false,
  740. async: func.async,
  741. typeParameters: func.typeParameters,
  742. returnType: func.returnType,
  743. span: {},
  744. };
  745. }