protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    checkExistingMethods(conflicts, true);
    checkExistingMethods(conflicts, false);
    final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      final Set<PsiMethod> setters = new HashSet<PsiMethod>();
      final Set<PsiMethod> getters = new HashSet<PsiMethod>();

      for (PsiClass aClass : classes) {
        final PsiMethod getterOverrider =
            myDescriptor.isToEncapsulateGet()
                ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false)
                : null;
        if (getterOverrider != null) {
          getters.add(getterOverrider);
        }
        final PsiMethod setterOverrider =
            myDescriptor.isToEncapsulateSet()
                ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false)
                : null;
        if (setterOverrider != null) {
          setters.add(setterOverrider);
        }
      }
      if (!getters.isEmpty() || !setters.isEmpty()) {
        final PsiField field = fieldDescriptor.getField();
        for (PsiReference reference : ReferencesSearch.search(field)) {
          final PsiElement place = reference.getElement();
          if (place instanceof PsiReferenceExpression) {
            final PsiExpression qualifierExpression =
                ((PsiReferenceExpression) place).getQualifierExpression();
            final PsiClass ancestor;
            if (qualifierExpression == null) {
              ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
            } else {
              ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType());
            }

            final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression) place);
            for (PsiMethod overridden : isGetter ? getters : setters) {
              if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) {
                conflicts.putValue(
                    overridden,
                    "There is already a "
                        + RefactoringUIUtil.getDescription(overridden, true)
                        + " which would hide generated "
                        + (isGetter ? "getter" : "setter")
                        + " for "
                        + place.getText());
                break;
              }
            }
          }
        }
      }
    }
    return showConflicts(conflicts, refUsages.get());
  }
Пример #2
0
  private static PsiType doNormalizeWildcardByPosition(
      final PsiType type, final PsiExpression expression, final PsiExpression toplevel) {
    if (type instanceof PsiCapturedWildcardType) {
      return doNormalizeWildcardByPosition(
          ((PsiCapturedWildcardType) type).getWildcard(), expression, toplevel);
    }

    if (type instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) type;

      if (PsiUtil.isAccessedForWriting(toplevel)) {
        return wildcardType.isSuper()
            ? wildcardType.getBound()
            : PsiCapturedWildcardType.create(wildcardType, expression);
      } else {
        if (wildcardType.isExtends()) {
          return wildcardType.getBound();
        } else {
          return PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
        }
      }
    } else if (type instanceof PsiArrayType) {
      final PsiType componentType = ((PsiArrayType) type).getComponentType();
      final PsiType normalizedComponentType =
          doNormalizeWildcardByPosition(componentType, expression, toplevel);
      if (normalizedComponentType != componentType) {
        return normalizedComponentType.createArrayType();
      }
    }

    return type;
  }
Пример #3
0
 private static boolean mayBeFinal(Set<PsiReference> refsSet, PsiElement firstElement) {
   for (PsiReference ref : refsSet) {
     PsiElement element = ref.getElement();
     if (element == firstElement) continue;
     if (element instanceof PsiExpression
         && PsiUtil.isAccessedForWriting((PsiExpression) element)) return false;
   }
   return true;
 }
 @Override
 public boolean process(PsiReference reference) {
   final PsiElement element = reference.getElement();
   if (element instanceof PsiReferenceExpression
       && PsiUtil.isAccessedForWriting((PsiExpression) element)) {
     myIsWriteRefFound = true;
     return false;
   }
   return true;
 }
 private static boolean notAccessedForWriting(
     @NotNull PsiVariable variable, @NotNull LocalSearchScope searchScope) {
   for (PsiReference reference : ReferencesSearch.search(variable, searchScope)) {
     final PsiElement element = reference.getElement();
     if (element instanceof PsiExpression
         && PsiUtil.isAccessedForWriting((PsiExpression) element)) {
       return false;
     }
   }
   return true;
 }
Пример #6
0
  public static PsiType normalizeWildcardTypeByPosition(
      @NotNull PsiType type, @NotNull PsiExpression expression) {
    PsiExpression toplevel = expression;
    while (toplevel.getParent() instanceof PsiArrayAccessExpression
        && ((PsiArrayAccessExpression) toplevel.getParent()).getArrayExpression() == toplevel) {
      toplevel = (PsiExpression) toplevel.getParent();
    }

    final PsiType normalized = doNormalizeWildcardByPosition(type, expression, toplevel);
    if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(toplevel)) {
      return PsiUtil.captureToplevelWildcards(normalized, expression);
    }

    return normalized;
  }
