/** @return leading regex or null if it does not exist */ @Nullable private static GrLiteral getRegexAtTheBeginning(PsiElement expr) { PsiElement fchild = expr; while (fchild != null) { if (fchild instanceof GrLiteral && GrStringUtil.isRegex((GrLiteral) fchild)) return (GrLiteral) fchild; fchild = fchild.getFirstChild(); } return null; }
@Nullable public static GrExpression replaceExpression( GrExpression oldExpr, GrExpression newExpr, boolean removeUnnecessaryParentheses) { PsiElement oldParent = oldExpr.getParent(); if (oldParent == null) throw new PsiInvalidElementAccessException(oldExpr); if (!(oldExpr instanceof GrApplicationStatement)) { newExpr = ApplicationStatementUtil.convertToMethodCallExpression(newExpr); } // Remove unnecessary parentheses if (removeUnnecessaryParentheses && oldParent instanceof GrParenthesizedExpression && !(oldParent.getParent() instanceof GrArgumentLabel)) { return ((GrExpression) oldParent) .replaceWithExpression(newExpr, removeUnnecessaryParentheses); } // regexes cannot be after identifier , try to replace it with simple string if (getRegexAtTheBeginning(newExpr) != null && isAfterIdentifier(oldExpr)) { final PsiElement copy = newExpr.copy(); final GrLiteral regex = getRegexAtTheBeginning(copy); LOG.assertTrue(regex != null); final GrLiteral stringLiteral = GrStringUtil.createStringFromRegex(regex); if (regex == copy) { return oldExpr.replaceWithExpression(stringLiteral, removeUnnecessaryParentheses); } else { regex.replace(stringLiteral); return oldExpr.replaceWithExpression((GrExpression) copy, removeUnnecessaryParentheses); } } GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(oldExpr.getProject()); if (oldParent instanceof GrStringInjection) { if (newExpr instanceof GrString || newExpr instanceof GrLiteral && ((GrLiteral) newExpr).getValue() instanceof String) { return GrStringUtil.replaceStringInjectionByLiteral( (GrStringInjection) oldParent, (GrLiteral) newExpr); } else { newExpr = factory.createExpressionFromText("{" + newExpr.getText() + "}"); oldParent.getNode().replaceChild(oldExpr.getNode(), newExpr.getNode()); return newExpr; } } if (PsiTreeUtil.getParentOfType(oldExpr, GrStringInjection.class, false, GrCodeBlock.class) != null) { final PsiElement replaced = oldExpr.replace(newExpr); final GrStringInjection stringInjection = PsiTreeUtil.getParentOfType(replaced, GrStringInjection.class); GrStringUtil.wrapInjection(stringInjection); assert stringInjection != null; return stringInjection.getClosableBlock(); } // check priorities if (oldParent instanceof GrExpression && !(oldParent instanceof GrParenthesizedExpression)) { GrExpression addedParenth = addParenthesesIfNeeded(newExpr, oldExpr, (GrExpression) oldParent); if (newExpr != addedParenth) { return oldExpr.replaceWithExpression(addedParenth, removeUnnecessaryParentheses); } } // if replace closure argument with expression // we should add the expression in arg list if (oldExpr instanceof GrClosableBlock && !(newExpr instanceof GrClosableBlock) && oldParent instanceof GrMethodCallExpression && ArrayUtil.contains( oldExpr, ((GrMethodCallExpression) oldParent).getClosureArguments())) { return ((GrMethodCallExpression) oldParent) .replaceClosureArgument((GrClosableBlock) oldExpr, newExpr); } newExpr = (GrExpression) oldExpr.replace(newExpr); // if newExpr is the first grand child of command argument list we should replace command arg // list with parenthesised arg list. // In other case the code will be broken. So we try to find wrapping command arg list counting // levels. After arg list replace we go inside it // to find target parenthesised expression. if (newExpr instanceof GrParenthesizedExpression && isFirstChild(newExpr)) { int parentCount = 0; PsiElement element = oldParent; while (element != null && !(element instanceof GrCommandArgumentList)) { if (element instanceof GrCodeBlock || element instanceof GrParenthesizedExpression) break; if (element instanceof PsiFile) break; final PsiElement parent = element.getParent(); if (parent == null) break; if (!isFirstChild(element)) break; element = parent; parentCount++; } if (element instanceof GrCommandArgumentList) { final GrCommandArgumentList commandArgList = (GrCommandArgumentList) element; final PsiElement parent = commandArgList.getParent(); LOG.assertTrue(parent instanceof GrApplicationStatement); final GrMethodCall methodCall = factory.createMethodCallByAppCall((GrApplicationStatement) parent); final GrMethodCall newCall = (GrMethodCall) parent.replace(methodCall); PsiElement result = newCall.getArgumentList().getAllArguments()[0]; for (int i = 0; i < parentCount; i++) { result = PsiUtil.skipWhitespacesAndComments(result.getFirstChild(), true); } LOG.assertTrue(result instanceof GrParenthesizedExpression); return (GrExpression) result; } } return newExpr; }