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(); }
// 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); } } }