memberAccessRule.js 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. "use strict";
  2. /**
  3. * @license
  4. * Copyright 2013 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 error_1 = require("../error");
  23. var Lint = require("../index");
  24. var OPTION_NO_PUBLIC = "no-public";
  25. var OPTION_CHECK_ACCESSOR = "check-accessor";
  26. var OPTION_CHECK_CONSTRUCTOR = "check-constructor";
  27. var OPTION_CHECK_PARAMETER_PROPERTY = "check-parameter-property";
  28. var Rule = /** @class */ (function (_super) {
  29. tslib_1.__extends(Rule, _super);
  30. function Rule() {
  31. return _super !== null && _super.apply(this, arguments) || this;
  32. }
  33. Rule.FAILURE_STRING_FACTORY = function (memberType, memberName) {
  34. memberName = memberName === undefined ? "" : " '" + memberName + "'";
  35. return "The " + memberType + memberName + " must be marked either 'private', 'public', or 'protected'";
  36. };
  37. Rule.prototype.apply = function (sourceFile) {
  38. var options = this.ruleArguments;
  39. var noPublic = options.indexOf(OPTION_NO_PUBLIC) !== -1;
  40. var checkAccessor = options.indexOf(OPTION_CHECK_ACCESSOR) !== -1;
  41. var checkConstructor = options.indexOf(OPTION_CHECK_CONSTRUCTOR) !== -1;
  42. var checkParameterProperty = options.indexOf(OPTION_CHECK_PARAMETER_PROPERTY) !== -1;
  43. if (noPublic) {
  44. if (checkAccessor || checkConstructor || checkParameterProperty) {
  45. error_1.showWarningOnce("Warning: " + this.ruleName + " - If 'no-public' is present, it should be the only option.");
  46. return [];
  47. }
  48. checkAccessor = checkConstructor = checkParameterProperty = true;
  49. }
  50. return this.applyWithFunction(sourceFile, walk, {
  51. checkAccessor: checkAccessor,
  52. checkConstructor: checkConstructor,
  53. checkParameterProperty: checkParameterProperty,
  54. noPublic: noPublic,
  55. });
  56. };
  57. /* tslint:disable:object-literal-sort-keys */
  58. Rule.metadata = {
  59. ruleName: "member-access",
  60. description: "Requires explicit visibility declarations for class members.",
  61. rationale: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n Explicit visibility declarations can make code more readable and accessible for those new to TS.\n\n Other languages such as C# default to `private`, unlike TypeScript's default of `public`.\n Members lacking a visibility declaration may be an indication of an accidental leak of class internals.\n "], ["\n Explicit visibility declarations can make code more readable and accessible for those new to TS.\n\n Other languages such as C# default to \\`private\\`, unlike TypeScript's default of \\`public\\`.\n Members lacking a visibility declaration may be an indication of an accidental leak of class internals.\n "]))),
  62. optionsDescription: Lint.Utils.dedent(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n These arguments may be optionally provided:\n\n * `\"no-public\"` forbids public accessibility to be specified, because this is the default.\n * `\"check-accessor\"` enforces explicit visibility on get/set accessors\n * `\"check-constructor\"` enforces explicit visibility on constructors\n * `\"check-parameter-property\"` enforces explicit visibility on parameter properties"], ["\n These arguments may be optionally provided:\n\n * \\`\"no-public\"\\` forbids public accessibility to be specified, because this is the default.\n * \\`\"check-accessor\"\\` enforces explicit visibility on get/set accessors\n * \\`\"check-constructor\"\\` enforces explicit visibility on constructors\n * \\`\"check-parameter-property\"\\` enforces explicit visibility on parameter properties"]))),
  63. options: {
  64. type: "array",
  65. items: {
  66. type: "string",
  67. enum: [OPTION_NO_PUBLIC, OPTION_CHECK_ACCESSOR, OPTION_CHECK_CONSTRUCTOR, OPTION_CHECK_PARAMETER_PROPERTY],
  68. },
  69. minLength: 0,
  70. maxLength: 4,
  71. },
  72. optionExamples: [true, [true, OPTION_NO_PUBLIC], [true, OPTION_CHECK_ACCESSOR]],
  73. type: "typescript",
  74. typescriptOnly: true,
  75. hasFix: true,
  76. };
  77. /* tslint:enable:object-literal-sort-keys */
  78. Rule.FAILURE_STRING_NO_PUBLIC = "'public' is implicit.";
  79. return Rule;
  80. }(Lint.Rules.AbstractRule));
  81. exports.Rule = Rule;
  82. function walk(ctx) {
  83. var _a = ctx.options, noPublic = _a.noPublic, checkAccessor = _a.checkAccessor, checkConstructor = _a.checkConstructor, checkParameterProperty = _a.checkParameterProperty;
  84. return ts.forEachChild(ctx.sourceFile, function recur(node) {
  85. if (tsutils_1.isClassLikeDeclaration(node)) {
  86. for (var _i = 0, _a = node.members; _i < _a.length; _i++) {
  87. var child = _a[_i];
  88. if (shouldCheck(child)) {
  89. check(child);
  90. }
  91. if (checkParameterProperty && tsutils_1.isConstructorDeclaration(child) && child.body !== undefined) {
  92. for (var _b = 0, _c = child.parameters; _b < _c.length; _b++) {
  93. var param = _c[_b];
  94. if (tsutils_1.isParameterProperty(param)) {
  95. check(param);
  96. }
  97. }
  98. }
  99. }
  100. }
  101. return ts.forEachChild(node, recur);
  102. });
  103. function shouldCheck(node) {
  104. switch (node.kind) {
  105. case ts.SyntaxKind.Constructor:
  106. return checkConstructor;
  107. case ts.SyntaxKind.GetAccessor:
  108. case ts.SyntaxKind.SetAccessor:
  109. return checkAccessor;
  110. case ts.SyntaxKind.MethodDeclaration:
  111. case ts.SyntaxKind.PropertyDeclaration:
  112. return true;
  113. default:
  114. return false;
  115. }
  116. }
  117. function check(node) {
  118. if (tsutils_1.hasModifier(node.modifiers, ts.SyntaxKind.ProtectedKeyword, ts.SyntaxKind.PrivateKeyword)) {
  119. return;
  120. }
  121. var publicKeyword = tsutils_1.getModifier(node, ts.SyntaxKind.PublicKeyword);
  122. if (noPublic && publicKeyword !== undefined) {
  123. // public is not optional for parameter property without the readonly modifier
  124. if (node.kind !== ts.SyntaxKind.Parameter || tsutils_1.hasModifier(node.modifiers, ts.SyntaxKind.ReadonlyKeyword)) {
  125. var start = publicKeyword.end - "public".length;
  126. ctx.addFailure(start, publicKeyword.end, Rule.FAILURE_STRING_NO_PUBLIC, Lint.Replacement.deleteFromTo(start, tsutils_1.getNextToken(publicKeyword, ctx.sourceFile).getStart(ctx.sourceFile)));
  127. }
  128. }
  129. if (!noPublic && publicKeyword === undefined) {
  130. var nameNode = node.kind === ts.SyntaxKind.Constructor
  131. ? tsutils_1.getChildOfKind(node, ts.SyntaxKind.ConstructorKeyword, ctx.sourceFile)
  132. : node.name !== undefined ? node.name : node;
  133. var memberName = node.name !== undefined && node.name.kind === ts.SyntaxKind.Identifier ? node.name.text : undefined;
  134. ctx.addFailureAtNode(nameNode, Rule.FAILURE_STRING_FACTORY(typeToString(node), memberName), Lint.Replacement.appendText(getInsertionPosition(node, ctx.sourceFile), "public "));
  135. }
  136. }
  137. }
  138. function getInsertionPosition(member, sourceFile) {
  139. var node = member.decorators === undefined ? member : tsutils_1.getTokenAtPosition(member, member.decorators.end, sourceFile);
  140. return node.getStart(sourceFile);
  141. }
  142. function typeToString(node) {
  143. switch (node.kind) {
  144. case ts.SyntaxKind.MethodDeclaration:
  145. return "class method";
  146. case ts.SyntaxKind.PropertyDeclaration:
  147. return "class property";
  148. case ts.SyntaxKind.Constructor:
  149. return "class constructor";
  150. case ts.SyntaxKind.GetAccessor:
  151. return "get property accessor";
  152. case ts.SyntaxKind.SetAccessor:
  153. return "set property accessor";
  154. case ts.SyntaxKind.Parameter:
  155. return "parameter property";
  156. default:
  157. throw new Error("unhandled node type " + ts.SyntaxKind[node.kind]);
  158. }
  159. }
  160. var templateObject_1, templateObject_2;