/// <summary>Gets the statement descriptors.</summary>
 /// <param name="scope">The scope.</param>
 /// <returns>Returns the statement descriptors.</returns>
 public virtual IEnumerable<StatementDescriptor> GetStatementDescriptors(AutoTemplateScope scope)
 {
   foreach (var smartTemplateDescriptor in this.ProcessTemplate(scope))
   {
     yield return smartTemplateDescriptor;
   }
 }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var ifStatement = statement as IIfStatement;
      if (ifStatement == null)
      {
        return null;
      }

      var condition = ifStatement.Condition;
      if (condition == null)
      {
        return null;
      }

      var expressionDescriptor = ExpressionTemplateBuilder.Handle(condition, scope.ScopeParameters);
      if (expressionDescriptor != null)
      {
        return new StatementDescriptor(scope, string.Format("if ({0}) {{ $END$ }}", expressionDescriptor.Template), expressionDescriptor.TemplateVariables);
      }

      var result = new StatementDescriptor(scope)
      {
        Template = string.Format("if ({0}) {{ $END$ }}", condition.GetText())
      };

      string variableName;
      if (scope.ScopeParameters.TryGetValue("VariableName", out variableName))
      {
        result.Template = result.Template.Replace(variableName, "$VariableName$");
      }

      return result;
    }
 /// <summary>Handles the specified statement.</summary>
 /// <param name="statement">The statement.</param>
 /// <param name="scope">The scope.</param>
 /// <returns>Returns the string.</returns>
 public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
 {
   return new StatementDescriptor(scope)
   {
     Template = "continue;"
   };
 }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var returnStatement = statement as IReturnStatement;
      if (returnStatement == null)
      {
        return null;
      }

      var value = returnStatement.Value;
      if (value == null)
      {
        return new StatementDescriptor(scope)
        {
          Template = "return;"
        };
      }

      var expressionDescriptor = ExpressionTemplateBuilder.Handle(value, scope.ScopeParameters);
      if (expressionDescriptor == null)
      {
        return null;
      }

      return new StatementDescriptor(scope, string.Format("return {0}", expressionDescriptor.Template), expressionDescriptor.TemplateVariables);
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var tryStatement = statement as ITryStatement;
      if (tryStatement == null)
      {
        return null;
      }

      var result = new StatementDescriptor(scope)
      {
        Template = string.Format("try {{ $END$ }}")
      };

      foreach (var catchClause in tryStatement.Catches)
      {
        var type = catchClause.ExceptionType;
        if (type == null)
        {
          result.Template += " catch { }";
          continue;
        }

        var typeName = type.GetLongPresentableName(tryStatement.Language);
        result.Template += string.Format(" catch ({0}) {{ }}", typeName);
      }

      return result;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var result = new StatementDescriptor(scope)
      {
        Template = string.Format("try {{ $END$ }} finally {{ }}")
      };

      return result;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <returns>Returns the I enumerable.</returns>
    public override AutoTemplateScope Handle(IStatement statement)
    {
      var usingStatement = statement as IUsingStatement;
      if (usingStatement == null)
      {
        return null;
      }

      var declarations = usingStatement.VariableDeclarations;
      if (declarations.Count != 1)
      {
        return null;
      }

      var localVariableDeclaration = declarations.FirstOrDefault();
      if (localVariableDeclaration == null)
      {
        return null;
      }

      var type = localVariableDeclaration.Type;
      if (!type.IsResolved || type.IsUnknown)
      {
        return null;
      }

      var localVariable = localVariableDeclaration as ILocalVariable;
      if (localVariable == null)
      {
        return null;
      }

      var scopeParameters = new Dictionary<string, string>();

      scopeParameters["VariableName"] = localVariable.ShortName;
      scopeParameters["VariableType"] = type.GetPresentableName(statement.Language);
      scopeParameters["FullName"] = type.GetLongPresentableName(statement.Language);

      var key = string.Format("Inside using of type \"{0}\"", type.GetLongPresentableName(statement.Language));

      var result = new AutoTemplateScope(statement, key, scopeParameters)
      {
        GetNextStatement = this.GetInnerStatement, 
        GetInsertPosition = this.GetInsertPosition
      };

      return result;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var expressionStatement = statement as IExpressionStatement;
      if (expressionStatement == null)
      {
        return null;
      }

      var invocationExpression = expressionStatement.Expression as IInvocationExpression;
      if (invocationExpression == null)
      {
        return null;
      }

      var expressionDescriptor = ExpressionTemplateBuilder.Handle(invocationExpression, scope.ScopeParameters);
      if (expressionDescriptor != null)
      {
        return new StatementDescriptor(scope, expressionDescriptor.Template + ";", expressionDescriptor.TemplateVariables);
      }

      return null;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <returns>Returns the I enumerable.</returns>
    public override AutoTemplateScope Handle(IStatement statement)
    {
      var parent = statement.Parent;
      if (parent == null)
      {
        return null;
      }

      var foreachStatement = parent as IForeachStatement;
      if (foreachStatement == null)
      {
        return null;
      }

      var type = foreachStatement.Collection.Type();
      if (!type.IsResolved || type.IsUnknown)
      {
        return null;
      }

      var scopeParameters = new Dictionary<string, string>();

      scopeParameters["VariableName"] = foreachStatement.IteratorDeclaration.DeclaredName;
      scopeParameters["VariableType"] = type.GetPresentableName(statement.Language);
      scopeParameters["FullName"] = type.GetLongPresentableName(statement.Language);

      var key = string.Format("Inside foreach loop of type \"{0}\"", type.GetLongPresentableName(statement.Language));

      var result = new AutoTemplateScope(statement, key, scopeParameters)
      {
        GetNextStatement = this.GetInnerStatement, 
        GetInsertPosition = this.GetInsertPosition
      };

      return result;
    }
    /// <summary>Processes the template.</summary>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the template.</returns>
    protected IEnumerable<StatementDescriptor> ProcessTemplate(AutoTemplateScope scope)
    {
      var nextStatement = scope.NextStatement;
      if (nextStatement == null)
      {
        yield break;
      }

      foreach (var statementTemplate in AutoTemplateManager.StatementTemplates)
      {
        if (!statementTemplate.CanHandle(nextStatement))
        {
          continue;
        }

        var statementDescriptor = statementTemplate.Handle(nextStatement, scope);
        if (statementDescriptor == null)
        {
          continue;
        }

        yield return statementDescriptor;
      }
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var declarationStatement = statement as IDeclarationStatement;
      if (declarationStatement == null)
      {
        return null;
      }

      var localVariableDeclarations = declarationStatement.VariableDeclarations;
      if (localVariableDeclarations.Count != 1)
      {
        return null;
      }

      var localVariableDeclaration = localVariableDeclarations.FirstOrDefault();
      if (localVariableDeclaration == null)
      {
        return null;
      }

      var expressionInitializer = localVariableDeclaration.Initializer as IExpressionInitializer;
      if (expressionInitializer == null)
      {
        return null;
      }

      var value = expressionInitializer.Value;
      if (value != null)
      {
        var expressionDescriptor = ExpressionTemplateBuilder.Handle(value, scope.ScopeParameters);
        if (expressionDescriptor != null)
        {
          var typeName = string.Empty;
          if (localVariableDeclaration.IsVar)
          {
            typeName += "var";
          }
          else
          {
            var type = localVariableDeclaration.Type;
            if (type != null && !type.IsUnknown && type.IsResolved)
            {
              typeName += type.GetPresentableName(localVariableDeclaration.Language);
            }
            else
            {
              var scalarTypeName = localVariableDeclaration.ScalarTypeName;
              if (scalarTypeName != null)
              {
                typeName += scalarTypeName.QualifiedName;
              }
              else
              {
                return null;
              }
            }
          }

          expressionDescriptor.Template = string.Format("{0} $name$ {1} {2};", typeName, localVariableDeclaration.AssignmentSign.GetTokenType().TokenRepresentation, expressionDescriptor.Template);
          expressionDescriptor.TemplateVariables["name"] = "suggestVariableName()";

          return new StatementDescriptor(scope, expressionDescriptor.Template, expressionDescriptor.TemplateVariables);
        }
      }

      var result = new StatementDescriptor(scope)
      {
        Template = declarationStatement.GetText()
      };

      string variableName;
      if (scope.ScopeParameters.TryGetValue("VariableName", out variableName))
      {
        result.Template = result.Template.Replace(variableName, "$VariableName$");
      }

      return result;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <param name="scope">The scope.</param>
    /// <returns>Returns the string.</returns>
    public override StatementDescriptor Handle(IStatement statement, AutoTemplateScope scope)
    {
      var parent = statement.Parent;
      if (parent == null)
      {
        return null;
      }

      var foreachStatement = parent as IForeachStatement;
      if (foreachStatement == null)
      {
        return null;
      }

      var collection = foreachStatement.Collection;
      if (collection == null)
      {
        return null;
      }

      var iteratorDeclaration = foreachStatement.IteratorDeclaration;
      if (iteratorDeclaration == null)
      {
        return null;
      }

      var iterator = string.Empty;
      if (iteratorDeclaration.IsVar)
      {
        iterator += "var";
      }
      else
      {
        var type = iteratorDeclaration.Type;
        if (type == null || type.IsUnknown || !type.IsResolved)
        {
          return null;
        }

        iterator += type.GetLongPresentableName(statement.Language);
      }

      iterator += " $iterator$";

      var expressionDescriptor = ExpressionTemplateBuilder.Handle(collection, scope.ScopeParameters);
      if (expressionDescriptor != null)
      {
        var r = new StatementDescriptor(scope, string.Format("foreach ({0} in {1}) {{ $END$ }}", iterator, expressionDescriptor.Template), expressionDescriptor.TemplateVariables);
        r.TemplateVariables["iterator"] = "suggestVariableName()";
        return r;
      }

      var result = new StatementDescriptor(scope)
      {
        Template = string.Format("foreach ({0} in {1}) {{ $END$ }}", iterator, collection.GetText())
      };

      string variableName;
      if (scope.ScopeParameters.TryGetValue("VariableName", out variableName))
      {
        result.Template = result.Template.Replace(variableName, "$VariableName$");
      }

      result.TemplateVariables["iterator"] = "suggestVariableName()";

      return result;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <returns>Returns the I enumerable.</returns>
    public override AutoTemplateScope Handle(IStatement statement)
    {
      var ifStatement = statement as IIfStatement;
      if (ifStatement == null)
      {
        return null;
      }

      var referenceExpression = ifStatement.Condition as IReferenceExpression;
      if (referenceExpression == null)
      {
        return null;
      }

      var resolveResult = referenceExpression.Reference.Resolve();
      if (!resolveResult.IsValid())
      {
        return null;
      }

      var declaredElement = resolveResult.DeclaredElement as ITypeMember;
      if (declaredElement == null)
      {
        return null;
      }

      var name = declaredElement.ShortName;

      var type = declaredElement.GetContainingType();
      if (type != null)
      {
        var ns = type.GetContainingNamespace();
        if (ns.QualifiedName != null)
        {
          name = type.ShortName + "." + name;
        }
        else
        {
          name = ns.QualifiedName + "." + type.ShortName + "." + name;
        }
      }

      var scopeParameters = new Dictionary<string, string>();

      var key = string.Format("If expression \"{0}\"", name);

      var result = new AutoTemplateScope(statement, key, scopeParameters)
      {
        GetNextStatement = this.GetInnerStatement, 
        GetInsertPosition = this.GetInsertPosition
      };

      return result;
    }
    /// <summary>Handles the specified statement.</summary>
    /// <param name="statement">The statement.</param>
    /// <returns>Returns the I enumerable.</returns>
    public override AutoTemplateScope Handle(IStatement statement)
    {
      var ifStatement = statement as IIfStatement;
      if (ifStatement == null)
      {
        return null;
      }

      var equalityExpression = ifStatement.Condition as IEqualityExpression;
      if (equalityExpression == null)
      {
        return null;
      }

      var operand = equalityExpression.RightOperand;
      if (operand == null)
      {
        return null;
      }

      if (operand.GetText() == "null")
      {
        operand = equalityExpression.LeftOperand;
      }

      if (operand == null)
      {
        return null;
      }

      var type = operand.Type();
      if (type.IsUnknown || !type.IsResolved)
      {
        return null;
      }

      var equalityType = equalityExpression.EqualityType == EqualityExpressionType.EQEQ ? "is" : "is not";

      var typeName = type.GetLongPresentableName(statement.Language);

      var scopeParameters = new Dictionary<string, string>();
      scopeParameters["VariableType"] = type.GetPresentableName(statement.Language);
      scopeParameters["FullName"] = type.GetLongPresentableName(statement.Language);

      var key = string.Format("If expression of type \"{0}\" {1} null", typeName, equalityType);

      var result = new AutoTemplateScope(statement, key, scopeParameters)
      {
        GetNextStatement = this.GetInnerStatement, 
        GetInsertPosition = this.GetInsertPosition
      };

      return result;
    }