Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Commit

Permalink
Add option for "allow-namespace-imports" to noDuplicateImports rule
Browse files Browse the repository at this point in the history
  • Loading branch information
Edward Drapkin committed Feb 19, 2019
1 parent 9785477 commit d4d1185
Showing 1 changed file with 37 additions and 8 deletions.
45 changes: 37 additions & 8 deletions src/rules/noDuplicateImportsRule.ts
Expand Up @@ -15,11 +15,13 @@
* limitations under the License.
*/

import { isImportDeclaration, isLiteralExpression, isModuleDeclaration } from "tsutils";
import { isImportDeclaration, isLiteralExpression, isModuleDeclaration, isNamespaceImport, } from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";

const OPTION_ALLOW_SEPARATE_NAMESPACE_IMPORTS = "allow-namespace-imports";

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
Expand All @@ -29,9 +31,13 @@ export class Rule extends Lint.Rules.AbstractRule {
rationale: Lint.Utils.dedent`
Using a single import statement per module will make the code clearer because you can see everything being imported
from that module on one line.`,
optionsDescription: "Not configurable",
options: null,
optionExamples: [true],
optionsDescription: Lint.Utils.dedent`
"${OPTION_ALLOW_SEPARATE_NAMESPACE_IMPORTS}" allows you to import namespaces on separate lines.`,
options: {
type: "string",
enum: [OPTION_ALLOW_SEPARATE_NAMESPACE_IMPORTS],
},
optionExamples: [OPTION_ALLOW_SEPARATE_NAMESPACE_IMPORTS],
type: "maintainability",
typescriptOnly: false,
};
Expand All @@ -41,21 +47,43 @@ export class Rule extends Lint.Rules.AbstractRule {
}

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
return this.applyWithFunction(sourceFile, (ctx: Lint.WalkContext<void>) =>
walk(ctx, this.getAllowNamespaceImports()),
);
}

private getAllowNamespaceImports() {
return !!(
this.getOptions().ruleArguments.length > 0 &&
this.getOptions().ruleArguments[0] === OPTION_ALLOW_SEPARATE_NAMESPACE_IMPORTS
);
}
}

function walk(ctx: Lint.WalkContext<void>): void {
walkWorker(ctx, ctx.sourceFile.statements, new Set());
function walk(ctx: Lint.WalkContext<void>, allowNamespaceImports: boolean): void {
walkWorker(ctx, ctx.sourceFile.statements, new Set(), allowNamespaceImports);
}

function statementIsNamespaceImport(statement: ts.ImportDeclaration) {
return !!(
statement.importClause !== undefined &&
statement.importClause.namedBindings !== undefined &&
isNamespaceImport(statement.importClause.namedBindings)
);
}

function walkWorker(
ctx: Lint.WalkContext<void>,
statements: ReadonlyArray<ts.Statement>,
seen: Set<string>,
allowNamespaceImports: boolean,
): void {
for (const statement of statements) {
if (isImportDeclaration(statement) && isLiteralExpression(statement.moduleSpecifier)) {
if (
isImportDeclaration(statement) &&
isLiteralExpression(statement.moduleSpecifier) &&
(!statementIsNamespaceImport(statement) || !allowNamespaceImports)
) {
const { text } = statement.moduleSpecifier;
if (seen.has(text)) {
ctx.addFailureAtNode(statement, Rule.FAILURE_STRING(text));
Expand All @@ -75,6 +103,7 @@ function walkWorker(
ctx,
(statement.body as ts.ModuleBlock).statements,
ts.isExternalModule(ctx.sourceFile) ? seen : new Set(),
allowNamespaceImports,
);
}
}
Expand Down

0 comments on commit d4d1185

Please sign in to comment.