1 | "use strict";
|
2 | var __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 | }));
|
9 | var __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 | });
|
14 | var __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 | };
|
21 | Object.defineProperty(exports, "__esModule", { value: true });
|
22 | const tsutils = __importStar(require("tsutils"));
|
23 | const ts = __importStar(require("typescript"));
|
24 | const util = __importStar(require("../util"));
|
25 | const util_1 = require("../util");
|
26 | exports.default = util.createRule({
|
27 | name: 'no-unnecessary-type-arguments',
|
28 | meta: {
|
29 | docs: {
|
30 | description: 'Enforces that type arguments will not be used if not required',
|
31 | recommended: false,
|
32 | requiresTypeChecking: true,
|
33 | },
|
34 | fixable: 'code',
|
35 | messages: {
|
36 | unnecessaryTypeParameter: 'This is the default value for this type parameter, so it can be omitted.',
|
37 | },
|
38 | schema: [],
|
39 | type: 'suggestion',
|
40 | },
|
41 | defaultOptions: [],
|
42 | create(context) {
|
43 | const parserServices = util.getParserServices(context);
|
44 | const checker = parserServices.program.getTypeChecker();
|
45 | function checkTSArgsAndParameters(esParameters, typeParameters) {
|
46 |
|
47 | const i = esParameters.params.length - 1;
|
48 | const arg = esParameters.params[i];
|
49 | const param = typeParameters[i];
|
50 | if (!(param === null || param === void 0 ? void 0 : param.default)) {
|
51 | return;
|
52 | }
|
53 |
|
54 | const defaultType = checker.getTypeAtLocation(param.default);
|
55 | const argTsNode = parserServices.esTreeNodeToTSNodeMap.get(arg);
|
56 | const argType = checker.getTypeAtLocation(argTsNode);
|
57 | if (!argType.aliasSymbol && !defaultType.aliasSymbol) {
|
58 | if (argType.flags !== defaultType.flags) {
|
59 | return;
|
60 | }
|
61 | }
|
62 | else if (argType.aliasSymbol !== defaultType.aliasSymbol ||
|
63 | argType.aliasTypeArguments !== defaultType.aliasTypeArguments) {
|
64 | return;
|
65 | }
|
66 | context.report({
|
67 | node: arg,
|
68 | messageId: 'unnecessaryTypeParameter',
|
69 | fix: fixer => fixer.removeRange(i === 0
|
70 | ? esParameters.range
|
71 | : [esParameters.params[i - 1].range[1], arg.range[1]]),
|
72 | });
|
73 | }
|
74 | return {
|
75 | TSTypeParameterInstantiation(node) {
|
76 | const expression = parserServices.esTreeNodeToTSNodeMap.get(node);
|
77 | const typeParameters = getTypeParametersFromNode(expression, checker);
|
78 | if (typeParameters) {
|
79 | checkTSArgsAndParameters(node, typeParameters);
|
80 | }
|
81 | },
|
82 | };
|
83 | },
|
84 | });
|
85 | function getTypeParametersFromNode(node, checker) {
|
86 | if (ts.isExpressionWithTypeArguments(node)) {
|
87 | return getTypeParametersFromType(node.expression, checker);
|
88 | }
|
89 | if (ts.isTypeReferenceNode(node)) {
|
90 | return getTypeParametersFromType(node.typeName, checker);
|
91 | }
|
92 | if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
|
93 | return getTypeParametersFromCall(node, checker);
|
94 | }
|
95 | return undefined;
|
96 | }
|
97 | function getTypeParametersFromType(type, checker) {
|
98 | const symAtLocation = checker.getSymbolAtLocation(type);
|
99 | if (!symAtLocation) {
|
100 | return undefined;
|
101 | }
|
102 | const sym = getAliasedSymbol(symAtLocation, checker);
|
103 | const declarations = sym.getDeclarations();
|
104 | if (!declarations) {
|
105 | return undefined;
|
106 | }
|
107 | return (0, util_1.findFirstResult)(declarations, decl => ts.isClassLike(decl) ||
|
108 | ts.isTypeAliasDeclaration(decl) ||
|
109 | ts.isInterfaceDeclaration(decl)
|
110 | ? decl.typeParameters
|
111 | : undefined);
|
112 | }
|
113 | function getTypeParametersFromCall(node, checker) {
|
114 | const sig = checker.getResolvedSignature(node);
|
115 | const sigDecl = sig === null || sig === void 0 ? void 0 : sig.getDeclaration();
|
116 | if (!sigDecl) {
|
117 | return ts.isNewExpression(node)
|
118 | ? getTypeParametersFromType(node.expression, checker)
|
119 | : undefined;
|
120 | }
|
121 | return sigDecl.typeParameters;
|
122 | }
|
123 | function getAliasedSymbol(symbol, checker) {
|
124 | return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias)
|
125 | ? checker.getAliasedSymbol(symbol)
|
126 | : symbol;
|
127 | }
|
128 |
|
\ | No newline at end of file |