public static boolean isAvailable(
     @Nullable PsiParameter myParameter, @Nullable PsiType type, @Nullable PsiClass targetClass) {
   return myParameter != null
       && myParameter.isValid()
       && myParameter.getManager().isInProject(myParameter)
       && myParameter.getDeclarationScope() instanceof PsiMethod
       && ((PsiMethod) myParameter.getDeclarationScope()).getBody() != null
       && type != null
       && type.isValid()
       && targetClass != null
       && !targetClass.isInterface()
       && getParameterAssignedToField(myParameter) == null;
 }
示例#2
0
  private static boolean isParameterUsedRecursively(
      @NotNull PsiElement element, @NotNull List<PsiReference> array) {
    if (!(element instanceof PsiParameter)) return false;
    PsiParameter parameter = (PsiParameter) element;
    PsiElement scope = parameter.getDeclarationScope();
    if (!(scope instanceof PsiMethod)) return false;
    PsiMethod method = (PsiMethod) scope;
    int paramIndex = ArrayUtilRt.find(method.getParameterList().getParameters(), parameter);

    for (PsiReference reference : array) {
      if (!(reference instanceof PsiElement)) return false;
      PsiElement argument = (PsiElement) reference;

      PsiMethodCallExpression methodCallExpression =
          (PsiMethodCallExpression)
              new PsiMatcherImpl(argument)
                  .dot(PsiMatchers.hasClass(PsiReferenceExpression.class))
                  .parent(PsiMatchers.hasClass(PsiExpressionList.class))
                  .parent(PsiMatchers.hasClass(PsiMethodCallExpression.class))
                  .getElement();
      if (methodCallExpression == null) return false;
      PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
      if (method != methodExpression.resolve()) return false;
      PsiExpressionList argumentList = methodCallExpression.getArgumentList();
      PsiExpression[] arguments = argumentList.getExpressions();
      int argumentIndex = ArrayUtilRt.find(arguments, argument);
      if (paramIndex != argumentIndex) return false;
    }

    return true;
  }
  private static void checkMagicParameterArgument(
      @NotNull PsiParameter parameter,
      PsiExpression argument,
      @NotNull AllowedValues allowedValues,
      @NotNull ProblemsHolder holder) {
    final PsiManager manager = PsiManager.getInstance(holder.getProject());

    if (!argument.getTextRange().isEmpty()
        && !isAllowed(parameter.getDeclarationScope(), argument, allowedValues, manager)) {
      registerProblem(argument, allowedValues, holder);
    }
  }
