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.

index.js 77KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jtpp = {}));
  5. }(this, (function (exports) { 'use strict';
  6. function tokenToString(token) {
  7. if (token.text !== undefined && token.text !== '') {
  8. return `'${token.type}' with value '${token.text}'`;
  9. }
  10. else {
  11. return `'${token.type}'`;
  12. }
  13. }
  14. class NoParsletFoundError extends Error {
  15. constructor(token) {
  16. super(`No parslet found for token: ${tokenToString(token)}`);
  17. this.token = token;
  18. Object.setPrototypeOf(this, NoParsletFoundError.prototype);
  19. }
  20. getToken() {
  21. return this.token;
  22. }
  23. }
  24. class EarlyEndOfParseError extends Error {
  25. constructor(token) {
  26. super(`The parsing ended early. The next token was: ${tokenToString(token)}`);
  27. this.token = token;
  28. Object.setPrototypeOf(this, EarlyEndOfParseError.prototype);
  29. }
  30. getToken() {
  31. return this.token;
  32. }
  33. }
  34. class UnexpectedTypeError extends Error {
  35. constructor(result) {
  36. super(`Unexpected type: '${result.type}'`);
  37. Object.setPrototypeOf(this, UnexpectedTypeError.prototype);
  38. }
  39. }
  40. // export class UnexpectedTokenError extends Error {
  41. // private expected: Token
  42. // private found: Token
  43. //
  44. // constructor (expected: Token, found: Token) {
  45. // super(`The parsing ended early. The next token was: ${tokenToString(token)}`)
  46. //
  47. // this.token = token
  48. //
  49. // Object.setPrototypeOf(this, EarlyEndOfParseError.prototype)
  50. // }
  51. //
  52. // getToken() {
  53. // return this.token
  54. // }
  55. // }
  56. function makePunctuationRule(type) {
  57. return text => {
  58. if (text.startsWith(type)) {
  59. return { type, text: type };
  60. }
  61. else {
  62. return null;
  63. }
  64. };
  65. }
  66. function getQuoted(text) {
  67. let position = 0;
  68. let char;
  69. const mark = text[0];
  70. let escaped = false;
  71. if (mark !== '\'' && mark !== '"') {
  72. return null;
  73. }
  74. while (position < text.length) {
  75. position++;
  76. char = text[position];
  77. if (!escaped && char === mark) {
  78. position++;
  79. break;
  80. }
  81. escaped = !escaped && char === '\\';
  82. }
  83. if (char !== mark) {
  84. throw new Error('Unterminated String');
  85. }
  86. return text.slice(0, position);
  87. }
  88. const identifierStartRegex = /[$_\p{ID_Start}]|\\u\p{Hex_Digit}{4}|\\u\{0*(?:\p{Hex_Digit}{1,5}|10\p{Hex_Digit}{4})\}/u;
  89. // A hyphen is not technically allowed, but to keep it liberal for now,
  90. // adding it here
  91. const identifierContinueRegex = /[$\-\p{ID_Continue}\u200C\u200D]|\\u\p{Hex_Digit}{4}|\\u\{0*(?:\p{Hex_Digit}{1,5}|10\p{Hex_Digit}{4})\}/u;
  92. function getIdentifier(text) {
  93. let char = text[0];
  94. if (!identifierStartRegex.test(char)) {
  95. return null;
  96. }
  97. let position = 1;
  98. do {
  99. char = text[position];
  100. if (!identifierContinueRegex.test(char)) {
  101. break;
  102. }
  103. position++;
  104. } while (position < text.length);
  105. return text.slice(0, position);
  106. }
  107. const numberRegex = /[0-9]/;
  108. function getNumber(text) {
  109. let position = 0;
  110. let char;
  111. do {
  112. char = text[position];
  113. if (!numberRegex.test(char)) {
  114. break;
  115. }
  116. position++;
  117. } while (position < text.length);
  118. if (position === 0) {
  119. return null;
  120. }
  121. return text.slice(0, position);
  122. }
  123. const identifierRule = text => {
  124. const value = getIdentifier(text);
  125. if (value == null) {
  126. return null;
  127. }
  128. return {
  129. type: 'Identifier',
  130. text: value
  131. };
  132. };
  133. function makeKeyWordRule(type) {
  134. return text => {
  135. if (!text.startsWith(type)) {
  136. return null;
  137. }
  138. const prepends = text[type.length];
  139. if (prepends !== undefined && identifierContinueRegex.test(prepends)) {
  140. return null;
  141. }
  142. return {
  143. type: type,
  144. text: type
  145. };
  146. };
  147. }
  148. const stringValueRule = text => {
  149. const value = getQuoted(text);
  150. if (value == null) {
  151. return null;
  152. }
  153. return {
  154. type: 'StringValue',
  155. text: value
  156. };
  157. };
  158. const eofRule = text => {
  159. if (text.length > 0) {
  160. return null;
  161. }
  162. return {
  163. type: 'EOF',
  164. text: ''
  165. };
  166. };
  167. const numberRule = text => {
  168. const value = getNumber(text);
  169. if (value === null) {
  170. return null;
  171. }
  172. return {
  173. type: 'Number',
  174. text: value
  175. };
  176. };
  177. const rules = [
  178. eofRule,
  179. makePunctuationRule('=>'),
  180. makePunctuationRule('('),
  181. makePunctuationRule(')'),
  182. makePunctuationRule('{'),
  183. makePunctuationRule('}'),
  184. makePunctuationRule('['),
  185. makePunctuationRule(']'),
  186. makePunctuationRule('|'),
  187. makePunctuationRule('&'),
  188. makePunctuationRule('<'),
  189. makePunctuationRule('>'),
  190. makePunctuationRule(','),
  191. makePunctuationRule(';'),
  192. makePunctuationRule('*'),
  193. makePunctuationRule('?'),
  194. makePunctuationRule('!'),
  195. makePunctuationRule('='),
  196. makePunctuationRule(':'),
  197. makePunctuationRule('...'),
  198. makePunctuationRule('.'),
  199. makePunctuationRule('#'),
  200. makePunctuationRule('~'),
  201. makePunctuationRule('/'),
  202. makePunctuationRule('@'),
  203. makeKeyWordRule('undefined'),
  204. makeKeyWordRule('null'),
  205. makeKeyWordRule('function'),
  206. makeKeyWordRule('this'),
  207. makeKeyWordRule('new'),
  208. makeKeyWordRule('module'),
  209. makeKeyWordRule('event'),
  210. makeKeyWordRule('external'),
  211. makeKeyWordRule('typeof'),
  212. makeKeyWordRule('keyof'),
  213. makeKeyWordRule('import'),
  214. identifierRule,
  215. stringValueRule,
  216. numberRule
  217. ];
  218. class Lexer {
  219. constructor() {
  220. this.text = '';
  221. }
  222. lex(text) {
  223. this.text = text;
  224. this.current = undefined;
  225. this.next = undefined;
  226. this.advance();
  227. }
  228. token() {
  229. if (this.current === undefined) {
  230. throw new Error('Lexer not lexing');
  231. }
  232. return this.current;
  233. }
  234. peek() {
  235. if (this.next === undefined) {
  236. this.next = this.read();
  237. }
  238. return this.next;
  239. }
  240. last() {
  241. return this.previous;
  242. }
  243. advance() {
  244. this.previous = this.current;
  245. if (this.next !== undefined) {
  246. this.current = this.next;
  247. this.next = undefined;
  248. return;
  249. }
  250. this.current = this.read();
  251. }
  252. read() {
  253. const text = this.text.trim();
  254. for (const rule of rules) {
  255. const token = rule(text);
  256. if (token !== null) {
  257. this.text = text.slice(token.text.length);
  258. return token;
  259. }
  260. }
  261. throw new Error('Unexpected Token ' + text);
  262. }
  263. }
  264. function assertTerminal(result) {
  265. if (result === undefined) {
  266. throw new Error('Unexpected undefined');
  267. }
  268. if (result.type === 'JsdocTypeKeyValue' || result.type === 'JsdocTypeParameterList' || result.type === 'JsdocTypeProperty') {
  269. throw new UnexpectedTypeError(result);
  270. }
  271. return result;
  272. }
  273. function assertKeyValueOrTerminal(result) {
  274. if (result.type === 'JsdocTypeKeyValue' && 'value' in result) {
  275. return result;
  276. }
  277. return assertTerminal(result);
  278. }
  279. function assertKeyValueOrName(result) {
  280. if (result.type === 'JsdocTypeKeyValue' && 'value' in result) {
  281. return result;
  282. }
  283. else if (result.type !== 'JsdocTypeName') {
  284. throw new UnexpectedTypeError(result);
  285. }
  286. return result;
  287. }
  288. function assertNumberOrVariadicName(result) {
  289. var _a;
  290. if (result.type === 'JsdocTypeVariadic') {
  291. if (((_a = result.element) === null || _a === void 0 ? void 0 : _a.type) === 'JsdocTypeName') {
  292. return result;
  293. }
  294. throw new UnexpectedTypeError(result);
  295. }
  296. if (result.type !== 'JsdocTypeNumber' && result.type !== 'JsdocTypeName') {
  297. throw new UnexpectedTypeError(result);
  298. }
  299. return result;
  300. }
  301. // higher precedence = higher importance
  302. var Precedence;
  303. (function (Precedence) {
  304. Precedence[Precedence["ALL"] = 0] = "ALL";
  305. Precedence[Precedence["PARAMETER_LIST"] = 1] = "PARAMETER_LIST";
  306. Precedence[Precedence["OBJECT"] = 2] = "OBJECT";
  307. Precedence[Precedence["KEY_VALUE"] = 3] = "KEY_VALUE";
  308. Precedence[Precedence["UNION"] = 4] = "UNION";
  309. Precedence[Precedence["INTERSECTION"] = 5] = "INTERSECTION";
  310. Precedence[Precedence["PREFIX"] = 6] = "PREFIX";
  311. Precedence[Precedence["POSTFIX"] = 7] = "POSTFIX";
  312. Precedence[Precedence["TUPLE"] = 8] = "TUPLE";
  313. Precedence[Precedence["SYMBOL"] = 9] = "SYMBOL";
  314. Precedence[Precedence["OPTIONAL"] = 10] = "OPTIONAL";
  315. Precedence[Precedence["NULLABLE"] = 11] = "NULLABLE";
  316. Precedence[Precedence["KEY_OF_TYPE_OF"] = 12] = "KEY_OF_TYPE_OF";
  317. Precedence[Precedence["FUNCTION"] = 13] = "FUNCTION";
  318. Precedence[Precedence["ARROW"] = 14] = "ARROW";
  319. Precedence[Precedence["GENERIC"] = 15] = "GENERIC";
  320. Precedence[Precedence["NAME_PATH"] = 16] = "NAME_PATH";
  321. Precedence[Precedence["ARRAY_BRACKETS"] = 17] = "ARRAY_BRACKETS";
  322. Precedence[Precedence["PARENTHESIS"] = 18] = "PARENTHESIS";
  323. Precedence[Precedence["SPECIAL_TYPES"] = 19] = "SPECIAL_TYPES";
  324. })(Precedence || (Precedence = {}));
  325. class Parser {
  326. constructor(grammar, lexer) {
  327. this.lexer = lexer !== null && lexer !== void 0 ? lexer : new Lexer();
  328. const { prefixParslets, infixParslets } = grammar;
  329. this.prefixParslets = prefixParslets;
  330. this.infixParslets = infixParslets;
  331. }
  332. parseText(text) {
  333. this.lexer.lex(text);
  334. const result = this.parseType(Precedence.ALL);
  335. if (!this.consume('EOF')) {
  336. throw new EarlyEndOfParseError(this.getToken());
  337. }
  338. return result;
  339. }
  340. getPrefixParslet() {
  341. return this.prefixParslets.find(p => p.accepts(this.getToken().type, this.peekToken().type));
  342. }
  343. getInfixParslet(precedence) {
  344. return this.infixParslets.find(p => {
  345. return p.getPrecedence() > precedence && p.accepts(this.getToken().type, this.peekToken().type);
  346. });
  347. }
  348. canParseType() {
  349. return this.getPrefixParslet() !== undefined;
  350. }
  351. parseType(precedence) {
  352. return assertTerminal(this.parseIntermediateType(precedence));
  353. }
  354. parseIntermediateType(precedence) {
  355. const parslet = this.getPrefixParslet();
  356. if (parslet === undefined) {
  357. throw new NoParsletFoundError(this.getToken());
  358. }
  359. const result = parslet.parsePrefix(this);
  360. return this.parseInfixIntermediateType(result, precedence);
  361. }
  362. parseInfixIntermediateType(result, precedence) {
  363. let parslet = this.getInfixParslet(precedence);
  364. while (parslet !== undefined) {
  365. result = parslet.parseInfix(this, result);
  366. parslet = this.getInfixParslet(precedence);
  367. }
  368. return result;
  369. }
  370. consume(type) {
  371. if (this.lexer.token().type !== type) {
  372. return false;
  373. }
  374. this.lexer.advance();
  375. return true;
  376. }
  377. getToken() {
  378. return this.lexer.token();
  379. }
  380. peekToken() {
  381. return this.lexer.peek();
  382. }
  383. previousToken() {
  384. return this.lexer.last();
  385. }
  386. getLexer() {
  387. return this.lexer;
  388. }
  389. }
  390. class SymbolParslet {
  391. accepts(type) {
  392. return type === '(';
  393. }
  394. getPrecedence() {
  395. return Precedence.SYMBOL;
  396. }
  397. parseInfix(parser, left) {
  398. if (left.type !== 'JsdocTypeName') {
  399. throw new Error('Symbol expects a name on the left side. (Reacting on \'(\')');
  400. }
  401. parser.consume('(');
  402. const result = {
  403. type: 'JsdocTypeSymbol',
  404. value: left.value
  405. };
  406. if (!parser.consume(')')) {
  407. const next = parser.parseIntermediateType(Precedence.SYMBOL);
  408. result.element = assertNumberOrVariadicName(next);
  409. if (!parser.consume(')')) {
  410. throw new Error('Symbol does not end after value');
  411. }
  412. }
  413. return result;
  414. }
  415. }
  416. class ArrayBracketsParslet {
  417. accepts(type, next) {
  418. return type === '[' && next === ']';
  419. }
  420. getPrecedence() {
  421. return Precedence.ARRAY_BRACKETS;
  422. }
  423. parseInfix(parser, left) {
  424. parser.consume('[');
  425. parser.consume(']');
  426. return {
  427. type: 'JsdocTypeGeneric',
  428. left: {
  429. type: 'JsdocTypeName',
  430. value: 'Array'
  431. },
  432. elements: [
  433. assertTerminal(left)
  434. ],
  435. meta: {
  436. brackets: 'square',
  437. dot: false
  438. }
  439. };
  440. }
  441. }
  442. class StringValueParslet {
  443. accepts(type) {
  444. return type === 'StringValue';
  445. }
  446. getPrecedence() {
  447. return Precedence.PREFIX;
  448. }
  449. parsePrefix(parser) {
  450. const token = parser.getToken();
  451. parser.consume('StringValue');
  452. return {
  453. type: 'JsdocTypeStringValue',
  454. value: token.text.slice(1, -1),
  455. meta: {
  456. quote: token.text[0] === '\'' ? 'single' : 'double'
  457. }
  458. };
  459. }
  460. }
  461. class BaseFunctionParslet {
  462. getParameters(value) {
  463. let parameters;
  464. if (value.type === 'JsdocTypeParameterList') {
  465. parameters = value.elements;
  466. }
  467. else if (value.type === 'JsdocTypeParenthesis') {
  468. parameters = [value.element];
  469. }
  470. else {
  471. throw new UnexpectedTypeError(value);
  472. }
  473. return parameters.map(p => assertKeyValueOrTerminal(p));
  474. }
  475. getUnnamedParameters(value) {
  476. const parameters = this.getParameters(value);
  477. if (parameters.some(p => p.type === 'JsdocTypeKeyValue')) {
  478. throw new Error('No parameter should be named');
  479. }
  480. return parameters;
  481. }
  482. }
  483. class FunctionParslet extends BaseFunctionParslet {
  484. constructor(options) {
  485. super();
  486. this.allowWithoutParenthesis = options.allowWithoutParenthesis;
  487. this.allowNamedParameters = options.allowNamedParameters;
  488. this.allowNoReturnType = options.allowNoReturnType;
  489. }
  490. accepts(type) {
  491. return type === 'function';
  492. }
  493. getPrecedence() {
  494. return Precedence.FUNCTION;
  495. }
  496. parsePrefix(parser) {
  497. parser.consume('function');
  498. const hasParenthesis = parser.getToken().type === '(';
  499. if (!hasParenthesis) {
  500. if (!this.allowWithoutParenthesis) {
  501. throw new Error('function is missing parameter list');
  502. }
  503. return {
  504. type: 'JsdocTypeName',
  505. value: 'function'
  506. };
  507. }
  508. const result = {
  509. type: 'JsdocTypeFunction',
  510. parameters: [],
  511. arrow: false,
  512. parenthesis: hasParenthesis
  513. };
  514. const value = parser.parseIntermediateType(Precedence.FUNCTION);
  515. if (this.allowNamedParameters === undefined) {
  516. result.parameters = this.getUnnamedParameters(value);
  517. }
  518. else {
  519. result.parameters = this.getParameters(value);
  520. for (const p of result.parameters) {
  521. if (p.type === 'JsdocTypeKeyValue' && (!this.allowNamedParameters.includes(p.value) || p.meta.quote !== undefined)) {
  522. throw new Error(`only allowed named parameters are ${this.allowNamedParameters.join(',')} but got ${p.type}`);
  523. }
  524. }
  525. }
  526. if (parser.consume(':')) {
  527. result.returnType = parser.parseType(Precedence.PREFIX);
  528. }
  529. else {
  530. if (!this.allowNoReturnType) {
  531. throw new Error('function is missing return type');
  532. }
  533. }
  534. return result;
  535. }
  536. }
  537. class UnionParslet {
  538. accepts(type) {
  539. return type === '|';
  540. }
  541. getPrecedence() {
  542. return Precedence.UNION;
  543. }
  544. parseInfix(parser, left) {
  545. parser.consume('|');
  546. const elements = [];
  547. do {
  548. elements.push(parser.parseType(Precedence.UNION));
  549. } while (parser.consume('|'));
  550. return {
  551. type: 'JsdocTypeUnion',
  552. elements: [assertTerminal(left), ...elements]
  553. };
  554. }
  555. }
  556. function isQuestionMarkUnknownType(next) {
  557. return next === 'EOF' || next === '|' || next === ',' || next === ')' || next === '>';
  558. }
  559. class SpecialTypesParslet {
  560. accepts(type, next) {
  561. return (type === '?' && isQuestionMarkUnknownType(next)) || type === 'null' || type === 'undefined' || type === '*';
  562. }
  563. getPrecedence() {
  564. return Precedence.SPECIAL_TYPES;
  565. }
  566. parsePrefix(parser) {
  567. if (parser.consume('null')) {
  568. return {
  569. type: 'JsdocTypeNull'
  570. };
  571. }
  572. if (parser.consume('undefined')) {
  573. return {
  574. type: 'JsdocTypeUndefined'
  575. };
  576. }
  577. if (parser.consume('*')) {
  578. return {
  579. type: 'JsdocTypeAny'
  580. };
  581. }
  582. if (parser.consume('?')) {
  583. return {
  584. type: 'JsdocTypeUnknown'
  585. };
  586. }
  587. throw new Error('Unacceptable token: ' + parser.getToken().text);
  588. }
  589. }
  590. class GenericParslet {
  591. accepts(type, next) {
  592. return type === '<' || (type === '.' && next === '<');
  593. }
  594. getPrecedence() {
  595. return Precedence.GENERIC;
  596. }
  597. parseInfix(parser, left) {
  598. const dot = parser.consume('.');
  599. parser.consume('<');
  600. const objects = [];
  601. do {
  602. objects.push(parser.parseType(Precedence.PARAMETER_LIST));
  603. } while (parser.consume(','));
  604. if (!parser.consume('>')) {
  605. throw new Error('Unterminated generic parameter list');
  606. }
  607. return {
  608. type: 'JsdocTypeGeneric',
  609. left: assertTerminal(left),
  610. elements: objects,
  611. meta: {
  612. brackets: 'angle',
  613. dot
  614. }
  615. };
  616. }
  617. }
  618. class ParenthesisParslet {
  619. accepts(type, next) {
  620. return type === '(';
  621. }
  622. getPrecedence() {
  623. return Precedence.PARENTHESIS;
  624. }
  625. parsePrefix(parser) {
  626. parser.consume('(');
  627. if (parser.consume(')')) {
  628. return {
  629. type: 'JsdocTypeParameterList',
  630. elements: []
  631. };
  632. }
  633. const result = parser.parseIntermediateType(Precedence.ALL);
  634. if (!parser.consume(')')) {
  635. throw new Error('Unterminated parenthesis');
  636. }
  637. if (result.type === 'JsdocTypeParameterList') {
  638. return result;
  639. }
  640. else if (result.type === 'JsdocTypeKeyValue' && 'value' in result) {
  641. return {
  642. type: 'JsdocTypeParameterList',
  643. elements: [result]
  644. };
  645. }
  646. return {
  647. type: 'JsdocTypeParenthesis',
  648. element: assertTerminal(result)
  649. };
  650. }
  651. }
  652. class NumberParslet {
  653. accepts(type, next) {
  654. return type === 'Number';
  655. }
  656. getPrecedence() {
  657. return Precedence.PREFIX;
  658. }
  659. parsePrefix(parser) {
  660. const token = parser.getToken();
  661. parser.consume('Number');
  662. return {
  663. type: 'JsdocTypeNumber',
  664. value: parseInt(token.text, 10)
  665. };
  666. }
  667. }
  668. class ParameterListParslet {
  669. constructor(option) {
  670. this.allowTrailingComma = option.allowTrailingComma;
  671. }
  672. accepts(type, next) {
  673. return type === ',';
  674. }
  675. getPrecedence() {
  676. return Precedence.PARAMETER_LIST;
  677. }
  678. parseInfix(parser, left) {
  679. const elements = [
  680. assertKeyValueOrTerminal(left)
  681. ];
  682. parser.consume(',');
  683. do {
  684. try {
  685. const next = parser.parseIntermediateType(Precedence.PARAMETER_LIST);
  686. elements.push(assertKeyValueOrTerminal(next));
  687. }
  688. catch (e) {
  689. if (this.allowTrailingComma && e instanceof NoParsletFoundError) {
  690. break;
  691. }
  692. else {
  693. throw e;
  694. }
  695. }
  696. } while (parser.consume(','));
  697. if (elements.length > 0 && elements.slice(0, -1).some(e => e.type === 'JsdocTypeVariadic')) {
  698. throw new Error('Only the last parameter may be a rest parameter');
  699. }
  700. return {
  701. type: 'JsdocTypeParameterList',
  702. elements
  703. };
  704. }
  705. }
  706. class NullablePrefixParslet {
  707. accepts(type, next) {
  708. return type === '?' && !isQuestionMarkUnknownType(next);
  709. }
  710. getPrecedence() {
  711. return Precedence.NULLABLE;
  712. }
  713. parsePrefix(parser) {
  714. parser.consume('?');
  715. return {
  716. type: 'JsdocTypeNullable',
  717. element: parser.parseType(Precedence.NULLABLE),
  718. meta: {
  719. position: 'prefix'
  720. }
  721. };
  722. }
  723. }
  724. class NullableInfixParslet {
  725. accepts(type, next) {
  726. return type === '?';
  727. }
  728. getPrecedence() {
  729. return Precedence.NULLABLE;
  730. }
  731. parseInfix(parser, left) {
  732. parser.consume('?');
  733. return {
  734. type: 'JsdocTypeNullable',
  735. element: assertTerminal(left),
  736. meta: {
  737. position: 'suffix'
  738. }
  739. };
  740. }
  741. }
  742. class OptionalParslet {
  743. accepts(type, next) {
  744. return type === '=';
  745. }
  746. getPrecedence() {
  747. return Precedence.OPTIONAL;
  748. }
  749. parsePrefix(parser) {
  750. parser.consume('=');
  751. return {
  752. type: 'JsdocTypeOptional',
  753. element: parser.parseType(Precedence.OPTIONAL),
  754. meta: {
  755. position: 'prefix'
  756. }
  757. };
  758. }
  759. parseInfix(parser, left) {
  760. parser.consume('=');
  761. return {
  762. type: 'JsdocTypeOptional',
  763. element: assertTerminal(left),
  764. meta: {
  765. position: 'suffix'
  766. }
  767. };
  768. }
  769. }
  770. class NotNullableParslet {
  771. accepts(type, next) {
  772. return type === '!';
  773. }
  774. getPrecedence() {
  775. return Precedence.NULLABLE;
  776. }
  777. parsePrefix(parser) {
  778. parser.consume('!');
  779. return {
  780. type: 'JsdocTypeNotNullable',
  781. element: parser.parseType(Precedence.NULLABLE),
  782. meta: {
  783. position: 'prefix'
  784. }
  785. };
  786. }
  787. parseInfix(parser, left) {
  788. parser.consume('!');
  789. return {
  790. type: 'JsdocTypeNotNullable',
  791. element: assertTerminal(left),
  792. meta: {
  793. position: 'suffix'
  794. }
  795. };
  796. }
  797. }
  798. const baseGrammar = () => {
  799. return {
  800. prefixParslets: [
  801. new NullablePrefixParslet(),
  802. new OptionalParslet(),
  803. new NumberParslet(),
  804. new ParenthesisParslet(),
  805. new SpecialTypesParslet(),
  806. new NotNullableParslet()
  807. ],
  808. infixParslets: [
  809. new ParameterListParslet({
  810. allowTrailingComma: true
  811. }),
  812. new GenericParslet(),
  813. new UnionParslet(),
  814. new OptionalParslet(),
  815. new NullableInfixParslet(),
  816. new NotNullableParslet()
  817. ]
  818. };
  819. };
  820. class NamePathParslet {
  821. constructor(opts) {
  822. this.allowJsdocNamePaths = opts.allowJsdocNamePaths;
  823. this.allowedPropertyTokenTypes = [
  824. 'Identifier',
  825. 'StringValue',
  826. 'Number'
  827. ];
  828. }
  829. accepts(type, next) {
  830. return (type === '.' && next !== '<') || (this.allowJsdocNamePaths && (type === '~' || type === '#'));
  831. }
  832. getPrecedence() {
  833. return Precedence.NAME_PATH;
  834. }
  835. parseInfix(parser, left) {
  836. let type;
  837. if (parser.consume('.')) {
  838. type = 'property';
  839. }
  840. else if (parser.consume('~')) {
  841. type = 'inner';
  842. }
  843. else {
  844. parser.consume('#');
  845. type = 'instance';
  846. }
  847. let right;
  848. const tokenType = this.allowedPropertyTokenTypes.find(token => parser.getToken().type === token);
  849. if (tokenType !== undefined) {
  850. const value = parser.getToken().text;
  851. parser.consume(tokenType);
  852. right = {
  853. type: 'JsdocTypeProperty',
  854. value: value
  855. };
  856. }
  857. else {
  858. const next = parser.parseIntermediateType(Precedence.NAME_PATH);
  859. if (next.type === 'JsdocTypeName' && next.value === 'event') {
  860. right = {
  861. type: 'JsdocTypeProperty',
  862. value: 'event'
  863. };
  864. }
  865. else if (next.type === 'JsdocTypeSpecialNamePath' && next.specialType === 'event') {
  866. right = next;
  867. }
  868. else {
  869. const validTokens = this.allowedPropertyTokenTypes.join(', ');
  870. throw new Error(`Unexpected property value. Expecting token of type ${validTokens} or 'event' ` +
  871. `name path. Next token is of type: ${parser.getToken().type}`);
  872. }
  873. }
  874. return {
  875. type: 'JsdocTypeNamePath',
  876. left: assertTerminal(left),
  877. right,
  878. pathType: type
  879. };
  880. }
  881. }
  882. class KeyValueParslet {
  883. constructor(opts) {
  884. this.allowKeyTypes = opts.allowKeyTypes;
  885. this.allowOptional = opts.allowOptional;
  886. }
  887. accepts(type, next) {
  888. return type === ':';
  889. }
  890. getPrecedence() {
  891. return Precedence.KEY_VALUE;
  892. }
  893. parseInfix(parser, left) {
  894. let optional = false;
  895. if (this.allowOptional && left.type === 'JsdocTypeNullable') {
  896. optional = true;
  897. left = left.element;
  898. }
  899. if (left.type === 'JsdocTypeNumber' || left.type === 'JsdocTypeName' || left.type === 'JsdocTypeStringValue') {
  900. parser.consume(':');
  901. let quote;
  902. if (left.type === 'JsdocTypeStringValue') {
  903. quote = left.meta.quote;
  904. }
  905. return {
  906. type: 'JsdocTypeKeyValue',
  907. value: left.value.toString(),
  908. right: parser.parseType(Precedence.KEY_VALUE),
  909. optional: optional,
  910. meta: {
  911. quote
  912. }
  913. };
  914. }
  915. else {
  916. if (!this.allowKeyTypes) {
  917. throw new UnexpectedTypeError(left);
  918. }
  919. parser.consume(':');
  920. return {
  921. type: 'JsdocTypeKeyValue',
  922. left: assertTerminal(left),
  923. right: parser.parseType(Precedence.KEY_VALUE)
  924. };
  925. }
  926. }
  927. }
  928. class VariadicParslet {
  929. constructor(opts) {
  930. this.allowEnclosingBrackets = opts.allowEnclosingBrackets;
  931. }
  932. accepts(type) {
  933. return type === '...';
  934. }
  935. getPrecedence() {
  936. return Precedence.PREFIX;
  937. }
  938. parsePrefix(parser) {
  939. parser.consume('...');
  940. const brackets = this.allowEnclosingBrackets && parser.consume('[');
  941. if (!parser.canParseType()) {
  942. if (brackets) {
  943. throw new Error('Empty square brackets for variadic are not allowed.');
  944. }
  945. return {
  946. type: 'JsdocTypeVariadic',
  947. meta: {
  948. position: undefined,
  949. squareBrackets: false
  950. }
  951. };
  952. }
  953. const element = parser.parseType(Precedence.PREFIX);
  954. if (brackets && !parser.consume(']')) {
  955. throw new Error('Unterminated variadic type. Missing \']\'');
  956. }
  957. return {
  958. type: 'JsdocTypeVariadic',
  959. element: assertTerminal(element),
  960. meta: {
  961. position: 'prefix',
  962. squareBrackets: brackets
  963. }
  964. };
  965. }
  966. parseInfix(parser, left) {
  967. parser.consume('...');
  968. return {
  969. type: 'JsdocTypeVariadic',
  970. element: assertTerminal(left),
  971. meta: {
  972. position: 'suffix',
  973. squareBrackets: false
  974. }
  975. };
  976. }
  977. }
  978. class NameParslet {
  979. constructor(options) {
  980. this.allowedAdditionalTokens = options.allowedAdditionalTokens;
  981. }
  982. accepts(type, next) {
  983. return type === 'Identifier' || type === 'this' || type === 'new' || this.allowedAdditionalTokens.includes(type);
  984. }
  985. getPrecedence() {
  986. return Precedence.PREFIX;
  987. }
  988. parsePrefix(parser) {
  989. const token = parser.getToken();
  990. parser.consume('Identifier') || parser.consume('this') || parser.consume('new') ||
  991. this.allowedAdditionalTokens.some(type => parser.consume(type));
  992. return {
  993. type: 'JsdocTypeName',
  994. value: token.text
  995. };
  996. }
  997. }
  998. const moduleGrammar = () => ({
  999. prefixParslets: [
  1000. new SpecialNamePathParslet({
  1001. allowedTypes: ['event']
  1002. }),
  1003. new NameParslet({
  1004. allowedAdditionalTokens: ['module', 'external']
  1005. }),
  1006. new NumberParslet(),
  1007. new StringValueParslet()
  1008. ],
  1009. infixParslets: [
  1010. new NamePathParslet({
  1011. allowJsdocNamePaths: true
  1012. })
  1013. ]
  1014. });
  1015. class SpecialNamePathParslet {
  1016. constructor(opts) {
  1017. this.allowedTypes = opts.allowedTypes;
  1018. }
  1019. accepts(type, next) {
  1020. return this.allowedTypes.includes(type);
  1021. }
  1022. getPrecedence() {
  1023. return Precedence.PREFIX;
  1024. }
  1025. parsePrefix(parser) {
  1026. const type = this.allowedTypes.find(type => parser.consume(type));
  1027. if (!parser.consume(':')) {
  1028. return {
  1029. type: 'JsdocTypeName',
  1030. value: type
  1031. };
  1032. }
  1033. const moduleParser = new Parser(moduleGrammar(), parser.getLexer());
  1034. let result;
  1035. let token = parser.getToken();
  1036. if (parser.consume('StringValue')) {
  1037. result = {
  1038. type: 'JsdocTypeSpecialNamePath',
  1039. value: token.text.slice(1, -1),
  1040. specialType: type,
  1041. meta: {
  1042. quote: token.text[0] === '\'' ? 'single' : 'double'
  1043. }
  1044. };
  1045. }
  1046. else {
  1047. let value = '';
  1048. const allowed = ['Identifier', '@', '/'];
  1049. while (allowed.some(type => parser.consume(type))) {
  1050. value += token.text;
  1051. token = parser.getToken();
  1052. }
  1053. result = {
  1054. type: 'JsdocTypeSpecialNamePath',
  1055. value,
  1056. specialType: type,
  1057. meta: {
  1058. quote: undefined
  1059. }
  1060. };
  1061. }
  1062. return assertTerminal(moduleParser.parseInfixIntermediateType(result, Precedence.ALL));
  1063. }
  1064. }
  1065. class ObjectParslet {
  1066. constructor(opts) {
  1067. this.allowKeyTypes = opts.allowKeyTypes;
  1068. }
  1069. accepts(type) {
  1070. return type === '{';
  1071. }
  1072. getPrecedence() {
  1073. return Precedence.OBJECT;
  1074. }
  1075. parsePrefix(parser) {
  1076. parser.consume('{');
  1077. const result = {
  1078. type: 'JsdocTypeObject',
  1079. meta: {
  1080. separator: 'comma'
  1081. },
  1082. elements: []
  1083. };
  1084. if (!parser.consume('}')) {
  1085. let separator;
  1086. while (true) {
  1087. let field = parser.parseIntermediateType(Precedence.OBJECT);
  1088. let optional = false;
  1089. if (field.type === 'JsdocTypeNullable') {
  1090. optional = true;
  1091. field = field.element;
  1092. }
  1093. if (field.type === 'JsdocTypeNumber' || field.type === 'JsdocTypeName' || field.type === 'JsdocTypeStringValue') {
  1094. let quote;
  1095. if (field.type === 'JsdocTypeStringValue') {
  1096. quote = field.meta.quote;
  1097. }
  1098. result.elements.push({
  1099. type: 'JsdocTypeKeyValue',
  1100. value: field.value.toString(),
  1101. right: undefined,
  1102. optional: optional,
  1103. meta: {
  1104. quote
  1105. }
  1106. });
  1107. }
  1108. else if (field.type === 'JsdocTypeKeyValue') {
  1109. result.elements.push(field);
  1110. }
  1111. else {
  1112. throw new UnexpectedTypeError(field);
  1113. }
  1114. if (parser.consume(',')) {
  1115. separator = 'comma';
  1116. }
  1117. else if (parser.consume(';')) {
  1118. separator = 'semicolon';
  1119. }
  1120. else {
  1121. break;
  1122. }
  1123. }
  1124. result.meta.separator = separator !== null && separator !== void 0 ? separator : 'comma';
  1125. if (!parser.consume('}')) {
  1126. throw new Error('Unterminated record type. Missing \'}\'');
  1127. }
  1128. }
  1129. return result;
  1130. }
  1131. }
  1132. const jsdocGrammar = () => {
  1133. const { prefixParslets, infixParslets } = baseGrammar();
  1134. return {
  1135. prefixParslets: [
  1136. ...prefixParslets,
  1137. new ObjectParslet({
  1138. allowKeyTypes: true
  1139. }),
  1140. new FunctionParslet({
  1141. allowWithoutParenthesis: true,
  1142. allowNamedParameters: ['this', 'new'],
  1143. allowNoReturnType: true
  1144. }),
  1145. new StringValueParslet(),
  1146. new SpecialNamePathParslet({
  1147. allowedTypes: ['module', 'external', 'event']
  1148. }),
  1149. new VariadicParslet({
  1150. allowEnclosingBrackets: true
  1151. }),
  1152. new NameParslet({
  1153. allowedAdditionalTokens: ['keyof']
  1154. })
  1155. ],
  1156. infixParslets: [
  1157. ...infixParslets,
  1158. new SymbolParslet(),
  1159. new ArrayBracketsParslet(),
  1160. new NamePathParslet({
  1161. allowJsdocNamePaths: true
  1162. }),
  1163. new KeyValueParslet({
  1164. allowKeyTypes: true,
  1165. allowOptional: false
  1166. }),
  1167. new VariadicParslet({
  1168. allowEnclosingBrackets: true
  1169. })
  1170. ]
  1171. };
  1172. };
  1173. class TypeOfParslet {
  1174. accepts(type, next) {
  1175. return type === 'typeof';
  1176. }
  1177. getPrecedence() {
  1178. return Precedence.KEY_OF_TYPE_OF;
  1179. }
  1180. parsePrefix(parser) {
  1181. parser.consume('typeof');
  1182. return {
  1183. type: 'JsdocTypeTypeof',
  1184. element: assertTerminal(parser.parseType(Precedence.KEY_OF_TYPE_OF))
  1185. };
  1186. }
  1187. }
  1188. const closureGrammar = () => {
  1189. const { prefixParslets, infixParslets } = baseGrammar();
  1190. return {
  1191. prefixParslets: [
  1192. ...prefixParslets,
  1193. new ObjectParslet({
  1194. allowKeyTypes: false
  1195. }),
  1196. new NameParslet({
  1197. allowedAdditionalTokens: ['event', 'external']
  1198. }),
  1199. new TypeOfParslet(),
  1200. new FunctionParslet({
  1201. allowWithoutParenthesis: false,
  1202. allowNamedParameters: ['this', 'new'],
  1203. allowNoReturnType: true
  1204. }),
  1205. new VariadicParslet({
  1206. allowEnclosingBrackets: false
  1207. }),
  1208. new NameParslet({
  1209. allowedAdditionalTokens: ['keyof']
  1210. }),
  1211. new SpecialNamePathParslet({
  1212. allowedTypes: ['module']
  1213. })
  1214. ],
  1215. infixParslets: [
  1216. ...infixParslets,
  1217. new NamePathParslet({
  1218. allowJsdocNamePaths: true
  1219. }),
  1220. new KeyValueParslet({
  1221. allowKeyTypes: false,
  1222. allowOptional: false
  1223. }),
  1224. new SymbolParslet()
  1225. ]
  1226. };
  1227. };
  1228. class TupleParslet {
  1229. constructor(opts) {
  1230. this.allowQuestionMark = opts.allowQuestionMark;
  1231. }
  1232. accepts(type, next) {
  1233. return type === '[';
  1234. }
  1235. getPrecedence() {
  1236. return Precedence.TUPLE;
  1237. }
  1238. parsePrefix(parser) {
  1239. parser.consume('[');
  1240. const result = {
  1241. type: 'JsdocTypeTuple',
  1242. elements: []
  1243. };
  1244. if (parser.consume(']')) {
  1245. return result;
  1246. }
  1247. const typeList = parser.parseIntermediateType(Precedence.ALL);
  1248. if (typeList.type === 'JsdocTypeParameterList') {
  1249. result.elements = typeList.elements.map(assertTerminal);
  1250. }
  1251. else {
  1252. result.elements = [assertTerminal(typeList)];
  1253. }
  1254. if (!parser.consume(']')) {
  1255. throw new Error('Unterminated \'[\'');
  1256. }
  1257. if (!this.allowQuestionMark && result.elements.some(e => e.type === 'JsdocTypeUnknown')) {
  1258. throw new Error('Question mark in tuple not allowed');
  1259. }
  1260. return result;
  1261. }
  1262. }
  1263. class KeyOfParslet {
  1264. accepts(type, next) {
  1265. return type === 'keyof';
  1266. }
  1267. getPrecedence() {
  1268. return Precedence.KEY_OF_TYPE_OF;
  1269. }
  1270. parsePrefix(parser) {
  1271. parser.consume('keyof');
  1272. return {
  1273. type: 'JsdocTypeKeyof',
  1274. element: assertTerminal(parser.parseType(Precedence.KEY_OF_TYPE_OF))
  1275. };
  1276. }
  1277. }
  1278. class ImportParslet {
  1279. accepts(type, next) {
  1280. return type === 'import';
  1281. }
  1282. getPrecedence() {
  1283. return Precedence.PREFIX;
  1284. }
  1285. parsePrefix(parser) {
  1286. parser.consume('import');
  1287. if (!parser.consume('(')) {
  1288. throw new Error('Missing parenthesis after import keyword');
  1289. }
  1290. const path = parser.parseType(Precedence.PREFIX);
  1291. if (path.type !== 'JsdocTypeStringValue') {
  1292. throw new Error('Only string values are allowed as paths for imports');
  1293. }
  1294. if (!parser.consume(')')) {
  1295. throw new Error('Missing closing parenthesis after import keyword');
  1296. }
  1297. return {
  1298. type: 'JsdocTypeImport',
  1299. element: path
  1300. };
  1301. }
  1302. }
  1303. class ArrowFunctionParslet extends BaseFunctionParslet {
  1304. accepts(type, next) {
  1305. return type === '=>';
  1306. }
  1307. getPrecedence() {
  1308. return Precedence.ARROW;
  1309. }
  1310. parseInfix(parser, left) {
  1311. parser.consume('=>');
  1312. return {
  1313. type: 'JsdocTypeFunction',
  1314. parameters: this.getParameters(left).map(assertKeyValueOrName),
  1315. arrow: true,
  1316. parenthesis: true,
  1317. returnType: parser.parseType(Precedence.ALL)
  1318. };
  1319. }
  1320. }
  1321. class IntersectionParslet {
  1322. accepts(type) {
  1323. return type === '&';
  1324. }
  1325. getPrecedence() {
  1326. return Precedence.INTERSECTION;
  1327. }
  1328. parseInfix(parser, left) {
  1329. parser.consume('&');
  1330. const elements = [];
  1331. do {
  1332. elements.push(parser.parseType(Precedence.INTERSECTION));
  1333. } while (parser.consume('&'));
  1334. return {
  1335. type: 'JsdocTypeIntersection',
  1336. elements: [assertTerminal(left), ...elements]
  1337. };
  1338. }
  1339. }
  1340. const typescriptGrammar = () => {
  1341. const { prefixParslets, infixParslets } = baseGrammar();
  1342. // module seems not to be supported
  1343. return {
  1344. parallel: [
  1345. moduleGrammar()
  1346. ],
  1347. prefixParslets: [
  1348. ...prefixParslets,
  1349. new ObjectParslet({
  1350. allowKeyTypes: false
  1351. }),
  1352. new TypeOfParslet(),
  1353. new KeyOfParslet(),
  1354. new ImportParslet(),
  1355. new StringValueParslet(),
  1356. new FunctionParslet({
  1357. allowWithoutParenthesis: true,
  1358. allowNoReturnType: false,
  1359. allowNamedParameters: ['this', 'new']
  1360. }),
  1361. new TupleParslet({
  1362. allowQuestionMark: false
  1363. }),
  1364. new VariadicParslet({
  1365. allowEnclosingBrackets: false
  1366. }),
  1367. new NameParslet({
  1368. allowedAdditionalTokens: ['event', 'external']
  1369. }),
  1370. new SpecialNamePathParslet({
  1371. allowedTypes: ['module']
  1372. })
  1373. ],
  1374. infixParslets: [
  1375. ...infixParslets,
  1376. new ArrayBracketsParslet(),
  1377. new ArrowFunctionParslet(),
  1378. new NamePathParslet({
  1379. allowJsdocNamePaths: false
  1380. }),
  1381. new KeyValueParslet({
  1382. allowKeyTypes: false,
  1383. allowOptional: true
  1384. }),
  1385. new IntersectionParslet()
  1386. ]
  1387. };
  1388. };
  1389. const parsers = {
  1390. jsdoc: new Parser(jsdocGrammar()),
  1391. closure: new Parser(closureGrammar()),
  1392. typescript: new Parser(typescriptGrammar())
  1393. };
  1394. /**
  1395. * This function parses the given expression in the given mode and produces a {@link ParseResult}.
  1396. * @param expression
  1397. * @param mode
  1398. */
  1399. function parse(expression, mode) {
  1400. return parsers[mode].parseText(expression);
  1401. }
  1402. /**
  1403. * This function tries to parse the given expression in multiple modes and returns the first successful
  1404. * {@link ParseResult}. By default it tries `'typescript'`, `'closure'` and `'jsdoc'` in this order. If
  1405. * no mode was successful it throws the error that was produced by the last parsing attempt.
  1406. * @param expression
  1407. * @param modes
  1408. */
  1409. function tryParse(expression, modes = ['typescript', 'closure', 'jsdoc']) {
  1410. let error;
  1411. for (const mode of modes) {
  1412. try {
  1413. return parsers[mode].parseText(expression);
  1414. }
  1415. catch (e) {
  1416. error = e;
  1417. }
  1418. }
  1419. throw error;
  1420. }
  1421. function transform(rules, parseResult) {
  1422. const rule = rules[parseResult.type];
  1423. if (rule === undefined) {
  1424. throw new Error(`In this set of transform rules exists no rule for type ${parseResult.type}.`);
  1425. }
  1426. return rule(parseResult, aParseResult => transform(rules, aParseResult));
  1427. }
  1428. function notAvailableTransform(parseResult) {
  1429. throw new Error('This transform is not available. Are you trying the correct parsing mode?');
  1430. }
  1431. function extractSpecialParams(source) {
  1432. const result = {
  1433. params: []
  1434. };
  1435. for (const param of source.parameters) {
  1436. if (param.type === 'JsdocTypeKeyValue' && param.meta.quote === undefined) {
  1437. if (param.value === 'this') {
  1438. result.this = param.right;
  1439. }
  1440. else if (param.value === 'new') {
  1441. result.new = param.right;
  1442. }
  1443. else {
  1444. result.params.push(param);
  1445. }
  1446. }
  1447. else {
  1448. result.params.push(param);
  1449. }
  1450. }
  1451. return result;
  1452. }
  1453. function applyPosition(position, target, value) {
  1454. return position === 'prefix' ? value + target : target + value;
  1455. }
  1456. function quote(value, quote) {
  1457. switch (quote) {
  1458. case 'double':
  1459. return `"${value}"`;
  1460. case 'single':
  1461. return `'${value}'`;
  1462. case undefined:
  1463. return value;
  1464. }
  1465. }
  1466. function stringifyRules() {
  1467. return {
  1468. JsdocTypeParenthesis: (result, transform) => `(${result.element !== undefined ? transform(result.element) : ''})`,
  1469. JsdocTypeKeyof: (result, transform) => `keyof ${transform(result.element)}`,
  1470. JsdocTypeFunction: (result, transform) => {
  1471. if (!result.arrow) {
  1472. let stringified = 'function';
  1473. if (!result.parenthesis) {
  1474. return stringified;
  1475. }
  1476. stringified += `(${result.parameters.map(transform).join(', ')})`;
  1477. if (result.returnType !== undefined) {
  1478. stringified += `: ${transform(result.returnType)}`;
  1479. }
  1480. return stringified;
  1481. }
  1482. else {
  1483. if (result.returnType === undefined) {
  1484. throw new Error('Arrow function needs a return type.');
  1485. }
  1486. return `(${result.parameters.map(transform).join(', ')}) => ${transform(result.returnType)}`;
  1487. }
  1488. },
  1489. JsdocTypeName: result => result.value,
  1490. JsdocTypeTuple: (result, transform) => `[${result.elements.map(transform).join(', ')}]`,
  1491. JsdocTypeVariadic: (result, transform) => result.meta.position === undefined
  1492. ? '...'
  1493. : applyPosition(result.meta.position, transform(result.element), '...'),
  1494. JsdocTypeNamePath: (result, transform) => {
  1495. const joiner = result.pathType === 'inner' ? '~' : result.pathType === 'instance' ? '#' : '.';
  1496. return `${transform(result.left)}${joiner}${transform(result.right)}`;
  1497. },
  1498. JsdocTypeStringValue: result => quote(result.value, result.meta.quote),
  1499. JsdocTypeAny: () => '*',
  1500. JsdocTypeGeneric: (result, transform) => {
  1501. if (result.meta.brackets === 'square') {
  1502. const element = result.elements[0];
  1503. const transformed = transform(element);
  1504. if (element.type === 'JsdocTypeUnion' || element.type === 'JsdocTypeIntersection') {
  1505. return `(${transformed})[]`;
  1506. }
  1507. else {
  1508. return `${transformed}[]`;
  1509. }
  1510. }
  1511. else {
  1512. return `${transform(result.left)}${result.meta.dot ? '.' : ''}<${result.elements.map(transform).join(', ')}>`;
  1513. }
  1514. },
  1515. JsdocTypeImport: (result, transform) => `import(${transform(result.element)})`,
  1516. JsdocTypeKeyValue: (result, transform) => {
  1517. if ('value' in result) {
  1518. const left = `${quote(result.value, result.meta.quote)}${result.optional ? '?' : ''}`;
  1519. if (result.right === undefined) {
  1520. return left;
  1521. }
  1522. else {
  1523. return left + `: ${transform(result.right)}`;
  1524. }
  1525. }
  1526. else {
  1527. return `${transform(result.left)}: ${transform(result.right)}`;
  1528. }
  1529. },
  1530. JsdocTypeSpecialNamePath: result => `${result.specialType}:${quote(result.value, result.meta.quote)}`,
  1531. JsdocTypeNotNullable: (result, transform) => applyPosition(result.meta.position, transform(result.element), '!'),
  1532. JsdocTypeNull: () => 'null',
  1533. JsdocTypeNullable: (result, transform) => applyPosition(result.meta.position, transform(result.element), '?'),
  1534. JsdocTypeNumber: result => result.value.toString(),
  1535. JsdocTypeObject: (result, transform) => `{${result.elements.map(transform).join((result.meta.separator === 'comma' ? ',' : ';') + ' ')}}`,
  1536. JsdocTypeOptional: (result, transform) => applyPosition(result.meta.position, transform(result.element), '='),
  1537. JsdocTypeSymbol: (result, transform) => `${result.value}(${result.element !== undefined ? transform(result.element) : ''})`,
  1538. JsdocTypeTypeof: (result, transform) => `typeof ${transform(result.element)}`,
  1539. JsdocTypeUndefined: () => 'undefined',
  1540. JsdocTypeUnion: (result, transform) => result.elements.map(transform).join(' | '),
  1541. JsdocTypeUnknown: () => '?',
  1542. JsdocTypeIntersection: (result, transform) => result.elements.map(transform).join(' & '),
  1543. JsdocTypeProperty: result => result.value
  1544. };
  1545. }
  1546. const storedStringifyRules = stringifyRules();
  1547. function stringify(result) {
  1548. return transform(storedStringifyRules, result);
  1549. }
  1550. const reservedWords = [
  1551. 'null',
  1552. 'true',
  1553. 'false',
  1554. 'break',
  1555. 'case',
  1556. 'catch',
  1557. 'class',
  1558. 'const',
  1559. 'continue',
  1560. 'debugger',
  1561. 'default',
  1562. 'delete',
  1563. 'do',
  1564. 'else',
  1565. 'export',
  1566. 'extends',
  1567. 'finally',
  1568. 'for',
  1569. 'function',
  1570. 'if',
  1571. 'import',
  1572. 'in',
  1573. 'instanceof',
  1574. 'new',
  1575. 'return',
  1576. 'super',
  1577. 'switch',
  1578. 'this',
  1579. 'throw',
  1580. 'try',
  1581. 'typeof',
  1582. 'var',
  1583. 'void',
  1584. 'while',
  1585. 'with',
  1586. 'yield'
  1587. ];
  1588. function makeName(value) {
  1589. const result = {
  1590. type: 'NameExpression',
  1591. name: value
  1592. };
  1593. if (reservedWords.includes(value)) {
  1594. result.reservedWord = true;
  1595. }
  1596. return result;
  1597. }
  1598. const catharsisTransformRules = {
  1599. JsdocTypeOptional: (result, transform) => {
  1600. const transformed = transform(result.element);
  1601. transformed.optional = true;
  1602. return transformed;
  1603. },
  1604. JsdocTypeNullable: (result, transform) => {
  1605. const transformed = transform(result.element);
  1606. transformed.nullable = true;
  1607. return transformed;
  1608. },
  1609. JsdocTypeNotNullable: (result, transform) => {
  1610. const transformed = transform(result.element);
  1611. transformed.nullable = false;
  1612. return transformed;
  1613. },
  1614. JsdocTypeVariadic: (result, transform) => {
  1615. if (result.element === undefined) {
  1616. throw new Error('dots without value are not allowed in catharsis mode');
  1617. }
  1618. const transformed = transform(result.element);
  1619. transformed.repeatable = true;
  1620. return transformed;
  1621. },
  1622. JsdocTypeAny: () => ({
  1623. type: 'AllLiteral'
  1624. }),
  1625. JsdocTypeNull: () => ({
  1626. type: 'NullLiteral'
  1627. }),
  1628. JsdocTypeStringValue: result => makeName(quote(result.value, result.meta.quote)),
  1629. JsdocTypeUndefined: () => ({
  1630. type: 'UndefinedLiteral'
  1631. }),
  1632. JsdocTypeUnknown: () => ({
  1633. type: 'UnknownLiteral'
  1634. }),
  1635. JsdocTypeFunction: (result, transform) => {
  1636. const params = extractSpecialParams(result);
  1637. const transformed = {
  1638. type: 'FunctionType',
  1639. params: params.params.map(transform)
  1640. };
  1641. if (params.this !== undefined) {
  1642. transformed.this = transform(params.this);
  1643. }
  1644. if (params.new !== undefined) {
  1645. transformed.new = transform(params.new);
  1646. }
  1647. if (result.returnType !== undefined) {
  1648. transformed.result = transform(result.returnType);
  1649. }
  1650. return transformed;
  1651. },
  1652. JsdocTypeGeneric: (result, transform) => ({
  1653. type: 'TypeApplication',
  1654. applications: result.elements.map(o => transform(o)),
  1655. expression: transform(result.left)
  1656. }),
  1657. JsdocTypeSpecialNamePath: result => makeName(result.specialType + ':' + quote(result.value, result.meta.quote)),
  1658. JsdocTypeName: result => {
  1659. if (result.value !== 'function') {
  1660. return makeName(result.value);
  1661. }
  1662. else {
  1663. return {
  1664. type: 'FunctionType',
  1665. params: []
  1666. };
  1667. }
  1668. },
  1669. JsdocTypeNumber: result => makeName(result.value.toString()),
  1670. JsdocTypeObject: (result, transform) => {
  1671. const transformed = {
  1672. type: 'RecordType',
  1673. fields: []
  1674. };
  1675. for (const field of result.elements) {
  1676. if (field.type !== 'JsdocTypeKeyValue') {
  1677. transformed.fields.push({
  1678. type: 'FieldType',
  1679. key: transform(field),
  1680. value: undefined
  1681. });
  1682. }
  1683. else {
  1684. transformed.fields.push(transform(field));
  1685. }
  1686. }
  1687. return transformed;
  1688. },
  1689. JsdocTypeUnion: (result, transform) => ({
  1690. type: 'TypeUnion',
  1691. elements: result.elements.map(e => transform(e))
  1692. }),
  1693. JsdocTypeKeyValue: (result, transform) => {
  1694. if ('value' in result) {
  1695. return {
  1696. type: 'FieldType',
  1697. key: makeName(quote(result.value, result.meta.quote)),
  1698. value: result.right === undefined ? undefined : transform(result.right)
  1699. };
  1700. }
  1701. else {
  1702. return {
  1703. type: 'FieldType',
  1704. key: transform(result.left),
  1705. value: transform(result.right)
  1706. };
  1707. }
  1708. },
  1709. JsdocTypeNamePath: (result, transform) => {
  1710. const leftResult = transform(result.left);
  1711. let rightValue;
  1712. if (result.right.type === 'JsdocTypeSpecialNamePath') {
  1713. rightValue = transform(result.right).name;
  1714. }
  1715. else {
  1716. rightValue = result.right.value;
  1717. }
  1718. const joiner = result.pathType === 'inner' ? '~' : result.pathType === 'instance' ? '#' : '.';
  1719. return makeName(`${leftResult.name}${joiner}${rightValue}`);
  1720. },
  1721. JsdocTypeSymbol: result => {
  1722. let value = '';
  1723. let element = result.element;
  1724. let trailingDots = false;
  1725. if ((element === null || element === void 0 ? void 0 : element.type) === 'JsdocTypeVariadic') {
  1726. if (element.meta.position === 'prefix') {
  1727. value = '...';
  1728. }
  1729. else {
  1730. trailingDots = true;
  1731. }
  1732. element = element.element;
  1733. }
  1734. if ((element === null || element === void 0 ? void 0 : element.type) === 'JsdocTypeName') {
  1735. value += element.value;
  1736. }
  1737. else if ((element === null || element === void 0 ? void 0 : element.type) === 'JsdocTypeNumber') {
  1738. value += element.value.toString();
  1739. }
  1740. if (trailingDots) {
  1741. value += '...';
  1742. }
  1743. return makeName(`${result.value}(${value})`);
  1744. },
  1745. JsdocTypeParenthesis: (result, transform) => transform(assertTerminal(result.element)),
  1746. JsdocTypeImport: notAvailableTransform,
  1747. JsdocTypeKeyof: notAvailableTransform,
  1748. JsdocTypeTuple: notAvailableTransform,
  1749. JsdocTypeTypeof: notAvailableTransform,
  1750. JsdocTypeIntersection: notAvailableTransform,
  1751. JsdocTypeProperty: notAvailableTransform
  1752. };
  1753. function catharsisTransform(result) {
  1754. return transform(catharsisTransformRules, result);
  1755. }
  1756. function getQuoteStyle(quote) {
  1757. switch (quote) {
  1758. case undefined:
  1759. return 'none';
  1760. case 'single':
  1761. return 'single';
  1762. case 'double':
  1763. return 'double';
  1764. }
  1765. }
  1766. function getMemberType(type) {
  1767. switch (type) {
  1768. case 'inner':
  1769. return 'INNER_MEMBER';
  1770. case 'instance':
  1771. return 'INSTANCE_MEMBER';
  1772. case 'property':
  1773. return 'MEMBER';
  1774. }
  1775. }
  1776. function nestResults(type, results) {
  1777. if (results.length === 2) {
  1778. return {
  1779. type,
  1780. left: results[0],
  1781. right: results[1]
  1782. };
  1783. }
  1784. else {
  1785. return {
  1786. type,
  1787. left: results[0],
  1788. right: nestResults(type, results.slice(1))
  1789. };
  1790. }
  1791. }
  1792. const jtpRules = {
  1793. JsdocTypeOptional: (result, transform) => ({
  1794. type: 'OPTIONAL',
  1795. value: transform(result.element),
  1796. meta: {
  1797. syntax: result.meta.position === 'prefix' ? 'PREFIX_EQUAL_SIGN' : 'SUFFIX_EQUALS_SIGN'
  1798. }
  1799. }),
  1800. JsdocTypeNullable: (result, transform) => ({
  1801. type: 'NULLABLE',
  1802. value: transform(result.element),
  1803. meta: {
  1804. syntax: result.meta.position === 'prefix' ? 'PREFIX_QUESTION_MARK' : 'SUFFIX_QUESTION_MARK'
  1805. }
  1806. }),
  1807. JsdocTypeNotNullable: (result, transform) => ({
  1808. type: 'NOT_NULLABLE',
  1809. value: transform(result.element),
  1810. meta: {
  1811. syntax: result.meta.position === 'prefix' ? 'PREFIX_BANG' : 'SUFFIX_BANG'
  1812. }
  1813. }),
  1814. JsdocTypeVariadic: (result, transform) => {
  1815. const transformed = {
  1816. type: 'VARIADIC',
  1817. meta: {
  1818. syntax: result.meta.position === 'prefix'
  1819. ? 'PREFIX_DOTS'
  1820. : result.meta.position === 'suffix' ? 'SUFFIX_DOTS' : 'ONLY_DOTS'
  1821. }
  1822. };
  1823. if (result.element !== undefined) {
  1824. transformed.value = transform(result.element);
  1825. }
  1826. return transformed;
  1827. },
  1828. JsdocTypeName: result => ({
  1829. type: 'NAME',
  1830. name: result.value
  1831. }),
  1832. JsdocTypeTypeof: (result, transform) => ({
  1833. type: 'TYPE_QUERY',
  1834. name: transform(result.element)
  1835. }),
  1836. JsdocTypeTuple: (result, transform) => ({
  1837. type: 'TUPLE',
  1838. entries: result.elements.map(transform)
  1839. }),
  1840. JsdocTypeKeyof: (result, transform) => ({
  1841. type: 'KEY_QUERY',
  1842. value: transform(result.element)
  1843. }),
  1844. JsdocTypeImport: result => ({
  1845. type: 'IMPORT',
  1846. path: {
  1847. type: 'STRING_VALUE',
  1848. quoteStyle: getQuoteStyle(result.element.meta.quote),
  1849. string: result.element.value
  1850. }
  1851. }),
  1852. JsdocTypeUndefined: () => ({
  1853. type: 'NAME',
  1854. name: 'undefined'
  1855. }),
  1856. JsdocTypeAny: () => ({
  1857. type: 'ANY'
  1858. }),
  1859. JsdocTypeFunction: (result, transform) => {
  1860. const specialParams = extractSpecialParams(result);
  1861. const transformed = {
  1862. type: result.arrow ? 'ARROW' : 'FUNCTION',
  1863. params: specialParams.params.map(param => {
  1864. if (param.type === 'JsdocTypeKeyValue') {
  1865. if (param.right === undefined) {
  1866. throw new Error('Function parameter without \':\' is not expected to be \'KEY_VALUE\'');
  1867. }
  1868. return {
  1869. type: 'NAMED_PARAMETER',
  1870. name: param.value,
  1871. typeName: transform(param.right)
  1872. };
  1873. }
  1874. else {
  1875. return transform(param);
  1876. }
  1877. }),
  1878. new: null,
  1879. returns: null
  1880. };
  1881. if (specialParams.this !== undefined) {
  1882. transformed.this = transform(specialParams.this);
  1883. }
  1884. else if (!result.arrow) {
  1885. transformed.this = null;
  1886. }
  1887. if (specialParams.new !== undefined) {
  1888. transformed.new = transform(specialParams.new);
  1889. }
  1890. if (result.returnType !== undefined) {
  1891. transformed.returns = transform(result.returnType);
  1892. }
  1893. return transformed;
  1894. },
  1895. JsdocTypeGeneric: (result, transform) => {
  1896. const transformed = {
  1897. type: 'GENERIC',
  1898. subject: transform(result.left),
  1899. objects: result.elements.map(transform),
  1900. meta: {
  1901. syntax: result.meta.brackets === 'square' ? 'SQUARE_BRACKET' : result.meta.dot ? 'ANGLE_BRACKET_WITH_DOT' : 'ANGLE_BRACKET'
  1902. }
  1903. };
  1904. if (result.meta.brackets === 'square' && result.elements[0].type === 'JsdocTypeFunction' && !result.elements[0].parenthesis) {
  1905. transformed.objects[0] = {
  1906. type: 'NAME',
  1907. name: 'function'
  1908. };
  1909. }
  1910. return transformed;
  1911. },
  1912. JsdocTypeKeyValue: (result, transform) => {
  1913. if ('left' in result) {
  1914. throw new Error('Keys may not be typed in jsdoctypeparser.');
  1915. }
  1916. if (result.right === undefined) {
  1917. return {
  1918. type: 'RECORD_ENTRY',
  1919. key: result.value.toString(),
  1920. quoteStyle: getQuoteStyle(result.meta.quote),
  1921. value: null,
  1922. readonly: false
  1923. };
  1924. }
  1925. let right = transform(result.right);
  1926. if (result.optional) {
  1927. right = {
  1928. type: 'OPTIONAL',
  1929. value: right,
  1930. meta: {
  1931. syntax: 'SUFFIX_KEY_QUESTION_MARK'
  1932. }
  1933. };
  1934. }
  1935. return {
  1936. type: 'RECORD_ENTRY',
  1937. key: result.value.toString(),
  1938. quoteStyle: getQuoteStyle(result.meta.quote),
  1939. value: right,
  1940. readonly: false
  1941. };
  1942. },
  1943. JsdocTypeObject: (result, transform) => {
  1944. const entries = [];
  1945. for (const field of result.elements) {
  1946. if (field.type === 'JsdocTypeKeyValue') {
  1947. entries.push(transform(field));
  1948. }
  1949. }
  1950. return {
  1951. type: 'RECORD',
  1952. entries
  1953. };
  1954. },
  1955. JsdocTypeSpecialNamePath: result => {
  1956. if (result.specialType !== 'module') {
  1957. throw new Error(`jsdoctypeparser does not support type ${result.specialType} at this point.`);
  1958. }
  1959. return {
  1960. type: 'MODULE',
  1961. value: {
  1962. type: 'FILE_PATH',
  1963. quoteStyle: getQuoteStyle(result.meta.quote),
  1964. path: result.value
  1965. }
  1966. };
  1967. },
  1968. JsdocTypeNamePath: (result, transform) => {
  1969. let hasEventPrefix = false;
  1970. let name;
  1971. let quoteStyle;
  1972. if (result.right.type === 'JsdocTypeSpecialNamePath' && result.right.specialType === 'event') {
  1973. hasEventPrefix = true;
  1974. name = result.right.value;
  1975. quoteStyle = getQuoteStyle(result.right.meta.quote);
  1976. }
  1977. else {
  1978. let quote;
  1979. let value = result.right.value;
  1980. if (value[0] === '\'') {
  1981. quote = 'single';
  1982. value = value.slice(1, -1);
  1983. }
  1984. else if (value[0] === '"') {
  1985. quote = 'double';
  1986. value = value.slice(1, -1);
  1987. }
  1988. name = `${value}`;
  1989. quoteStyle = getQuoteStyle(quote);
  1990. }
  1991. const transformed = {
  1992. type: getMemberType(result.pathType),
  1993. owner: transform(result.left),
  1994. name,
  1995. quoteStyle,
  1996. hasEventPrefix
  1997. };
  1998. if (transformed.owner.type === 'MODULE') {
  1999. const tModule = transformed.owner;
  2000. transformed.owner = transformed.owner.value;
  2001. tModule.value = transformed;
  2002. return tModule;
  2003. }
  2004. else {
  2005. return transformed;
  2006. }
  2007. },
  2008. JsdocTypeUnion: (result, transform) => nestResults('UNION', result.elements.map(transform)),
  2009. JsdocTypeParenthesis: (result, transform) => ({
  2010. type: 'PARENTHESIS',
  2011. value: transform(assertTerminal(result.element))
  2012. }),
  2013. JsdocTypeNull: () => ({
  2014. type: 'NAME',
  2015. name: 'null'
  2016. }),
  2017. JsdocTypeUnknown: () => ({
  2018. type: 'UNKNOWN'
  2019. }),
  2020. JsdocTypeStringValue: result => ({
  2021. type: 'STRING_VALUE',
  2022. quoteStyle: getQuoteStyle(result.meta.quote),
  2023. string: result.value
  2024. }),
  2025. JsdocTypeIntersection: (result, transform) => nestResults('INTERSECTION', result.elements.map(transform)),
  2026. JsdocTypeNumber: result => ({
  2027. type: 'NUMBER_VALUE',
  2028. number: result.value.toString()
  2029. }),
  2030. JsdocTypeSymbol: notAvailableTransform,
  2031. JsdocTypeProperty: notAvailableTransform
  2032. };
  2033. function jtpTransform(result) {
  2034. return transform(jtpRules, result);
  2035. }
  2036. function identityTransformRules() {
  2037. return {
  2038. JsdocTypeIntersection: (result, transform) => ({
  2039. type: 'JsdocTypeIntersection',
  2040. elements: result.elements.map(transform)
  2041. }),
  2042. JsdocTypeGeneric: (result, transform) => ({
  2043. type: 'JsdocTypeGeneric',
  2044. left: transform(result.left),
  2045. elements: result.elements.map(transform),
  2046. meta: {
  2047. dot: result.meta.dot,
  2048. brackets: result.meta.brackets
  2049. }
  2050. }),
  2051. JsdocTypeNullable: result => result,
  2052. JsdocTypeUnion: (result, transform) => ({
  2053. type: 'JsdocTypeUnion',
  2054. elements: result.elements.map(transform)
  2055. }),
  2056. JsdocTypeUnknown: result => result,
  2057. JsdocTypeUndefined: result => result,
  2058. JsdocTypeTypeof: (result, transform) => ({
  2059. type: 'JsdocTypeTypeof',
  2060. element: transform(result.element)
  2061. }),
  2062. JsdocTypeSymbol: (result, transform) => {
  2063. const transformed = {
  2064. type: 'JsdocTypeSymbol',
  2065. value: result.value
  2066. };
  2067. if (result.element !== undefined) {
  2068. transformed.element = transform(result.element);
  2069. }
  2070. return transformed;
  2071. },
  2072. JsdocTypeOptional: (result, transform) => ({
  2073. type: 'JsdocTypeOptional',
  2074. element: transform(result.element),
  2075. meta: {
  2076. position: result.meta.position
  2077. }
  2078. }),
  2079. JsdocTypeObject: (result, transform) => ({
  2080. type: 'JsdocTypeObject',
  2081. meta: {
  2082. separator: 'comma'
  2083. },
  2084. elements: result.elements.map(transform)
  2085. }),
  2086. JsdocTypeNumber: result => result,
  2087. JsdocTypeNull: result => result,
  2088. JsdocTypeNotNullable: (result, transform) => ({
  2089. type: 'JsdocTypeNotNullable',
  2090. element: transform(result.element),
  2091. meta: {
  2092. position: result.meta.position
  2093. }
  2094. }),
  2095. JsdocTypeSpecialNamePath: result => result,
  2096. JsdocTypeKeyValue: (result, transform) => {
  2097. if ('value' in result) {
  2098. return {
  2099. type: 'JsdocTypeKeyValue',
  2100. value: result.value,
  2101. right: result.right === undefined ? undefined : transform(result.right),
  2102. optional: result.optional,
  2103. meta: result.meta
  2104. };
  2105. }
  2106. else {
  2107. return {
  2108. type: 'JsdocTypeKeyValue',
  2109. left: transform(result.left),
  2110. right: transform(result.right)
  2111. };
  2112. }
  2113. },
  2114. JsdocTypeImport: (result, transform) => ({
  2115. type: 'JsdocTypeImport',
  2116. element: transform(result.element)
  2117. }),
  2118. JsdocTypeAny: result => result,
  2119. JsdocTypeStringValue: result => result,
  2120. JsdocTypeNamePath: result => result,
  2121. JsdocTypeVariadic: (result, transform) => {
  2122. const transformed = {
  2123. type: 'JsdocTypeVariadic',
  2124. meta: {
  2125. position: result.meta.position,
  2126. squareBrackets: result.meta.squareBrackets
  2127. }
  2128. };
  2129. if (result.element !== undefined) {
  2130. transformed.element = transform(result.element);
  2131. }
  2132. return transformed;
  2133. },
  2134. JsdocTypeTuple: (result, transform) => ({
  2135. type: 'JsdocTypeTuple',
  2136. elements: result.elements.map(transform)
  2137. }),
  2138. JsdocTypeName: result => result,
  2139. JsdocTypeFunction: (result, transform) => {
  2140. const transformed = {
  2141. type: 'JsdocTypeFunction',
  2142. arrow: result.arrow,
  2143. parameters: result.parameters.map(transform),
  2144. parenthesis: result.parenthesis
  2145. };
  2146. if (result.returnType !== undefined) {
  2147. transformed.returnType = transform(result.returnType);
  2148. }
  2149. return transformed;
  2150. },
  2151. JsdocTypeKeyof: (result, transform) => ({
  2152. type: 'JsdocTypeKeyof',
  2153. element: transform(result.element)
  2154. }),
  2155. JsdocTypeParenthesis: (result, transform) => ({
  2156. type: 'JsdocTypeParenthesis',
  2157. element: transform(result.element)
  2158. }),
  2159. JsdocTypeProperty: result => result
  2160. };
  2161. }
  2162. function _traverse(node, parentNode, property, onEnter, onLeave) {
  2163. onEnter === null || onEnter === void 0 ? void 0 : onEnter(node, parentNode, property);
  2164. if ('left' in node && node.left !== undefined) {
  2165. _traverse(node.left, node, 'left', onEnter, onLeave);
  2166. }
  2167. if ('element' in node && node.element !== undefined) {
  2168. _traverse(node.element, node, 'element', onEnter, onLeave);
  2169. }
  2170. if ('elements' in node && node.elements !== undefined) {
  2171. for (const element of node.elements) {
  2172. _traverse(element, node, 'elements', onEnter, onLeave);
  2173. }
  2174. }
  2175. if ('parameters' in node && node.parameters !== undefined) {
  2176. for (const param of node.parameters) {
  2177. _traverse(param, node, 'parameters', onEnter, onLeave);
  2178. }
  2179. }
  2180. if ('right' in node && node.right !== undefined) {
  2181. _traverse(node.right, node, 'right', onEnter, onLeave);
  2182. }
  2183. if ('returnType' in node && node.returnType !== undefined) {
  2184. _traverse(node.returnType, node, 'returnType', onEnter, onLeave);
  2185. }
  2186. onLeave === null || onLeave === void 0 ? void 0 : onLeave(node, parentNode, property);
  2187. }
  2188. function traverse(node, onEnter, onLeave) {
  2189. _traverse(node, undefined, undefined, onEnter, onLeave);
  2190. }
  2191. const visitorKeys = {
  2192. JsdocTypeAny: [],
  2193. JsdocTypeFunction: ['parameters', 'returnType'],
  2194. JsdocTypeGeneric: ['left', 'elements'],
  2195. JsdocTypeImport: [],
  2196. JsdocTypeIntersection: ['elements'],
  2197. JsdocTypeKeyof: ['element'],
  2198. JsdocTypeKeyValue: ['right'],
  2199. JsdocTypeName: [],
  2200. JsdocTypeNamePath: ['left', 'right'],
  2201. JsdocTypeNotNullable: ['element'],
  2202. JsdocTypeNull: [],
  2203. JsdocTypeNullable: ['element'],
  2204. JsdocTypeNumber: [],
  2205. JsdocTypeObject: ['elements'],
  2206. JsdocTypeOptional: ['element'],
  2207. JsdocTypeParenthesis: ['element'],
  2208. JsdocTypeSpecialNamePath: [],
  2209. JsdocTypeStringValue: [],
  2210. JsdocTypeSymbol: ['element'],
  2211. JsdocTypeTuple: ['elements'],
  2212. JsdocTypeTypeof: ['element'],
  2213. JsdocTypeUndefined: [],
  2214. JsdocTypeUnion: ['elements'],
  2215. JsdocTypeUnknown: [],
  2216. JsdocTypeVariadic: ['element'],
  2217. JsdocTypeProperty: []
  2218. };
  2219. exports.catharsisTransform = catharsisTransform;
  2220. exports.identityTransformRules = identityTransformRules;
  2221. exports.jtpTransform = jtpTransform;
  2222. exports.parse = parse;
  2223. exports.stringify = stringify;
  2224. exports.stringifyRules = stringifyRules;
  2225. exports.transform = transform;
  2226. exports.traverse = traverse;
  2227. exports.tryParse = tryParse;
  2228. exports.visitorKeys = visitorKeys;
  2229. Object.defineProperty(exports, '__esModule', { value: true });
  2230. })));