private static void registerSwapFixes(final PsiExpression[] expressions, final PsiCall callExpression, final List<PsiCall> permutations, MethodCandidateInfo candidate, final int incompatibilitiesCount, final int minIncompatibleIndex, final int maxIncompatibleIndex) throws IncorrectOperationException { PsiMethod method = candidate.getElement(); PsiSubstitutor substitutor = candidate.getSubstitutor(); if (incompatibilitiesCount >= 3) return; // no way we can fix it by swapping for (int i = minIncompatibleIndex; i < maxIncompatibleIndex; i++) { for (int j = i+1; j <= maxIncompatibleIndex; j++) { ArrayUtil.swap(expressions, i, j); if (PsiUtil.isApplicable(method, substitutor, expressions)) { PsiCall copy = (PsiCall)callExpression.copy(); PsiExpression[] copyExpressions = copy.getArgumentList().getExpressions(); copyExpressions[i].replace(expressions[i]); copyExpressions[j].replace(expressions[j]); JavaResolveResult result = copy.resolveMethodGenerics(); if (result.getElement() != null && result.isValidResult()) { permutations.add(copy); if (permutations.size() > 1) return; } } ArrayUtil.swap(expressions, i, j); } } }
protected InlineToAnonymousClassDialog(Project project, PsiClass psiClass, final PsiCall callToInline, boolean isInvokeOnReference) { super(project, true, psiClass); myClass = psiClass; myCallToInline = callToInline; myInvokedOnReference = isInvokeOnReference; setTitle(RefactoringBundle.message("inline.to.anonymous.refactoring")); init(); }
private void performAction(final boolean inlineThisOnly, final boolean searchInNonJavaFiles) { PsiElement element = TargetElementUtil .findTargetElement(myEditor, TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED); PsiCall callToInline = InlineToAnonymousClassHandler.findCallToInline(myEditor); PsiClass classToInline = (PsiClass) element; assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); final InlineToAnonymousClassProcessor processor = new InlineToAnonymousClassProcessor(getProject(), classToInline, callToInline, inlineThisOnly, false, searchInNonJavaFiles); UsageInfo[] usages = processor.findUsages(); MultiMap<PsiElement, String> conflicts = processor.getConflicts(usages); assertEquals(0, conflicts.size()); processor.run(); }
private void doTestCanBeInvokedOnReference(boolean canBeInvokedOnReference) throws Exception { configureByFile("/refactoring/inlineToAnonymousClass/" + getTestName(false) + ".java"); PsiElement element = TargetElementUtil .findTargetElement(myEditor, TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED); PsiCall callToInline = InlineToAnonymousClassHandler.findCallToInline(myEditor); PsiClass classToInline = (PsiClass) element; assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); final PsiClassType superType = InlineToAnonymousClassProcessor.getSuperType(classToInline); assertTrue(superType != null); assertEquals(canBeInvokedOnReference, InlineToAnonymousClassHandler.canBeInvokedOnReference(callToInline, superType)); }
private void performAction(final boolean inlineThisOnly, final boolean searchInNonJavaFiles) { PsiElement element = TargetElementUtilBase .findTargetElement(myEditor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED); PsiCall callToInline = InlineToAnonymousClassHandler.findCallToInline(myEditor); PsiClass classToInline = (PsiClass) element; assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); final InlineToAnonymousClassProcessor processor = new InlineToAnonymousClassProcessor(getProject(), classToInline, callToInline, inlineThisOnly, false, searchInNonJavaFiles); UsageInfo[] usages = processor.findUsages(); MultiMap<PsiElement, String> conflicts = processor.getConflicts(usages); assertEquals(0, conflicts.size()); processor.run(); }
private void doTestCanBeInvokedOnReference(boolean canBeInvokedOnReference) throws Exception { configureByFile("/refactoring/inlineToAnonymousClass/" + getTestName(false) + ".java"); PsiElement element = TargetElementUtilBase .findTargetElement(myEditor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED); PsiCall callToInline = InlineToAnonymousClassHandler.findCallToInline(myEditor); PsiClass classToInline = (PsiClass) element; assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); final PsiClassType superType = InlineToAnonymousClassProcessor.getSuperType(classToInline); assertTrue(superType != null); assertEquals(canBeInvokedOnReference, InlineToAnonymousClassHandler.canBeInvokedOnReference(callToInline, superType)); }
public static void registerFix(HighlightInfo info, PsiCall callExpression, final CandidateInfo[] candidates, final TextRange fixRange) { PsiExpression[] expressions = callExpression.getArgumentList().getExpressions(); if (expressions.length < 2) return; List<PsiCall> permutations = new ArrayList<PsiCall>(); for (CandidateInfo candidate : candidates) { if (candidate instanceof MethodCandidateInfo) { MethodCandidateInfo methodCandidate = (MethodCandidateInfo)candidate; PsiMethod method = methodCandidate.getElement(); PsiSubstitutor substitutor = methodCandidate.getSubstitutor(); PsiParameter[] parameters = method.getParameterList().getParameters(); if (expressions.length != parameters.length || parameters.length ==0) continue; int minIncompatibleIndex = parameters.length; int maxIncompatibleIndex = 0; int incompatibilitiesCount = 0; for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; PsiType type = substitutor.substitute(parameter.getType()); if (TypeConversionUtil.areTypesAssignmentCompatible(type, expressions[i])) continue; if (minIncompatibleIndex == parameters.length) minIncompatibleIndex = i; maxIncompatibleIndex = i; incompatibilitiesCount++; } try { registerSwapFixes(expressions, callExpression, permutations, methodCandidate, incompatibilitiesCount, minIncompatibleIndex, maxIncompatibleIndex); registerShiftFixes(expressions, callExpression, permutations, methodCandidate, minIncompatibleIndex, maxIncompatibleIndex); } catch (IncorrectOperationException e) { LOG.error(e); } } } if (permutations.size() == 1) { PermuteArgumentsFix fix = new PermuteArgumentsFix(callExpression, permutations.get(0)); QuickFixAction.registerQuickFixAction(info, fixRange, fix); } }
@RequiredReadAction public static void registerChosenMethod(PsiMethod method, PsiCall call) { TextRange nameRange = getAnchorRange(call); if(nameRange == null) { return; } Document document = call.getContainingFile().getViewProvider().getDocument(); if(document == null) { return; } addToMemory(document, createChosenMethodMarker(document, CompletionUtil.getOriginalOrSelf(method), nameRange)); }
@Nullable @RequiredReadAction public static PsiMethod getChosenMethod(PsiCall call) { TextRange range = getAnchorRange(call); if(range == null) { return null; } Document document = call.getContainingFile().getViewProvider().getDocument(); if(document == null) { return null; } LinkedList<RangeMarker> completedMethods = document.getUserData(LAST_CHOSEN_METHODS); if(completedMethods == null) { return null; } RangeMarker rangeMarker = ContainerUtil.find(completedMethods, m -> haveSameRange(m, range)); if(rangeMarker == null) { return null; } SmartPsiElementPointer<PsiMethod> pointer = rangeMarker.getUserData(CHOSEN_METHODS); return pointer == null ? null : pointer.getElement(); }
private void performAction(final boolean inlineThisOnly, final boolean searchInNonJavaFiles) { PsiElement element = TargetElementUtil.findTargetElement(myEditor, ContainerUtil.newHashSet(TargetElementUtilEx.ELEMENT_NAME_ACCEPTED, TargetElementUtilEx.REFERENCED_ELEMENT_ACCEPTED)); PsiCall callToInline = InlineToAnonymousClassHandler.findCallToInline(myEditor); PsiClass classToInline = (PsiClass) element; assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); final InlineToAnonymousClassProcessor processor = new InlineToAnonymousClassProcessor(getProject(), classToInline, callToInline, inlineThisOnly, false, searchInNonJavaFiles); UsageInfo[] usages = processor.findUsages(); MultiMap<PsiElement, String> conflicts = processor.getConflicts(usages); assertEquals(0, conflicts.size()); processor.run(); }
private void doTestCanBeInvokedOnReference(boolean canBeInvokedOnReference) throws Exception { configureByFile("/refactoring/inlineToAnonymousClass/" + getTestName(false) + ".java"); PsiElement element = TargetElementUtil.findTargetElement(myEditor, ContainerUtil.newHashSet(TargetElementUtilEx.ELEMENT_NAME_ACCEPTED, TargetElementUtilEx.REFERENCED_ELEMENT_ACCEPTED)); PsiCall callToInline = InlineToAnonymousClassHandler.findCallToInline(myEditor); PsiClass classToInline = (PsiClass) element; assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); final PsiClassType superType = InlineToAnonymousClassProcessor.getSuperType(classToInline); assertTrue(superType != null); assertEquals(canBeInvokedOnReference, InlineToAnonymousClassHandler.canBeInvokedOnReference(callToInline, superType)); }
InitialInferenceState getInitialState(PsiCall call) { return myInitialStates.get(call); }
private PermuteArgumentsFix(@NotNull PsiCall call, @NotNull PsiCall permutation) { myCall = call; myPermutation = permutation; }