From 3653077c9507ca1ac0b552a931333eff5ad353fb Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Fri, 18 Aug 2023 17:39:57 +0200 Subject: [PATCH] Add an experiment reading out a JSDoc comment --- README.md | 2 + package.json5 | 5 +- pnpm-lock.yaml | 125 +++++++++++++---------------- src/experiment/arithmeticInfer3.js | 16 ++++ src/generic/infer.ts | 2 +- src/plugins/infer1.ts | 2 +- src/plugins/infer3.ts | 67 ++++++++++++++++ 7 files changed, 148 insertions(+), 71 deletions(-) create mode 100644 src/experiment/arithmeticInfer3.js create mode 100644 src/plugins/infer3.ts diff --git a/README.md b/README.md index ebd41b6..6402234 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ None of the experiments (`infer1` and `infer2`) are outputting something useful pnpm experiment:infer1 pnpm experiment:infer1-direct pnpm experiment:infer2 + pnpm experiment:infer3 ### Read more @@ -59,3 +60,4 @@ None of the experiments (`infer1` and `infer2`) are outputting something useful - https://stackoverflow.com/questions/63944135/typescript-compiler-api-how-to-get-type-with-resolved-type-arguments - https://stackoverflow.com/questions/48886508/typechecker-api-how-do-i-find-inferred-type-arguments-to-a-function - https://blog.logrocket.com/using-typescript-transforms-to-enrich-runtime-code-3fd2863221ed/ +- https://github.com/itsdouges/typescript-transformer-handbook#transforms diff --git a/package.json5 b/package.json5 index 0044401..3c214e5 100644 --- a/package.json5 +++ b/package.json5 @@ -5,9 +5,10 @@ main: 'index.ts', scripts: { 'build-and-run': 'ttsc -b && node build', - 'experiment:infer1': 'ttsc -b && node build/plugins/infer.js ./src/generic/arithmetic.ts', - 'experiment:infer1-direct': 'ttsc -b && node build/plugins/infer.js ./src/experiment/arithmeticInfer1.ts', + 'experiment:infer1': 'ttsc -b && node build/plugins/infer1.js ./src/generic/arithmetic.ts', + 'experiment:infer1-direct': 'ttsc -b && node build/plugins/infer1.js ./src/experiment/arithmeticInfer1.ts', 'experiment:infer2': 'ttsc -b && node build/plugins/infer2.js ./src/experiment/arithmeticInfer2.ts', + 'experiment:infer3': 'ttsc -b && node build/plugins/infer3.js ./src/experiment/arithmeticInfer3.js', test: 'echo "Error: no test specified" && exit 1', }, keywords: [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ec9e4e..47c4737 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,152 +1,143 @@ -lockfileVersion: '6.0' +lockfileVersion: 5.4 -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false +specifiers: + '@types/node': 18.11.18 + reflect-metadata: 0.1.13 + source-map: ^0.7.4 + ts-node: 10.9.1 + ttypescript: 1.5.15 + typescript: 4.7.4 + typescript-rtti: 0.8.3 dependencies: - reflect-metadata: - specifier: 0.1.13 - version: 0.1.13 - source-map: - specifier: ^0.7.4 - version: 0.7.4 - typescript-rtti: - specifier: 0.8.3 - version: 0.8.3(reflect-metadata@0.1.13)(typescript@4.7.4) + reflect-metadata: 0.1.13 + source-map: 0.7.4 + typescript-rtti: 0.8.3_qh5shpxvbkbt6m3jqtkkp2svgu devDependencies: - '@types/node': - specifier: 18.11.18 - version: 18.11.18 - ts-node: - specifier: 10.9.1 - version: 10.9.1(@types/node@18.11.18)(typescript@4.7.4) - ttypescript: - specifier: 1.5.15 - version: 1.5.15(ts-node@10.9.1)(typescript@4.7.4) - typescript: - specifier: 4.7.4 - version: 4.7.4 + '@types/node': 18.11.18 + ts-node: 10.9.1_nv75g3i7xuh23du6z7qul3uiqi + ttypescript: 1.5.15_6oasmw356qmm23djlsjgkwvrtm + typescript: 4.7.4 packages: - /@cspotcode/source-map-support@0.8.1: + /@cspotcode/source-map-support/0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} dependencies: '@jridgewell/trace-mapping': 0.3.9 dev: true - /@jridgewell/resolve-uri@3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + /@jridgewell/resolve-uri/3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} dev: true - /@jridgewell/sourcemap-codec@1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + /@jridgewell/sourcemap-codec/1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: true - /@jridgewell/trace-mapping@0.3.9: + /@jridgewell/trace-mapping/0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /@tsconfig/node10@1.0.9: + /@tsconfig/node10/1.0.9: resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} dev: true - /@tsconfig/node12@1.0.11: + /@tsconfig/node12/1.0.11: resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} dev: true - /@tsconfig/node14@1.0.3: + /@tsconfig/node14/1.0.3: resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} dev: true - /@tsconfig/node16@1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + /@tsconfig/node16/1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} dev: true - /@types/node@18.11.18: + /@types/node/18.11.18: resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} dev: true - /acorn-walk@8.2.0: + /acorn-walk/8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} dev: true - /acorn@8.8.2: - resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + /acorn/8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} hasBin: true dev: true - /arg@4.1.3: + /arg/4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true - /create-require@1.1.1: + /create-require/1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true - /diff@4.0.2: + /diff/4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} dev: true - /function-bind@1.1.1: + /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true - /has@1.0.3: + /has/1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 dev: true - /is-core-module@2.11.0: - resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + /is-core-module/2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} dependencies: has: 1.0.3 dev: true - /make-error@1.3.6: + /make-error/1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true - /path-parse@1.0.7: + /path-parse/1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true - /reflect-metadata@0.1.13: + /reflect-metadata/0.1.13: resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} dev: false - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + /resolve/1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} hasBin: true dependencies: - is-core-module: 2.11.0 + is-core-module: 2.13.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true - /source-map@0.7.4: + /source-map/0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} dev: false - /supports-preserve-symlinks-flag@1.0.0: + /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} dev: true - /ts-node@10.9.1(@types/node@18.11.18)(typescript@4.7.4): + /ts-node/10.9.1_nv75g3i7xuh23du6z7qul3uiqi: resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -164,9 +155,9 @@ packages: '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 + '@tsconfig/node16': 1.0.4 '@types/node': 18.11.18 - acorn: 8.8.2 + acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 @@ -177,19 +168,19 @@ packages: yn: 3.1.1 dev: true - /ttypescript@1.5.15(ts-node@10.9.1)(typescript@4.7.4): + /ttypescript/1.5.15_6oasmw356qmm23djlsjgkwvrtm: resolution: {integrity: sha512-48ykDNHzFnPMnv4hYX1P8Q84TvCZyL1QlFxeuxsuZ48X2+ameBgPenvmCkHJtoOSxpoWTWi8NcgNrRnVDOmfSg==} hasBin: true peerDependencies: ts-node: '>=8.0.2' typescript: '>=3.2.2' dependencies: - resolve: 1.22.1 - ts-node: 10.9.1(@types/node@18.11.18)(typescript@4.7.4) + resolve: 1.22.4 + ts-node: 10.9.1_nv75g3i7xuh23du6z7qul3uiqi typescript: 4.7.4 dev: true - /typescript-rtti@0.8.3(reflect-metadata@0.1.13)(typescript@4.7.4): + /typescript-rtti/0.8.3_qh5shpxvbkbt6m3jqtkkp2svgu: resolution: {integrity: sha512-uX1A0JKs1o/ptLJqkubRCGgN7NOCYSTKRXyRIjG80exsLrPDq4jJWMfQxlHMAcv/zjoX0V6iIGU7bwjGWTzpLg==} engines: {node: '>=10'} peerDependencies: @@ -200,16 +191,16 @@ packages: typescript: 4.7.4 dev: false - /typescript@4.7.4: + /typescript/4.7.4: resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==} engines: {node: '>=4.2.0'} hasBin: true - /v8-compile-cache-lib@3.0.1: + /v8-compile-cache-lib/3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true - /yn@3.1.1: + /yn/3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} dev: true diff --git a/src/experiment/arithmeticInfer3.js b/src/experiment/arithmeticInfer3.js new file mode 100644 index 0000000..2d0b6da --- /dev/null +++ b/src/experiment/arithmeticInfer3.js @@ -0,0 +1,16 @@ +// @ts-check + +/** + * Function square + * + * Description of function square bla bla bla + * + * @param {{ + * multiply: (a: number, b: number) => number, + * unaryMinus: (x: number) => number + * }} dep + * @return {(a: number) => number} + */ +export function square3 (dep) { + return z => dep.multiply(z, z) +} diff --git a/src/generic/infer.ts b/src/generic/infer.ts index 6e654cb..ac038dd 100644 --- a/src/generic/infer.ts +++ b/src/generic/infer.ts @@ -1,4 +1,4 @@ export function infer(arg: T) : T { - console.error('infer should be replace with runtime type information by a magic TypeScript plugin') + console.error('infer should be replaced with runtime type information by a magic TypeScript plugin') return arg } diff --git a/src/plugins/infer1.ts b/src/plugins/infer1.ts index 81fa0a6..9aea0da 100644 --- a/src/plugins/infer1.ts +++ b/src/plugins/infer1.ts @@ -27,7 +27,7 @@ export function infer(sourceFile: ts.SourceFile) { // z => dep.multiply(z, z) // ) if (node?.['name']?.kind === ts.SyntaxKind.Identifier && node?.['name']['escapedText'] === 'dep') { - console.log('dep', getType(node['type'].kind), node) + // console.log('dep', getType(node['type'].kind), node) node['type']?.members?.forEach(member => { console.log('member', { diff --git a/src/plugins/infer3.ts b/src/plugins/infer3.ts new file mode 100644 index 0000000..c57fd22 --- /dev/null +++ b/src/plugins/infer3.ts @@ -0,0 +1,67 @@ +import { readFileSync } from "fs"; +import * as ts from "typescript"; +import { inspect } from 'util' + +export function infer3(sourceFile: ts.SourceFile) { + recurse(sourceFile); + + function getType(kind: number) { + switch(kind) { + case ts.SyntaxKind.NumberKeyword: return 'number' + case ts.SyntaxKind.StringKeyword: return 'string' + case ts.SyntaxKind.BooleanKeyword: return 'boolean' + case ts.SyntaxKind.JSDoc: return 'jsdoc' + default: return String(ts.SyntaxKind[kind]) // TODO: work out all types + } + } + + function recurse(node: ts.Node) { + if (node.kind === ts.SyntaxKind.Identifier) { + console.log('Identifier', node['escapedText'], ts.SyntaxKind[node.kind]) + } + + if (node['jsDoc']) { + console.log('Found a JSDoc comment:') + // console.log(inspect(node['jsDoc'], { depth: null, colors: true })) + + const fullComment = sourceFile.text.slice(node.pos, node.end) + console.log(fullComment) + // TODO: next steps: + // - either get the types from the TypeScript AST, + // or extract them ourselves with regex or anything from the comment text + // - After that, we have to transform the source file and insert the comments + // as string or object that is runtime accessible in JavaScript + } + + ts.forEachChild(node, recurse); + } +} + +const fileNames = process.argv.slice(2); +console.log('infer files', fileNames) +fileNames.forEach(fileName => { + // Parse a file + const sourceFile = ts.createSourceFile( + fileName, + readFileSync(fileName).toString(), + ts.ScriptTarget.ES2022, + /*setParentNodes */ true + ); + + console.log('FILE') + console.log(fileName) + console.log() + + console.log('SOURCE') + console.log(sourceFile.text) + console.log() + + console.log('AST') + console.log(inspect(sourceFile, { depth: null, colors: true })) + console.log() + + console.log('INFER') + infer3(sourceFile); +}); + +console.log('test!!!')