public static void registerQuickFix( PsiMember refElement, PsiJavaCodeReferenceElement place, PsiClass accessObjectClass, HighlightInfo error) { if (refElement instanceof PsiField && place instanceof PsiReferenceExpression) { final PsiField psiField = (PsiField) refElement; final PsiClass containingClass = psiField.getContainingClass(); if (containingClass != null) { if (PsiUtil.isOnAssignmentLeftHand((PsiExpression) place)) { final PsiMethod setterPrototype = PropertyUtil.generateSetterPrototype(psiField); final PsiMethod setter = containingClass.findMethodBySignature(setterPrototype, true); if (setter != null && PsiUtil.isAccessible(setter, place, accessObjectClass)) { QuickFixAction.registerQuickFixAction( error, new ReplaceInaccessibleFieldWithGetterSetterFix(place, setter, true)); } } else if (PsiUtil.isAccessedForReading((PsiExpression) place)) { final PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(psiField); final PsiMethod getter = containingClass.findMethodBySignature(getterPrototype, true); if (getter != null && PsiUtil.isAccessible(getter, place, accessObjectClass)) { QuickFixAction.registerQuickFixAction( error, new ReplaceInaccessibleFieldWithGetterSetterFix(place, getter, false)); } } } } }
private static ArrayList<PsiMethod> filterConstructorsIfFieldAlreadyAssigned( PsiMethod[] constructors, PsiField field) { final ArrayList<PsiMethod> result = new ArrayList<PsiMethod>(Arrays.asList(constructors)); for (PsiReference reference : ReferencesSearch.search(field, new LocalSearchScope(constructors))) { final PsiElement element = reference.getElement(); if (element instanceof PsiReferenceExpression && PsiUtil.isOnAssignmentLeftHand((PsiExpression) element)) { result.remove(PsiTreeUtil.getParentOfType(element, PsiMethod.class)); } } return result; }
@Nullable public NonCodeUsageSearchInfo findUsages( @NotNull final PsiElement element, @NotNull final PsiElement[] allElementsToDelete, @NotNull final List<UsageInfo> usages) { Condition<PsiElement> insideDeletedCondition = getUsageInsideDeletedFilter(allElementsToDelete); if (element instanceof PsiClass) { findClassUsages((PsiClass) element, allElementsToDelete, usages); if (element instanceof PsiTypeParameter) { findTypeParameterExternalUsages((PsiTypeParameter) element, usages); } } else if (element instanceof PsiMethod) { insideDeletedCondition = findMethodUsages((PsiMethod) element, allElementsToDelete, usages); } else if (element instanceof PsiField) { insideDeletedCondition = findFieldUsages((PsiField) element, usages, allElementsToDelete); } else if (element instanceof PsiParameter) { LOG.assertTrue(((PsiParameter) element).getDeclarationScope() instanceof PsiMethod); findParameterUsages((PsiParameter) element, usages); } else if (element instanceof PsiLocalVariable) { for (PsiReference reference : ReferencesSearch.search(element)) { PsiReferenceExpression referencedElement = (PsiReferenceExpression) reference.getElement(); final PsiStatement statement = PsiTreeUtil.getParentOfType(referencedElement, PsiStatement.class); boolean isSafeToDelete = PsiUtil.isAccessedForWriting(referencedElement); boolean hasSideEffects = false; if (PsiUtil.isOnAssignmentLeftHand(referencedElement)) { hasSideEffects = RemoveUnusedVariableUtil.checkSideEffects( ((PsiAssignmentExpression) referencedElement.getParent()).getRExpression(), ((PsiLocalVariable) element), new ArrayList<>()); } usages.add( new SafeDeleteReferenceJavaDeleteUsageInfo( statement, element, isSafeToDelete && !hasSideEffects)); } } return new NonCodeUsageSearchInfo(insideDeletedCondition, element); }
public void inlineElement( final Project project, final Editor editor, final PsiElement psiElement) { final PsiParameter psiParameter = (PsiParameter) psiElement; final PsiParameterList parameterList = (PsiParameterList) psiParameter.getParent(); if (!(parameterList.getParent() instanceof PsiMethod)) { return; } final int index = parameterList.getParameterIndex(psiParameter); final PsiMethod method = (PsiMethod) parameterList.getParent(); String errorMessage = getCannotInlineMessage(psiParameter, method); if (errorMessage != null) { CommonRefactoringUtil.showErrorHint( project, editor, errorMessage, RefactoringBundle.message("inline.parameter.refactoring"), null); return; } final Ref<PsiExpression> refInitializer = new Ref<PsiExpression>(); final Ref<PsiExpression> refConstantInitializer = new Ref<PsiExpression>(); final Ref<PsiCallExpression> refMethodCall = new Ref<PsiCallExpression>(); final List<PsiReference> occurrences = Collections.synchronizedList(new ArrayList<PsiReference>()); final Collection<PsiFile> containingFiles = Collections.synchronizedSet(new HashSet<PsiFile>()); containingFiles.add(psiParameter.getContainingFile()); boolean result = ReferencesSearch.search(method) .forEach( new Processor<PsiReference>() { public boolean process(final PsiReference psiReference) { PsiElement element = psiReference.getElement(); final PsiElement parent = element.getParent(); if (parent instanceof PsiCallExpression) { final PsiCallExpression methodCall = (PsiCallExpression) parent; occurrences.add(psiReference); containingFiles.add(element.getContainingFile()); final PsiExpression[] expressions = methodCall.getArgumentList().getExpressions(); if (expressions.length <= index) return false; PsiExpression argument = expressions[index]; if (!refInitializer.isNull()) { return argument != null && PsiEquivalenceUtil.areElementsEquivalent( refInitializer.get(), argument) && PsiEquivalenceUtil.areElementsEquivalent( refMethodCall.get(), methodCall); } if (InlineToAnonymousConstructorProcessor.isConstant(argument) || getReferencedFinalField(argument) != null) { if (refConstantInitializer.isNull()) { refConstantInitializer.set(argument); } else if (!isSameConstant(argument, refConstantInitializer.get())) { return false; } } else if (!isRecursiveReferencedParameter(argument, psiParameter)) { if (!refConstantInitializer.isNull()) return false; refInitializer.set(argument); refMethodCall.set(methodCall); } } return true; } }); final int offset = editor.getCaretModel().getOffset(); final PsiElement refExpr = psiElement.getContainingFile().findElementAt(offset); final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(refExpr, PsiCodeBlock.class); if (codeBlock != null) { final PsiElement[] defs = DefUseUtil.getDefs(codeBlock, psiParameter, refExpr); if (defs.length == 1) { final PsiElement def = defs[0]; if (def instanceof PsiReferenceExpression && PsiUtil.isOnAssignmentLeftHand((PsiExpression) def)) { final PsiExpression rExpr = ((PsiAssignmentExpression) def.getParent()).getRExpression(); if (rExpr != null) { final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr); if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs, def) == null) { new WriteCommandAction(project) { @Override protected void run(Result result) throws Throwable { for (final PsiElement ref : refs) { InlineUtil.inlineVariable( psiParameter, rExpr, (PsiJavaCodeReferenceElement) ref); } def.getParent().delete(); } }.execute(); return; } } } } } if (occurrences.isEmpty()) { CommonRefactoringUtil.showErrorHint( project, editor, "Method has no usages", RefactoringBundle.message("inline.parameter.refactoring"), null); return; } if (!result) { CommonRefactoringUtil.showErrorHint( project, editor, "Cannot find constant initializer for parameter", RefactoringBundle.message("inline.parameter.refactoring"), null); return; } if (!refInitializer.isNull()) { if (ApplicationManager.getApplication().isUnitTestMode()) { final InlineParameterExpressionProcessor processor = new InlineParameterExpressionProcessor( refMethodCall.get(), method, psiParameter, refInitializer.get(), method .getProject() .getUserData(InlineParameterExpressionProcessor.CREATE_LOCAL_FOR_TESTS)); processor.run(); } else { final boolean createLocal = ReferencesSearch.search(psiParameter).findAll().size() > 1; InlineParameterDialog dlg = new InlineParameterDialog( refMethodCall.get(), method, psiParameter, refInitializer.get(), createLocal); dlg.show(); } return; } if (refConstantInitializer.isNull()) { CommonRefactoringUtil.showErrorHint( project, editor, "Cannot find constant initializer for parameter", RefactoringBundle.message("inline.parameter.refactoring"), null); return; } final Ref<Boolean> isNotConstantAccessible = new Ref<Boolean>(); final PsiExpression constantExpression = refConstantInitializer.get(); constantExpression.accept( new JavaRecursiveElementVisitor() { @Override public void visitReferenceExpression(PsiReferenceExpression expression) { super.visitReferenceExpression(expression); final PsiElement resolved = expression.resolve(); if (resolved instanceof PsiMember && !PsiUtil.isAccessible((PsiMember) resolved, method, null)) { isNotConstantAccessible.set(Boolean.TRUE); } } }); if (!isNotConstantAccessible.isNull() && isNotConstantAccessible.get()) { CommonRefactoringUtil.showErrorHint( project, editor, "Constant initializer is not accessible in method body", RefactoringBundle.message("inline.parameter.refactoring"), null); return; } for (PsiReference psiReference : ReferencesSearch.search(psiParameter)) { final PsiElement element = psiReference.getElement(); if (element instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression) element)) { CommonRefactoringUtil.showErrorHint( project, editor, "Inline parameter which has write usages is not supported", RefactoringBundle.message("inline.parameter.refactoring"), null); return; } } if (!ApplicationManager.getApplication().isUnitTestMode()) { String occurencesString = RefactoringBundle.message("occurences.string", occurrences.size()); String question = RefactoringBundle.message( "inline.parameter.confirmation", psiParameter.getName(), constantExpression.getText()) + " " + occurencesString; RefactoringMessageDialog dialog = new RefactoringMessageDialog( REFACTORING_NAME, question, HelpID.INLINE_VARIABLE, "OptionPane.questionIcon", true, project); dialog.show(); if (!dialog.isOK()) { return; } } final RefactoringEventData data = new RefactoringEventData(); data.addElement(psiElement.copy()); project .getMessageBus() .syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringStarted(REFACTORING_ID, data); SameParameterValueInspection.InlineParameterValueFix.inlineSameParameterValue( method, psiParameter, constantExpression); project .getMessageBus() .syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringDone(REFACTORING_ID, null); }
@Nullable public static PsiType getFunctionalInterfaceType( PsiElement expression, final boolean tryToSubstitute, int paramIdx) { PsiElement parent = expression.getParent(); PsiElement element = expression; while (parent instanceof PsiParenthesizedExpression || parent instanceof PsiConditionalExpression) { if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression) parent).getThenExpression() != element && ((PsiConditionalExpression) parent).getElseExpression() != element) break; element = parent; parent = parent.getParent(); } if (parent instanceof PsiArrayInitializerExpression) { final PsiType psiType = ((PsiArrayInitializerExpression) parent).getType(); if (psiType instanceof PsiArrayType) { return ((PsiArrayType) psiType).getComponentType(); } } else if (parent instanceof PsiTypeCastExpression) { final PsiType castType = ((PsiTypeCastExpression) parent).getType(); if (castType instanceof PsiIntersectionType) { for (PsiType conjunctType : ((PsiIntersectionType) castType).getConjuncts()) { if (getFunctionalInterfaceMethod(conjunctType) != null) return conjunctType; } } return castType; } else if (parent instanceof PsiVariable) { return ((PsiVariable) parent).getType(); } else if (parent instanceof PsiAssignmentExpression && expression instanceof PsiExpression && !PsiUtil.isOnAssignmentLeftHand((PsiExpression) expression)) { final PsiExpression lExpression = ((PsiAssignmentExpression) parent).getLExpression(); return lExpression.getType(); } else if (parent instanceof PsiExpressionList) { final PsiExpressionList expressionList = (PsiExpressionList) parent; final int lambdaIdx = getLambdaIdx(expressionList, expression); if (lambdaIdx > -1) { PsiType cachedType = null; final Pair<PsiMethod, PsiSubstitutor> method = MethodCandidateInfo.getCurrentMethod(parent); if (method != null) { final PsiParameter[] parameters = method.first.getParameterList().getParameters(); cachedType = lambdaIdx < parameters.length ? method.second.substitute( getNormalizedType( parameters[adjustLambdaIdx(lambdaIdx, method.first, parameters)])) : null; if (!tryToSubstitute) return cachedType; } PsiElement gParent = expressionList.getParent(); if (gParent instanceof PsiAnonymousClass) { gParent = gParent.getParent(); } if (gParent instanceof PsiCall) { final PsiCall contextCall = (PsiCall) gParent; final JavaResolveResult resolveResult = contextCall.resolveMethodGenerics(); final PsiElement resolve = resolveResult.getElement(); if (resolve instanceof PsiMethod) { final PsiParameter[] parameters = ((PsiMethod) resolve).getParameterList().getParameters(); final int finalLambdaIdx = adjustLambdaIdx(lambdaIdx, (PsiMethod) resolve, parameters); if (finalLambdaIdx < parameters.length) { if (!tryToSubstitute) return getNormalizedType(parameters[finalLambdaIdx]); if (cachedType != null && paramIdx > -1) { final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(cachedType); if (interfaceMethod != null) { final PsiClassType.ClassResolveResult cachedResult = PsiUtil.resolveGenericsClassInType(cachedType); final PsiType interfaceMethodParameterType = interfaceMethod.getParameterList().getParameters()[paramIdx].getType(); if (!dependsOnTypeParams( cachedResult.getSubstitutor().substitute(interfaceMethodParameterType), cachedType, expression)) { return cachedType; } } } return PsiResolveHelper.ourGuard.doPreventingRecursion( expression, true, new Computable<PsiType>() { @Override public PsiType compute() { return resolveResult .getSubstitutor() .substitute(getNormalizedType(parameters[finalLambdaIdx])); } }); } } return null; } } } else if (parent instanceof PsiReturnStatement) { final PsiLambdaExpression gParent = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class); if (gParent != null) { return getFunctionalInterfaceTypeByContainingLambda(gParent); } else { final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); if (method != null) { return method.getReturnType(); } } } else if (parent instanceof PsiLambdaExpression) { return getFunctionalInterfaceTypeByContainingLambda((PsiLambdaExpression) parent); } return null; }