Пример #7
0
  /** Types should be proceed by the callers themselves */
  @Deprecated
  public static PsiType normalizeWildcardTypeByPosition(
      @NotNull PsiType type, @NotNull PsiExpression expression) {
    PsiUtilCore.ensureValid(expression);
    PsiUtil.ensureValidType(type);

    PsiExpression topLevel = expression;
    while (topLevel.getParent() instanceof PsiArrayAccessExpression
        && ((PsiArrayAccessExpression) topLevel.getParent()).getArrayExpression() == topLevel) {
      topLevel = (PsiExpression) topLevel.getParent();
    }

    if (topLevel instanceof PsiArrayAccessExpression && !PsiUtil.isAccessedForWriting(topLevel)) {
      return PsiUtil.captureToplevelWildcards(type, expression);
    }

    final PsiType normalized = doNormalizeWildcardByPosition(type, expression, topLevel);
    LOG.assertTrue(normalized.isValid(), type);
    if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(topLevel)) {
      return PsiUtil.captureToplevelWildcards(normalized, expression);
    }

    return normalized;
  }
Пример #8
0
 public boolean isReferencedForWrite(@NotNull PsiVariable variable) {
   List<PsiReference> array;
   synchronized (myLocalRefsMap) {
     array = myLocalRefsMap.getKeysByValue(variable);
   }
   if (array == null) return false;
   for (PsiReference ref : array) {
     final PsiElement refElement = ref.getElement();
     if (!(refElement instanceof PsiExpression)) { // possible with incomplete code
       return true;
     }
     if (PsiUtil.isAccessedForWriting((PsiExpression) refElement)) {
       return true;
     }
   }
   return false;
 }
  @Nullable
  public EncapsulateFieldUsageInfo createUsage(
      @NotNull EncapsulateFieldsDescriptor descriptor,
      @NotNull FieldDescriptor fieldDescriptor,
      @NotNull PsiReference reference) {
    if (!(reference instanceof PsiReferenceExpression)) return null;

    boolean findSet = descriptor.isToEncapsulateSet();
    boolean findGet = descriptor.isToEncapsulateGet();
    PsiReferenceExpression ref = (PsiReferenceExpression) reference;
    // [Jeka] to avoid recursion in the field's accessors
    if (findGet
        && isUsedInExistingAccessor(
            descriptor.getTargetClass(), fieldDescriptor.getGetterPrototype(), ref)) return null;
    if (findSet
        && isUsedInExistingAccessor(
            descriptor.getTargetClass(), fieldDescriptor.getSetterPrototype(), ref)) return null;
    if (!findGet) {
      if (!PsiUtil.isAccessedForWriting(ref)) return null;
    }
    if (!findSet || fieldDescriptor.getField().hasModifierProperty(PsiModifier.FINAL)) {
      if (!PsiUtil.isAccessedForReading(ref)) return null;
    }
    if (!descriptor.isToUseAccessorsWhenAccessible()) {
      PsiModifierList newModifierList = createNewModifierList(descriptor);

      PsiClass accessObjectClass = null;
      PsiExpression qualifier = ref.getQualifierExpression();
      if (qualifier != null) {
        accessObjectClass = (PsiClass) PsiUtil.getAccessObjectClass(qualifier).getElement();
      }
      final PsiResolveHelper helper =
          JavaPsiFacade.getInstance(((PsiReferenceExpression) reference).getProject())
              .getResolveHelper();
      if (helper.isAccessible(
          fieldDescriptor.getField(), newModifierList, ref, accessObjectClass, null)) {
        return null;
      }
    }
    return new EncapsulateFieldUsageInfo(ref, fieldDescriptor);
  }
 private static boolean canBeFinal(PsiVariable variable, List<PsiReferenceExpression> references) {
   // if there is at least one assignment to this variable, it cannot be final
   Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems =
       new THashMap<PsiElement, Collection<PsiReferenceExpression>>();
   Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems =
       new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>();
   for (PsiReferenceExpression expression : references) {
     if (ControlFlowUtil.isVariableAssignedInLoop(expression, variable)) return false;
     HighlightInfo highlightInfo =
         HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(
             expression, variable, uninitializedVarProblems);
     if (highlightInfo != null) return false;
     highlightInfo =
         HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(
             variable, expression, finalVarProblems);
     if (highlightInfo != null) return false;
     if (variable instanceof PsiParameter && PsiUtil.isAccessedForWriting(expression))
       return false;
   }
   return true;
 }
  @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);
  }
