Defines the ExpressionDescriptor class.
    /// <summary>Handles the specified expression.</summary>
    /// <param name="castExpression">As expression.</param>
    /// <param name="scopeParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(ICastExpression castExpression, Dictionary<string, string> scopeParameters)
    {
      var operand = castExpression.Op;
      if (operand == null)
      {
        return null;
      }

      var type = castExpression.TargetType;
      if (type == null)
      {
        return null;
      }

      var expressionDescriptor = ExpressionTemplateBuilder.Handle(operand, scopeParameters);
      if (expressionDescriptor == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor
      {
        Template = string.Format("({0}){1}", type.GetText(), expressionDescriptor.Template)
      };

      foreach (var variable in expressionDescriptor.TemplateVariables)
      {
        result.TemplateVariables[variable.Key] = variable.Value;
      }

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="asExpression">As expression.</param>
    /// <param name="scopeParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IAsExpression asExpression, Dictionary<string, string> scopeParameters)
    {
      var operand = asExpression.Operand;
      if (operand == null)
      {
        return null;
      }

      var type = asExpression.TypeOperand;
      if (type == null)
      {
        return null;
      }

      var expressionDescriptor = ExpressionTemplateBuilder.Handle(operand, scopeParameters);
      if (expressionDescriptor == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor
      {
        Template = string.Format("{0} {1} {2}", expressionDescriptor.Template, asExpression.OperatorSign.GetTokenType().TokenRepresentation, type.GetText())
      };

      foreach (var variable in expressionDescriptor.TemplateVariables)
      {
        result.TemplateVariables[variable.Key] = variable.Value;
      }

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="parenthesizedExpression">The invocation expression.</param>
    /// <param name="statementParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IParenthesizedExpression parenthesizedExpression, Dictionary<string, string> statementParameters)
    {
      var expression = parenthesizedExpression.Expression;
      if (expression == null)
      {
        return null;
      }

      var statement = ExpressionTemplateBuilder.Handle(expression, statementParameters);
      if (statement == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor
      {
        Template = string.Format("({0})", statement.Template)
      };

      foreach (var variable in statement.TemplateVariables)
      {
        result.TemplateVariables[variable.Key] = variable.Value;
      }

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="unaryOperatorExpression">The invocation expression.</param>
    /// <param name="scopeParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IUnaryOperatorExpression unaryOperatorExpression, Dictionary<string, string> scopeParameters)
    {
      var left = unaryOperatorExpression.Operand;
      if (left == null)
      {
        return null;
      }

      var statement = ExpressionTemplateBuilder.Handle(left, scopeParameters);
      if (statement == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor
      {
        Template = string.Format("{0}{1}", unaryOperatorExpression.OperatorSign.GetTokenType().TokenRepresentation, statement.Template)
      };

      foreach (var variable in statement.TemplateVariables)
      {
        result.TemplateVariables[variable.Key] = variable.Value;
      }

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="thisExpression">The invoked expression.</param>
    /// <param name="statementParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IThisExpression thisExpression, Dictionary<string, string> statementParameters)
    {
      var name = thisExpression.Type().GetPresentableName(thisExpression.Language).Replace("<", string.Empty).Replace(">", string.Empty).Replace(".", string.Empty);

      var result = new ExpressionDescriptor
      {
        Template = "$" + name + "$"
      };

      result.TemplateVariables[name] = string.Format("variableOfType(\"{0}\")", thisExpression.Type().GetLongPresentableName(thisExpression.Language));

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="binaryExpression">The invocation expression.</param>
    /// <param name="statementParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IBinaryExpression binaryExpression, Dictionary<string, string> statementParameters)
    {
      var left = binaryExpression.LeftOperand;
      if (left == null)
      {
        return null;
      }

      var right = binaryExpression.RightOperand;
      if (right == null)
      {
        return null;
      }

      var leftStatement = ExpressionTemplateBuilder.Handle(left, statementParameters);
      if (leftStatement == null)
      {
        return null;
      }

      var rightStatement = ExpressionTemplateBuilder.Handle(right, statementParameters);
      if (rightStatement == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor
      {
        Template = string.Format("{0} {1} {2}", leftStatement.Template, binaryExpression.OperatorSign.GetTokenType().TokenRepresentation, rightStatement.Template)
      };

      foreach (var variable in rightStatement.TemplateVariables)
      {
        result.TemplateVariables[variable.Key] = variable.Value;
      }

      foreach (var variable in leftStatement.TemplateVariables)
      {
        result.TemplateVariables[variable.Key] = variable.Value;
      }

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="invocationExpression">The invocation expression.</param>
    /// <param name="statementParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IInvocationExpression invocationExpression, Dictionary<string, string> statementParameters)
    {
      var invokedExpression = invocationExpression.InvokedExpression as IReferenceExpression;
      if (invokedExpression == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor();

      var qualifierExpression = invokedExpression.QualifierExpression;
      if (qualifierExpression != null)
      {
        var descriptor = ExpressionTemplateBuilder.Handle(qualifierExpression, statementParameters);

        if (descriptor != null)
        {
          result.Template = descriptor.Template;

          foreach (var variable in descriptor.TemplateVariables)
          {
            result.TemplateVariables[variable.Key] = variable.Value;
          }
        }
        else
        {
          result.Template += qualifierExpression.GetText();
        }
      }

      string variableName;
      if (!statementParameters.TryGetValue("VariableName", out variableName))
      {
        variableName = string.Empty;
      }

      if (!string.IsNullOrEmpty(result.Template))
      {
        result.Template += ".";
      }

      result.Template += invokedExpression.NameIdentifier.GetText() + "(";

      var index = 0;
      foreach (var argument in invocationExpression.Arguments)
      {
        var parameter = argument.MatchingParameter;
        if (parameter == null)
        {
          continue;
        }

        var parameterName = parameter.Element.ShortName;

        if (index > 0)
        {
          result.Template += ", ";
        }

        index++;

        var argumentText = argument.GetText();

        if (argumentText == variableName)
        {
          result.Template += "$VariableName$";
          continue;
        }

        /*
        if (argument.Value.IsConstantValue())
        {
          var constantValue = argument.Value.ConstantValue;
          result.Template += "$" + parameterName + "$";

          string s;
          if (constantValue.IsPureNull(argument.Language))
          {
            s = "null";
          }
          else
          {
            s = constantValue.Value.ToString().Replace(",", "&#44;").Replace(",", "&quot;");
            if (constantValue.IsString())
            {
              s = "\"" + s + "\"";
            }
          }

          result.TemplateVariables[parameterName] = "c:" + s;
          continue;
        }
        */
        result.Template += "$" + parameterName + "$";
        result.TemplateVariables[parameterName] = string.Empty;
      }

      result.Template += ")";

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="creationExpression">The invocation expression.</param>
    /// <param name="statementParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IObjectCreationExpression creationExpression, Dictionary<string, string> statementParameters)
    {
      string variableName;
      if (!statementParameters.TryGetValue("VariableName", out variableName))
      {
        variableName = string.Empty;
      }

      var typeName = creationExpression.TypeName;
      if (typeName == null)
      {
        return null;
      }

      var result = new ExpressionDescriptor
      {
        Template = creationExpression.NewKeyword.GetTokenType().TokenRepresentation + " "
      };

      var qualifiedName = string.Empty;

      var resolveResult = typeName.Reference.Resolve();
      if (resolveResult.IsValid())
      {
        var declaredElement = resolveResult.DeclaredElement;
        var typeElement = declaredElement as ITypeElement;
        if (typeElement != null)
        {
          qualifiedName = typeElement.ShortName;

          var ns = typeElement.GetContainingNamespace();

          if (!string.IsNullOrEmpty(ns.QualifiedName))
          {
            qualifiedName = ns.QualifiedName + "." + qualifiedName;
          }
        }
      }

      if (string.IsNullOrEmpty(qualifiedName))
      {
        qualifiedName = typeName.QualifiedName;
      }

      result.Template += qualifiedName + "(";

      var index = 0;
      foreach (var argument in creationExpression.Arguments)
      {
        var parameter = argument.MatchingParameter;
        if (parameter == null)
        {
          continue;
        }

        var parameterName = parameter.Element.ShortName;

        if (index > 0)
        {
          result.Template += ", ";
        }

        index++;

        var argumentText = argument.GetText();

        if (argumentText == variableName)
        {
          result.Template += "$VariableName$";
          continue;
        }

        /*
         if (argument.Value.IsConstantValue())
         {
           var constantValue = argument.Value.ConstantValue;
           result.Template += "$" + parameterName + "$";

           string s;
           if (constantValue.IsPureNull(argument.Language))
           {
             s = "null";
           }
           else
           {
             s = constantValue.Value.ToString().Replace(",", "&#44;").Replace(",", "&quot;");
             if (constantValue.IsString())
             {
               s = "\"" + s + "\"";
             }
           }

           result.TemplateVariables[parameterName] = "c:" + s;
           continue;
         }
         */
        result.Template += "$" + parameterName + "$";
        result.TemplateVariables[parameterName] = string.Empty;
      }

      result.Template += ")";

      return result;
    }
    public static ExpressionDescriptor Handle(IExpression expression, Dictionary<string, string> scopeParameters)
    {
      var invocationExpression = expression as IInvocationExpression;
      if (invocationExpression != null)
      {
        return new InvocationExpression().Handle(invocationExpression, scopeParameters);
      }

      var referenceExpression = expression as IReferenceExpression;
      if (referenceExpression != null)
      {
        return new ReferenceExpression().Handle(referenceExpression, scopeParameters);
      }

      var binaryExpression = expression as IBinaryExpression;
      if (binaryExpression != null)
      {
        return new BinaryExpression().Handle(binaryExpression, scopeParameters);
      }

      var isExpression = expression as IIsExpression;
      if (isExpression != null)
      {
        return new IsExpression().Handle(isExpression, scopeParameters);
      }

      var asExpression = expression as IAsExpression;
      if (asExpression != null)
      {
        return new AsExpression().Handle(asExpression, scopeParameters);
      }

      var castExpression = expression as ICastExpression;
      if (castExpression != null)
      {
        return new CastExpression().Handle(castExpression, scopeParameters);
      }

      var unaryOperatorExpression = expression as IUnaryOperatorExpression;
      if (unaryOperatorExpression != null)
      {
        return new UnaryOperatorExpression().Handle(unaryOperatorExpression, scopeParameters);
      }

      var parenthesizedExpression = expression as IParenthesizedExpression;
      if (parenthesizedExpression != null)
      {
        return new ParenthesizedExpression().Handle(parenthesizedExpression, scopeParameters);
      }

      var thisExpression = expression as IThisExpression;
      if (thisExpression != null)
      {
        return new ThisExpression().Handle(thisExpression, scopeParameters);
      }

      var creationExpression = expression as IObjectCreationExpression;
      if (creationExpression != null)
      {
        return new CreationExpression().Handle(creationExpression, scopeParameters);
      }

      var result = new ExpressionDescriptor
      {
        Template = expression.GetText()
      };

      return result;
    }
    /// <summary>Handles the specified expression.</summary>
    /// <param name="referenceExpression">The invoked expression.</param>
    /// <param name="statementParameters">The parameters.</param>
    /// <returns>Returns the string.</returns>
    public ExpressionDescriptor Handle(IReferenceExpression referenceExpression, Dictionary<string, string> statementParameters)
    {
      var result = new ExpressionDescriptor();

      var qualifierExpression = referenceExpression.QualifierExpression;
      if (qualifierExpression != null)
      {
        var descriptor = ExpressionTemplateBuilder.Handle(qualifierExpression, statementParameters);
        if (descriptor != null)
        {
          result.Template = descriptor.Template;

          foreach (var variable in descriptor.TemplateVariables)
          {
            result.TemplateVariables[variable.Key] = variable.Value;
          }
        }
        else
        {
          result.Template += qualifierExpression.GetText();
        }
      }

      if (!string.IsNullOrEmpty(result.Template))
      {
        result.Template += ".";
      }

      var resolveResult = referenceExpression.Reference.Resolve();
      var declaredElement = resolveResult.DeclaredElement;

      string qualifiedName = null;
      if (qualifierExpression == null && declaredElement != null)
      {
        var typeElement = declaredElement as ITypeElement;
        if (typeElement != null)
        {
          qualifiedName = typeElement.ShortName;

          var ns = typeElement.GetContainingNamespace();

          if (!string.IsNullOrEmpty(ns.QualifiedName))
          {
            qualifiedName = ns.QualifiedName + "." + qualifiedName;
          }
        }
      }

      if (string.IsNullOrEmpty(qualifiedName))
      {
        qualifiedName = referenceExpression.NameIdentifier.GetText();
      }

      string variableName;
      if (!statementParameters.TryGetValue("VariableName", out variableName))
      {
        variableName = string.Empty;
      }

      if (qualifiedName == variableName)
      {
        qualifiedName = "$VariableName$";
      }
      else
      {
        if (declaredElement != null)
        {
          var localVariable = declaredElement as ILocalVariable;
          if (localVariable != null)
          {
            if (localVariable.Type.IsUnknown)
            {
              var name = declaredElement.ShortName;
              qualifiedName = "$" + name + "$";
              result.TemplateVariables[name] = "suggestVariableName()";
            }
            else
            {
              var name = localVariable.Type.GetPresentableName(declaredElement.PresentationLanguage).Replace("<", string.Empty).Replace(">", string.Empty).Replace(".", string.Empty);
              qualifiedName = "$" + name + "$";
              result.TemplateVariables[name] = string.Format("variableOfType(\"{0}\")", localVariable.Type.GetLongPresentableName(declaredElement.PresentationLanguage));
            }
          }

          var parameter = declaredElement as IParameter;
          if (parameter != null)
          {
            if (parameter.Type.IsUnknown)
            {
              var name = declaredElement.ShortName;
              qualifiedName = "$" + name + "$";
              result.TemplateVariables[name] = "suggestVariableName()";
            }
            else
            {
              var name = parameter.Type.GetPresentableName(declaredElement.PresentationLanguage).Replace("<", string.Empty).Replace(">", string.Empty).Replace(".", string.Empty);
              qualifiedName = "$" + name + "$";
              result.TemplateVariables[name] = string.Format("variableOfType(\"{0}\")", parameter.Type.GetLongPresentableName(declaredElement.PresentationLanguage));
            }
          }
        }
      }

      result.Template += qualifiedName;

      return result;
    }