public Expression transform(Expression exp) {
   if (exp == null) return null;
   if (exp.getClass() == VariableExpression.class) {
     return transformVariableExpression((VariableExpression) exp);
   }
   if (exp.getClass() == BinaryExpression.class) {
     return transformBinaryExpression((BinaryExpression) exp);
   }
   if (exp.getClass() == PropertyExpression.class) {
     return transformPropertyExpression((PropertyExpression) exp);
   }
   if (exp.getClass() == MethodCallExpression.class) {
     return transformMethodCallExpression((MethodCallExpression) exp);
   }
   if (exp.getClass() == ClosureExpression.class) {
     return transformClosureExpression((ClosureExpression) exp);
   }
   if (exp.getClass() == ConstructorCallExpression.class) {
     return transformConstructorCallExpression((ConstructorCallExpression) exp);
   }
   if (exp.getClass() == ArgumentListExpression.class) {
     Expression result = exp.transformExpression(this);
     if (inPropertyExpression) {
       foundArgs = result;
     }
     return result;
   }
   if (exp instanceof ConstantExpression) {
     Expression result = exp.transformExpression(this);
     if (inPropertyExpression) {
       foundConstant = result;
     }
     if (inAnnotation && exp instanceof AnnotationConstantExpression) {
       ConstantExpression ce = (ConstantExpression) result;
       if (ce.getValue() instanceof AnnotationNode) {
         // replicate a little bit of AnnotationVisitor here
         // because we can't wait until later to do this
         AnnotationNode an = (AnnotationNode) ce.getValue();
         Map<String, Expression> attributes = an.getMembers();
         for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
           Expression attrExpr = transform(entry.getValue());
           entry.setValue(attrExpr);
         }
       }
     }
     return result;
   }
   return exp.transformExpression(this);
 }
  protected Expression transformMethodCallExpression(MethodCallExpression mce) {
    Expression args = transform(mce.getArguments());
    Expression method = transform(mce.getMethod());
    Expression object = transform(mce.getObjectExpression());
    boolean isExplicitThisOrSuper = false;
    boolean isExplicitSuper = false;
    if (object instanceof VariableExpression) {
      VariableExpression ve = (VariableExpression) object;
      isExplicitThisOrSuper =
          !mce.isImplicitThis() && (ve.isThisExpression() || ve.isSuperExpression());
      isExplicitSuper = ve.isSuperExpression();
    }

    if (mce.isImplicitThis() || isExplicitThisOrSuper) {
      if (mce.isImplicitThis()) {
        Expression ret = findStaticMethodImportFromModule(method, args);
        if (ret != null) {
          setSourcePosition(ret, mce);
          return ret;
        }
        if (method instanceof ConstantExpression && !inLeftExpression) {
          // could be a closure field
          String methodName = (String) ((ConstantExpression) method).getValue();
          ret = findStaticFieldOrPropAccessorImportFromModule(methodName);
          if (ret != null) {
            ret = new MethodCallExpression(ret, "call", args);
            setSourcePosition(ret, mce);
            return ret;
          }
        }
      } else if (currentMethod != null && currentMethod.isStatic() && isExplicitSuper) {
        MethodCallExpression ret =
            new MethodCallExpression(
                new ClassExpression(currentClass.getSuperClass()), method, args);
        setSourcePosition(ret, mce);
        return ret;
      }

      if (method instanceof ConstantExpression) {
        ConstantExpression ce = (ConstantExpression) method;
        Object value = ce.getValue();
        if (value instanceof String) {
          String methodName = (String) value;
          boolean lookForPossibleStaticMethod = !methodName.equals("call");
          if (currentMethod != null && !currentMethod.isStatic()) {
            if (currentClass.hasPossibleMethod(methodName, args)) {
              lookForPossibleStaticMethod = false;
            }
          }
          if (!inClosure
              && (inSpecialConstructorCall
                  || (lookForPossibleStaticMethod
                      && currentClass.hasPossibleStaticMethod(methodName, args)))) {
            StaticMethodCallExpression smce =
                new StaticMethodCallExpression(currentClass, methodName, args);
            setSourcePosition(smce, mce);
            return smce;
          }
        }
      }
    }

    MethodCallExpression result = new MethodCallExpression(object, method, args);
    result.setSafe(mce.isSafe());
    result.setImplicitThis(mce.isImplicitThis());
    result.setSpreadSafe(mce.isSpreadSafe());
    result.setMethodTarget(mce.getMethodTarget());
    // GROOVY-6757
    result.setGenericsTypes(mce.getGenericsTypes());
    setSourcePosition(result, mce);
    return result;
  }
 private Expression findStaticMethodImportFromModule(Expression method, Expression args) {
   ModuleNode module = currentClass.getModule();
   if (module == null || !(method instanceof ConstantExpression)) return null;
   Map<String, ImportNode> importNodes = module.getStaticImports();
   ConstantExpression ce = (ConstantExpression) method;
   Expression expression;
   Object value = ce.getValue();
   // skip non-Strings, e.g. Integer
   if (!(value instanceof String)) return null;
   final String name = (String) value;
   // look for one of these:
   //   import static SomeClass.method [as otherName]
   // when resolving methodCall() or getProp() or setProp()
   if (importNodes.containsKey(name)) {
     ImportNode importNode = importNodes.get(name);
     expression = findStaticMethod(importNode.getType(), importNode.getFieldName(), args);
     if (expression != null) return expression;
     expression =
         findStaticPropertyAccessorGivenArgs(
             importNode.getType(), getPropNameForAccessor(importNode.getFieldName()), args);
     if (expression != null) {
       return new StaticMethodCallExpression(
           importNode.getType(), importNode.getFieldName(), args);
     }
   }
   // look for one of these:
   //   import static SomeClass.someProp [as otherName]
   // when resolving getProp() or setProp()
   if (validPropName(name)) {
     String propName = getPropNameForAccessor(name);
     if (importNodes.containsKey(propName)) {
       ImportNode importNode = importNodes.get(propName);
       expression =
           findStaticMethod(
               importNode.getType(), prefix(name) + capitalize(importNode.getFieldName()), args);
       if (expression != null) return expression;
       expression =
           findStaticPropertyAccessorGivenArgs(
               importNode.getType(), importNode.getFieldName(), args);
       if (expression != null) {
         return new StaticMethodCallExpression(
             importNode.getType(), prefix(name) + capitalize(importNode.getFieldName()), args);
       }
     }
   }
   Map<String, ImportNode> starImports = module.getStaticStarImports();
   ClassNode starImportType;
   if (currentClass.isEnum() && starImports.containsKey(currentClass.getName())) {
     ImportNode importNode = starImports.get(currentClass.getName());
     starImportType = importNode == null ? null : importNode.getType();
     expression = findStaticMethod(starImportType, name, args);
     if (expression != null) return expression;
   } else {
     for (ImportNode importNode : starImports.values()) {
       starImportType = importNode == null ? null : importNode.getType();
       expression = findStaticMethod(starImportType, name, args);
       if (expression != null) return expression;
       expression =
           findStaticPropertyAccessorGivenArgs(starImportType, getPropNameForAccessor(name), args);
       if (expression != null) {
         return new StaticMethodCallExpression(starImportType, name, args);
       }
     }
   }
   return null;
 }
  protected Expression transformMethodCallExpression(MethodCallExpression mce) {
    Expression args = transform(mce.getArguments());
    Expression method = transform(mce.getMethod());
    Expression object = transform(mce.getObjectExpression());
    boolean isExplicitThisOrSuper = false;
    if (object instanceof VariableExpression) {
      VariableExpression ve = (VariableExpression) object;
      isExplicitThisOrSuper =
          !mce.isImplicitThis() && (ve.getName().equals("this") || ve.getName().equals("super"));
    }

    if (mce.isImplicitThis() || isExplicitThisOrSuper) {
      if (mce.isImplicitThis()) {
        Expression ret = findStaticMethodImportFromModule(method, args);
        if (ret != null) {
          // GRECLIPSE add
          if (!((StaticMethodCallExpression) ret).getMethod().equals(method.getText())) {
            // store the identifier to facilitate organizing static imports
            ret.setNodeMetaData("static.import.alias", method.getText());
          }
          // GRECLIPSE end
          setSourcePosition(ret, mce);
          return ret;
        }
        if (method instanceof ConstantExpression && !inLeftExpression) {
          // could be a closure field
          String methodName = (String) ((ConstantExpression) method).getValue();
          ret = findStaticFieldOrPropAccessorImportFromModule(methodName);
          if (ret != null) {
            ret = new MethodCallExpression(ret, "call", args);
            setSourcePosition(ret, mce);
            return ret;
          }
        }
      }

      if (method instanceof ConstantExpression) {
        ConstantExpression ce = (ConstantExpression) method;
        Object value = ce.getValue();
        if (value instanceof String) {
          String methodName = (String) value;
          boolean lookForPossibleStaticMethod = !methodName.equals("call");
          if (currentMethod != null && !currentMethod.isStatic()) {
            if (currentClass.hasPossibleMethod(methodName, args)) {
              lookForPossibleStaticMethod = false;
            }
          }
          if (inSpecialConstructorCall
              || (lookForPossibleStaticMethod
                  && currentClass.hasPossibleStaticMethod(methodName, args))) {
            StaticMethodCallExpression smce =
                new StaticMethodCallExpression(currentClass, methodName, args);
            setSourcePosition(smce, mce);
            return smce;
          }
        }
      }
    }

    MethodCallExpression result = new MethodCallExpression(object, method, args);
    result.setSafe(mce.isSafe());
    result.setImplicitThis(mce.isImplicitThis());
    result.setSpreadSafe(mce.isSpreadSafe());
    result.setMethodTarget(mce.getMethodTarget());
    // GROOVY-6757
    result.setGenericsTypes(mce.getGenericsTypes());
    setSourcePosition(result, mce);
    return result;
  }