4 * Copyright 2017 Palantir Technologies, Inc.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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 LINE_BREAK_REGEX = /\r?\n/;
24 var Rule = /** @class */ (function (_super) {
25 tslib_1.__extends(Rule, _super);
27 return _super !== null && _super.apply(this, arguments) || this;
29 Rule.prototype.apply = function (sourceFile) {
30 return this.applyWithWalker(new Walker(sourceFile, this.ruleName, undefined));
32 /* tslint:disable:object-literal-sort-keys */
34 ruleName: "import-spacing",
35 description: "Ensures proper spacing between import statement keywords",
36 optionsDescription: "Not configurable.",
38 optionExamples: [true],
40 typescriptOnly: false,
42 Rule.ADD_SPACE_AFTER_IMPORT = "Add space after 'import'";
43 Rule.TOO_MANY_SPACES_AFTER_IMPORT = "Too many spaces after 'import'";
44 Rule.ADD_SPACE_AFTER_STAR = "Add space after '*'";
45 Rule.TOO_MANY_SPACES_AFTER_STAR = "Too many spaces after '*'";
46 Rule.ADD_SPACE_AFTER_FROM = "Add space after 'from'";
47 Rule.TOO_MANY_SPACES_AFTER_FROM = "Too many spaces after 'from'";
48 Rule.ADD_SPACE_BEFORE_FROM = "Add space before 'from'";
49 Rule.TOO_MANY_SPACES_BEFORE_FROM = "Too many spaces before 'from'";
50 Rule.NO_LINE_BREAKS = "Line breaks are not allowed in import declaration";
52 }(Lint.Rules.AbstractRule));
54 var Walker = /** @class */ (function (_super) {
55 tslib_1.__extends(Walker, _super);
57 return _super !== null && _super.apply(this, arguments) || this;
59 Walker.prototype.walk = function (_a) {
60 var statements = _a.statements;
61 for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) {
62 var statement = statements_1[_i];
63 if (!tsutils_1.isImportDeclaration(statement)) {
66 var importClause = statement.importClause;
67 if (importClause === undefined) {
68 this.checkModuleWithSideEffect(statement);
71 this.checkImportClause(statement, importClause);
72 var namedBindings = importClause.namedBindings;
73 if (namedBindings !== undefined && tsutils_1.isNamespaceImport(namedBindings)) {
74 this.checkNamespaceImport(namedBindings);
79 Walker.prototype.checkImportClause = function (node, importClause) {
80 var text = node.getText(this.sourceFile);
81 var nodeStart = node.getStart(this.sourceFile);
82 var importKeywordEnd = nodeStart + "import".length;
83 var moduleSpecifierStart = node.moduleSpecifier.getStart(this.sourceFile);
84 var importClauseEnd = importClause.getEnd();
85 var importClauseStart = importClause.getStart(this.sourceFile);
86 if (importKeywordEnd === importClauseStart) {
87 this.addFailureAt(nodeStart, "import".length, Rule.ADD_SPACE_AFTER_IMPORT);
89 else if (importClauseStart > importKeywordEnd + 1) {
90 this.addFailure(nodeStart, importClauseStart, Rule.TOO_MANY_SPACES_AFTER_IMPORT);
92 var fromString = text.substring(importClauseEnd - nodeStart, moduleSpecifierStart - nodeStart);
93 if (/from$/.test(fromString)) {
94 this.addFailureAt(importClauseEnd, fromString.length, Rule.ADD_SPACE_AFTER_FROM);
96 else if (/from\s{2,}$/.test(fromString)) {
97 this.addFailureAt(importClauseEnd, fromString.length, Rule.TOO_MANY_SPACES_AFTER_FROM);
99 if (/^\s{2,}from/.test(fromString)) {
100 this.addFailureAt(importClauseEnd, fromString.length, Rule.TOO_MANY_SPACES_BEFORE_FROM);
102 else if (/^from/.test(fromString)) {
103 this.addFailureAt(importClauseEnd, fromString.length, Rule.ADD_SPACE_BEFORE_FROM);
105 var beforeImportClauseText = text.substring(0, importClauseStart - nodeStart);
106 var afterImportClauseText = text.substring(importClauseEnd - nodeStart);
107 if (LINE_BREAK_REGEX.test(beforeImportClauseText)) {
108 this.addFailure(nodeStart, importClauseStart - 1, Rule.NO_LINE_BREAKS);
110 if (LINE_BREAK_REGEX.test(afterImportClauseText)) {
111 this.addFailure(importClauseEnd, node.getEnd(), Rule.NO_LINE_BREAKS);
114 Walker.prototype.checkNamespaceImport = function (node) {
115 var text = node.getText(this.sourceFile);
116 if (text.indexOf("*as") > -1) {
117 this.addFailureAtNode(node, Rule.ADD_SPACE_AFTER_STAR);
119 else if (/\*\s{2,}as/.test(text)) {
120 this.addFailureAtNode(node, Rule.TOO_MANY_SPACES_AFTER_STAR);
122 else if (LINE_BREAK_REGEX.test(text)) {
123 this.addFailureAtNode(node, Rule.NO_LINE_BREAKS);
126 Walker.prototype.checkModuleWithSideEffect = function (node) {
127 var nodeStart = node.getStart(this.sourceFile);
128 var moduleSpecifierStart = node.moduleSpecifier.getStart(this.sourceFile);
129 if (nodeStart + "import".length + 1 < moduleSpecifierStart) {
130 this.addFailure(nodeStart, moduleSpecifierStart, Rule.TOO_MANY_SPACES_AFTER_IMPORT);
132 else if (nodeStart + "import".length === moduleSpecifierStart) {
133 this.addFailureAtNode(tsutils_1.getChildOfKind(node, ts.SyntaxKind.ImportKeyword, this.sourceFile), Rule.ADD_SPACE_AFTER_IMPORT);
135 if (LINE_BREAK_REGEX.test(node.getText())) {
136 this.addFailureAtNode(node, Rule.NO_LINE_BREAKS);
140 }(Lint.AbstractWalker));