示例#4
0
 public static boolean isOverrideOfLibraryMethodParameter(@Nullable PsiVariable variable) {
   if (!(variable instanceof PsiParameter)) {
     return false;
   }
   final PsiParameter parameter = (PsiParameter) variable;
   final PsiElement scope = parameter.getDeclarationScope();
   if (!(scope instanceof PsiMethod)) {
     return false;
   }
   final PsiMethod method = (PsiMethod) scope;
   return isOverrideOfLibraryMethod(method);
 }
 private static PsiAnnotation[] getHierarchyAnnotations(
     PsiModifierListOwner listOwner, PsiModifierList modifierList) {
   final Set<PsiAnnotation> all =
       new HashSet<PsiAnnotation>() {
         public boolean add(PsiAnnotation o) {
           // don't overwrite "higher level" annotations
           return !contains(o) && super.add(o);
         }
       };
   if (listOwner instanceof PsiMethod) {
     ContainerUtil.addAll(all, modifierList.getAnnotations());
     SuperMethodsSearch.search((PsiMethod) listOwner, null, true, true)
         .forEach(
             new Processor<MethodSignatureBackedByPsiMethod>() {
               public boolean process(final MethodSignatureBackedByPsiMethod superMethod) {
                 ContainerUtil.addAll(
                     all, superMethod.getMethod().getModifierList().getAnnotations());
                 return true;
               }
             });
     return all.toArray(new PsiAnnotation[all.size()]);
   }
   if (listOwner instanceof PsiParameter) {
     PsiParameter parameter = (PsiParameter) listOwner;
     PsiElement declarationScope = parameter.getDeclarationScope();
     PsiParameterList parameterList;
     if (declarationScope instanceof PsiMethod
         && parameter.getParent()
             == (parameterList = ((PsiMethod) declarationScope).getParameterList())) {
       PsiMethod method = (PsiMethod) declarationScope;
       final int parameterIndex = parameterList.getParameterIndex(parameter);
       ContainerUtil.addAll(all, modifierList.getAnnotations());
       SuperMethodsSearch.search(method, null, true, true)
           .forEach(
               new Processor<MethodSignatureBackedByPsiMethod>() {
                 public boolean process(final MethodSignatureBackedByPsiMethod superMethod) {
                   PsiParameter superParameter =
                       superMethod.getMethod().getParameterList().getParameters()[parameterIndex];
                   PsiModifierList modifierList = superParameter.getModifierList();
                   if (modifierList != null) {
                     ContainerUtil.addAll(all, modifierList.getAnnotations());
                   }
                   return true;
                 }
               });
       return all.toArray(new PsiAnnotation[all.size()]);
     }
   }
   return modifierList.getAnnotations();
 }
  @Nullable
  public static PsiType getSubstitutedType(@Nullable PsiParameter parameter) {
    if (parameter == null) return null;

    final PsiType type = getType(parameter);

    if (type instanceof PsiArrayType) {
      return type;
    }

    final PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type);
    final PsiClass psiClass = result.getElement();
    if (psiClass == null) return type;

    final Set<PsiTypeParameter> usedTypeParameters = new HashSet<PsiTypeParameter>();
    RefactoringUtil.collectTypeParameters(usedTypeParameters, parameter);
    for (Iterator<PsiTypeParameter> iterator = usedTypeParameters.iterator();
        iterator.hasNext(); ) {
      PsiTypeParameter usedTypeParameter = iterator.next();
      if (parameter.getDeclarationScope() != usedTypeParameter.getOwner()) {
        iterator.remove();
      }
    }

    PsiSubstitutor subst = PsiSubstitutor.EMPTY;
    for (PsiTypeParameter usedTypeParameter : usedTypeParameters) {
      subst =
          subst.put(usedTypeParameter, TypeConversionUtil.typeParameterErasure(usedTypeParameter));
    }

    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    final Map<PsiTypeParameter, PsiType> typeMap = result.getSubstitutor().getSubstitutionMap();
    for (PsiTypeParameter typeParameter : typeMap.keySet()) {
      final PsiType psiType = typeMap.get(typeParameter);
      substitutor =
          substitutor.put(typeParameter, psiType != null ? subst.substitute(psiType) : null);
    }

    if (psiClass instanceof PsiTypeParameter) {
      return subst.substitute((PsiTypeParameter) psiClass);
    } else {
      return JavaPsiFacade.getElementFactory(parameter.getProject())
          .createType(psiClass, substitutor);
    }
  }
 private static PsiElement[] getParameterElementsToSearch(final PsiParameter parameter) {
   final PsiMethod method = (PsiMethod) parameter.getDeclarationScope();
   PsiMethod[] overrides =
       OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY);
   for (int i = 0; i < overrides.length; i++) {
     overrides[i] = (PsiMethod) overrides[i].getNavigationElement();
   }
   List<PsiElement> elementsToSearch = new ArrayList<PsiElement>(overrides.length + 1);
   elementsToSearch.add(parameter);
   int idx = method.getParameterList().getParameterIndex(parameter);
   for (PsiMethod override : overrides) {
     final PsiParameter[] parameters = override.getParameterList().getParameters();
     if (idx < parameters.length) {
       elementsToSearch.add(parameters[idx]);
     }
   }
   return elementsToSearch.toArray(new PsiElement[elementsToSearch.size()]);
 }
 @Nullable
 public static PsiField getParameterAssignedToField(final PsiParameter parameter) {
   for (PsiReference reference :
       ReferencesSearch.search(
           parameter, new LocalSearchScope(parameter.getDeclarationScope()), false)) {
     if (!(reference instanceof PsiReferenceExpression)) continue;
     final PsiReferenceExpression expression = (PsiReferenceExpression) reference;
     if (!(expression.getParent() instanceof PsiAssignmentExpression)) continue;
     final PsiAssignmentExpression assignmentExpression =
         (PsiAssignmentExpression) expression.getParent();
     if (assignmentExpression.getRExpression() != expression) continue;
     final PsiExpression lExpression = assignmentExpression.getLExpression();
     if (!(lExpression instanceof PsiReferenceExpression)) continue;
     final PsiElement element = ((PsiReferenceExpression) lExpression).resolve();
     if (element instanceof PsiField) return (PsiField) element;
   }
   return null;
 }
  @Override
  @NotNull
  public PsiElement[] getPrimaryElements() {
    final PsiElement element = getPsiElement();
    if (element instanceof PsiParameter) {
      final PsiParameter parameter = (PsiParameter) element;
      final PsiElement scope = parameter.getDeclarationScope();
      if (scope instanceof PsiMethod) {
        final PsiMethod method = (PsiMethod) scope;
        if (PsiUtil.canBeOverriden(method)) {
          final PsiClass aClass = method.getContainingClass();
          LOG.assertTrue(aClass != null); // Otherwise can not be overriden

          boolean hasOverridden = OverridingMethodsSearch.search(method).findFirst() != null;
          if (hasOverridden
              && askWhetherShouldSearchForParameterInOverridingMethods(element, parameter)) {
            return getParameterElementsToSearch(parameter);
          }
        }
      }
    }
    return myElementsToSearch.length == 0 ? new PsiElement[] {element} : myElementsToSearch;
  }
  private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) {
    PsiMethod method = null;
    if (owner instanceof PsiParameter) {
      PsiParameter parameter = (PsiParameter) owner;
      PsiElement scope = parameter.getDeclarationScope();
      if (!(scope instanceof PsiMethod)) return null;
      PsiElement nav = scope.getNavigationElement();
      if (!(nav instanceof PsiMethod)) return null;
      method = (PsiMethod) nav;
      if (method.isConstructor()) {
        // not a property, try the @ConstructorProperties({"prop"})
        PsiAnnotation annotation =
            AnnotationUtil.findAnnotation(method, "java.beans.ConstructorProperties");
        if (annotation == null) return null;
        PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
        if (!(value instanceof PsiArrayInitializerMemberValue)) return null;
        PsiAnnotationMemberValue[] initializers =
            ((PsiArrayInitializerMemberValue) value).getInitializers();
        PsiElement parent = parameter.getParent();
        if (!(parent instanceof PsiParameterList)) return null;
        int index = ((PsiParameterList) parent).getParameterIndex(parameter);
        if (index >= initializers.length) return null;
        PsiAnnotationMemberValue initializer = initializers[index];
        if (!(initializer instanceof PsiLiteralExpression)) return null;
        Object val = ((PsiLiteralExpression) initializer).getValue();
        if (!(val instanceof String)) return null;
        PsiMethod setter =
            PropertyUtil.findPropertySetter(
                method.getContainingClass(), (String) val, false, false);
        if (setter == null) return null;
        // try the @beaninfo of the corresponding setter
        method = (PsiMethod) setter.getNavigationElement();
      }
    } else if (owner instanceof PsiMethod) {
      PsiElement nav = owner.getNavigationElement();
      if (!(nav instanceof PsiMethod)) return null;
      method = (PsiMethod) nav;
    }
    if (method == null) return null;

    PsiClass aClass = method.getContainingClass();
    if (aClass == null) return null;
    if (PropertyUtil.isSimplePropertyGetter(method)) {
      List<PsiMethod> setters =
          PropertyUtil.getSetters(aClass, PropertyUtil.getPropertyNameByGetter(method));
      if (setters.size() != 1) return null;
      method = setters.get(0);
    }
    if (!PropertyUtil.isSimplePropertySetter(method)) return null;
    PsiDocComment doc = method.getDocComment();
    if (doc == null) return null;
    PsiDocTag beaninfo = doc.findTagByName("beaninfo");
    if (beaninfo == null) return null;
    String data =
        StringUtil.join(
            beaninfo.getDataElements(),
            new Function<PsiElement, String>() {
              @Override
              public String fun(PsiElement element) {
                return element.getText();
              }
            },
            "\n");
    int enumIndex = StringUtil.indexOfSubstringEnd(data, "enum:");
    if (enumIndex == -1) return null;
    data = data.substring(enumIndex);
    int colon = data.indexOf(":");
    int last = colon == -1 ? data.length() : data.substring(0, colon).lastIndexOf("\n");
    data = data.substring(0, last);

    List<PsiAnnotationMemberValue> values = new ArrayList<PsiAnnotationMemberValue>();
    for (String line : StringUtil.splitByLines(data)) {
      List<String> words = StringUtil.split(line, " ", true, true);
      if (words.size() != 2) continue;
      String ref = words.get(1);
      PsiExpression constRef =
          JavaPsiFacade.getElementFactory(aClass.getProject())
              .createExpressionFromText(ref, aClass);
      if (!(constRef instanceof PsiReferenceExpression)) continue;
      PsiReferenceExpression expr = (PsiReferenceExpression) constRef;
      values.add(expr);
    }
    if (values.isEmpty()) return null;
    PsiAnnotationMemberValue[] array = values.toArray(new PsiAnnotationMemberValue[values.size()]);
    return new AllowedValues(array, false);
  }
  private void findUsagesForMethod(
      PsiMethod overridingMethod, List<FixableUsageInfo> usages, boolean changeSignature) {
    final PsiCodeBlock body = overridingMethod.getBody();
    final String baseParameterName = StringUtil.decapitalize(className);
    final String fixedParamName =
        body != null
            ? JavaCodeStyleManager.getInstance(myProject)
                .suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
            : JavaCodeStyleManager.getInstance(myProject)
                .propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);

    usages.add(
        new MergeMethodArguments(
            overridingMethod,
            className,
            packageName,
            fixedParamName,
            paramsToMerge,
            typeParams,
            keepMethodAsDelegate,
            myCreateInnerClass ? method.getContainingClass() : null,
            changeSignature));

    final ParamUsageVisitor visitor = new ParamUsageVisitor(overridingMethod, paramsToMerge);
    overridingMethod.accept(visitor);
    final Set<PsiReferenceExpression> values = visitor.getParameterUsages();
    for (PsiReferenceExpression paramUsage : values) {
      final PsiParameter parameter = (PsiParameter) paramUsage.resolve();
      assert parameter != null;
      final PsiMethod containingMethod = (PsiMethod) parameter.getDeclarationScope();
      final int index = containingMethod.getParameterList().getParameterIndex(parameter);
      final PsiParameter replacedParameter = method.getParameterList().getParameters()[index];
      final ParameterChunk parameterChunk =
          ParameterChunk.getChunkByParameter(parameter, parameters);

      @NonNls String getter = parameterChunk != null ? parameterChunk.getter : null;
      final String paramName =
          parameterChunk != null ? parameterChunk.parameter.name : replacedParameter.getName();
      final PsiType paramType =
          parameterChunk != null ? parameterChunk.parameter.type : replacedParameter.getType();
      if (getter == null) {
        getter = GenerateMembersUtil.suggestGetterName(paramName, paramType, myProject);
        paramsNeedingGetters.add(replacedParameter);
      }
      @NonNls String setter = parameterChunk != null ? parameterChunk.setter : null;
      if (setter == null) {
        setter = GenerateMembersUtil.suggestSetterName(paramName, paramType, myProject);
      }
      if (RefactoringUtil.isPlusPlusOrMinusMinus(paramUsage.getParent())) {
        usages.add(
            new ReplaceParameterIncrementDecrement(paramUsage, fixedParamName, setter, getter));
        if (parameterChunk == null || parameterChunk.setter == null) {
          paramsNeedingSetters.add(replacedParameter);
        }
      } else if (RefactoringUtil.isAssignmentLHS(paramUsage)) {
        usages.add(
            new ReplaceParameterAssignmentWithCall(paramUsage, fixedParamName, setter, getter));
        if (parameterChunk == null || parameterChunk.setter == null) {
          paramsNeedingSetters.add(replacedParameter);
        }
      } else {
        usages.add(new ReplaceParameterReferenceWithCall(paramUsage, fixedParamName, getter));
      }
    }
  }
 public static boolean isAssigned(@NotNull PsiParameter parameter) {
   ParamWriteProcessor processor = new ParamWriteProcessor();
   ReferencesSearch.search(parameter, new LocalSearchScope(parameter.getDeclarationScope()), true)
       .forEach(processor);
   return processor.isWriteRefFound();
 }
  private static void findParameterUsages(
      final PsiParameter parameter, final List<UsageInfo> usages) {
    final PsiMethod method = (PsiMethod) parameter.getDeclarationScope();
    final int parameterIndex = method.getParameterList().getParameterIndex(parameter);
    // search for refs to current method only, do not search for refs to overriding methods, they'll
    // be searched separately
    ReferencesSearch.search(method)
        .forEach(
            reference -> {
              PsiElement element = reference.getElement();
              if (element != null) {
                final JavaSafeDeleteDelegate safeDeleteDelegate =
                    JavaSafeDeleteDelegate.EP.forLanguage(element.getLanguage());
                if (safeDeleteDelegate != null) {
                  safeDeleteDelegate.createUsageInfoForParameter(
                      reference, usages, parameter, method);
                }
                if (!parameter.isVarArgs()
                    && !RefactoringChangeUtil.isSuperMethodCall(element.getParent())) {
                  final PsiParameter paramInCaller =
                      SafeDeleteJavaCallerChooser.isTheOnlyOneParameterUsage(
                          element.getParent(), parameterIndex, method);
                  if (paramInCaller != null) {
                    final PsiMethod callerMethod = (PsiMethod) paramInCaller.getDeclarationScope();
                    if (ApplicationManager.getApplication().isUnitTestMode()) {
                      usages.add(
                          new SafeDeleteParameterCallHierarchyUsageInfo(
                              callerMethod, paramInCaller, callerMethod));
                    } else {
                      usages.add(
                          new SafeDeleteParameterCallHierarchyUsageInfo(
                              method, parameter, callerMethod));
                    }
                  }
                }
              }
              return true;
            });

    ReferencesSearch.search(parameter)
        .forEach(
            reference -> {
              PsiElement element = reference.getElement();
              final PsiDocTag docTag = PsiTreeUtil.getParentOfType(element, PsiDocTag.class);
              if (docTag != null) {
                usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(docTag, parameter, true));
                return true;
              }

              boolean isSafeDelete = false;
              if (element.getParent().getParent() instanceof PsiMethodCallExpression) {
                PsiMethodCallExpression call =
                    (PsiMethodCallExpression) element.getParent().getParent();
                PsiReferenceExpression methodExpression = call.getMethodExpression();
                if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
                  isSafeDelete = true;
                } else if (methodExpression.getQualifierExpression()
                    instanceof PsiSuperExpression) {
                  final PsiMethod superMethod = call.resolveMethod();
                  if (superMethod != null
                      && MethodSignatureUtil.isSuperMethod(superMethod, method)) {
                    isSafeDelete = true;
                  }
                }
              }

              usages.add(
                  new SafeDeleteReferenceJavaDeleteUsageInfo(element, parameter, isSafeDelete));
              return true;
            });

    findFunctionalExpressions(usages, method);
  }
 @Override
 public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
   final PsiReferenceExpression parameterReference =
       (PsiReferenceExpression) descriptor.getPsiElement();
   final PsiElement target = parameterReference.resolve();
   if (!(target instanceof PsiParameter)) {
     return;
   }
   final PsiParameter parameter = (PsiParameter) target;
   final PsiElement declarationScope = parameter.getDeclarationScope();
   final PsiElement body;
   if (declarationScope instanceof PsiMethod) {
     final PsiMethod method = (PsiMethod) declarationScope;
     body = method.getBody();
   } else if (declarationScope instanceof PsiCatchSection) {
     final PsiCatchSection catchSection = (PsiCatchSection) declarationScope;
     body = catchSection.getCatchBlock();
   } else if (declarationScope instanceof PsiLoopStatement) {
     final PsiLoopStatement forStatement = (PsiLoopStatement) declarationScope;
     final PsiStatement forBody = forStatement.getBody();
     if (forBody instanceof PsiBlockStatement) {
       final PsiBlockStatement blockStatement = (PsiBlockStatement) forBody;
       body = blockStatement.getCodeBlock();
     } else {
       body = forBody;
     }
   } else {
     return;
   }
   if (body == null) {
     return;
   }
   final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
   final String parameterName = parameterReference.getText();
   final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
   final String variableName =
       javaCodeStyleManager.suggestUniqueVariableName(parameterName, parameterReference, true);
   final SearchScope scope = parameter.getUseScope();
   final Query<PsiReference> search = ReferencesSearch.search(parameter, scope);
   final PsiReference reference = search.findFirst();
   if (reference == null) {
     return;
   }
   final PsiElement element = reference.getElement();
   if (!(element instanceof PsiReferenceExpression)) {
     return;
   }
   final PsiReferenceExpression firstReference = (PsiReferenceExpression) element;
   final PsiElement[] children = body.getChildren();
   final int startIndex;
   final int endIndex;
   if (body instanceof PsiCodeBlock) {
     startIndex = 1;
     endIndex = children.length - 1;
   } else {
     startIndex = 0;
     endIndex = children.length;
   }
   boolean newDeclarationCreated = false;
   final StringBuilder buffer = new StringBuilder();
   for (int i = startIndex; i < endIndex; i++) {
     final PsiElement child = children[i];
     newDeclarationCreated |=
         replaceVariableName(child, firstReference, variableName, parameterName, buffer);
   }
   final String replacementText;
   if (newDeclarationCreated) {
     replacementText = "{" + buffer + '}';
   } else {
     final PsiType type = parameterReference.getType();
     if (type == null) {
       return;
     }
     final String className = type.getCanonicalText();
     replacementText =
         '{' + className + ' ' + variableName + " = " + parameterName + ';' + buffer + '}';
   }
   final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
   final PsiCodeBlock block = elementFactory.createCodeBlockFromText(replacementText, null);
   body.replace(block);
   codeStyleManager.reformat(declarationScope);
 }