noRedundantJsdocRule.js 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. "use strict";
  2. /**
  3. * @license
  4. * Copyright 2017 Palantir Technologies, Inc.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. Object.defineProperty(exports, "__esModule", { value: true });
  19. var tslib_1 = require("tslib");
  20. var tsutils_1 = require("tsutils");
  21. var ts = require("typescript");
  22. var Lint = require("../index");
  23. var Rule = /** @class */ (function (_super) {
  24. tslib_1.__extends(Rule, _super);
  25. function Rule() {
  26. return _super !== null && _super.apply(this, arguments) || this;
  27. }
  28. Rule.FAILURE_STRING_REDUNDANT_TAG = function (tagName) {
  29. return "JSDoc tag '@" + tagName + "' is redundant in TypeScript code.";
  30. };
  31. Rule.FAILURE_STRING_NO_COMMENT = function (tagName) {
  32. return "'@" + tagName + "' is redundant in TypeScript code if it has no description.";
  33. };
  34. Rule.prototype.apply = function (sourceFile) {
  35. return this.applyWithFunction(sourceFile, walk);
  36. };
  37. /* tslint:disable:object-literal-sort-keys */
  38. Rule.metadata = {
  39. ruleName: "no-redundant-jsdoc",
  40. description: "Forbids JSDoc which duplicates TypeScript functionality.",
  41. optionsDescription: "Not configurable.",
  42. options: null,
  43. optionExamples: [true],
  44. type: "style",
  45. typescriptOnly: true,
  46. };
  47. /* tslint:enable:object-literal-sort-keys */
  48. Rule.FAILURE_STRING_REDUNDANT_TYPE = "Type annotation in JSDoc is redundant in TypeScript code.";
  49. return Rule;
  50. }(Lint.Rules.AbstractRule));
  51. exports.Rule = Rule;
  52. function walk(ctx) {
  53. var sourceFile = ctx.sourceFile;
  54. // Intentionally exclude EndOfFileToken: it can have JSDoc, but it is only relevant in JavaScript files
  55. return sourceFile.statements.forEach(function cb(node) {
  56. if (tsutils_1.canHaveJsDoc(node)) {
  57. for (var _i = 0, _a = tsutils_1.getJsDoc(node, sourceFile); _i < _a.length; _i++) {
  58. var tags = _a[_i].tags;
  59. if (tags !== undefined) {
  60. for (var _b = 0, tags_1 = tags; _b < tags_1.length; _b++) {
  61. var tag = tags_1[_b];
  62. checkTag(tag);
  63. }
  64. }
  65. }
  66. }
  67. return ts.forEachChild(node, cb);
  68. });
  69. function checkTag(tag) {
  70. switch (tag.kind) {
  71. case ts.SyntaxKind.JSDocTag:
  72. if (redundantTags.has(tag.tagName.text)) {
  73. ctx.addFailureAtNode(tag.tagName, Rule.FAILURE_STRING_REDUNDANT_TAG(tag.tagName.text));
  74. }
  75. break;
  76. case ts.SyntaxKind.JSDocAugmentsTag:
  77. // OK
  78. break;
  79. case ts.SyntaxKind.JSDocClassTag:
  80. case ts.SyntaxKind.JSDocTypeTag:
  81. case ts.SyntaxKind.JSDocTypedefTag:
  82. case ts.SyntaxKind.JSDocPropertyTag:
  83. // Always redundant
  84. ctx.addFailureAtNode(tag.tagName, Rule.FAILURE_STRING_REDUNDANT_TAG(tag.tagName.text));
  85. break;
  86. case ts.SyntaxKind.JSDocTemplateTag:
  87. if (tag.comment === undefined || tag.comment === "") {
  88. ctx.addFailureAtNode(tag.tagName, Rule.FAILURE_STRING_NO_COMMENT(tag.tagName.text));
  89. }
  90. break;
  91. case ts.SyntaxKind.JSDocReturnTag:
  92. case ts.SyntaxKind.JSDocParameterTag: {
  93. var _a = tag, typeExpression = _a.typeExpression, comment = _a.comment;
  94. if (typeExpression !== undefined) {
  95. ctx.addFailureAtNode(typeExpression, Rule.FAILURE_STRING_REDUNDANT_TYPE);
  96. }
  97. if (comment === undefined || comment === "") {
  98. // Redundant if no documentation
  99. ctx.addFailureAtNode(tag.tagName, Rule.FAILURE_STRING_NO_COMMENT(tag.tagName.text));
  100. }
  101. break;
  102. }
  103. default:
  104. throw new Error("Unexpected tag kind: " + ts.SyntaxKind[tag.kind]);
  105. }
  106. }
  107. }
  108. var redundantTags = new Set([
  109. "abstract",
  110. "access",
  111. "class",
  112. "constant",
  113. "constructs",
  114. "default",
  115. "enum",
  116. "exports",
  117. "function",
  118. "global",
  119. "implements",
  120. "interface",
  121. "instance",
  122. "member",
  123. "memberof",
  124. "mixes",
  125. "mixin",
  126. "module",
  127. "name",
  128. "namespace",
  129. "override",
  130. "private",
  131. "property",
  132. "protected",
  133. "public",
  134. "readonly",
  135. "requires",
  136. "static",
  137. "this",
  138. ]);