spaceWithinParensRule.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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_NEEDS_SPACE = function (count) {
  29. return "Needs " + count + " whitespace" + (count > 1 ? "s" : "") + " within parentheses";
  30. };
  31. Rule.FAILURE_NO_EXTRA_SPACE = function (count) {
  32. return "No more than " + count + " whitespace" + (count > 1 ? "s" : "") + " within parentheses allowed";
  33. };
  34. Rule.prototype.apply = function (sourceFile) {
  35. return this.applyWithWalker(new SpaceWithinParensWalker(sourceFile, this.ruleName, parseOptions(this.ruleArguments[0])));
  36. };
  37. /* tslint:disable:object-literal-sort-keys */
  38. Rule.metadata = {
  39. ruleName: "space-within-parens",
  40. description: "Enforces spaces within parentheses or disallow them. Empty parentheses () are always allowed.",
  41. hasFix: true,
  42. optionsDescription: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n You may enforce the amount of whitespace within parentheses.\n "], ["\n You may enforce the amount of whitespace within parentheses.\n "]))),
  43. options: { type: "number", min: 0 },
  44. type: "style",
  45. typescriptOnly: false,
  46. };
  47. /* tslint:enable:object-literal-sort-keys */
  48. Rule.FAILURE_NO_SPACE = "Whitespace within parentheses is not allowed";
  49. return Rule;
  50. }(Lint.Rules.AbstractRule));
  51. exports.Rule = Rule;
  52. function parseOptions(whitespaceSize) {
  53. var size = 0;
  54. if (typeof whitespaceSize === "number") {
  55. if (whitespaceSize >= 0) {
  56. size = whitespaceSize;
  57. }
  58. }
  59. else if (typeof whitespaceSize === "string") {
  60. var parsedSize = parseInt(whitespaceSize, 10);
  61. if (!Number.isNaN(parsedSize) && parsedSize >= 0) {
  62. size = parsedSize;
  63. }
  64. }
  65. return {
  66. size: size,
  67. };
  68. }
  69. var SpaceWithinParensWalker = /** @class */ (function (_super) {
  70. tslib_1.__extends(SpaceWithinParensWalker, _super);
  71. function SpaceWithinParensWalker() {
  72. return _super !== null && _super.apply(this, arguments) || this;
  73. }
  74. SpaceWithinParensWalker.prototype.walk = function (sourceFile) {
  75. var _this = this;
  76. tsutils_1.forEachToken(sourceFile, function (token) {
  77. if (token.kind === ts.SyntaxKind.OpenParenToken) {
  78. if (sourceFile.text.charAt(token.end) !== ")") {
  79. _this.checkOpenParenToken(token);
  80. }
  81. }
  82. else if (token.kind === ts.SyntaxKind.CloseParenToken) {
  83. if (sourceFile.text.charAt(token.end - 2) !== "(") {
  84. _this.checkCloseParenToken(token);
  85. }
  86. }
  87. });
  88. };
  89. SpaceWithinParensWalker.prototype.checkOpenParenToken = function (tokenNode) {
  90. var currentPos = tokenNode.end;
  91. var currentChar = this.sourceFile.text.charCodeAt(currentPos);
  92. var allowedSpaceCount = this.options.size;
  93. while (ts.isWhiteSpaceSingleLine(currentChar)) {
  94. ++currentPos;
  95. currentChar = this.sourceFile.text.charCodeAt(currentPos);
  96. }
  97. if (!ts.isLineBreak(currentChar)) {
  98. var whitespaceCount = currentPos - tokenNode.end;
  99. if (whitespaceCount !== allowedSpaceCount) {
  100. var length = 0;
  101. var pos = tokenNode.end;
  102. if (whitespaceCount > allowedSpaceCount) {
  103. pos += allowedSpaceCount;
  104. length = whitespaceCount - allowedSpaceCount;
  105. }
  106. else if (whitespaceCount > 0 && whitespaceCount < allowedSpaceCount) {
  107. pos += allowedSpaceCount - whitespaceCount;
  108. }
  109. this.addFailureAtWithFix(pos, length, whitespaceCount);
  110. }
  111. }
  112. };
  113. SpaceWithinParensWalker.prototype.checkCloseParenToken = function (tokenNode) {
  114. var currentPos = tokenNode.end - 2;
  115. var currentChar = this.sourceFile.text.charCodeAt(currentPos);
  116. var allowedSpaceCount = this.options.size;
  117. while (ts.isWhiteSpaceSingleLine(currentChar)) {
  118. --currentPos;
  119. currentChar = this.sourceFile.text.charCodeAt(currentPos);
  120. }
  121. /**
  122. * Number 40 is open parenthese char code, we skip this cause
  123. * it's already been caught by `checkOpenParenToken`
  124. */
  125. if (!ts.isLineBreak(currentChar) && currentChar !== 40) {
  126. var whitespaceCount = tokenNode.end - currentPos - 2;
  127. if (whitespaceCount !== allowedSpaceCount) {
  128. var length = 0;
  129. var pos = currentPos + 1;
  130. if (whitespaceCount > allowedSpaceCount) {
  131. length = whitespaceCount - allowedSpaceCount;
  132. }
  133. this.addFailureAtWithFix(pos, length, whitespaceCount);
  134. }
  135. }
  136. };
  137. SpaceWithinParensWalker.prototype.addFailureAtWithFix = function (position, length, whitespaceCount) {
  138. var lintMsg;
  139. var lintFix;
  140. var allowedSpaceCount = this.options.size;
  141. if (allowedSpaceCount === 0) {
  142. lintMsg = Rule.FAILURE_NO_SPACE;
  143. lintFix = Lint.Replacement.deleteText(position, length);
  144. }
  145. else if (allowedSpaceCount > whitespaceCount) {
  146. lintMsg = Rule.FAILURE_NEEDS_SPACE(allowedSpaceCount - whitespaceCount);
  147. var whitespace = " ".repeat(allowedSpaceCount - whitespaceCount);
  148. lintFix = Lint.Replacement.appendText(position, whitespace);
  149. }
  150. else {
  151. lintMsg = Rule.FAILURE_NO_EXTRA_SPACE(allowedSpaceCount);
  152. lintFix = Lint.Replacement.deleteText(position, whitespaceCount - allowedSpaceCount);
  153. }
  154. this.addFailureAt(position, length, lintMsg, lintFix);
  155. };
  156. return SpaceWithinParensWalker;
  157. }(Lint.AbstractWalker));
  158. var templateObject_1;