UNPKG

8.38 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
11}) : function(o, v) {
12 o["default"] = v;
13});
14var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
16 var result = {};
17 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
19 return result;
20};
21Object.defineProperty(exports, "__esModule", { value: true });
22const utils_1 = require("@typescript-eslint/utils");
23const util = __importStar(require("../util"));
24exports.default = util.createRule({
25 name: 'no-invalid-void-type',
26 meta: {
27 type: 'problem',
28 docs: {
29 description: 'Disallows usage of `void` type outside of generic or return types',
30 recommended: false,
31 },
32 messages: {
33 invalidVoidForGeneric: '{{ generic }} may not have void as a type variable.',
34 invalidVoidNotReturnOrGeneric: 'void is only valid as a return type or generic type variable.',
35 invalidVoidNotReturn: 'void is only valid as a return type.',
36 invalidVoidNotReturnOrThisParam: 'void is only valid as return type or type of `this` parameter.',
37 invalidVoidNotReturnOrThisParamOrGeneric: 'void is only valid as a return type or generic type variable or the type of a `this` parameter.',
38 },
39 schema: [
40 {
41 type: 'object',
42 properties: {
43 allowInGenericTypeArguments: {
44 oneOf: [
45 { type: 'boolean' },
46 {
47 type: 'array',
48 items: { type: 'string' },
49 minLength: 1,
50 },
51 ],
52 },
53 allowAsThisParameter: {
54 type: 'boolean',
55 },
56 },
57 additionalProperties: false,
58 },
59 ],
60 },
61 defaultOptions: [
62 { allowInGenericTypeArguments: true, allowAsThisParameter: false },
63 ],
64 create(context, [{ allowInGenericTypeArguments, allowAsThisParameter }]) {
65 const validParents = [
66 utils_1.AST_NODE_TYPES.TSTypeAnnotation, //
67 ];
68 const invalidGrandParents = [
69 utils_1.AST_NODE_TYPES.TSPropertySignature,
70 utils_1.AST_NODE_TYPES.CallExpression,
71 utils_1.AST_NODE_TYPES.PropertyDefinition,
72 utils_1.AST_NODE_TYPES.Identifier,
73 ];
74 const validUnionMembers = [
75 utils_1.AST_NODE_TYPES.TSVoidKeyword,
76 utils_1.AST_NODE_TYPES.TSNeverKeyword,
77 ];
78 if (allowInGenericTypeArguments === true) {
79 validParents.push(utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation);
80 }
81 /**
82 * @brief check if the given void keyword is used as a valid generic type
83 *
84 * reports if the type parametrized by void is not in the whitelist, or
85 * allowInGenericTypeArguments is false.
86 * no-op if the given void keyword is not used as generic type
87 */
88 function checkGenericTypeArgument(node) {
89 var _a, _b;
90 // only matches T<..., void, ...>
91 // extra check for precaution
92 /* istanbul ignore next */
93 if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) !== utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation ||
94 ((_b = node.parent.parent) === null || _b === void 0 ? void 0 : _b.type) !== utils_1.AST_NODE_TYPES.TSTypeReference) {
95 return;
96 }
97 // check whitelist
98 if (Array.isArray(allowInGenericTypeArguments)) {
99 const sourceCode = context.getSourceCode();
100 const fullyQualifiedName = sourceCode
101 .getText(node.parent.parent.typeName)
102 .replace(/ /gu, '');
103 if (!allowInGenericTypeArguments
104 .map(s => s.replace(/ /gu, ''))
105 .includes(fullyQualifiedName)) {
106 context.report({
107 messageId: 'invalidVoidForGeneric',
108 data: { generic: fullyQualifiedName },
109 node,
110 });
111 }
112 return;
113 }
114 if (!allowInGenericTypeArguments) {
115 context.report({
116 messageId: allowAsThisParameter
117 ? 'invalidVoidNotReturnOrThisParam'
118 : 'invalidVoidNotReturn',
119 node,
120 });
121 }
122 }
123 /**
124 * @brief checks that a union containing void is valid
125 * @return true if every member of the union is specified as a valid type in
126 * validUnionMembers, or is a valid generic type parametrized by void
127 */
128 function isValidUnionType(node) {
129 return node.types.every(member => {
130 var _a, _b;
131 return validUnionMembers.includes(member.type) ||
132 // allows any T<..., void, ...> here, checked by checkGenericTypeArgument
133 (member.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
134 ((_a = member.typeParameters) === null || _a === void 0 ? void 0 : _a.type) ===
135 utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation &&
136 ((_b = member.typeParameters) === null || _b === void 0 ? void 0 : _b.params.map(param => param.type).includes(utils_1.AST_NODE_TYPES.TSVoidKeyword)));
137 });
138 }
139 return {
140 TSVoidKeyword(node) {
141 var _a;
142 /* istanbul ignore next */
143 if (!((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent)) {
144 return;
145 }
146 // checks T<..., void, ...> against specification of allowInGenericArguments option
147 if (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation &&
148 node.parent.parent.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
149 checkGenericTypeArgument(node);
150 return;
151 }
152 // union w/ void must contain types from validUnionMembers, or a valid generic void type
153 if (node.parent.type === utils_1.AST_NODE_TYPES.TSUnionType &&
154 isValidUnionType(node.parent)) {
155 return;
156 }
157 // this parameter is ok to be void.
158 if (allowAsThisParameter &&
159 node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation &&
160 node.parent.parent.type === utils_1.AST_NODE_TYPES.Identifier &&
161 node.parent.parent.name === 'this') {
162 return;
163 }
164 // default cases
165 if (validParents.includes(node.parent.type) &&
166 !invalidGrandParents.includes(node.parent.parent.type)) {
167 return;
168 }
169 context.report({
170 messageId: allowInGenericTypeArguments && allowAsThisParameter
171 ? 'invalidVoidNotReturnOrThisParamOrGeneric'
172 : allowInGenericTypeArguments
173 ? 'invalidVoidNotReturnOrGeneric'
174 : allowAsThisParameter
175 ? 'invalidVoidNotReturnOrThisParam'
176 : 'invalidVoidNotReturn',
177 node,
178 });
179 },
180 };
181 },
182});
183//# sourceMappingURL=no-invalid-void-type.js.map
\No newline at end of file