private static void generateElseBranchTextAndRemoveTailStatements(
      @NotNull GrIfStatement ifStatement, @NotNull GrIfStatement newIf) {
    final GrStatement thenBranch = newIf.getThenBranch();
    assert thenBranch != null;

    GrStatement elseBranch = ifStatement.getElseBranch();
    if (elseBranch != null) {
      thenBranch.replaceWithStatement(elseBranch);
      return;
    }

    PsiElement parent = ifStatement.getParent();
    if (!(parent instanceof GrStatementOwner)) return;

    if (!isTailAfterIf(ifStatement, ((GrStatementOwner) parent))) return;

    final PsiElement start = ifStatement.getNextSibling();
    PsiElement end =
        parent instanceof GrCodeBlock
            ? ((GrCodeBlock) parent).getRBrace().getPrevSibling()
            : parent.getLastChild();

    final GrOpenBlock block = ((GrBlockStatement) thenBranch).getBlock();
    block.addRangeAfter(start, end, block.getLBrace());
    parent.deleteChildRange(start, end);
  }
        @Override
        public PsiType fun(GrMethodBaseImpl method) {
          PsiType nominal = method.getNominalType();
          if (nominal != null) {
            if (!(nominal instanceof PsiClassType
                && hasTypeParametersToInfer((PsiClassType) nominal))) {
              return nominal;
            }
          }

          if (!GppTypeConverter.hasTypedContext(method)) {
            LOG.assertTrue(method.isValid(), "invalid method");

            final GrOpenBlock block = method.getBlock();
            if (block != null) {
              LOG.assertTrue(block.isValid(), "invalid code block");
              PsiType inferred =
                  GroovyPsiManager.inferType(method, new MethodTypeInferencer(block));
              if (inferred != null) {
                if (nominal == null || nominal.isAssignableFrom(inferred)) {
                  return inferred;
                }
              }
            }
          }
          if (nominal != null) {
            return nominal;
          }

          return TypesUtil.getJavaLangObject(method);
        }
 @Override
 public void visitFinallyClause(GrFinallyClause finallyClause) {
   builder.append("finally ");
   final GrOpenBlock body = finallyClause.getBody();
   if (body != null) {
     body.accept(this);
   }
 }
  public static PsiCodeBlock getOrCreatePsiCodeBlock(GrOpenBlock block) {
    if (block == null) return null;

    final SoftReference<PsiCodeBlock> ref = block.getUserData(PSI_CODE_BLOCK);
    final PsiCodeBlock body = ref == null ? null : ref.get();
    if (body != null) return body;
    final GrSyntheticCodeBlock newBody = new GrSyntheticCodeBlock(block);
    block.putUserData(PSI_CODE_BLOCK, new SoftReference<PsiCodeBlock>(newBody));
    return newBody;
  }
 @Override
 public void setBlock(GrCodeBlock newBlock) {
   ASTNode newNode = newBlock.getNode().copyElement();
   final GrOpenBlock oldBlock = getBlock();
   if (oldBlock == null) {
     getNode().addChild(newNode);
     return;
   }
   getNode().replaceChild(oldBlock.getNode(), newNode);
 }
 @Override
 public void visitCatchClause(GrCatchClause catchClause) {
   final GrParameter parameter = catchClause.getParameter();
   builder.append("catch (");
   writeVariableWithoutSemicolonAndInitializer(builder, parameter, context);
   builder.append(") ");
   final GrOpenBlock body = catchClause.getBody();
   if (body != null) {
     body.accept(this);
   }
 }
 private static boolean openBlocksAreEquivalent(GrOpenBlock block1, GrOpenBlock block2) {
   final GrStatement[] statements1 = block1.getStatements();
   final GrStatement[] statements2 = block2.getStatements();
   if (statements1.length != statements2.length) {
     return false;
   }
   for (int i = 0; i < statements1.length; i++) {
     if (!statementsAreEquivalent(statements1[i], statements2[i])) {
       return false;
     }
   }
   return true;
 }
 @Override
 public void visitTryStatement(GrTryCatchStatement tryCatchStatement) {
   final GrOpenBlock tryBlock = tryCatchStatement.getTryBlock();
   final GrCatchClause[] catchClauses = tryCatchStatement.getCatchClauses();
   final GrFinallyClause finallyClause = tryCatchStatement.getFinallyClause();
   builder.append("try");
   tryBlock.accept(this);
   for (GrCatchClause catchClause : catchClauses) {
     catchClause.accept(this);
   }
   if (finallyClause != null) {
     finallyClause.accept(this);
   }
 }
 @Override
 public void visitOpenBlock(GrOpenBlock block) {
   final GrStatement[] statements = block.getStatements();
   if (statements.length > 0 && myExpression.equals(statements[statements.length - 1])) {
     checkExitPoint();
   }
 }
  @Nullable
  public static GrConstructorInvocation getChainingConstructorInvocation(GrMethod constructor) {
    if (constructor instanceof GrReflectedMethod
        && ((GrReflectedMethod) constructor).getSkippedParameters().length > 0) return null;

    LOG.assertTrue(constructor.isConstructor());

    GrOpenBlock body = constructor.getBlock();
    if (body == null) return null;

    GrStatement[] statements = body.getStatements();

    if (statements.length > 0 && statements[0] instanceof GrConstructorInvocation) {
      return (GrConstructorInvocation) statements[0];
    }

    return null;
  }
  public void visitOpenBlock(GrOpenBlock block) {
    final PsiElement parent = block.getParent();
    final PsiElement lbrace = block.getLBrace();
    if (lbrace != null && parent instanceof GrMethod) {
      for (GrParameter parameter : ((GrMethod) parent).getParameters()) {
        if (myPolicy.isVariableInitialized(parameter)) {
          addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, WRITE));
        }
      }
    }
    super.visitOpenBlock(block);

    if (!(block.getParent() instanceof GrBlockStatement
        && block.getParent().getParent() instanceof GrLoopStatement)) {
      final GrStatement[] statements = block.getStatements();
      if (statements.length > 0) {
        handlePossibleReturn(statements[statements.length - 1]);
      }
    }
  }
  private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) {
    final PsiClass containingClass = constructor.getContainingClass();
    final PsiClass baseClass = changeInfo.getMethod().getContainingClass();
    final PsiSubstitutor substitutor =
        TypeConversionUtil.getSuperClassSubstitutor(
            baseClass, containingClass, PsiSubstitutor.EMPTY);

    GrOpenBlock block = constructor.getBlock();
    GrConstructorInvocation invocation =
        GroovyPsiElementFactory.getInstance(constructor.getProject())
            .createConstructorInvocation("super()");
    invocation =
        (GrConstructorInvocation) block.addStatementBefore(invocation, getFirstStatement(block));
    processMethodUsage(
        invocation.getInvokedExpression(),
        changeInfo,
        changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(),
        changeInfo.isExceptionSetChanged(),
        GrClosureSignatureUtil.ArgInfo.<PsiElement>empty_array(),
        substitutor);
  }
  @Override
  @NotNull
  public Map<String, NamedArgumentDescriptor> getNamedParameters() {
    final GrMethodStub stub = getStub();
    if (stub != null) {
      String[] namedParameters = stub.getNamedParameters();
      if (namedParameters.length == 0) return Collections.emptyMap();

      Map<String, NamedArgumentDescriptor> result = ContainerUtil.newHashMap();

      for (String parameter : namedParameters) {
        result.put(parameter, GrNamedArgumentSearchVisitor.CODE_NAMED_ARGUMENTS_DESCR);
      }
      return result;
    }

    GrOpenBlock body = getBlock();
    if (body == null) return Collections.emptyMap();

    GrParameter[] parameters = getParameters();
    if (parameters.length == 0) return Collections.emptyMap();
    GrParameter firstParameter = parameters[0];

    PsiType type = firstParameter.getTypeGroovy();
    GrTypeElement typeElement = firstParameter.getTypeElementGroovy();
    // equalsToText can't be called here because of stub creating

    if (type != null
        && typeElement != null
        && type.getPresentableText() != null
        && !type.getPresentableText().endsWith("Map")) {
      return Collections.emptyMap();
    }

    GrNamedArgumentSearchVisitor visitor =
        new GrNamedArgumentSearchVisitor(firstParameter.getNameIdentifierGroovy().getText());

    body.accept(visitor);
    return visitor.getResult();
  }
  @Override
  protected void performRefactoring(UsageInfo[] usages) {
    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject);

    PsiType initializerType = mySettings.getSelectedType();

    // Changing external occurrences (the tricky part)

    IntroduceParameterUtil.processUsages(usages, this);

    final GrMethod toReplaceIn = (GrMethod) mySettings.getToReplaceIn();
    final PsiMethod toSearchFor = (PsiMethod) mySettings.getToSearchFor();

    final boolean methodsToProcessAreDifferent = toReplaceIn != toSearchFor;
    if (mySettings.generateDelegate()) {
      GroovyIntroduceParameterUtil.generateDelegate(toReplaceIn, myParameterInitializer, myProject);
      if (methodsToProcessAreDifferent) {
        final GrMethod method =
            GroovyIntroduceParameterUtil.generateDelegate(
                toSearchFor, myParameterInitializer, myProject);
        final PsiClass containingClass = method.getContainingClass();
        if (containingClass != null && containingClass.isInterface()) {
          final GrOpenBlock block = method.getBlock();
          if (block != null) {
            block.delete();
          }
        }
      }
    }

    // Changing signature of initial method
    // (signature of myMethodToReplaceIn will be either changed now or have already been changed)
    LOG.assertTrue(initializerType == null || initializerType.isValid());

    final FieldConflictsResolver fieldConflictsResolver =
        new FieldConflictsResolver(mySettings.getName(), toReplaceIn.getBlock());
    IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts(
        new UsageInfo(toReplaceIn), usages, this);
    if (methodsToProcessAreDifferent) {
      IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts(
          new UsageInfo(toSearchFor), usages, this);
    }

    // Replacing expression occurrences
    for (UsageInfo usage : usages) {
      if (usage instanceof ChangedMethodCallInfo) {
        PsiElement element = usage.getElement();

        GroovyIntroduceParameterUtil.processChangedMethodCall(element, mySettings, myProject);
      } else if (usage instanceof InternalUsageInfo) {
        PsiElement element = usage.getElement();
        if (element == null) continue;
        GrExpression newExpr = factory.createExpressionFromText(mySettings.getName());
        if (element instanceof GrExpression) {
          ((GrExpression) element).replaceWithExpression(newExpr, true);
        } else {
          element.replace(newExpr);
        }
      }
    }

    final StringPartInfo stringPartInfo = mySettings.getStringPartInfo();
    if (stringPartInfo != null) {
      final GrExpression expr =
          GrIntroduceHandlerBase.processLiteral(
              mySettings.getName(), mySettings.getStringPartInfo(), mySettings.getProject());
      final Editor editor = PsiUtilBase.findEditor(expr);
      if (editor != null) {
        editor.getSelectionModel().removeSelection();
        editor.getCaretModel().moveToOffset(expr.getTextRange().getEndOffset());
      }
    }

    final GrVariable var = mySettings.getVar();
    if (var != null && mySettings.removeLocalVariable()) {
      var.delete();
    }
    fieldConflictsResolver.fix();
  }
