text: "use strict";
  var __extends = (this && this.__extends) || (function () {
      var extendStatics = function (d, b) {
          extendStatics = Object.setPrototypeOf ||
              ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
              function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
          return extendStatics(d, b);
      };
      return function (d, b) {
          extendStatics(d, b);
          function __() { this.constructor = d; }
          d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
      };
  })();
  Object.defineProperty(exports, "__esModule", { value: true });
  var compiler = require("@angular/compiler");
  var Lint = require("tslint");
  var ts = require("typescript");
  var logger_1 = require("../util/logger");
  var utils_1 = require("../util/utils");
  var config_1 = require("./config");
  var metadata_1 = require("./metadata");
  var ngWalkerFactoryUtils_1 = require("./ngWalkerFactoryUtils");
  var basicCssAstVisitor_1 = require("./styles/basicCssAstVisitor");
  var parseCss_1 = require("./styles/parseCss");
  var basicTemplateAstVisitor_1 = require("./templates/basicTemplateAstVisitor");
  var recursiveAngularExpressionVisitor_1 = require("./templates/recursiveAngularExpressionVisitor");
  var referenceCollectorVisitor_1 = require("./templates/referenceCollectorVisitor");
  var templateParser_1 = require("./templates/templateParser");
  var getDecoratorStringArgs = function (decorator) {
      var expression = decorator.expression;
      var args = ts.isCallExpression(expression) ? expression.arguments : ts.createNodeArray();
      return args.filter(ts.isStringLiteral).map(function (x) { return x.text; });
  };
  var getPosition = function (node) {
      var pos = 0;
      if (node) {
          pos = node.pos + 1;
          try {
              pos = node.getStart() + 1;
          }
          catch (_a) { }
      }
      return pos;
  };
  var NgWalker = (function (_super) {
      __extends(NgWalker, _super);
      function NgWalker(sourceFile, _originalOptions, _config, _metadataReader) {
          var _this = _super.call(this, sourceFile, _originalOptions) || this;
          _this._originalOptions = _originalOptions;
          _this._config = _config;
          _this._metadataReader = _metadataReader;
          _this._metadataReader = _this._metadataReader || ngWalkerFactoryUtils_1.ngWalkerFactoryUtils.defaultMetadataReader();
          _this._config = Object.assign({
              cssVisitorCtrl: basicCssAstVisitor_1.BasicCssAstVisitor,
              templateVisitorCtrl: basicTemplateAstVisitor_1.BasicTemplateAstVisitor,
              expressionVisitorCtrl: recursiveAngularExpressionVisitor_1.RecursiveAngularExpressionVisitor
          }, _this._config || {});
          return _this;
      }
      NgWalker.prototype.visitClassDeclaration = function (declaration) {
          if (this.hasClassName(declaration)) {
              var metadata = this._metadataReader.read(declaration);
              if (metadata instanceof metadata_1.ComponentMetadata) {
                  this.visitNgComponent(metadata);
              }
              else if (metadata instanceof metadata_1.DirectiveMetadata) {
                  this.visitNgDirective(metadata);
              }
              else if (metadata instanceof metadata_1.PipeMetadata) {
                  this.visitNgPipe(metadata);
              }
              else if (metadata instanceof metadata_1.ModuleMetadata) {
                  this.visitNgModule(metadata);
              }
              else if (metadata instanceof metadata_1.InjectableMetadata) {
                  this.visitNgInjectable(metadata);
              }
          }
          utils_1.maybeNodeArray(ts.createNodeArray(declaration.decorators)).forEach(this.visitClassDecorator.bind(this));
          _super.prototype.visitClassDeclaration.call(this, declaration);
      };
      NgWalker.prototype.visitMethodDeclaration = function (method) {
          utils_1.maybeNodeArray(ts.createNodeArray(method.decorators)).forEach(this.visitMethodDecorator.bind(this));
          _super.prototype.visitMethodDeclaration.call(this, method);
      };
      NgWalker.prototype.visitPropertyDeclaration = function (prop) {
          utils_1.maybeNodeArray(ts.createNodeArray(prop.decorators)).forEach(this.visitPropertyDecorator.bind(this));
          _super.prototype.visitPropertyDeclaration.call(this, prop);
      };
      NgWalker.prototype.visitMethodDecorator = function (decorator) {
          var name = utils_1.getDecoratorName(decorator);
          if (name === 'HostListener') {
              this.visitNgHostListener(decorator.parent, decorator, getDecoratorStringArgs(decorator));
          }
      };
      NgWalker.prototype.visitPropertyDecorator = function (decorator) {
          var name = utils_1.getDecoratorName(decorator);
          switch (name) {
              case 'Input':
                  this.visitNgInput(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
              case 'Output':
                  this.visitNgOutput(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
              case 'HostBinding':
                  this.visitNgHostBinding(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
              case 'ContentChild':
                  this.visitNgContentChild(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
              case 'ContentChildren':
                  this.visitNgContentChildren(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
              case 'ViewChild':
                  this.visitNgViewChild(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
              case 'ViewChildren':
                  this.visitNgViewChildren(decorator.parent, decorator, getDecoratorStringArgs(decorator));
                  break;
          }
      };
      NgWalker.prototype.visitNgComponent = function (metadata) {
          var _a = metadata.styles, styles = _a === void 0 ? [] : _a;
          for (var _i = 0, styles_1 = styles; _i < styles_1.length; _i++) {
              var style = styles_1[_i];
              try {
                  var cssAst = parseCss_1.parseCss(style.style.code);
                  this.visitNgStyleHelper(cssAst, metadata, style, getPosition(style.node));
              }
              catch (e) {
                  var name_1 = metadata.controller.name;
                  var text = name_1 && ts.isIdentifier(name_1) ? name_1.text : '';
                  logger_1.logger.error('Cannot parse the styles of', text, e);
              }
          }
          var template = metadata.template;
          if (template && template.template) {
              try {
                  var templateAst = templateParser_1.parseTemplate(template.template.code, config_1.Config.predefinedDirectives);
                  this.visitNgTemplateHelper(templateAst, metadata, getPosition(template.node));
              }
              catch (e) {
                  var name_2 = metadata.controller.name;
                  var text = name_2 && ts.isIdentifier(name_2) ? name_2.text : '';
                  logger_1.logger.error('Cannot parse the template of', text, e);
              }
          }
      };
      NgWalker.prototype.visitClassDecorator = function (decorator) { };
      NgWalker.prototype.visitNgModule = function (metadata) { };
      NgWalker.prototype.visitNgDirective = function (metadata) { };
      NgWalker.prototype.visitNgPipe = function (metadata) { };
      NgWalker.prototype.visitNgInjectable = function (metadata) { };
      NgWalker.prototype.visitNgInput = function (property, input, args) { };
      NgWalker.prototype.visitNgOutput = function (property, output, args) { };
      NgWalker.prototype.visitNgHostBinding = function (property, decorator, args) { };
      NgWalker.prototype.visitNgHostListener = function (method, decorator, args) { };
      NgWalker.prototype.visitNgContentChild = function (property, input, args) { };
      NgWalker.prototype.visitNgContentChildren = function (property, input, args) { };
      NgWalker.prototype.visitNgViewChild = function (property, input, args) { };
      NgWalker.prototype.visitNgViewChildren = function (property, input, args) { };
      NgWalker.prototype.visitNgTemplateHelper = function (roots, context, baseStart) {
          var _this = this;
          if (!roots || !roots.length) {
              return;
          }
          var sourceFile = this.getContextSourceFile(context.template.url, context.template.template.source);
          var referenceVisitor = new referenceCollectorVisitor_1.ReferenceCollectorVisitor();
          var visitor = new this._config.templateVisitorCtrl(sourceFile, this._originalOptions, context, baseStart, this._config.expressionVisitorCtrl);
          compiler.templateVisitAll(referenceVisitor, roots, null);
          visitor._variables = referenceVisitor.variables;
          roots.forEach(function (r) { return visitor.visit(r, context.controller); });
          visitor.getFailures().forEach(function (f) { return _this.addFailure(f); });
      };
      NgWalker.prototype.visitNgStyleHelper = function (style, context, styleMetadata, baseStart) {
          var _this = this;
          if (!style) {
              return;
          }
          var sourceFile = this.getContextSourceFile(styleMetadata.url, styleMetadata.style.source);
          var visitor = new this._config.cssVisitorCtrl(sourceFile, this._originalOptions, context, styleMetadata, baseStart);
          style.visit(visitor);
          visitor.getFailures().forEach(function (f) { return _this.addFailure(f); });
      };
      NgWalker.prototype.getContextSourceFile = function (path, content) {
          if (!path) {
              return this.getSourceFile();
          }
          var sf = ts.createSourceFile(path, "`" + content + "`", ts.ScriptTarget.ES5);
          var original = sf.getFullText;
          sf.getFullText = function () {
              var text = original.apply(sf);
              return text.substring(1, text.length - 1);
          };
          return sf;
      };
      NgWalker.prototype.hasClassName = function (node) {
          return (ts.isDecorator(node) && utils_1.getClassName(node.parent)) || (ts.isClassDeclaration(node) && utils_1.getClassName(node));
      };
      return NgWalker;
  }(Lint.RuleWalker));
  exports.NgWalker = NgWalker;
  