private void doAddConstructor(final ClassNode cNode, final ConstructorNode constructorNode) {
    cNode.addConstructor(constructorNode);
    // GROOVY-5814: Immutable is not compatible with @CompileStatic
    Parameter argsParam = null;
    for (Parameter p : constructorNode.getParameters()) {
      if ("args".equals(p.getName())) {
        argsParam = p;
        break;
      }
    }
    if (argsParam != null) {
      final Parameter arg = argsParam;
      ClassCodeVisitorSupport variableExpressionFix =
          new ClassCodeVisitorSupport() {
            @Override
            protected SourceUnit getSourceUnit() {
              return cNode.getModule().getContext();
            }

            @Override
            public void visitVariableExpression(final VariableExpression expression) {
              super.visitVariableExpression(expression);
              if ("args".equals(expression.getName())) {
                expression.setAccessedVariable(arg);
              }
            }
          };
      variableExpressionFix.visitConstructor(constructorNode);
    }
  }
  public void visitConstructorCallExpression(ConstructorCallExpression call) {
    isSpecialConstructorCall = call.isSpecialCall();
    super.visitConstructorCallExpression(call);
    isSpecialConstructorCall = false;
    if (!call.isUsingAnonymousInnerClass()) return;

    pushState();
    InnerClassNode innerClass = (InnerClassNode) call.getType();
    innerClass.setVariableScope(currentScope);
    for (MethodNode method : innerClass.getMethods()) {
      Parameter[] parameters = method.getParameters();
      if (parameters.length == 0) parameters = null; // null means no implicit "it"
      ClosureExpression cl = new ClosureExpression(parameters, method.getCode());
      visitClosureExpression(cl);
    }

    for (FieldNode field : innerClass.getFields()) {
      final Expression expression = field.getInitialExpression();
      if (expression != null) {
        expression.visit(this);
      }
    }

    for (Statement statement : innerClass.getObjectInitializerStatements()) {
      statement.visit(this);
    }
    markClosureSharedVariables();
    popState();
  }
  public void visitClosureExpression(ClosureExpression expression) {
    pushState();

    expression.setVariableScope(currentScope);

    if (expression.isParameterSpecified()) {
      Parameter[] parameters = expression.getParameters();
      for (Parameter parameter : parameters) {
        parameter.setInStaticContext(currentScope.isInStaticContext());
        if (parameter.hasInitialExpression()) {
          parameter.getInitialExpression().visit(this);
        }
        declare(parameter, expression);
      }
    } else if (expression.getParameters() != null) {
      Parameter var = new Parameter(ClassHelper.OBJECT_TYPE, "it");
      var.setInStaticContext(currentScope.isInStaticContext());
      currentScope.putDeclaredVariable(var);
    }

    super.visitClosureExpression(expression);
    markClosureSharedVariables();

    popState();
  }
  public void visitBinaryExpression(BinaryExpression expression) {
    if (expression.getOperation().getType() == Types.LEFT_SQUARE_BRACKET
        && expression.getRightExpression() instanceof MapEntryExpression) {
      addError(
          "You tried to use a map entry for an index operation, this is not allowed. "
              + "Maybe something should be set in parentheses or a comma is missing?",
          expression.getRightExpression());
    }
    super.visitBinaryExpression(expression);

    switch (expression.getOperation().getType()) {
      case Types.EQUAL: // = assignment
      case Types.BITWISE_AND_EQUAL:
      case Types.BITWISE_OR_EQUAL:
      case Types.BITWISE_XOR_EQUAL:
      case Types.PLUS_EQUAL:
      case Types.MINUS_EQUAL:
      case Types.MULTIPLY_EQUAL:
      case Types.DIVIDE_EQUAL:
      case Types.INTDIV_EQUAL:
      case Types.MOD_EQUAL:
      case Types.POWER_EQUAL:
      case Types.LEFT_SHIFT_EQUAL:
      case Types.RIGHT_SHIFT_EQUAL:
      case Types.RIGHT_SHIFT_UNSIGNED_EQUAL:
        checkFinalFieldAccess(expression.getLeftExpression());
        break;
      default:
        break;
    }
  }
 @Override
 public void visitClosureExpression(final ClosureExpression expression) {
   boolean old = inAssignment;
   inAssignment = false;
   super.visitClosureExpression(expression);
   inAssignment = old;
 }
 @Override
 public void visitPostfixExpression(final PostfixExpression expression) {
   inAssignment = expression.getExpression() instanceof VariableExpression;
   super.visitPostfixExpression(expression);
   inAssignment = false;
   checkPrePostfixOperation(expression.getExpression(), expression);
 }
 /**
  * Adds the annotation to the internal target list if a match is found.
  *
  * @param node the AST node we are processing
  */
 public void visitAnnotations(AnnotatedNode node) {
   super.visitAnnotations(node);
   for (AnnotationNode an : node.getAnnotations()) {
     String name = an.getClassNode().getName();
     if ((GRAB_CLASS_NAME.equals(name))
         || (allowShortGrab && GRAB_SHORT_NAME.equals(name))
         || (grabAliases.contains(name))) {
       grabAnnotations.add(an);
     }
     if ((GRABEXCLUDE_CLASS_NAME.equals(name))
         || (allowShortGrabExcludes && GRABEXCLUDE_SHORT_NAME.equals(name))
         || (grabExcludeAliases.contains(name))) {
       grabExcludeAnnotations.add(an);
     }
     if ((GRABCONFIG_CLASS_NAME.equals(name))
         || (allowShortGrabConfig && GRABCONFIG_SHORT_NAME.equals(name))
         || (grabConfigAliases.contains(name))) {
       grabConfigAnnotations.add(an);
     }
     if ((GRAPES_CLASS_NAME.equals(name))
         || (allowShortGrapes && GRAPES_SHORT_NAME.equals(name))
         || (grapesAliases.contains(name))) {
       grapesAnnotations.add(an);
     }
     if ((GRABRESOLVER_CLASS_NAME.equals(name))
         || (allowShortGrabResolver && GRABRESOLVER_SHORT_NAME.equals(name))
         || (grabResolverAliases.contains(name))) {
       grabResolverAnnotations.add(an);
     }
   }
 }
  public void visitMethodCallExpression(MethodCallExpression call) {
    if (call.isImplicitThis() && call.getMethod() instanceof ConstantExpression) {
      ConstantExpression methodNameConstant = (ConstantExpression) call.getMethod();
      Object value = methodNameConstant.getText();

      if (!(value instanceof String)) {
        throw new GroovyBugError(
            "tried to make a method call with a non-String constant method name.");
      }

      String methodName = (String) value;
      Variable v = checkVariableNameForDeclaration(methodName, call);
      if (v != null && !(v instanceof DynamicVariable)) {
        checkVariableContextAccess(v, call);
      }

      if (v instanceof VariableExpression || v instanceof Parameter) {
        VariableExpression object = new VariableExpression(v);
        object.setSourcePosition(methodNameConstant);
        call.setObjectExpression(object);
        ConstantExpression method = new ConstantExpression("call");
        method.setSourcePosition(methodNameConstant); // important for GROOVY-4344
        call.setImplicitThis(false);
        call.setMethod(method);
      }
    }
    super.visitMethodCallExpression(call);
  }
 public void visitCatchStatement(CatchStatement statement) {
   pushState();
   Parameter p = statement.getVariable();
   p.setInStaticContext(currentScope.isInStaticContext());
   declare(p, statement);
   super.visitCatchStatement(statement);
   popState();
 }
 @Override
 public void visitMethodCallExpression(final MethodCallExpression call) {
   super.visitMethodCallExpression(call);
   MethodNode mn = call.getMethodTarget();
   if (mn == null) {
     call.setMethodTarget(doCallMethod);
   }
 }
 /**
  * Adds the annotation to the internal target list if a match is found.
  *
  * @param node the node to be processed
  */
 public void visitAnnotations(AnnotatedNode node) {
   super.visitAnnotations(node);
   for (AnnotationNode annotation : node.getAnnotations()) {
     if (transforms.containsKey(annotation)) {
       targetNodes.add(new ASTNode[] {annotation, node});
     }
   }
 }
 public void visitField(FieldNode node) {
   if (currentClass.getDeclaredField(node.getName()) != node) {
     addError("The " + getDescription(node) + " is declared multiple times.", node);
   }
   checkInterfaceFieldModifiers(node);
   checkGenericsUsage(node, node.getType());
   super.visitField(node);
 }
 public void visitForLoop(ForStatement forLoop) {
   pushState();
   forLoop.setVariableScope(currentScope);
   Parameter p = forLoop.getVariable();
   p.setInStaticContext(currentScope.isInStaticContext());
   if (p != ForStatement.FOR_LOOP_DUMMY) declare(p, forLoop);
   super.visitForLoop(forLoop);
   popState();
 }
 @Override
 public void visitPackage(final PackageNode node) {
   if (node != null) {
     pushContext(node);
   }
   super.visitPackage(node);
   if (node != null) {
     popContext();
   }
 }
 public void visitMethod(MethodNode node) {
   inConstructor = false;
   inStaticConstructor = node.isStaticConstructor();
   checkAbstractDeclaration(node);
   checkRepetitiveMethod(node);
   checkOverloadingPrivateAndPublic(node);
   checkMethodModifiers(node);
   checkGenericsUsage(node, node.getParameters());
   checkGenericsUsage(node, node.getReturnType());
   super.visitMethod(node);
 }
 public void visitMethodCallExpression(MethodCallExpression mce) {
   super.visitMethodCallExpression(mce);
   Expression aexp = mce.getArguments();
   if (aexp instanceof TupleExpression) {
     TupleExpression arguments = (TupleExpression) aexp;
     for (Expression e : arguments.getExpressions()) {
       checkForInvalidDeclaration(e);
     }
   } else {
     checkForInvalidDeclaration(aexp);
   }
 }
 @Override
 public void visitMethodCallExpression(MethodCallExpression call) {
   String name =
       call.getMethodAsString(); // Could be null (for 'funny' calls where target name is dynamic)
   SearchingCodeVisitor.MethodCallAction action = getMethodCallAction(name);
   if (action != null) {
     Assert.isLegal(action.methodName.equals(name));
     if (!isVisited(call)) {
       action.doit(this, call);
     }
   }
   super.visitMethodCallExpression(call);
 }
 @Override
 public void visitVariableExpression(final VariableExpression expression) {
   super.visitVariableExpression(expression);
   if (inAssignment) {
     Map<Variable, VariableState> state = getState();
     Variable key = expression.getAccessedVariable();
     VariableState variableState = state.get(key);
     if (variableState == VariableState.is_uninitialized) {
       variableState = VariableState.is_var;
       state.put(key, variableState);
     }
   }
 }
  public void visitClass(ClassNode node) {
    // AIC are already done, doing them here again will lead
    // to wrong scopes
    if (node instanceof InnerClassNode) {
      InnerClassNode in = (InnerClassNode) node;
      if (in.isAnonymous()) return;
    }

    pushState();

    prepareVisit(node);

    super.visitClass(node);
    popState();
  }
 @Override
 public void visitDeclarationExpression(DeclarationExpression expression) {
   super.visitDeclarationExpression(expression);
   if (expression.isMultipleAssignmentDeclaration()) return;
   checkInvalidDeclarationModifier(expression, ACC_ABSTRACT, "abstract");
   checkInvalidDeclarationModifier(expression, ACC_NATIVE, "native");
   checkInvalidDeclarationModifier(expression, ACC_PRIVATE, "private");
   checkInvalidDeclarationModifier(expression, ACC_PROTECTED, "protected");
   checkInvalidDeclarationModifier(expression, ACC_PUBLIC, "public");
   checkInvalidDeclarationModifier(expression, ACC_STATIC, "static");
   checkInvalidDeclarationModifier(expression, ACC_STRICT, "strictfp");
   checkInvalidDeclarationModifier(expression, ACC_SYNCHRONIZED, "synchronized");
   checkInvalidDeclarationModifier(expression, ACC_TRANSIENT, "transient");
   checkInvalidDeclarationModifier(expression, ACC_VOLATILE, "volatile");
 }
 @Override
 public void visitBlockStatement(final BlockStatement block) {
   Set<VariableExpression> old = declaredFinalVariables;
   declaredFinalVariables = new HashSet<VariableExpression>();
   super.visitBlockStatement(block);
   if (callback != null) {
     Map<Variable, VariableState> state = getState();
     for (VariableExpression declaredFinalVariable : declaredFinalVariables) {
       VariableState variableState = state.get(declaredFinalVariable.getAccessedVariable());
       if (variableState == null || variableState != VariableState.is_final) {
         callback.variableNotAlwaysInitialized(declaredFinalVariable);
       }
     }
   }
   declaredFinalVariables = old;
 }
 @Override
 public void visitClass(ClassNode node) {
   boolean isToplevel = false;
   if (currentTopLevelClass == null) {
     // entering top level class
     currentTopLevelClass = node;
     isToplevel = true;
   }
   try {
     super.visitClass(node);
   } finally {
     if (isToplevel) {
       // Exiting top level class
       currentTopLevelClass = null;
     }
   }
 }
 public void visitClass(ClassNode node) {
   ClassNode oldClass = currentClass;
   currentClass = node;
   checkImplementsAndExtends(node);
   if (source != null && !source.getErrorCollector().hasErrors()) {
     checkClassForIncorrectModifiers(node);
     checkInterfaceMethodVisibility(node);
     checkClassForOverwritingFinal(node);
     checkMethodsForIncorrectModifiers(node);
     checkMethodsForWeakerAccess(node);
     checkMethodsForOverridingFinal(node);
     checkNoAbstractMethodsNonabstractClass(node);
     checkGenericsUsage(node, node.getUnresolvedInterfaces());
     checkGenericsUsage(node, node.getUnresolvedSuperClass());
   }
   super.visitClass(node);
   currentClass = oldClass;
 }
    @Override
    public void visitBytecodeExpression(BytecodeExpression expression) {
      // LOG.debug "Transforming expression '${expression}':"

      if (expression.getLineNumber() >= 0 && expression.getLineNumber() < lineNumbers.length) {
        // LOG.debug "   start from ${expression.lineNumber} to ${lineNumbers[expression.lineNumber
        // - 1]}"
        expression.setLineNumber(lineNumbers[expression.getLineNumber() - 1]);
      }

      if (expression.getLastLineNumber() > 0
          && expression.getLastLineNumber() < lineNumbers.length) {
        // LOG.debug "   end from ${expression.lastLineNumber} to
        // ${lineNumbers[expression.lastLineNumber - 1]}"
        expression.setLastLineNumber(lineNumbers[expression.getLastLineNumber() - 1]);
      }
      super.visitBytecodeExpression(expression);
    }
  /**
   * If the annotation is annotated with {@link GroovyASTTransformation} the annotation is added to
   * <code>stageVisitors</code> at the appropriate processor visitor.
   *
   * @param node the node to process
   */
  public void visitAnnotations(AnnotatedNode node) {
    super.visitAnnotations(node);
    List<AnnotationNode> collected = new ArrayList<AnnotationNode>();
    for (Iterator<AnnotationNode> it = node.getAnnotations().iterator(); it.hasNext(); ) {
      AnnotationNode annotation = it.next();
      if (addCollectedAnnotations(collected, annotation, node)) it.remove();
    }
    node.getAnnotations().addAll(collected);

    for (AnnotationNode annotation : node.getAnnotations()) {

      // GRECLIPSE: start: under eclipse we may be asking a node that has no backing class
      /*{
      Annotation transformClassAnnotation = getTransformClassAnnotation(annotation.getClassNode());
      if (transformClassAnnotation == null) {
          // skip if there is no such annotation
          continue;
      }
      addTransformsToClassNode(annotation, transformClassAnnotation);
      }*/
      // newcode:
      if (!this.allowTransforms) {
        if (!isAllowed(annotation.getClassNode().getName())) {
          continue;
        }
      }
      // GRECLIPSE end
      String[] transformClassNames = getTransformClassNames(annotation.getClassNode());
      Class[] transformClasses = getTransformClasses(annotation.getClassNode());
      if (transformClassNames == null && transformClasses == null) {
        continue;
      }
      if (transformClassNames == null) {
        transformClassNames = NONE;
      }
      if (transformClasses == null) {
        transformClasses = NO_CLASSES;
      }
      addTransformsToClassNode(annotation, transformClassNames, transformClasses);
      // end
    }
  }
 @Override
 public void visitBinaryExpression(BinaryExpression be) {
   super.visitBinaryExpression(be);
   switch (be.getOperation().getType()) {
     case Types.EQUAL: // = assignment
     case Types.BITWISE_AND_EQUAL:
     case Types.BITWISE_OR_EQUAL:
     case Types.BITWISE_XOR_EQUAL:
     case Types.PLUS_EQUAL:
     case Types.MINUS_EQUAL:
     case Types.MULTIPLY_EQUAL:
     case Types.DIVIDE_EQUAL:
     case Types.INTDIV_EQUAL:
     case Types.MOD_EQUAL:
     case Types.POWER_EQUAL:
     case Types.LEFT_SHIFT_EQUAL:
     case Types.RIGHT_SHIFT_EQUAL:
     case Types.RIGHT_SHIFT_UNSIGNED_EQUAL:
       checkFinalFieldAccess(be.getLeftExpression());
       break;
     default:
       break;
   }
 }
 @Override
 protected void visitEmptyStatement(final EmptyStatement statement) {
   pushContext(statement);
   super.visitEmptyStatement(statement);
   popContext();
 }
 @Override
 public void visitWhileLoop(final WhileStatement loop) {
   pushContext(loop);
   super.visitWhileLoop(loop);
   popContext();
 }
 @Override
 public void visitTryCatchFinally(final TryCatchStatement statement) {
   pushContext(statement);
   super.visitTryCatchFinally(statement);
   popContext();
 }
 @Override
 public void visitThrowStatement(final ThrowStatement statement) {
   pushContext(statement);
   super.visitThrowStatement(statement);
   popContext();
 }