diff --git a/client/packages/plugin-declaration-generator/package.json b/client/packages/plugin-declaration-generator/package.json index 2ce896a0..b40a2532 100644 --- a/client/packages/plugin-declaration-generator/package.json +++ b/client/packages/plugin-declaration-generator/package.json @@ -8,7 +8,9 @@ "build": "tsc", "watch": "tsc --watch", "prepare": "tsc", - "test": "ts-node ./test/index.ts" + "test": "ts-node ./test/index.ts", + "test:parser": "ts-node ./test/parser.ts", + "test:parser:debug": "node -r ts-node/register --inspect-brk ./test/parser.ts" }, "author": "", "license": "MIT", @@ -21,6 +23,7 @@ "glob": "^7.2.0", "lodash": "^4.17.21", "mkdirp": "^1.0.4", + "ts-morph": "^16.0.0", "typescript": "^4.5.2" }, "devDependencies": { @@ -31,7 +34,7 @@ "@types/fs-extra": "^9.0.13", "@types/lodash": "^4.14.170", "@types/mkdirp": "^1.0.2", - "@types/node": "^15.12.5", + "@types/node": "^18.11.7", "ts-node": "^10.0.0" } } diff --git a/client/packages/plugin-declaration-generator/src/parser.ts b/client/packages/plugin-declaration-generator/src/parser.ts new file mode 100644 index 00000000..34763710 --- /dev/null +++ b/client/packages/plugin-declaration-generator/src/parser.ts @@ -0,0 +1,78 @@ +import { + Project, + ProjectOptions, + Symbol, + SyntaxKind, + ts, + Type, +} from 'ts-morph'; + +interface Options { + entryPath: string; + project?: ProjectOptions; +} + +export function parseDeclarationEntry(options: Options) { + const project = new Project(options.project); + const sourceFile = project.getSourceFileOrThrow(options.entryPath); + + for (const [name, declarations] of sourceFile.getExportedDeclarations()) { + console.log( + `${name}: ${declarations + .map((d) => { + if (d.isKind(SyntaxKind.FunctionDeclaration)) { + return d + .getType() + .getCallSignatures() + .map( + (s) => + `(${s + .getParameters() + .map((s) => parseFunctionParameter(s)) + .join(', ')}) => ${s.getReturnType().getText()}` + ) + .join(' | '); + } else { + return d.getType().getText(); + } + }) + .join(' | ')}` + ); + } + + return project; +} + +/** + * 解析函数参数为字符串 + */ +function parseFunctionParameter(parameter: Symbol): string { + debugger; + parameter.getFlags(); + + const name = parameter.getName(); + const isOptional = parameter.isOptional(); + const type = parseType(parameter.getDeclarations()[0].getType()); + + if (isOptional) { + return `${name}?: ${type}`; + } else { + return `${name}: ${type}`; + } +} + +/** + * 解析函数 + */ +function parseType(type: Type): string { + if (type.isObject()) { + const properties = type.getApparentProperties(); + return `{ ${properties + .map( + (p) => `${p.getName()}: ${parseType(p.getDeclarations()[0].getType())}` + ) + .join(', ')} }`; + } + + return type.getText(); +} diff --git a/client/packages/plugin-declaration-generator/test/demo/bar.ts b/client/packages/plugin-declaration-generator/test/demo/bar.ts index 5c5ec3db..7d5eb22d 100644 --- a/client/packages/plugin-declaration-generator/test/demo/bar.ts +++ b/client/packages/plugin-declaration-generator/test/demo/bar.ts @@ -4,3 +4,23 @@ export function bar() { console.log('Anything else'); } + +interface E { + f: symbol; +} + +interface Options { + a: number; + b: string; + c: { + d: string; + e: E; + }; +} + +/** + * This is bar with complex input + */ +export function complexBar(input: Options) { + console.log('Anything else', input); +} diff --git a/client/packages/plugin-declaration-generator/test/demo/foo.ts b/client/packages/plugin-declaration-generator/test/demo/foo.ts index 64aac6c3..e1c08f93 100644 --- a/client/packages/plugin-declaration-generator/test/demo/foo.ts +++ b/client/packages/plugin-declaration-generator/test/demo/foo.ts @@ -3,7 +3,11 @@ import * as mkdirp from 'mkdirp'; /** * This is foo */ -export function foo(): void { - console.log('Anything'); +export function foo(input: string) { + console.log('Anything', input); mkdirp('./foo/foo/foo/foo/foo/foo/foo'); + + return input + 1; } + +export const fooVar = 'fooVar' as string; diff --git a/client/packages/plugin-declaration-generator/test/demo/index.ts b/client/packages/plugin-declaration-generator/test/demo/index.ts index a90b8b13..2a88800b 100644 --- a/client/packages/plugin-declaration-generator/test/demo/index.ts +++ b/client/packages/plugin-declaration-generator/test/demo/index.ts @@ -1,5 +1,5 @@ -export { foo } from '@/foo'; -export { bar } from '@/bar'; +export { foo, fooVar } from '@/foo'; +export { bar, complexBar } from '@/bar'; /** * Root export diff --git a/client/packages/plugin-declaration-generator/test/parser.ts b/client/packages/plugin-declaration-generator/test/parser.ts new file mode 100644 index 00000000..e5192f24 --- /dev/null +++ b/client/packages/plugin-declaration-generator/test/parser.ts @@ -0,0 +1,14 @@ +import { parseDeclarationEntry } from '../src/parser'; +import path from 'path'; + +const project = parseDeclarationEntry({ + entryPath: path.resolve(__dirname, './demo/index.ts'), + project: { + tsConfigFilePath: path.resolve(__dirname, './demo/tsconfig.json'), + }, +}); + +console.log( + 'sourceFile', + project.getSourceFiles().map((item) => item.getFilePath()) +); diff --git a/client/packages/plugin-declaration-generator/tsconfig.json b/client/packages/plugin-declaration-generator/tsconfig.json index 8a74a36e..aefa88d0 100644 --- a/client/packages/plugin-declaration-generator/tsconfig.json +++ b/client/packages/plugin-declaration-generator/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "esnext", - "lib": ["DOM"], + "lib": ["ESNext"], "outDir": "lib", "declaration": true, "esModuleInterop": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96c69550..0ae969bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -230,11 +230,12 @@ importers: '@types/fs-extra': ^9.0.13 '@types/lodash': ^4.14.170 '@types/mkdirp': ^1.0.2 - '@types/node': ^15.12.5 + '@types/node': ^18.11.7 fs-extra: ^10.0.0 glob: ^7.2.0 lodash: ^4.17.21 mkdirp: ^1.0.4 + ts-morph: ^16.0.0 ts-node: ^10.0.0 typescript: ^4.5.2 dependencies: @@ -246,6 +247,7 @@ importers: glob: 7.2.3 lodash: 4.17.21 mkdirp: 1.0.4 + ts-morph: 16.0.0 typescript: 4.7.4 devDependencies: '@babel/types': 7.18.13 @@ -255,8 +257,8 @@ importers: '@types/fs-extra': 9.0.13 '@types/lodash': 4.14.184 '@types/mkdirp': 1.0.2 - '@types/node': 15.14.9 - ts-node: 10.9.1_bqee57coj3oib6dw4m24wknwqe + '@types/node': 18.11.7 + ts-node: 10.9.1_piiski4mlexhenq5w47wjhr3ty client/shared: specifiers: @@ -8982,6 +8984,15 @@ packages: engines: {node: '>=10.13.0'} dev: false + /@ts-morph/common/0.17.0: + resolution: {integrity: sha512-RMSSvSfs9kb0VzkvQ2NWobwnj7TxCA9vI/IjR9bDHqgAyVbu2T0DN4wiKVqomyDWqO7dPr/tErSfq7urQ1Q37g==} + dependencies: + fast-glob: 3.2.11 + minimatch: 5.1.0 + mkdirp: 1.0.4 + path-browserify: 1.0.1 + dev: false + /@tsconfig/docusaurus/1.0.6: resolution: {integrity: sha512-1QxDaP54hpzM6bq9E+yFEo4F9WbWHhsDe4vktZXF/iDlc9FqGr9qlg+3X/nuKQXx8QxHV7ue8NXFazzajsxFBA==} dev: true @@ -9340,7 +9351,7 @@ packages: /@types/fs-extra/9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 18.7.11 + '@types/node': 18.11.7 /@types/glob/7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} @@ -9625,7 +9636,7 @@ packages: /@types/mkdirp/1.0.2: resolution: {integrity: sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==} dependencies: - '@types/node': 18.7.11 + '@types/node': 18.11.7 dev: true /@types/mongoose/5.11.97: @@ -9661,6 +9672,9 @@ packages: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: false + /@types/node/18.11.7: + resolution: {integrity: sha512-LhFTglglr63mNXUSRYD8A+ZAIu5sFqNJ4Y2fPuY7UlrySJH87rRRlhtVmMHplmfk5WkoJGmDjE9oiTfyX94CpQ==} + /@types/node/18.7.11: resolution: {integrity: sha512-KZhFpSLlmK/sdocfSAjqPETTMd0ug6HIMIAwkwUpU79olnZdQtMxpQP+G1wDzCH7na+FltSIhbaZuKdwZ8RDrw==} @@ -12850,6 +12864,10 @@ packages: chalk: 2.4.2 q: 1.5.1 + /code-block-writer/11.0.3: + resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==} + dev: false + /code-excerpt/3.0.0: resolution: {integrity: sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw==} engines: {node: '>=10'} @@ -23372,6 +23390,10 @@ packages: resolution: {integrity: sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==} dev: true + /path-browserify/1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + /path-case/2.1.1: resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} dependencies: @@ -29952,6 +29974,13 @@ packages: yargs-parser: 20.2.9 dev: true + /ts-morph/16.0.0: + resolution: {integrity: sha512-jGNF0GVpFj0orFw55LTsQxVYEUOCWBAbR5Ls7fTYE5pQsbW18ssTb/6UXx/GYAEjS+DQTp8VoTw0vqYMiaaQuw==} + dependencies: + '@ts-morph/common': 0.17.0 + code-block-writer: 11.0.3 + dev: false + /ts-nkeys/1.0.16: resolution: {integrity: sha512-1qrhAlavbm36wtW+7NtKOgxpzl+70NTF8xlz9mEhiA5zHMlMxjj3sEVKWm3pGZhHXE0Q3ykjrj+OSRVaYw+Dqg==} dependencies: @@ -30019,6 +30048,37 @@ packages: yn: 3.1.1 dev: true + /ts-node/10.9.1_piiski4mlexhenq5w47wjhr3ty: + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.3 + '@types/node': 18.11.7 + acorn: 8.8.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.7.4 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + /ts-node/10.9.1_rk33jgomelnuriwr3foeinccb4: resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true