Skip to content

Commit 25e2a09

Browse files
feat: add enforcement for optional parameters that the docs and the signature match
1 parent b2d95bf commit 25e2a09

File tree

7 files changed

+81
-10
lines changed

7 files changed

+81
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
dist
33
*api.json
4+
tsconfig.tsbuildinfo

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"typescript.preferences.quoteStyle": "single",
55
"search.exclude": {
66
"**/dist": true
7-
}
7+
},
8+
"typescript.tsdk": "node_modules/typescript/lib"
89
}

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
"@types/pretty-ms": "^4.0.0",
2626
"jest": "^24.7.1",
2727
"prettier": "^1.17.0",
28-
"ts-jest": "^24.0.2",
2928
"semantic-release": "^15.13.3",
30-
"typescript": "^3.4.5"
29+
"ts-jest": "^24.0.2",
30+
"typescript": "^3.5.1"
3131
},
3232
"dependencies": {
3333
"@types/markdown-it": "^0.0.7",
@@ -40,4 +40,4 @@
4040
"ora": "^3.4.0",
4141
"pretty-ms": "^5.0.0"
4242
}
43-
}
43+
}

src/block-parsers.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,61 @@ import {
1818
EventDocumentationBlock,
1919
} from './ParsedDocumentation';
2020

21+
type GuessedParam = {
22+
name: string;
23+
optional: boolean;
24+
};
25+
26+
export const guessParametersFromSignature = (signature: string) => {
27+
expect(signature).to.match(
28+
/^\(([a-zA-Z,\[\] ]+|(\.\.\.[^\.])|([a-zA-Z][0-9]))+\)$/g,
29+
'signature should be a bracket wrapped group of parameters',
30+
);
31+
const justParams = signature.slice(1, signature.length - 1);
32+
let optionalDepth = 0;
33+
const params: GuessedParam[] = [];
34+
let currentParam = '';
35+
let currentOptional = false;
36+
const maybePushCurrent = () => {
37+
const trimmed = currentParam.trim();
38+
if (trimmed) {
39+
params.push({
40+
name: trimmed,
41+
optional: currentOptional,
42+
});
43+
currentParam = '';
44+
}
45+
};
46+
for (let i = 0; i < justParams.length; i++) {
47+
const char = justParams[i];
48+
switch (char) {
49+
case '[':
50+
optionalDepth++;
51+
break;
52+
case ']':
53+
maybePushCurrent();
54+
optionalDepth--;
55+
expect(optionalDepth).to.be.gte(
56+
0,
57+
`optional depth should never be negative, you have too many "]" characters in your signature: "${signature}"`,
58+
);
59+
break;
60+
case ',':
61+
maybePushCurrent();
62+
break;
63+
default:
64+
if (!currentParam.trim()) currentOptional = optionalDepth > 0;
65+
currentParam += char;
66+
}
67+
}
68+
maybePushCurrent();
69+
expect(optionalDepth).to.equal(
70+
0,
71+
`optional depth should return to 0, you have mismateched [ and ] characters in your signature: "${signature}"`,
72+
);
73+
return params;
74+
};
75+
2176
export const _headingToMethodBlock = (
2277
heading: HeadingContent | null,
2378
): MethodDocumentationBlock | null => {
@@ -34,6 +89,7 @@ export const _headingToMethodBlock = (
3489

3590
let parameters: MethodDocumentationBlock['parameters'] = [];
3691
if (methodSignature !== '()') {
92+
const guessedParams = guessParametersFromSignature(methodSignature);
3793
// If we have parameters we need to find the list of typed keys
3894
const list = findNextList(heading.content)!;
3995
expect(list).to.not.equal(
@@ -46,6 +102,18 @@ export const _headingToMethodBlock = (
46102
required: typedKey.required,
47103
...typedKey.type,
48104
}));
105+
expect(parameters).to.have.lengthOf(
106+
guessedParams.length,
107+
`should have the same number of documented parameters as we have in the method signature: "${methodSignature}"`,
108+
);
109+
for (let i = 0; i < parameters.length; i++) {
110+
expect(parameters[i].required).to.equal(
111+
!guessedParams[i].optional,
112+
`the optionalality of a paramater in the signature should match the documented optionality in the parameter description: "${methodString}${methodSignature}", while parsing parameter: "${
113+
parameters[i].name
114+
}"`,
115+
);
116+
}
49117
}
50118

51119
const returnTokens =

src/markdown-helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ export const rawTypeToTypeInformation = (
298298
...typedKey.type,
299299
}))
300300
: []
301-
: genericProvidedParams,
301+
: (genericProvidedParams as MethodParameterDocumentation[]),
302302
returns: innerTypes[innerTypes.length - 1],
303303
};
304304
}

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"rootDir": "src",
1313
"experimentalDecorators": true,
1414
"strict": true,
15-
"esModuleInterop": true
15+
"esModuleInterop": true,
16+
"incremental": true
1617
}
1718
}

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6238,10 +6238,10 @@ typedarray@^0.0.6:
62386238
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
62396239
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
62406240

6241-
typescript@^3.4.5:
6242-
version "3.4.5"
6243-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
6244-
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
6241+
typescript@^3.5.1:
6242+
version "3.5.1"
6243+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.1.tgz#ba72a6a600b2158139c5dd8850f700e231464202"
6244+
integrity sha512-64HkdiRv1yYZsSe4xC1WVgamNigVYjlssIoaH2HcZF0+ijsk5YK2g0G34w9wJkze8+5ow4STd22AynfO6ZYYLw==
62456245

62466246
uc.micro@^1.0.1, uc.micro@^1.0.5:
62476247
version "1.0.5"

0 commit comments

Comments
 (0)