private static PsiAnnotationMemberValue[] readFromClass( @NonNls String attributeName, @NotNull PsiAnnotation magic, PsiType type) { PsiAnnotationMemberValue fromClassAttr = magic.findAttributeValue(attributeName); PsiType fromClassType = fromClassAttr instanceof PsiClassObjectAccessExpression ? ((PsiClassObjectAccessExpression) fromClassAttr).getOperand().getType() : null; PsiClass fromClass = fromClassType instanceof PsiClassType ? ((PsiClassType) fromClassType).resolve() : null; if (fromClass == null) return null; String fqn = fromClass.getQualifiedName(); if (fqn == null) return null; List<PsiAnnotationMemberValue> constants = new ArrayList<PsiAnnotationMemberValue>(); for (PsiField field : fromClass.getFields()) { if (!field.hasModifierProperty(PsiModifier.PUBLIC) || !field.hasModifierProperty(PsiModifier.STATIC) || !field.hasModifierProperty(PsiModifier.FINAL)) continue; PsiType fieldType = field.getType(); if (!Comparing.equal(fieldType, type)) continue; PsiAssignmentExpression e = (PsiAssignmentExpression) JavaPsiFacade.getElementFactory(field.getProject()) .createExpressionFromText("x=" + fqn + "." + field.getName(), field); PsiReferenceExpression refToField = (PsiReferenceExpression) e.getRExpression(); constants.add(refToField); } if (constants.isEmpty()) return null; return constants.toArray(new PsiAnnotationMemberValue[constants.size()]); }
private static boolean onTheLeftSideOfConditionalAssignment(final PsiElement psiAnchor) { final PsiElement parent = psiAnchor.getParent(); if (parent instanceof PsiAssignmentExpression) { final PsiAssignmentExpression expression = (PsiAssignmentExpression) parent; if (expression.getLExpression() == psiAnchor) return true; } return false; }
private static boolean writtenInside(PsiVariable variable, PsiElement element) { if (element instanceof PsiAssignmentExpression) { PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) element; PsiExpression lExpression = assignmentExpression.getLExpression(); if (lExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression) lExpression).resolve() == variable) return true; } else if (PsiUtil.isIncrementDecrementOperation(element)) { PsiElement operand = element instanceof PsiPostfixExpression ? ((PsiPostfixExpression) element).getOperand() : ((PsiPrefixExpression) element).getOperand(); if (operand instanceof PsiReferenceExpression && ((PsiReferenceExpression) operand).resolve() == variable) return true; } PsiElement[] children = element.getChildren(); for (PsiElement child : children) { if (writtenInside(variable, child)) return true; } return false; }
public void visitAssignmentExpression(PsiAssignmentExpression expression) { super.visitAssignmentExpression(expression); final PsiExpression lhs = expression.getLExpression(); if (isProhibitedReference(lhs)) { final PsiField field = getReferencedField(lhs); if (!hasGetter(field) && !isStaticFinal(field) && !field.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { fieldsNeedingSetter.add(field); } } }
/** * @param sideEffects if null, delete usages, otherwise collect side effects * @return true if there are at least one unrecoverable side effect found, false if no side * effects, null if read usage found (may happen if interval between fix creation in invoke() * call was long enough) * @throws com.intellij.util.IncorrectOperationException */ static Boolean processUsage( PsiElement element, PsiVariable variable, List<PsiElement> sideEffects, int deleteMode) throws IncorrectOperationException { if (!element.isValid()) return null; PsiElementFactory factory = JavaPsiFacade.getInstance(variable.getProject()).getElementFactory(); while (element != null) { if (element instanceof PsiAssignmentExpression) { PsiAssignmentExpression expression = (PsiAssignmentExpression) element; PsiExpression lExpression = expression.getLExpression(); // there should not be read access to the variable, otherwise it is not unused if (!(lExpression instanceof PsiReferenceExpression) || variable != ((PsiReferenceExpression) lExpression).resolve()) { return null; } PsiExpression rExpression = expression.getRExpression(); rExpression = PsiUtil.deparenthesizeExpression(rExpression); if (rExpression == null) return true; // replace assignment with expression and resimplify boolean sideEffectFound = checkSideEffects(rExpression, variable, sideEffects); if (!(element.getParent() instanceof PsiExpressionStatement) || PsiUtil.isStatement(rExpression)) { if (deleteMode == MAKE_STATEMENT || deleteMode == DELETE_ALL && !(element.getParent() instanceof PsiExpressionStatement)) { element = replaceElementWithExpression(rExpression, factory, element); while (element.getParent() instanceof PsiParenthesizedExpression) { element = element.getParent().replace(element); } List<PsiElement> references = new ArrayList<PsiElement>(); collectReferences(element, variable, references); deleteReferences(variable, references, deleteMode); } else if (deleteMode == DELETE_ALL) { deleteWholeStatement(element, factory); } return true; } else { if (deleteMode != CANCEL) { deleteWholeStatement(element, factory); } return !sideEffectFound; } } else if (element instanceof PsiExpressionStatement && deleteMode != CANCEL) { final PsiElement parent = element.getParent(); if (parent instanceof PsiIfStatement || parent instanceof PsiLoopStatement && ((PsiLoopStatement) parent).getBody() == element) { element.replace( JavaPsiFacade.getElementFactory(element.getProject()) .createStatementFromText(";", element)); } else { element.delete(); } break; } else if (element instanceof PsiVariable && element == variable) { PsiExpression expression = variable.getInitializer(); if (expression != null) { expression = PsiUtil.deparenthesizeExpression(expression); } boolean sideEffectsFound = checkSideEffects(expression, variable, sideEffects); if (expression != null && PsiUtil.isStatement(expression) && variable instanceof PsiLocalVariable && !(variable.getParent() instanceof PsiDeclarationStatement && ((PsiDeclarationStatement) variable.getParent()).getDeclaredElements().length > 1)) { if (deleteMode == MAKE_STATEMENT) { element = element.replace(createStatementIfNeeded(expression, factory, element)); List<PsiElement> references = new ArrayList<PsiElement>(); collectReferences(element, variable, references); deleteReferences(variable, references, deleteMode); } else if (deleteMode == DELETE_ALL) { element.delete(); } return true; } else { if (deleteMode != CANCEL) { if (element instanceof PsiField) { ((PsiField) element).normalizeDeclaration(); } element.delete(); } return !sideEffectsFound; } } element = element.getParent(); } return true; }
@Nullable private PsiStatement hasCommonInitializer( PsiStatement commonInitializer, PsiMethod subConstructor, PsiField field, ArrayList<PsiElement> statementsToRemove) { final PsiCodeBlock body = subConstructor.getBody(); if (body == null) return null; final PsiStatement[] statements = body.getStatements(); // Algorithm: there should be only one write usage of field in a subConstructor, // and in that usage field must be a target of top-level assignment, and RHS of assignment // should be the same as commonInitializer if latter is non-null. // // There should be no usages before that initializer, and there should be // no write usages afterwards. PsiStatement commonInitializerCandidate = null; for (PsiStatement statement : statements) { final HashSet<PsiStatement> collectedStatements = new HashSet<PsiStatement>(); collectPsiStatements(statement, collectedStatements); boolean doLookup = true; for (PsiStatement collectedStatement : collectedStatements) { if (collectedStatement instanceof PsiExpressionStatement) { final PsiExpression expression = ((PsiExpressionStatement) collectedStatement).getExpression(); if (expression instanceof PsiAssignmentExpression) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) expression; final PsiExpression lExpression = assignmentExpression.getLExpression(); if (lExpression instanceof PsiReferenceExpression) { final PsiReferenceExpression lRef = (PsiReferenceExpression) lExpression; if (lRef.getQualifierExpression() == null || lRef.getQualifierExpression() instanceof PsiThisExpression) { final PsiElement resolved = lRef.resolve(); if (resolved == field) { doLookup = false; if (commonInitializerCandidate == null) { final PsiExpression initializer = assignmentExpression.getRExpression(); if (initializer == null) return null; if (commonInitializer == null) { final IsMovableInitializerVisitor visitor = new IsMovableInitializerVisitor(); statement.accept(visitor); if (visitor.isMovable()) { ChangeContextUtil.encodeContextInfo(statement, true); PsiStatement statementCopy = (PsiStatement) statement.copy(); ChangeContextUtil.clearContextInfo(statement); statementsToRemove.add(statement); commonInitializerCandidate = statementCopy; } else { return null; } } else { if (PsiEquivalenceUtil.areElementsEquivalent(commonInitializer, statement)) { statementsToRemove.add(statement); commonInitializerCandidate = commonInitializer; } else { return null; } } } else if (!PsiEquivalenceUtil.areElementsEquivalent( commonInitializerCandidate, statement)) { return null; } } } } } } } if (doLookup) { final PsiReference[] references = ReferencesSearch.search(field, new LocalSearchScope(statement), false) .toArray(new PsiReference[0]); if (commonInitializerCandidate == null && references.length > 0) { return null; } for (PsiReference reference : references) { if (RefactoringUtil.isAssignmentLHS(reference.getElement())) return null; } } } return commonInitializerCandidate; }
private NamesByExprInfo suggestVariableNameByExpressionPlace( PsiExpression expr, final VariableKind variableKind, boolean correctKeywords) { if (expr.getParent() instanceof PsiExpressionList) { PsiExpressionList list = (PsiExpressionList) expr.getParent(); PsiElement listParent = list.getParent(); PsiSubstitutor subst = PsiSubstitutor.EMPTY; PsiMethod method = null; if (listParent instanceof PsiMethodCallExpression) { final JavaResolveResult resolveResult = ((PsiMethodCallExpression) listParent).getMethodExpression().advancedResolve(false); method = (PsiMethod) resolveResult.getElement(); subst = resolveResult.getSubstitutor(); } else { if (listParent instanceof PsiAnonymousClass) { listParent = listParent.getParent(); } if (listParent instanceof PsiNewExpression) { method = ((PsiNewExpression) listParent).resolveConstructor(); } } if (method != null) { final PsiElement navElement = method.getNavigationElement(); if (navElement instanceof PsiMethod) { method = (PsiMethod) navElement; } PsiExpression[] expressions = list.getExpressions(); int index = -1; for (int i = 0; i < expressions.length; i++) { if (expressions[i] == expr) { index = i; break; } } PsiParameter[] parameters = method.getParameterList().getParameters(); if (index < parameters.length) { String name = parameters[index].getName(); if (name != null && TypeConversionUtil.areTypesAssignmentCompatible( subst.substitute(parameters[index].getType()), expr)) { name = variableNameToPropertyName(name, VariableKind.PARAMETER); String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); if (expressions.length == 1) { final String methodName = method.getName(); String[] words = NameUtil.nameToWords(methodName); if (words.length > 0) { final String firstWord = words[0]; if (SET_PREFIX.equals(firstWord)) { final String propertyName = methodName.substring(firstWord.length()); final String[] setterNames = getSuggestionsByName(propertyName, variableKind, false, correctKeywords); names = ArrayUtil.mergeArrays(names, setterNames); } } } return new NamesByExprInfo(name, names); } } } } else if (expr.getParent() instanceof PsiAssignmentExpression && variableKind == VariableKind.PARAMETER) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) expr.getParent(); if (expr == assignmentExpression.getRExpression()) { final PsiExpression leftExpression = assignmentExpression.getLExpression(); if (leftExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression) leftExpression).getQualifier() == null) { String name = leftExpression.getText(); if (name != null) { final PsiElement resolve = ((PsiReferenceExpression) leftExpression).resolve(); if (resolve instanceof PsiVariable) { name = variableNameToPropertyName(name, getVariableKind((PsiVariable) resolve)); } String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); return new NamesByExprInfo(name, names); } } } } return new NamesByExprInfo(null, ArrayUtil.EMPTY_STRING_ARRAY); }