@Override public boolean execute(@NotNull final SuperMethodsSearch.SearchParameters queryParameters, @NotNull final Processor<MethodSignatureBackedByPsiMethod> consumer) { final PsiClass parentClass = queryParameters.getPsiClass(); final PsiMethod method = queryParameters.getMethod(); return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @Override public Boolean compute() { HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature(); final boolean checkBases = queryParameters.isCheckBases(); final boolean allowStaticMethod = queryParameters.isAllowStaticMethod(); final List<HierarchicalMethodSignature> supers = signature.getSuperSignatures(); for (HierarchicalMethodSignature superSignature : supers) { if (MethodSignatureUtil.isSubsignature(superSignature, signature)) { if (!addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer)) return false; } } return true; } }); }
private static boolean addSuperMethods(final HierarchicalMethodSignature signature, final PsiMethod method, final PsiClass parentClass, final boolean allowStaticMethod, final boolean checkBases, final Processor<MethodSignatureBackedByPsiMethod> consumer) { PsiMethod signatureMethod = signature.getMethod(); PsiClass hisClass = signatureMethod.getContainingClass(); if (parentClass == null || InheritanceUtil.isInheritorOrSelf(parentClass, hisClass, true)) { if (isAcceptable(signatureMethod, method, allowStaticMethod)) { if (parentClass != null && !parentClass.equals(hisClass) && !checkBases) { return true; } LOG.assertTrue(signatureMethod != method, method); // method != method.getsuper() return consumer.process(signature); //no need to check super classes } } for (HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) { if (MethodSignatureUtil.isSubsignature(superSignature, signature)) { addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer); } } return true; }
public PsiMethodPattern definedInClass(final ElementPattern<? extends PsiClass> pattern) { return with(new PatternConditionPlus<PsiMethod, PsiClass>("definedInClass", pattern) { @Override public boolean processValues(PsiMethod t, final ProcessingContext context, final PairProcessor<PsiClass, ProcessingContext> processor) { if (!processor.process(t.getContainingClass(), context)) return false; final Ref<Boolean> result = Ref.create(Boolean.TRUE); SuperMethodsSearch.search(t, null, true, false).forEach(new Processor<MethodSignatureBackedByPsiMethod>() { @Override public boolean process(final MethodSignatureBackedByPsiMethod signature) { if (!processor.process(signature.getMethod().getContainingClass(), context)) { result.set(Boolean.FALSE); return false; } return true; } }); return result.get(); } }); }
static void checkMethodOverridesDeprecated(MethodSignatureBackedByPsiMethod methodSignature, List<MethodSignatureBackedByPsiMethod> superMethodSignatures, boolean ignoreAbstractDeprecatedOverrides, ProblemsHolder holder) { PsiMethod method = methodSignature.getMethod(); PsiElement methodName = method.getNameIdentifier(); for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) { PsiMethod superMethod = superMethodSignature.getMethod(); PsiClass aClass = superMethod.getContainingClass(); if (aClass == null) continue; // do not show deprecated warning for class implementing deprecated methods if (ignoreAbstractDeprecatedOverrides && !aClass.isDeprecated() && superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) continue; if (superMethod.isDeprecated()) { String description = JavaErrorMessages.message("overrides.deprecated.method", HighlightMessageUtil.getSymbolName(aClass, PsiSubstitutor.EMPTY)); holder.registerProblem(methodName, description, ProblemHighlightType.LIKE_DEPRECATED); } } }
@Override public void visitMethod(@NotNull PsiMethod method) { final PsiParameterList parameterList = method.getParameterList(); if (parameterList.getParametersCount() == 0) { return; } final Query<MethodSignatureBackedByPsiMethod> query = SuperMethodsSearch.search( method, method.getContainingClass(), true, false); final MethodSignatureBackedByPsiMethod methodSignature = query.findFirst(); if (methodSignature == null) { return; } final PsiMethod superMethod = methodSignature.getMethod(); final PsiParameter[] parameters = parameterList.getParameters(); checkParameters(superMethod, parameters); }
@Override public boolean execute(@NotNull final SuperMethodsSearch.SearchParameters queryParameters, @NotNull final Processor<MethodSignatureBackedByPsiMethod> consumer) { final PsiClass parentClass = queryParameters.getPsiClass(); final PsiMethod method = queryParameters.getMethod(); HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature(); final boolean checkBases = queryParameters.isCheckBases(); final boolean allowStaticMethod = queryParameters.isAllowStaticMethod(); final List<HierarchicalMethodSignature> supers = signature.getSuperSignatures(); for (HierarchicalMethodSignature superSignature : supers) { if (MethodSignatureUtil.isSubsignature(superSignature, signature)) { if (!addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer)) return false; } } return true; }
@Override public int compare(MethodSignature o1, MethodSignature o2) { if (o1 instanceof MethodSignatureBackedByPsiMethod && o2 instanceof MethodSignatureBackedByPsiMethod) { PsiMethod m1 = ((MethodSignatureBackedByPsiMethod)o1).getMethod(); PsiMethod m2 = ((MethodSignatureBackedByPsiMethod)o2).getMethod(); PsiClass c1 = m1.getContainingClass(); PsiClass c2 = m2.getContainingClass(); if (c1 != null && c2 != null) { if (c1 == c2) { final List<PsiMethod> methods = Arrays.asList(c1.getMethods()); return methods.indexOf(m1) - methods.indexOf(m2); } if (c1.isInheritor(c2, true)) return -1; if (c2.isInheritor(c1, true)) return 1; return StringUtil.notNullize(c1.getName()).compareTo(StringUtil.notNullize(c2.getName())); } return m1.getTextOffset() - m2.getTextOffset(); } return 0; }
@Override public void visitMethod(PsiMethod method) { ArrangementSettingsToken type = method.isConstructor() ? CONSTRUCTOR : METHOD; JavaElementArrangementEntry entry = createNewEntry(method, method.getTextRange(), type, method.getName(), true); if (entry == null) { return; } processEntry(entry, method, method.getBody()); parseProperties(method, entry); myInfo.onMethodEntryCreated(method, entry); MethodSignatureBackedByPsiMethod overridden = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (overridden != null) { myInfo.onOverriddenMethod(overridden.getMethod(), method); } boolean reset = myMethodBodyProcessor.setBaseMethod(method); try { method.accept(myMethodBodyProcessor); } finally { if (reset) { myMethodBodyProcessor.setBaseMethod(null); } } }
@Nullable @Override public ProblemDescriptor[] checkMethod(PsiMethod method, InspectionManager manager, boolean isOnTheFly) { if (isNonPrivateMethod(method)) { List<ProblemDescriptor> problemDescriptors = new ArrayList<>(); List<MethodSignatureBackedByPsiMethod> superMethodSignatures = superMethods(method); PsiParameter[] parameters = method.getParameterList().getParameters(); checkMethodParams(manager, problemDescriptors, superMethodSignatures, parameters); checkMethodReturnType(method, manager, problemDescriptors); return problemDescriptors.isEmpty() ? null : problemDescriptors.toArray(new ProblemDescriptor[problemDescriptors.size()]); } return null; }
private void checkMethodParams(InspectionManager manager, List<ProblemDescriptor> aProblemDescriptors, List<MethodSignatureBackedByPsiMethod> aSuperMethodSignatures, PsiParameter[] aParameters) { for (int i = 0, parametersLength = aParameters.length; i < parametersLength; i++) { PsiParameter parameter = aParameters[i]; if (parameterNeedsAnnotation(parameter)) { if (!hasAnnotation(parameter) && !hasAnnotationInHierarchy(i, aSuperMethodSignatures)) { createProblemDescriptorWithQuickFixes(parameter, manager, aProblemDescriptors, parameter); } } } }
private boolean hasAnnotationInHierarchy(int parameter, List<MethodSignatureBackedByPsiMethod> superMethodSignatures) { for (MethodSignatureBackedByPsiMethod methodSignature : superMethodSignatures) { PsiMethod superMethod = methodSignature.getMethod(); PsiParameter[] superParameters = superMethod.getParameterList().getParameters(); PsiParameter superParameter = superParameters[parameter]; if (hasAnnotation(superParameter)) { return true; } } return false; }
private List<MethodSignatureBackedByPsiMethod> superMethods(PsiMethod method) { List<MethodSignatureBackedByPsiMethod> signatures = method.findSuperMethodSignaturesIncludingStatic(true); signatures.removeIf(superSignature -> superSignature.getMethod().getParameterList().getParametersCount() != method.getParameterList().getParametersCount()); return signatures; }
private static List<MethodSignatureBackedByPsiMethod> superMethods(PsiMethod method) { List<MethodSignatureBackedByPsiMethod> signatures = method.findSuperMethodSignaturesIncludingStatic(true); signatures.removeIf(superSignature -> superSignature.getMethod().getParameterList().getParametersCount() != method.getParameterList().getParametersCount()); return signatures; }
@NotNull public static Query<MethodSignatureBackedByPsiMethod> search(@NotNull PsiMethod derivedMethod, @Nullable final PsiClass psiClass, boolean checkBases, boolean allowStaticMethod) { final SearchParameters parameters = new SearchParameters(derivedMethod, psiClass, checkBases, allowStaticMethod); return SUPER_METHODS_SEARCH_INSTANCE.createUniqueResultsQuery(parameters, MethodSignatureUtil.METHOD_BASED_HASHING_STRATEGY); }
@Override public String getLocationString() { if (!Registry.is("show.method.base.class.in.java.file.structure")) return null; final PsiMethod method = getElement(); if (myLocation == null && method != null && !DumbService.isDumb(method.getProject())) { if (isInherited()) { return super.getLocationString(); } else { try { final MethodSignatureBackedByPsiMethod baseMethod = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (baseMethod != null && !method.isEquivalentTo(baseMethod.getMethod())) { PsiMethod base = baseMethod.getMethod(); PsiClass baseClass = base.getContainingClass(); if (baseClass != null /*&& !CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())*/) { if (baseClass.getMethods().length > 1) { myLocation = baseClass.getName(); } } } } catch (IndexNotReadyException e) { //some searchers (EJB) require indices. What shall we do? } if (StringUtil.isEmpty(myLocation)) { myLocation = ""; } else { char upArrow = '\u2191'; myLocation = UIUtil.getLabelFont().canDisplay(upArrow) ? upArrow + myLocation : myLocation; } } } return StringUtil.isEmpty(myLocation) ? null : myLocation; }
@Override public void visitMethod(PsiMethod method){ MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY); if (!method.isConstructor()) { List<MethodSignatureBackedByPsiMethod> superMethodSignatures = method.findSuperMethodSignaturesIncludingStatic(true); checkMethodOverridesDeprecated(methodSignature, superMethodSignatures, myIgnoreAbstractDeprecatedOverrides, myHolder); } else { checkImplicitCallToSuper(method); } }
@Override public void visitMethod(PsiMethod method) { boolean isSectionCommentsDetected = registerSectionComments(method); final TextRange range = isSectionCommentsDetected ? getElementRangeWithoutComments(method) : method.getTextRange(); ArrangementSettingsToken type = method.isConstructor() ? CONSTRUCTOR : METHOD; JavaElementArrangementEntry entry = createNewEntry(method, range, type, method.getName(), true); if (entry == null) { return; } processEntry(entry, method, method.getBody()); parseProperties(method, entry); myInfo.onMethodEntryCreated(method, entry); MethodSignatureBackedByPsiMethod overridden = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (overridden != null) { entry.addModifier(OVERRIDDEN); myInfo.onOverriddenMethod(overridden.getMethod(), method); } boolean reset = myMethodBodyProcessor.setBaseMethod(method); try { method.accept(myMethodBodyProcessor); } finally { if (reset) { myMethodBodyProcessor.setBaseMethod(null); } } }
@Override public void visitMethod(PsiMethod method) { super.visitMethod(method); final PsiCodeBlock body = method.getBody(); if (body == null) { return; } if (method.getNameIdentifier() == null) { return; } final Query<MethodSignatureBackedByPsiMethod> superMethodQuery = SuperMethodsSearch.search(method, null, true, false); final MethodSignatureBackedByPsiMethod signature = superMethodQuery.findFirst(); if (signature == null) { return; } final PsiMethod superMethod = signature.getMethod(); final PsiCodeBlock superBody = superMethod.getBody(); if (superBody == null) { return; } if (!modifierListsAreEquivalent(method.getModifierList(), superMethod.getModifierList())) { return; } final PsiType superReturnType = superMethod.getReturnType(); if (superReturnType == null || !superReturnType.equals(method.getReturnType())) { return; } if (!EquivalenceChecker.codeBlocksAreEquivalent(body, superBody)) { return; } registerMethodError(method); }
@Override public void visitMethod(@NotNull PsiMethod method) { if (!CloneUtils.isClone(method)) { return; } if (method.hasModifierProperty(PsiModifier.FINAL)) { return; } if (onlyWarnOnProtectedClone && method.hasModifierProperty(PsiModifier.PUBLIC)) { return; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return; } if (containingClass.hasModifierProperty(PsiModifier.FINAL)) { return; } if (MethodUtils.hasInThrows(method, "java.lang.CloneNotSupportedException")) { return; } final MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (signature == null) { return; } final PsiMethod superMethod = signature.getMethod(); if (!MethodUtils.hasInThrows(superMethod, "java.lang.CloneNotSupportedException")) { return; } registerMethodError(method); }
private static boolean hasSuperMethods(@NotNull GrMethod method) { final GrReflectedMethod[] reflectedMethods = method.getReflectedMethods(); if (reflectedMethods.length > 0) { for (GrReflectedMethod reflectedMethod : reflectedMethods) { final MethodSignatureBackedByPsiMethod first = SuperMethodsSearch.search(reflectedMethod, null, true, false).findFirst(); if (first != null) return true; } return false; } else { return SuperMethodsSearch.search(method, null, true, false).findFirst() != null; } }
@Override public String getLocationString() { if (!Registry.is("show.method.base.class.in.java.file.structure")) return null; final PsiMethod method = getElement(); if (myLocation == null) { if (isInherited()) { return super.getLocationString(); } else { try { final MethodSignatureBackedByPsiMethod baseMethod = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (baseMethod != null && !method.isEquivalentTo(baseMethod.getMethod())) { PsiMethod base = baseMethod.getMethod(); PsiClass baseClass = base.getContainingClass(); if (baseClass != null /*&& !CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())*/) { if (baseClass.getMethods().length > 1) { myLocation = baseClass.getName(); } } } } catch (IndexNotReadyException e) { //some searchers (EJB) require indices. What shall we do? } if (StringUtil.isEmpty(myLocation)) { myLocation = ""; } else { char upArrow = '\u2191'; myLocation = UIUtil.getLabelFont().canDisplay(upArrow) ? upArrow + myLocation : myLocation; } } } return StringUtil.isEmpty(myLocation) ? null : myLocation; }
@Override public void visitMethod(@NotNull PsiMethod method) { if (!CloneUtils.isClone(method)) { return; } if (method.hasModifierProperty(PsiModifier.FINAL)) { return; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return; } if (containingClass.hasModifierProperty(PsiModifier.FINAL)) { return; } if (MethodUtils.hasInThrows(method, "java.lang.CloneNotSupportedException")) { return; } final MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (signature == null) { return; } final PsiMethod superMethod = signature.getMethod(); if (!MethodUtils.hasInThrows(superMethod, "java.lang.CloneNotSupportedException")) { return; } registerMethodError(method); }
private static boolean hasSuperMethods(GrMethod method) { final GrReflectedMethod[] reflectedMethods = method.getReflectedMethods(); for (GrReflectedMethod reflectedMethod : reflectedMethods) { final MethodSignatureBackedByPsiMethod first = SuperMethodsSearch.search(reflectedMethod, null, true, false).findFirst(); if (first != null) return true; } return false; }
@NotNull private static List<MethodSignatureBackedByPsiMethod> findSuperMethodSignatures(PsiMethod method, PsiClass parentClass, boolean allowStaticMethod) { return new ArrayList<MethodSignatureBackedByPsiMethod>(SuperMethodsSearch.search(method, parentClass, true, allowStaticMethod).findAll()); }
public boolean checkAndAddMethod(PsiMethod method, PsiSubstitutor substitutor) { PropertyAccessorMatchLevel matchLevel = getPropertyAccessorMatchLevel(method); if(matchLevel == PropertyAccessorMatchLevel.NotAccessor) { return false; } final MethodSignature signature = method.getSignature(substitutor); final PsiMethod alreadyStoredMethod = myMethods.get(signature); if(alreadyStoredMethod != null) { for(final MethodSignatureBackedByPsiMethod methodSignature : SuperMethodsSearch.search(alreadyStoredMethod, alreadyStoredMethod.getContainingClass(), true, false).findAll()) { if(methodSignature.equals(signature)) { return true; } } } if(matchLevel.compareTo(myMatchLevel) > 0) { myMethods.clear(); myMethods.put(signature, method); myMatchLevel = matchLevel; } else if(matchLevel == myMatchLevel) { myMethods.put(signature, method); } return true; }
@Override public boolean execute(@NotNull final SuperMethodsSearch.SearchParameters queryParameters, @NotNull final Processor<MethodSignatureBackedByPsiMethod> consumer) { final PsiClass parentClass = queryParameters.getPsiClass(); final PsiMethod method = queryParameters.getMethod(); return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @Override public Boolean compute() { HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature(); final boolean checkBases = queryParameters.isCheckBases(); final boolean allowStaticMethod = queryParameters.isAllowStaticMethod(); final List<HierarchicalMethodSignature> supers = signature.getSuperSignatures(); for(HierarchicalMethodSignature superSignature : supers) { if(MethodSignatureUtil.isSubsignature(superSignature, signature)) { if(!addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer)) { return false; } } } return true; } }); }
private static boolean addSuperMethods(final HierarchicalMethodSignature signature, final PsiMethod method, final PsiClass parentClass, final boolean allowStaticMethod, final boolean checkBases, final Processor<MethodSignatureBackedByPsiMethod> consumer) { PsiMethod signatureMethod = signature.getMethod(); PsiClass hisClass = signatureMethod.getContainingClass(); if(parentClass == null || InheritanceUtil.isInheritorOrSelf(parentClass, hisClass, true)) { if(isAcceptable(signatureMethod, method, allowStaticMethod)) { if(parentClass != null && !parentClass.equals(hisClass) && !checkBases) { return true; } LOG.assertTrue(signatureMethod != method, method); // method != method.getsuper() return consumer.process(signature); //no need to check super classes } } for(HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) { if(MethodSignatureUtil.isSubsignature(superSignature, signature)) { addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer); } } return true; }
@Override public int compare(MethodSignature o1, MethodSignature o2) { if(o1 instanceof MethodSignatureBackedByPsiMethod && o2 instanceof MethodSignatureBackedByPsiMethod) { PsiMethod m1 = ((MethodSignatureBackedByPsiMethod) o1).getMethod(); PsiMethod m2 = ((MethodSignatureBackedByPsiMethod) o2).getMethod(); PsiClass c1 = m1.getContainingClass(); PsiClass c2 = m2.getContainingClass(); if(c1 != null && c2 != null) { if(c1 == c2) { final List<PsiMethod> methods = Arrays.asList(c1.getMethods()); return methods.indexOf(m1) - methods.indexOf(m2); } if(c1.isInheritor(c2, true)) { return -1; } if(c2.isInheritor(c1, true)) { return 1; } return StringUtil.notNullize(c1.getQualifiedName()).compareTo(StringUtil.notNullize(c2.getQualifiedName())); } return m1.getTextOffset() - m2.getTextOffset(); } return 0; }
@Override @NotNull public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor) { if(substitutor == PsiSubstitutor.EMPTY) { return CachedValuesManager.getCachedValue(this, () -> { MethodSignature signature = MethodSignatureBackedByPsiMethod.create(this, PsiSubstitutor.EMPTY); return CachedValueProvider.Result.create(signature, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); }); } return MethodSignatureBackedByPsiMethod.create(this, substitutor); }
@Override public void visitMethod(PsiMethod method) { MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY); if(!method.isConstructor()) { List<MethodSignatureBackedByPsiMethod> superMethodSignatures = method.findSuperMethodSignaturesIncludingStatic(true); checkMethodOverridesDeprecated(methodSignature, superMethodSignatures, myIgnoreAbstractDeprecatedOverrides, myHolder); } else { checkImplicitCallToSuper(method); } }
static void checkMethodOverridesDeprecated(MethodSignatureBackedByPsiMethod methodSignature, List<MethodSignatureBackedByPsiMethod> superMethodSignatures, boolean ignoreAbstractDeprecatedOverrides, ProblemsHolder holder) { PsiMethod method = methodSignature.getMethod(); PsiElement methodName = method.getNameIdentifier(); for(MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) { PsiMethod superMethod = superMethodSignature.getMethod(); PsiClass aClass = superMethod.getContainingClass(); if(aClass == null) { continue; } // do not show deprecated warning for class implementing deprecated methods if(ignoreAbstractDeprecatedOverrides && !aClass.isDeprecated() && superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) { continue; } if(superMethod.isDeprecated()) { String description = JavaErrorMessages.message("overrides.deprecated.method", HighlightMessageUtil.getSymbolName(aClass, PsiSubstitutor.EMPTY)); holder.registerProblem(methodName, description, ProblemHighlightType.LIKE_DEPRECATED); } } }
@Nullable public static PsiMethod getSuper(@NotNull PsiMethod method) { final MethodSignatureBackedByPsiMethod signature = getSuperMethodSignature(method); if(signature == null) { return null; } return signature.getMethod(); }
@Nullable public static MethodSignatureBackedByPsiMethod getSuperMethodSignature(@NotNull PsiMethod method) { if(method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC) || method.hasModifierProperty(PsiModifier.PRIVATE)) { return null; } return SuperMethodsSearch.search(method, null, true, false).findFirst(); }