forked from tsdjs/tsd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
informational.ts
87 lines (70 loc) · 3 KB
/
informational.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import {CallExpression, TypeChecker, TypeFormatFlags} from '@tsd/typescript';
import {Diagnostic} from '../../interfaces';
import {makeDiagnostic, tsutils} from '../../utils';
/**
* Default formatting flags set by TS plus the {@link TypeFormatFlags.NoTruncation NoTruncation} flag.
*
* @see {@link https://github.dev/microsoft/TypeScript/blob/b975dfa1027d1f3073fa7cbe6f7045bf4c882785/src/compiler/checker.ts#L4717 TypeChecker.typeToString}
*/
const typeToStringFormatFlags =
TypeFormatFlags.AllowUniqueESSymbolType |
TypeFormatFlags.UseAliasDefinedOutsideCurrentScope |
TypeFormatFlags.NoTruncation;
/**
* Prints the type of the argument of the assertion as a warning.
*
* @param checker - The TypeScript type checker.
* @param nodes - The `printType` AST nodes.
* @return List of warning diagnostics containing the type of the first argument.
*/
export const printTypeWarning = (checker: TypeChecker, nodes: Set<CallExpression>): Diagnostic[] => {
const diagnostics: Diagnostic[] = [];
if (!nodes) {
return diagnostics;
}
for (const node of nodes) {
const argumentType = checker.getTypeAtLocation(node.arguments[0]);
const argumentExpression = node.arguments[0].getText();
const typeString = checker.typeToString(argumentType, node, typeToStringFormatFlags);
diagnostics.push(makeDiagnostic(node, `Type for expression \`${argumentExpression}\` is: \`${typeString}\``, 'warning'));
}
return diagnostics;
};
/**
* Asserts that the documentation comment for the argument of the assertion
* includes the string literal generic type of the assertion.
*
* @param checker - The TypeScript type checker.
* @param nodes - The `expectDocCommentIncludes` AST nodes.
* @return List of diagnostics.
*/
export const expectDocCommentIncludes = (checker: TypeChecker, nodes: Set<CallExpression>): Diagnostic[] => {
const diagnostics: Diagnostic[] = [];
if (!nodes) {
return diagnostics;
}
for (const node of nodes) {
const expression = tsutils.expressionToString(checker, node.arguments[0]) ?? '?';
if (!node.typeArguments) {
diagnostics.push(makeDiagnostic(node, `Expected documentation comment for expression \`${expression}\` not specified.`));
continue;
}
const maybeExpectedDocComment = checker.getTypeFromTypeNode(node.typeArguments[0]);
if (!maybeExpectedDocComment.isStringLiteral()) {
diagnostics.push(makeDiagnostic(node, `Expected documentation comment for expression \`${expression}\` should be a string literal.`));
continue;
}
const expectedDocComment = maybeExpectedDocComment.value;
const docComment = tsutils.resolveDocComment(checker, node.arguments[0]);
if (!docComment) {
diagnostics.push(makeDiagnostic(node, `Documentation comment for expression \`${expression}\` not found.`));
continue;
}
if (docComment.includes(expectedDocComment)) {
// Do nothing
continue;
}
diagnostics.push(makeDiagnostic(node, `Documentation comment \`${docComment}\` for expression \`${expression}\` does not include expected \`${expectedDocComment}\`.`));
}
return diagnostics;
};