@Override public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { try { if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; final PsiJavaToken token = (PsiJavaToken) element; final PsiPolyadicExpression expression = SplitConditionUtil.findCondition(element, true, false); final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(expression, PsiLambdaExpression.class); LOG.assertTrue(lambdaExpression != null); final String lambdaParameterName = lambdaExpression.getParameterList().getParameters()[0].getName(); final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class); LOG.assertTrue(methodCallExpression != null, expression); PsiExpression lOperand = getLOperands(expression, token); PsiExpression rOperand = getROperands(expression, token); final Collection<PsiComment> comments = PsiTreeUtil.findChildrenOfType(expression, PsiComment.class); final PsiMethodCallExpression chainedCall = (PsiMethodCallExpression) JavaPsiFacade.getElementFactory(project) .createExpressionFromText( "a.filter(" + lambdaParameterName + " -> x)", expression); final PsiExpression argExpression = chainedCall.getArgumentList().getExpressions()[0]; final PsiElement rReplaced = ((PsiLambdaExpression) argExpression).getBody().replace(rOperand); final PsiExpression compoundArg = methodCallExpression.getArgumentList().getExpressions()[0]; final int separatorOffset = token.getTextOffset(); for (PsiComment comment : comments) { if (comment.getTextOffset() < separatorOffset) { compoundArg.getParent().add(comment); } else { rReplaced.getParent().add(comment); } } ((PsiLambdaExpression) compoundArg).getBody().replace(lOperand); chainedCall.getMethodExpression().getQualifierExpression().replace(methodCallExpression); methodCallExpression.replace(chainedCall); } catch (IncorrectOperationException e) { LOG.error(e); } }
static String createContainsExpressionText( @NotNull PsiMethodCallExpression call, @NotNull PsiJavaToken sign, boolean flipped) { final IElementType tokenType = sign.getTokenType(); final PsiReferenceExpression methodExpression = call.getMethodExpression(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); final String qualifierText; if (qualifierExpression == null) { qualifierText = ""; } else { qualifierText = qualifierExpression.getText(); } final PsiExpressionList argumentList = call.getArgumentList(); final PsiExpression expression = argumentList.getExpressions()[0]; @NonNls final String newExpressionText = qualifierText + ".contains(" + expression.getText() + ')'; if (tokenType.equals(JavaTokenType.EQEQ)) { return '!' + newExpressionText; } else if (!flipped && (tokenType.equals(JavaTokenType.LT) || tokenType.equals(JavaTokenType.LE))) { return '!' + newExpressionText; } else if (flipped && (tokenType.equals(JavaTokenType.GT) || tokenType.equals(JavaTokenType.GE))) { return '!' + newExpressionText; } return newExpressionText; }
private Pair<PsiVariable, PsiType> findVariable(final PsiElement element) { PsiVariable variable = null; if (element instanceof PsiIdentifier) { if (element.getParent() instanceof PsiVariable) { variable = (PsiVariable) element.getParent(); } } else if (element instanceof PsiJavaToken) { final PsiJavaToken token = (PsiJavaToken) element; if (token.getTokenType() != JavaTokenType.EQ) return null; if (token.getParent() instanceof PsiVariable) { variable = (PsiVariable) token.getParent(); } } if (variable == null) { return null; } variableName = variable.getName(); final PsiExpression initializer = variable.getInitializer(); if (initializer == null) return null; final PsiType variableType = variable.getType(); final PsiType initializerType = initializer.getType(); if (!(variableType instanceof PsiClassType)) return null; final PsiClassType variableClassType = (PsiClassType) variableType; if (!variableClassType.isRaw()) return null; if (!(initializerType instanceof PsiClassType)) return null; final PsiClassType initializerClassType = (PsiClassType) initializerType; if (initializerClassType.isRaw()) return null; final PsiClassType.ClassResolveResult variableResolveResult = variableClassType.resolveGenerics(); final PsiClassType.ClassResolveResult initializerResolveResult = initializerClassType.resolveGenerics(); if (initializerResolveResult.getElement() == null) return null; final PsiSubstitutor targetSubstitutor = TypeConversionUtil.getClassSubstitutor( variableResolveResult.getElement(), initializerResolveResult.getElement(), initializerResolveResult.getSubstitutor()); if (targetSubstitutor == null) return null; PsiType type = JavaPsiFacade.getInstance(variable.getProject()) .getElementFactory() .createType(variableResolveResult.getElement(), targetSubstitutor); newTypeName = type.getCanonicalText(); return Pair.create(variable, type); }
public static @NotNull PsiType getOOType(PsiType left, PsiType right, PsiJavaToken op) { if (op == null) return NoType; String methodname = OOMethods.binary.get(op.getText()); if (methodname != null && right != null) { PsiType res = resolveMethod(left, methodname, right); if (res == null) res = resolveMethod(right, methodname + OOMethods.revSuffix, left); if (res != null) if (OOMethods.compareTo.equals(methodname)) return PsiType.BOOLEAN; else return res; } return NoType; }
public static boolean areParenthesesNeeded(PsiJavaToken sign, PsiExpression rhs) { if (rhs instanceof PsiPolyadicExpression) { final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression) rhs; final int precedence1 = getPrecedenceForOperator(binaryExpression.getOperationTokenType()); final IElementType signTokenType = sign.getTokenType(); final IElementType newOperatorToken = tokenMap.get(signTokenType); final int precedence2 = getPrecedenceForOperator(newOperatorToken); return precedence1 >= precedence2 || !isCommutativeOperator(newOperatorToken); } else { return rhs instanceof PsiConditionalExpression; } }
private void checkSetterNeeded(final PsiExpression operand, final PsiJavaToken sign) { final IElementType tokenType = sign.getTokenType(); if (!tokenType.equals(JavaTokenType.PLUSPLUS) && !tokenType.equals(JavaTokenType.MINUSMINUS)) { return; } if (isProhibitedReference(operand)) { final PsiField field = getReferencedField(operand); if (!hasSetter(field) && !isStaticFinal(field)) { fieldsNeedingSetter.add(field); } } }
@Override public void visitPostfixExpression(@NotNull PsiPostfixExpression postfixExpression) { if (read || written) { return; } super.visitPostfixExpression(postfixExpression); final PsiJavaToken operationSign = postfixExpression.getOperationSign(); final IElementType tokenType = operationSign.getTokenType(); if (!tokenType.equals(JavaTokenType.PLUSPLUS) && !tokenType.equals(JavaTokenType.MINUSMINUS)) { return; } final PsiExpression operand = postfixExpression.getOperand(); if (!(operand instanceof PsiReferenceExpression)) { return; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) operand; final PsiElement target = referenceExpression.resolve(); if (!variable.equals(target)) { return; } written = true; }
@Nullable private static String buildFromOffsetText(PsiExpression expression, PsiLocalVariable variable) throws IncorrectOperationException { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return null; } final String expressionText = expression.getText(); final String variableName = variable.getName(); if (expressionText.equals(variableName)) { final PsiExpression initialValue = variable.getInitializer(); if (initialValue == null) { return null; } return initialValue.getText(); } if (expression instanceof PsiBinaryExpression) { final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) expression; final PsiExpression lhs = binaryExpression.getLOperand(); final PsiExpression rhs = binaryExpression.getROperand(); final String rhsText = buildFromOffsetText(rhs, variable); final PsiJavaToken sign = binaryExpression.getOperationSign(); final IElementType tokenType = sign.getTokenType(); if (ExpressionUtils.isZero(lhs)) { if (tokenType.equals(JavaTokenType.MINUS)) { return '-' + rhsText; } return rhsText; } final String lhsText = buildFromOffsetText(lhs, variable); if (ExpressionUtils.isZero(rhs)) { return lhsText; } return collapseConstant(lhsText + sign.getText() + rhsText, variable); } return collapseConstant(expression.getText(), variable); }
@Nullable public static PsiExpression findExpressionInRange(PsiFile file, int startOffset, int endOffset) { if (!file.getViewProvider().getLanguages().contains(StdLanguages.JAVA)) return null; PsiExpression expression = findElementInRange(file, startOffset, endOffset, PsiExpression.class); if (expression == null && findStatementsInRange(file, startOffset, endOffset).length == 0) { PsiElement element2 = file.getViewProvider().findElementAt(endOffset - 1, StdLanguages.JAVA); if (element2 instanceof PsiJavaToken) { final PsiJavaToken token = (PsiJavaToken) element2; final IElementType tokenType = token.getTokenType(); if (tokenType.equals(JavaTokenType.SEMICOLON)) { expression = findElementInRange( file, startOffset, element2.getTextRange().getStartOffset(), PsiExpression.class); } } } if (expression == null && findStatementsInRange(file, startOffset, endOffset).length == 0) { PsiElement element = PsiTreeUtil.skipSiblingsBackward(file.findElementAt(endOffset), PsiWhiteSpace.class); if (element != null) { element = PsiTreeUtil.skipSiblingsBackward( element.getLastChild(), PsiWhiteSpace.class, PsiComment.class); if (element != null) { final int newEndOffset = element.getTextRange().getEndOffset(); if (newEndOffset < endOffset) { expression = findExpressionInRange(file, startOffset, newEndOffset); } } } } if (expression instanceof PsiReferenceExpression && expression.getParent() instanceof PsiMethodCallExpression) return null; return expression; }
@Nullable static PsiPolyadicExpression getSubexpression( PsiPolyadicExpression expression, PsiJavaToken token) { final PsiExpression[] operands = expression.getOperands(); if (operands.length == 2) { return expression; } for (int i = 1; i < operands.length; i++) { final PsiExpression operand = operands[i]; final PsiJavaToken currentToken = expression.getTokenBeforeOperand(operand); if (currentToken == token) { final String binaryExpressionText = operands[i - 1].getText() + ' ' + token.getText() + ' ' + operand.getText(); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(expression.getProject()); return (PsiPolyadicExpression) factory.createExpressionFromText(binaryExpressionText, expression); } } return null; }
private static boolean canBeReplacedByContains( PsiExpression lhs, PsiJavaToken sign, PsiExpression rhs, boolean flipped) { final PsiMethodCallExpression callExpression = (PsiMethodCallExpression) lhs; if (!isIndexOfCall(callExpression)) { return false; } final Object object = ExpressionUtils.computeConstantExpression(rhs); if (!(object instanceof Integer)) { return false; } final Integer integer = (Integer) object; final int constant = integer.intValue(); final IElementType tokenType = sign.getTokenType(); if (flipped) { if (constant == -1 && (JavaTokenType.NE.equals(tokenType) || JavaTokenType.LT.equals(tokenType) || JavaTokenType.EQEQ.equals(tokenType) || JavaTokenType.GE.equals(tokenType))) { return true; } else if (constant == 0 && (JavaTokenType.LE.equals(tokenType) || JavaTokenType.GT.equals(tokenType))) { return true; } } else { if (constant == -1 && (JavaTokenType.NE.equals(tokenType) || JavaTokenType.GT.equals(tokenType) || JavaTokenType.EQEQ.equals(tokenType) || JavaTokenType.LE.equals(tokenType))) { return true; } else if (constant == 0 && (JavaTokenType.GE.equals(tokenType) || JavaTokenType.LT.equals(tokenType))) { return true; } } return false; }
public List<TextRange> select( PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) { List<TextRange> result = new ArrayList<TextRange>(); PsiElement parent = e.getParent(); if (!(parent instanceof PsiCodeBlock) && !(parent instanceof PsiBlockStatement) || parent instanceof JspCodeBlock) { return result; } PsiElement startElement = e; PsiElement endElement = e; while (startElement.getPrevSibling() != null) { PsiElement sibling = startElement.getPrevSibling(); if (sibling instanceof PsiJavaToken) { PsiJavaToken token = (PsiJavaToken) sibling; if (token.getTokenType() == JavaTokenType.LBRACE) { break; } } if (sibling instanceof PsiWhiteSpace) { PsiWhiteSpace whiteSpace = (PsiWhiteSpace) sibling; String[] strings = LineTokenizer.tokenize(whiteSpace.getText().toCharArray(), false); if (strings.length > 2) { break; } } startElement = sibling; } while (startElement instanceof PsiWhiteSpace) { startElement = startElement.getNextSibling(); } while (endElement.getNextSibling() != null) { PsiElement sibling = endElement.getNextSibling(); if (sibling instanceof PsiJavaToken) { PsiJavaToken token = (PsiJavaToken) sibling; if (token.getTokenType() == JavaTokenType.RBRACE) { break; } } if (sibling instanceof PsiWhiteSpace) { PsiWhiteSpace whiteSpace = (PsiWhiteSpace) sibling; String[] strings = LineTokenizer.tokenize(whiteSpace.getText().toCharArray(), false); if (strings.length > 2) { break; } } endElement = sibling; } while (endElement instanceof PsiWhiteSpace) { endElement = endElement.getPrevSibling(); } result.addAll( expandToWholeLine( editorText, new TextRange( startElement.getTextRange().getStartOffset(), endElement.getTextRange().getEndOffset()))); return result; }
public boolean processUsage( @NotNull EncapsulateFieldUsageInfo usage, @NotNull EncapsulateFieldsDescriptor descriptor, PsiMethod setter, PsiMethod getter) { final PsiElement element = usage.getElement(); if (!(element instanceof PsiReferenceExpression)) return false; final FieldDescriptor fieldDescriptor = usage.getFieldDescriptor(); PsiField field = fieldDescriptor.getField(); boolean processGet = descriptor.isToEncapsulateGet(); boolean processSet = descriptor.isToEncapsulateSet() && !field.hasModifierProperty(PsiModifier.FINAL); if (!processGet && !processSet) return true; PsiElementFactory factory = JavaPsiFacade.getInstance(descriptor.getTargetClass().getProject()).getElementFactory(); try { final PsiReferenceExpression expr = (PsiReferenceExpression) element; final PsiElement parent = expr.getParent(); if (parent instanceof PsiAssignmentExpression && expr.equals(((PsiAssignmentExpression) parent).getLExpression())) { PsiAssignmentExpression assignment = (PsiAssignmentExpression) parent; if (assignment.getRExpression() == null) return true; PsiJavaToken opSign = assignment.getOperationSign(); IElementType opType = opSign.getTokenType(); if (opType == JavaTokenType.EQ) { { if (!processSet) return true; final PsiExpression setterArgument = assignment.getRExpression(); PsiMethodCallExpression methodCall = createSetterCall( fieldDescriptor, setterArgument, expr, descriptor.getTargetClass(), setter); if (methodCall != null) { assignment.replace(methodCall); } // TODO: check if value is used!!! } } else if (opType == JavaTokenType.ASTERISKEQ || opType == JavaTokenType.DIVEQ || opType == JavaTokenType.PERCEQ || opType == JavaTokenType.PLUSEQ || opType == JavaTokenType.MINUSEQ || opType == JavaTokenType.LTLTEQ || opType == JavaTokenType.GTGTEQ || opType == JavaTokenType.GTGTGTEQ || opType == JavaTokenType.ANDEQ || opType == JavaTokenType.OREQ || opType == JavaTokenType.XOREQ) { { // Q: side effects of qualifier??! String opName = opSign.getText(); LOG.assertTrue(StringUtil.endsWithChar(opName, '=')); opName = opName.substring(0, opName.length() - 1); PsiExpression getExpr = expr; if (processGet) { final PsiMethodCallExpression getterCall = createGetterCall(fieldDescriptor, expr, descriptor.getTargetClass(), getter); if (getterCall != null) { getExpr = getterCall; } } @NonNls String text = "a" + opName + "b"; PsiBinaryExpression binExpr = (PsiBinaryExpression) factory.createExpressionFromText(text, expr); binExpr.getLOperand().replace(getExpr); binExpr.getROperand().replace(assignment.getRExpression()); PsiExpression setExpr; if (processSet) { setExpr = createSetterCall( fieldDescriptor, binExpr, expr, descriptor.getTargetClass(), setter); } else { text = "a = b"; PsiAssignmentExpression assignment1 = (PsiAssignmentExpression) factory.createExpressionFromText(text, null); assignment1.getLExpression().replace(expr); assignment1.getRExpression().replace(binExpr); setExpr = assignment1; } assignment.replace(setExpr); // TODO: check if value is used!!! } } } else if (RefactoringUtil.isPlusPlusOrMinusMinus(parent)) { IElementType sign; if (parent instanceof PsiPrefixExpression) { sign = ((PsiPrefixExpression) parent).getOperationTokenType(); } else { sign = ((PsiPostfixExpression) parent).getOperationTokenType(); } PsiExpression getExpr = expr; if (processGet) { final PsiMethodCallExpression getterCall = createGetterCall(fieldDescriptor, expr, descriptor.getTargetClass(), getter); if (getterCall != null) { getExpr = getterCall; } } @NonNls String text; if (sign == JavaTokenType.PLUSPLUS) { text = "a+1"; } else { text = "a-1"; } PsiBinaryExpression binExpr = (PsiBinaryExpression) factory.createExpressionFromText(text, null); binExpr.getLOperand().replace(getExpr); PsiExpression setExpr; if (processSet) { setExpr = createSetterCall(fieldDescriptor, binExpr, expr, descriptor.getTargetClass(), setter); } else { text = "a = b"; PsiAssignmentExpression assignment = (PsiAssignmentExpression) factory.createExpressionFromText(text, null); assignment.getLExpression().replace(expr); assignment.getRExpression().replace(binExpr); setExpr = assignment; } parent.replace(setExpr); } else { if (!processGet) return true; PsiMethodCallExpression methodCall = createGetterCall(fieldDescriptor, expr, descriptor.getTargetClass(), getter); if (methodCall != null) { expr.replace(methodCall); } } } catch (IncorrectOperationException e) { LOG.error(e); } return true; }
@Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiExpression expression = (PsiExpression) descriptor.getPsiElement(); final PsiType type = expression.getType(); if (type == null) { return; } final PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type); if (unboxedType == null) { return; } final String newExpressionText = buildNewExpressionText(expression, unboxedType); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiElementFactory factory = psiFacade.getElementFactory(); final PsiElement parent = expression.getParent(); final String expressionText = expression.getText(); if (parent instanceof PsiPrefixExpression && !unboxedType.equalsToText("boolean")) { final PsiPrefixExpression prefixExpression = (PsiPrefixExpression) parent; final IElementType tokenType = prefixExpression.getOperationTokenType(); if (JavaTokenType.PLUSPLUS.equals(tokenType)) { replaceExpression(prefixExpression, expressionText + '=' + newExpressionText + "+1"); } else if (JavaTokenType.MINUSMINUS.equals(tokenType)) { replaceExpression(prefixExpression, expressionText + '=' + newExpressionText + "-1"); } else { replaceExpression( prefixExpression, prefixExpression.getOperationSign().getText() + newExpressionText); } } else if (parent instanceof PsiPostfixExpression) { final PsiPostfixExpression postfixExpression = (PsiPostfixExpression) parent; final IElementType tokenType = postfixExpression.getOperationTokenType(); final PsiElement grandParent = postfixExpression.getParent(); if (grandParent instanceof PsiExpressionStatement) { if (JavaTokenType.PLUSPLUS.equals(tokenType)) { replaceExpression(postfixExpression, expressionText + '=' + newExpressionText + "+1"); } else if (JavaTokenType.MINUSMINUS.equals(tokenType)) { replaceExpression(postfixExpression, expressionText + '=' + newExpressionText + "-1"); } } else { final PsiElement element = postfixExpression.replace(postfixExpression.getOperand()); final PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); if (statement == null) { return; } final PsiStatement newStatement; if (JavaTokenType.PLUSPLUS.equals(tokenType)) { newStatement = factory.createStatementFromText( expressionText + '=' + newExpressionText + "+1;", statement); } else { newStatement = factory.createStatementFromText( expressionText + '=' + newExpressionText + "-1;", statement); } final PsiElement greatGrandParent = statement.getParent(); greatGrandParent.addAfter(newStatement, statement); } } else if (parent instanceof PsiAssignmentExpression) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) parent; final PsiExpression lExpression = assignmentExpression.getLExpression(); if (expression.equals(lExpression)) { final PsiJavaToken operationSign = assignmentExpression.getOperationSign(); final String operationSignText = operationSign.getText(); final char sign = operationSignText.charAt(0); final PsiExpression rExpression = assignmentExpression.getRExpression(); if (rExpression == null) { return; } final String text = lExpression.getText() + '=' + newExpressionText + sign + rExpression.getText(); final PsiExpression newExpression = factory.createExpressionFromText(text, assignmentExpression); assignmentExpression.replace(newExpression); } else { replaceExpression(expression, newExpressionText); } } else { replaceExpression(expression, newExpressionText); } }