示例#15
0
  // See org.spockframework.compiler.WhereBlockRewriter
  public static Map<String, SpockVariableDescriptor> createVariableMap(GrMethod method) {
    GrOpenBlock block = method.getBlock();
    if (block == null) return Collections.emptyMap();

    PsiElement elementUnderLabel = null;
    PsiElement elementAfterLabel = null;

    main:
    for (PsiElement e = block.getFirstChild(); e != null; e = e.getNextSibling()) {
      if (e instanceof GrLabeledStatement) {
        GrLabeledStatement l = (GrLabeledStatement) e;

        elementAfterLabel = l.getNextSibling();

        while (true) {
          GrStatement statement = l.getStatement();

          if ("where".equals(l.getName())) {
            elementUnderLabel = statement;
            break main;
          }

          if (statement instanceof GrLabeledStatement) {
            l = (GrLabeledStatement) statement;
            continue;
          }

          break;
        }
      }
    }

    if (elementUnderLabel == null) return Collections.emptyMap();

    Map<String, SpockVariableDescriptor> res = new HashMap<>();

    PsiElement e = elementUnderLabel;

    while (e != null) {
      if (e instanceof GrBinaryExpression
          && ((GrBinaryExpression) e).getOperationTokenType()
              == GroovyElementTypes.COMPOSITE_LSHIFT_SIGN) {
        GrBinaryExpression shift = (GrBinaryExpression) e;
        GrExpression leftOperand = shift.getLeftOperand();
        GrExpression rightOperand = shift.getRightOperand();

        if (leftOperand instanceof GrReferenceExpression) {
          String name = getNameByReference(leftOperand);
          if (name != null) {
            SpockVariableDescriptor descriptor = new SpockVariableDescriptor(leftOperand, name);
            descriptor.addExpressionOfCollection(rightOperand);
            res.put(name, descriptor);
          }
        } else if (leftOperand instanceof GrListOrMap) {
          GrExpression[] variableDefinitions = ((GrListOrMap) leftOperand).getInitializers();

          SpockVariableDescriptor[] variables =
              createVariables(res, Arrays.asList(variableDefinitions));

          if (rightOperand instanceof GrListOrMap) {
            for (GrExpression expression : ((GrListOrMap) rightOperand).getInitializers()) {
              if (expression instanceof GrListOrMap) {
                add(variables, Arrays.asList(((GrListOrMap) expression).getInitializers()));
              } else {
                for (SpockVariableDescriptor variable : variables) {
                  if (variable != null) {
                    variable.addExpressionOfCollection(expression);
                  }
                }
              }
            }
          }
        }
      } else if (e instanceof GrAssignmentExpression) {
        GrAssignmentExpression assExpr = (GrAssignmentExpression) e;
        GrExpression lValue = assExpr.getLValue();
        String name = getNameByReference(lValue);
        if (name != null) {
          res.put(
              name, new SpockVariableDescriptor(lValue, name).addExpression(assExpr.getRValue()));
        }
      } else if (isOrStatement(e)) {
        // See org.spockframework.compiler.WhereBlockRewriter#rewriteTableLikeParameterization()
        List<GrExpression> variableDefinitions = new ArrayList<>();
        splitOr(variableDefinitions, (GrExpression) e);

        SpockVariableDescriptor[] variables = createVariables(res, variableDefinitions);

        List<GrExpression> row = new ArrayList<>();

        PsiElement rowElement = getNext(e, elementUnderLabel, elementAfterLabel);
        while (isOrStatement(rowElement)) {
          row.clear();
          splitOr(row, (GrExpression) rowElement);

          add(variables, row);

          rowElement = getNext(rowElement, elementUnderLabel, elementAfterLabel);
        }

        e = rowElement;
        continue;
      }

      e = getNext(e, elementUnderLabel, elementAfterLabel);
    }

    return res;
  }
  public void visitTryStatement(GrTryCatchStatement tryCatchStatement) {
    final GrOpenBlock tryBlock = tryCatchStatement.getTryBlock();
    final GrCatchClause[] catchClauses = tryCatchStatement.getCatchClauses();
    final GrFinallyClause finallyClause = tryCatchStatement.getFinallyClause();

    for (int i = catchClauses.length - 1; i >= 0; i--) {
      myCaughtExceptionInfos.push(new ExceptionInfo(catchClauses[i]));
    }

    if (finallyClause != null) myFinallyCount++;

    List<Pair<InstructionImpl, GroovyPsiElement>> oldPending = null;
    if (finallyClause != null) {
      oldPending = myPending;
      myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
    }

    InstructionImpl tryBegin = startNode(tryBlock);
    tryBlock.accept(this);
    InstructionImpl tryEnd = myHead;
    finishNode(tryBegin);

    Set<Pair<InstructionImpl, GroovyPsiElement>> pendingAfterTry =
        new LinkedHashSet<Pair<InstructionImpl, GroovyPsiElement>>(myPending);

    @SuppressWarnings("unchecked")
    List<InstructionImpl>[] throwers = new List[catchClauses.length];

    for (int i = 0; i < catchClauses.length; i++) {
      throwers[i] = myCaughtExceptionInfos.pop().myThrowers;
    }

    InstructionImpl[] catches = new InstructionImpl[catchClauses.length];

    for (int i = 0; i < catchClauses.length; i++) {
      interruptFlow();
      final InstructionImpl catchBeg = startNode(catchClauses[i]);
      for (InstructionImpl thrower : throwers[i]) {
        addEdge(thrower, catchBeg);
      }

      final GrParameter parameter = catchClauses[i].getParameter();
      if (parameter != null && myPolicy.isVariableInitialized(parameter)) {
        addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, WRITE));
      }
      catchClauses[i].accept(this);
      catches[i] = myHead;
      finishNode(catchBeg);
    }

    pendingAfterTry.addAll(myPending);
    myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>(pendingAfterTry);

    if (finallyClause != null) {
      myFinallyCount--;
      interruptFlow();
      final InstructionImpl finallyInstruction = startNode(finallyClause, false);
      Set<AfterCallInstruction> postCalls = new LinkedHashSet<AfterCallInstruction>();

      final List<Pair<InstructionImpl, GroovyPsiElement>> copy = myPending;
      myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
      for (Pair<InstructionImpl, GroovyPsiElement> pair : copy) {
        postCalls.add(addCallNode(finallyInstruction, pair.getSecond(), pair.getFirst()));
      }

      if (tryEnd != null) {
        postCalls.add(addCallNode(finallyInstruction, tryCatchStatement, tryEnd));
      }

      for (InstructionImpl catchEnd : catches) {
        if (catchEnd != null) {
          postCalls.add(addCallNode(finallyInstruction, tryCatchStatement, catchEnd));
        }
      }

      // save added postcalls into separate list because we don't want returnInstruction grabbed
      // their pending edges
      List<Pair<InstructionImpl, GroovyPsiElement>> pendingPostCalls = myPending;
      myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();

      myHead = finallyInstruction;
      finallyClause.accept(this);
      final ReturnInstruction returnInstruction = new ReturnInstruction(finallyClause);
      for (AfterCallInstruction postCall : postCalls) {
        postCall.setReturnInstruction(returnInstruction);
        addEdge(returnInstruction, postCall);
      }
      addNodeAndCheckPending(returnInstruction);
      interruptFlow();
      finishNode(finallyInstruction);

      if (oldPending == null) {
        error();
      }
      oldPending.addAll(pendingPostCalls);
      myPending = oldPending;
    } else {
      if (tryEnd != null) {
        addPendingEdge(tryCatchStatement, tryEnd);
      }
      for (InstructionImpl catchEnd : catches) {
        addPendingEdge(tryBlock, catchEnd);
      }
    }
  }