text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  const path_1 = require("path");
  const ts = require("typescript");
  const Lint = require("tslint");
  class Rule extends Lint.Rules.AbstractRule {
      apply(sourceFile) {
          return this.applyWithWalker(new NoCircularImportsWalker(sourceFile, this.getOptions()));
      }
  }
  Rule.FAILURE_STRING = 'circular import detected';
  Rule.metadata = {
      ruleName: 'no-circular-imports',
      description: 'Disallows circular imports.',
      rationale: Lint.Utils.dedent `
          Circular dependencies cause hard-to-catch runtime exceptions.`,
      optionsDescription: 'Not configurable.',
      options: null,
      optionExamples: ['true'],
      type: 'functionality',
      typescriptOnly: false
  };
  exports.Rule = Rule;
  const imports = new Map();
  class NoCircularImportsWalker extends Lint.RuleWalker {
      visitImportDeclaration(node) {
          if (!node.parent || !ts.isSourceFile(node.parent)) {
              return;
          }
          const thisFileName = node.parent.fileName;
          const resolvedThisFileName = path_1.resolve(thisFileName);
          if (!ts.isStringLiteral(node.moduleSpecifier)) {
              return;
          }
          const importFileName = node.moduleSpecifier.text;
          // TODO: does TSLint expose an API for this? it would be nice to use TSC's
          // resolveModuleNames to avoid doing this ourselves, and get support for
          // roots defined in tsconfig.json.
          const resolvedImportFileName = path_1.resolve(path_1.dirname(thisFileName), importFileName + '.ts');
          // add to import graph
          this.addToGraph(resolvedThisFileName, resolvedImportFileName);
          // check for cycles
          if (this.hasCycle(resolvedThisFileName)) {
              this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `${Rule.FAILURE_STRING}: ${this.getCycle(resolvedThisFileName).concat(resolvedThisFileName).map(_ => path_1.basename(_)).join(' -> ')}`));
          }
          super.visitImportDeclaration(node);
      }
      /**
       * TODO: don't rely on import name
       */
      addToGraph(thisFileName, importCanonicalName) {
          if (!imports.get(thisFileName)) {
              imports.set(thisFileName, new Set);
          }
          imports.get(thisFileName).add(importCanonicalName);
      }
      hasCycle(moduleName) {
          return this.getCycle(moduleName).length > 0;
      }
      getCycle(moduleName, accumulator = []) {
          if (!imports.get(moduleName))
              return [];
          if (accumulator.includes(moduleName))
              return accumulator;
          return Array.from(imports.get(moduleName).values()).reduce((_prev, _) => {
              const c = this.getCycle(_, accumulator.concat(moduleName));
              return c.length ? c : [];
          }, []);
      }
  }
  //# sourceMappingURL=noCircularImportsRule.js.map