Пример #12
0
 IntroduceParameterDialog(
     @NotNull Project project,
     @NotNull List<UsageInfo> classMembersList,
     PsiExpression[] occurences,
     PsiLocalVariable onLocalVariable,
     PsiExpression onExpression,
     @NotNull NameSuggestionsGenerator generator,
     @NotNull TypeSelectorManager typeSelectorManager,
     @NotNull PsiMethod methodToSearchFor,
     @NotNull PsiMethod methodToReplaceIn,
     @NotNull TIntArrayList parametersToRemove,
     final boolean mustBeFinal) {
   super(project, true);
   myPanel =
       new IntroduceParameterSettingsPanel(
           onLocalVariable, onExpression, methodToReplaceIn, parametersToRemove);
   myProject = project;
   myClassMembersList = classMembersList;
   myOccurenceNumber = occurences.length;
   for (PsiExpression occurence : occurences) {
     if (PsiUtil.isAccessedForWriting(occurence)) {
       myHasWriteAccess = true;
       break;
     }
   }
   myExpression = onExpression;
   myLocalVar = onLocalVariable;
   myMethodToReplaceIn = methodToReplaceIn;
   myMustBeFinal = mustBeFinal;
   myMethodToSearchFor = methodToSearchFor;
   myNameSuggestionsGenerator = generator;
   myTypeSelectorManager = typeSelectorManager;
   setTitle(REFACTORING_NAME);
   init();
   myPanel.updateTypeSelector();
 }
  @Nullable
  public static HighlightInfo checkFinalVariableMightAlreadyHaveBeenAssignedTo(
      @NotNull PsiVariable variable,
      @NotNull PsiReferenceExpression expression,
      @NotNull Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems) {
    if (!PsiUtil.isAccessedForWriting(expression)) return null;

    final PsiElement scope =
        variable instanceof PsiField
            ? variable.getParent()
            : variable.getParent() == null ? null : variable.getParent().getParent();
    PsiElement codeBlock = PsiUtil.getTopLevelEnclosingCodeBlock(expression, scope);
    if (codeBlock == null) return null;
    Collection<ControlFlowUtil.VariableInfo> codeBlockProblems =
        getFinalVariableProblemsInBlock(finalVarProblems, codeBlock);

    boolean alreadyAssigned = false;
    for (ControlFlowUtil.VariableInfo variableInfo : codeBlockProblems) {
      if (variableInfo.expression == expression) {
        alreadyAssigned = true;
        break;
      }
    }

    if (!alreadyAssigned) {
      if (!(variable instanceof PsiField)) return null;
      final PsiField field = (PsiField) variable;
      final PsiClass aClass = field.getContainingClass();
      if (aClass == null) return null;
      // field can get assigned in other field initializers
      final PsiField[] fields = aClass.getFields();
      boolean isFieldStatic = field.hasModifierProperty(PsiModifier.STATIC);
      for (PsiField psiField : fields) {
        PsiExpression initializer = psiField.getInitializer();
        if (psiField != field
            && psiField.hasModifierProperty(PsiModifier.STATIC) == isFieldStatic
            && initializer != null
            && initializer != codeBlock
            && !variableDefinitelyNotAssignedIn(field, initializer)) {
          alreadyAssigned = true;
          break;
        }
      }

      if (!alreadyAssigned) {
        // field can get assigned in class initializers
        final PsiMember enclosingConstructorOrInitializer =
            PsiUtil.findEnclosingConstructorOrInitializer(expression);
        if (enclosingConstructorOrInitializer == null
            || !aClass
                .getManager()
                .areElementsEquivalent(
                    enclosingConstructorOrInitializer.getContainingClass(), aClass)) {
          return null;
        }
        final PsiClassInitializer[] initializers = aClass.getInitializers();
        for (PsiClassInitializer initializer : initializers) {
          if (initializer.hasModifierProperty(PsiModifier.STATIC)
              == field.hasModifierProperty(PsiModifier.STATIC)) {
            final PsiCodeBlock body = initializer.getBody();
            if (body == codeBlock) return null;
            try {
              final ControlFlow controlFlow = getControlFlow(body);
              if (!ControlFlowUtil.isVariableDefinitelyNotAssigned(field, controlFlow)) {
                alreadyAssigned = true;
                break;
              }
            } catch (AnalysisCanceledException e) {
              // incomplete code
              return null;
            }
          }
        }
      }

      if (!alreadyAssigned && !field.hasModifierProperty(PsiModifier.STATIC)) {
        // then check if instance field already assigned in other constructor
        final PsiMethod ctr =
            codeBlock.getParent() instanceof PsiMethod ? (PsiMethod) codeBlock.getParent() : null;
        // assignment to final field in several constructors threatens us only if these are linked
        // (there is this() call in the beginning)
        final List<PsiMethod> redirectedConstructors =
            ctr != null && ctr.isConstructor()
                ? JavaHighlightUtil.getChainedConstructors(ctr)
                : null;
        for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
          PsiMethod redirectedConstructor = redirectedConstructors.get(j);
          PsiCodeBlock body = redirectedConstructor.getBody();
          if (body != null && variableDefinitelyAssignedIn(variable, body)) {
            alreadyAssigned = true;
            break;
          }
        }
      }
    }

    if (alreadyAssigned) {
      String description =
          JavaErrorMessages.message("variable.already.assigned", variable.getName());
      final HighlightInfo highlightInfo =
          HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
              .range(expression)
              .descriptionAndTooltip(description)
              .create();
      QuickFixAction.registerQuickFixAction(
          highlightInfo,
          QUICK_FIX_FACTORY.createModifierListFix(variable, PsiModifier.FINAL, false, false));
      QuickFixAction.registerQuickFixAction(
          highlightInfo, QUICK_FIX_FACTORY.createDeferFinalAssignmentFix(variable, expression));
      return highlightInfo;
    }

    return null;
  }
 @Override
 public void visitReferenceExpression(PsiReferenceExpression expression) {
   if (myWritten && myRead) {
     return;
   }
   super.visitReferenceExpression(expression);
   final PsiElement target = expression.resolve();
   if (target != myVariable) {
     return;
   }
   if (PsiUtil.isAccessedForWriting(expression)) {
     final PsiElement parent =
         PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
     if (parent instanceof PsiAssignmentExpression) {
       final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) parent;
       final PsiExpression rhs = assignmentExpression.getRExpression();
       if (isComplexArrayExpression(rhs)) {
         myWritten = true;
         myRead = true;
       } else if (!isSimpleArrayExpression(rhs)) {
         myWritten = true;
       }
     }
     return;
   }
   myIsReferenced = true;
   PsiElement parent = getParent(expression);
   if (parent instanceof PsiArrayAccessExpression) {
     PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression) parent;
     parent = getParent(parent);
     while (parent instanceof PsiArrayAccessExpression) {
       arrayAccessExpression = (PsiArrayAccessExpression) parent;
       parent = getParent(parent);
     }
     final PsiType type = arrayAccessExpression.getType();
     if (type != null) {
       final int dimensions = type.getArrayDimensions();
       if (dimensions > 0 && dimensions != myVariable.getType().getArrayDimensions()) {
         myWritten = true;
       }
     }
     if (PsiUtil.isAccessedForWriting(arrayAccessExpression)) {
       myWritten = true;
     }
     if (PsiUtil.isAccessedForReading(arrayAccessExpression)) {
       myRead = true;
     }
   } else if (parent instanceof PsiReferenceExpression) {
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) parent;
     final String name = referenceExpression.getReferenceName();
     if ("length".equals(name)
         || ("clone".equals(name)
             && referenceExpression.getParent() instanceof PsiMethodCallExpression)) {
       myRead = true;
     }
   } else if (parent instanceof PsiForeachStatement) {
     final PsiForeachStatement foreachStatement = (PsiForeachStatement) parent;
     final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
     if (PsiTreeUtil.isAncestor(iteratedValue, expression, false)) {
       myRead = true;
     }
   } else if (parent instanceof PsiExpressionList) {
     final PsiExpressionList expressionList = (PsiExpressionList) parent;
     parent = parent.getParent();
     if (parent instanceof PsiMethodCallExpression) {
       final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) parent;
       final PsiMethod method = methodCallExpression.resolveMethod();
       if (method != null) {
         final PsiClass aClass = method.getContainingClass();
         if (aClass != null) {
           final String methodName = method.getName();
           final String qualifiedName = aClass.getQualifiedName();
           if ("java.lang.System".equals(qualifiedName)) {
             if ("arraycopy".equals(methodName)) {
               final PsiExpression[] expressions = expressionList.getExpressions();
               if (expressions.length == 5) {
                 if (PsiTreeUtil.isAncestor(expressions[0], expression, false)) {
                   myRead = true;
                   return;
                 } else if (PsiTreeUtil.isAncestor(expressions[2], expression, false)) {
                   myWritten = true;
                   return;
                 }
               }
             }
           } else if (CommonClassNames.JAVA_UTIL_ARRAYS.equals(qualifiedName)) {
             if ("fill".equals(methodName)
                 || "parallelPrefix".equals(methodName)
                 || "parallelSetAll".equals(methodName)
                 || "parallelSort".equals(methodName)
                 || "setAll".equals(methodName)
                 || "sort".equals(methodName)) {
               myWritten = true;
             } else {
               myRead = true;
             }
             return;
           }
         }
       }
     }
     myRead = true;
     myWritten = true;
   } else {
     myWritten = true;
     myRead = true;
   }
 }
  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);
  }