Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
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.

exportParser.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _jsdoccomment = require("@es-joy/jsdoccomment");
  7. var _debug = _interopRequireDefault(require("debug"));
  8. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  9. const debug = (0, _debug.default)('requireExportJsdoc');
  10. const createNode = function () {
  11. return {
  12. props: {}
  13. };
  14. };
  15. const getSymbolValue = function (symbol) {
  16. /* istanbul ignore next */
  17. if (!symbol) {
  18. /* istanbul ignore next */
  19. return null;
  20. }
  21. /* istanbul ignore next */
  22. if (symbol.type === 'literal') {
  23. return symbol.value.value;
  24. }
  25. /* istanbul ignore next */
  26. return null;
  27. };
  28. const getIdentifier = function (node, globals, scope, opts) {
  29. if (opts.simpleIdentifier) {
  30. // Type is Identier for noncomputed properties
  31. const identifierLiteral = createNode();
  32. identifierLiteral.type = 'literal';
  33. identifierLiteral.value = {
  34. value: node.name
  35. };
  36. return identifierLiteral;
  37. }
  38. /* istanbul ignore next */
  39. const block = scope || globals; // As scopes are not currently supported, they are not traversed upwards recursively
  40. if (block.props[node.name]) {
  41. return block.props[node.name];
  42. } // Seems this will only be entered once scopes added and entered
  43. /* istanbul ignore next */
  44. if (globals.props[node.name]) {
  45. return globals.props[node.name];
  46. }
  47. return null;
  48. };
  49. let createSymbol = null;
  50. const getSymbol = function (node, globals, scope, opt) {
  51. const opts = opt || {};
  52. /* istanbul ignore next */
  53. switch (node.type) {
  54. case 'Identifier':
  55. {
  56. return getIdentifier(node, globals, scope, opts);
  57. }
  58. case 'MemberExpression':
  59. {
  60. const obj = getSymbol(node.object, globals, scope, opts);
  61. const propertySymbol = getSymbol(node.property, globals, scope, {
  62. simpleIdentifier: !node.computed
  63. });
  64. const propertyValue = getSymbolValue(propertySymbol);
  65. /* istanbul ignore next */
  66. if (obj && propertyValue && obj.props[propertyValue]) {
  67. const block = obj.props[propertyValue];
  68. return block;
  69. }
  70. /*
  71. if (opts.createMissingProps && propertyValue) {
  72. obj.props[propertyValue] = createNode();
  73. return obj.props[propertyValue];
  74. }
  75. */
  76. /* istanbul ignore next */
  77. debug(`MemberExpression: Missing property ${node.property.name}`);
  78. /* istanbul ignore next */
  79. return null;
  80. }
  81. case 'TSTypeAliasDeclaration':
  82. case 'TSEnumDeclaration':
  83. case 'TSInterfaceDeclaration':
  84. case 'ClassDeclaration':
  85. case 'ClassExpression':
  86. case 'FunctionExpression':
  87. case 'FunctionDeclaration':
  88. case 'ArrowFunctionExpression':
  89. {
  90. const val = createNode();
  91. val.props.prototype = createNode();
  92. val.props.prototype.type = 'object';
  93. val.type = 'object';
  94. val.value = node;
  95. return val;
  96. }
  97. case 'AssignmentExpression':
  98. {
  99. return createSymbol(node.left, globals, node.right, scope, opts);
  100. }
  101. case 'ClassBody':
  102. {
  103. const val = createNode();
  104. node.body.forEach(method => {
  105. val.props[method.key.name] = createNode();
  106. val.props[method.key.name].type = 'object';
  107. val.props[method.key.name].value = method.value;
  108. });
  109. val.type = 'object';
  110. val.value = node;
  111. return val;
  112. }
  113. case 'ObjectExpression':
  114. {
  115. const val = createNode();
  116. val.type = 'object';
  117. node.properties.forEach(prop => {
  118. if ([// @typescript-eslint/parser, espree, acorn, etc.
  119. 'SpreadElement', // @babel/eslint-parser
  120. 'ExperimentalSpreadProperty'].includes(prop.type)) {
  121. return;
  122. }
  123. const propVal = getSymbol(prop.value, globals, scope, opts);
  124. /* istanbul ignore next */
  125. if (propVal) {
  126. val.props[prop.key.name] = propVal;
  127. }
  128. });
  129. return val;
  130. }
  131. case 'Literal':
  132. {
  133. const val = createNode();
  134. val.type = 'literal';
  135. val.value = node;
  136. return val;
  137. }
  138. }
  139. /* istanbul ignore next */
  140. return null;
  141. };
  142. const createBlockSymbol = function (block, name, value, globals, isGlobal) {
  143. block.props[name] = value;
  144. if (isGlobal && globals.props.window && globals.props.window.special) {
  145. globals.props.window.props[name] = value;
  146. }
  147. };
  148. createSymbol = function (node, globals, value, scope, isGlobal) {
  149. const block = scope || globals;
  150. let symbol;
  151. switch (node.type) {
  152. case 'FunctionDeclaration':
  153. /* istanbul ignore next */
  154. // Fall through
  155. case 'TSEnumDeclaration':
  156. case 'TSInterfaceDeclaration':
  157. /* istanbul ignore next */
  158. // Fall through
  159. case 'TSTypeAliasDeclaration':
  160. case 'ClassDeclaration':
  161. {
  162. /* istanbul ignore next */
  163. if (node.id && node.id.type === 'Identifier') {
  164. return createSymbol(node.id, globals, node, globals);
  165. }
  166. /* istanbul ignore next */
  167. break;
  168. }
  169. case 'Identifier':
  170. {
  171. if (value) {
  172. const valueSymbol = getSymbol(value, globals, block);
  173. /* istanbul ignore next */
  174. if (valueSymbol) {
  175. createBlockSymbol(block, node.name, valueSymbol, globals, isGlobal);
  176. return block.props[node.name];
  177. }
  178. /* istanbul ignore next */
  179. debug('Identifier: Missing value symbol for %s', node.name);
  180. } else {
  181. createBlockSymbol(block, node.name, createNode(), globals, isGlobal);
  182. return block.props[node.name];
  183. }
  184. /* istanbul ignore next */
  185. break;
  186. }
  187. case 'MemberExpression':
  188. {
  189. symbol = getSymbol(node.object, globals, block);
  190. const propertySymbol = getSymbol(node.property, globals, block, {
  191. simpleIdentifier: !node.computed
  192. });
  193. const propertyValue = getSymbolValue(propertySymbol);
  194. if (symbol && propertyValue) {
  195. createBlockSymbol(symbol, propertyValue, getSymbol(value, globals, block), globals, isGlobal);
  196. return symbol.props[propertyValue];
  197. }
  198. /* istanbul ignore next */
  199. debug('MemberExpression: Missing symbol: %s', node.property.name);
  200. break;
  201. }
  202. }
  203. return null;
  204. }; // Creates variables from variable definitions
  205. const initVariables = function (node, globals, opts) {
  206. switch (node.type) {
  207. case 'Program':
  208. {
  209. node.body.forEach(childNode => {
  210. initVariables(childNode, globals, opts);
  211. });
  212. break;
  213. }
  214. case 'ExpressionStatement':
  215. {
  216. initVariables(node.expression, globals, opts);
  217. break;
  218. }
  219. case 'VariableDeclaration':
  220. {
  221. node.declarations.forEach(declaration => {
  222. // let and const
  223. const symbol = createSymbol(declaration.id, globals, null, globals);
  224. if (opts.initWindow && node.kind === 'var' && globals.props.window) {
  225. // If var, also add to window
  226. globals.props.window.props[declaration.id.name] = symbol;
  227. }
  228. });
  229. break;
  230. }
  231. case 'ExportNamedDeclaration':
  232. {
  233. if (node.declaration) {
  234. initVariables(node.declaration, globals, opts);
  235. }
  236. break;
  237. }
  238. }
  239. }; // Populates variable maps using AST
  240. const mapVariables = function (node, globals, opt, isExport) {
  241. /* istanbul ignore next */
  242. const opts = opt || {};
  243. /* istanbul ignore next */
  244. switch (node.type) {
  245. case 'Program':
  246. {
  247. if (opts.ancestorsOnly) {
  248. return false;
  249. }
  250. node.body.forEach(childNode => {
  251. mapVariables(childNode, globals, opts);
  252. });
  253. break;
  254. }
  255. case 'ExpressionStatement':
  256. {
  257. mapVariables(node.expression, globals, opts);
  258. break;
  259. }
  260. case 'AssignmentExpression':
  261. {
  262. createSymbol(node.left, globals, node.right);
  263. break;
  264. }
  265. case 'VariableDeclaration':
  266. {
  267. node.declarations.forEach(declaration => {
  268. const isGlobal = opts.initWindow && node.kind === 'var' && globals.props.window;
  269. const symbol = createSymbol(declaration.id, globals, declaration.init, globals, isGlobal);
  270. if (symbol && isExport) {
  271. symbol.exported = true;
  272. }
  273. });
  274. break;
  275. }
  276. case 'FunctionDeclaration':
  277. {
  278. /* istanbul ignore next */
  279. if (node.id.type === 'Identifier') {
  280. createSymbol(node.id, globals, node, globals, true);
  281. }
  282. break;
  283. }
  284. case 'ExportDefaultDeclaration':
  285. {
  286. const symbol = createSymbol(node.declaration, globals, node.declaration);
  287. if (symbol) {
  288. symbol.exported = true;
  289. } else if (!node.id) {
  290. globals.ANONYMOUS_DEFAULT = node.declaration;
  291. }
  292. break;
  293. }
  294. case 'ExportNamedDeclaration':
  295. {
  296. if (node.declaration) {
  297. if (node.declaration.type === 'VariableDeclaration') {
  298. mapVariables(node.declaration, globals, opts, true);
  299. } else {
  300. const symbol = createSymbol(node.declaration, globals, node.declaration);
  301. /* istanbul ignore next */
  302. if (symbol) {
  303. symbol.exported = true;
  304. }
  305. }
  306. }
  307. node.specifiers.forEach(specifier => {
  308. mapVariables(specifier, globals, opts);
  309. });
  310. break;
  311. }
  312. case 'ExportSpecifier':
  313. {
  314. const symbol = getSymbol(node.local, globals, globals);
  315. /* istanbul ignore next */
  316. if (symbol) {
  317. symbol.exported = true;
  318. }
  319. break;
  320. }
  321. case 'ClassDeclaration':
  322. {
  323. createSymbol(node.id, globals, node.body, globals);
  324. break;
  325. }
  326. default:
  327. {
  328. /* istanbul ignore next */
  329. return false;
  330. }
  331. }
  332. return true;
  333. };
  334. const findNode = function (node, block, cache) {
  335. let blockCache = cache || [];
  336. /* istanbul ignore next */
  337. if (!block || blockCache.includes(block)) {
  338. return false;
  339. }
  340. blockCache = blockCache.slice();
  341. blockCache.push(block);
  342. if ((block.type === 'object' || block.type === 'MethodDefinition') && block.value === node) {
  343. return true;
  344. }
  345. const {
  346. props = block.body
  347. } = block;
  348. for (const propval of Object.values(props || {})) {
  349. if (Array.isArray(propval)) {
  350. /* istanbul ignore if */
  351. if (propval.some(val => {
  352. return findNode(node, val, blockCache);
  353. })) {
  354. return true;
  355. }
  356. } else if (findNode(node, propval, blockCache)) {
  357. return true;
  358. }
  359. }
  360. return false;
  361. };
  362. const exportTypes = new Set(['ExportNamedDeclaration', 'ExportDefaultDeclaration']);
  363. const getExportAncestor = function (nde) {
  364. let node = nde;
  365. while (node) {
  366. if (exportTypes.has(node.type)) {
  367. return node;
  368. }
  369. node = node.parent;
  370. }
  371. return false;
  372. };
  373. const canExportedByAncestorType = new Set(['TSPropertySignature', 'TSMethodSignature', 'ClassProperty', 'Method']);
  374. const canExportChildrenType = new Set(['TSInterfaceBody', 'TSInterfaceDeclaration', 'ClassDefinition', 'ClassExpression', 'Program']);
  375. const isExportByAncestor = function (nde) {
  376. if (!canExportedByAncestorType.has(nde.type)) {
  377. return false;
  378. }
  379. let node = nde.parent;
  380. while (node) {
  381. if (exportTypes.has(node.type)) {
  382. return node;
  383. }
  384. if (!canExportChildrenType.has(node.type)) {
  385. return false;
  386. }
  387. node = node.parent;
  388. }
  389. return false;
  390. };
  391. const findExportedNode = function (block, node, cache) {
  392. /* istanbul ignore next */
  393. if (block === null) {
  394. return false;
  395. }
  396. const blockCache = cache || [];
  397. const {
  398. props
  399. } = block;
  400. for (const propval of Object.values(props)) {
  401. blockCache.push(propval);
  402. if (propval.exported && (node === propval.value || findNode(node, propval.value))) {
  403. return true;
  404. } // No need to check `propval` for exported nodes as ESM
  405. // exports are only global
  406. }
  407. return false;
  408. };
  409. const isNodeExported = function (node, globals, opt) {
  410. if (opt.initModuleExports && globals.props.module && globals.props.module.props.exports && findNode(node, globals.props.module.props.exports)) {
  411. return true;
  412. }
  413. if (opt.initWindow && globals.props.window && findNode(node, globals.props.window)) {
  414. return true;
  415. }
  416. if (opt.esm && findExportedNode(globals, node)) {
  417. return true;
  418. }
  419. return false;
  420. };
  421. const parseRecursive = function (node, globalVars, opts) {
  422. // Iterate from top using recursion - stop at first processed node from top
  423. if (node.parent && parseRecursive(node.parent, globalVars, opts)) {
  424. return true;
  425. }
  426. return mapVariables(node, globalVars, opts);
  427. };
  428. const parse = function (ast, node, opt) {
  429. /* istanbul ignore next */
  430. const opts = opt || {
  431. ancestorsOnly: false,
  432. esm: true,
  433. initModuleExports: true,
  434. initWindow: true
  435. };
  436. const globalVars = createNode();
  437. if (opts.initModuleExports) {
  438. globalVars.props.module = createNode();
  439. globalVars.props.module.props.exports = createNode();
  440. globalVars.props.exports = globalVars.props.module.props.exports;
  441. }
  442. if (opts.initWindow) {
  443. globalVars.props.window = createNode();
  444. globalVars.props.window.special = true;
  445. }
  446. if (opts.ancestorsOnly) {
  447. parseRecursive(node, globalVars, opts);
  448. } else {
  449. initVariables(ast, globalVars, opts);
  450. mapVariables(ast, globalVars, opts);
  451. }
  452. return {
  453. globalVars
  454. };
  455. };
  456. const isUncommentedExport = function (node, sourceCode, opt, settings) {
  457. // console.log({node});
  458. // Optimize with ancestor check for esm
  459. if (opt.esm) {
  460. const exportNode = getExportAncestor(node); // Is export node comment
  461. if (exportNode && !(0, _jsdoccomment.findJSDocComment)(exportNode, sourceCode, settings)) {
  462. return true;
  463. }
  464. /** Some typescript types are not in variable map, but inherit exported (interface property and method)*/
  465. if (isExportByAncestor(node) && !(0, _jsdoccomment.findJSDocComment)(node, sourceCode, settings)) {
  466. return true;
  467. }
  468. }
  469. const parseResult = parse(sourceCode.ast, node, opt);
  470. return isNodeExported(node, parseResult.globalVars, opt);
  471. };
  472. var _default = {
  473. isUncommentedExport,
  474. parse
  475. };
  476. exports.default = _default;
  477. module.exports = exports.default;
  478. //# sourceMappingURL=exportParser.js.map