public static boolean areSignaturesEqualLightweight( @NotNull MethodSignature sig1, @NotNull MethodSignature sig2) { final boolean isConstructor1 = sig1.isConstructor(); final boolean isConstructor2 = sig2.isConstructor(); if (isConstructor1 != isConstructor2) return false; if (!isConstructor1 || !(sig1 instanceof HierarchicalMethodSignature || sig2 instanceof HierarchicalMethodSignature)) { final String name1 = sig1.getName(); final String name2 = sig2.getName(); if (!name1.equals(name2)) return false; } final PsiType[] parameterTypes1 = sig1.getParameterTypes(); final PsiType[] parameterTypes2 = sig2.getParameterTypes(); if (parameterTypes1.length != parameterTypes2.length) return false; // optimization: check for really different types in method parameters for (int i = 0; i < parameterTypes1.length; i++) { final PsiType type1 = parameterTypes1[i]; final PsiType type2 = parameterTypes2[i]; if (type1 instanceof PsiPrimitiveType != type2 instanceof PsiPrimitiveType) return false; if (type1 instanceof PsiPrimitiveType && !type1.equals(type2)) return false; } return true; }
@Nullable private static PsiMethod doFindMethodInSuperClassBySignatureInDerived( @NotNull PsiClass superClass, @NotNull PsiSubstitutor superSubstitutor, @NotNull MethodSignature signature, final boolean checkDeep) { final String name = signature.getName(); final PsiMethod[] methods = superClass.findMethodsByName(name, false); for (final PsiMethod method : methods) { if (isSubsignature(method.getSignature(superSubstitutor), signature)) { return method; } } if (checkDeep) { final PsiClass clazz = superClass.getSuperClass(); if (clazz != null && clazz != superClass) { PsiSubstitutor substitutor1 = TypeConversionUtil.getSuperClassSubstitutor(clazz, superClass, superSubstitutor); return doFindMethodInSuperClassBySignatureInDerived(clazz, substitutor1, signature, true); } } return null; }
@Nullable private static PsiMethod getMethod(PsiClass psiClass, MethodSignature methodSignature) { final PsiMethod[] methodsByName = psiClass.findMethodsByName(methodSignature.getName(), true); for (PsiMethod psiMethod : methodsByName) { if (MethodSignatureUtil.areSignaturesEqual( getMethodSignature(psiMethod, psiClass, psiMethod.getContainingClass()), methodSignature)) { return psiMethod; } } return null; }
@Nullable public static PsiMethod findMethodBySignature( @NotNull PsiClass aClass, @NotNull MethodSignature methodSignature, boolean checkBases) { String name = methodSignature.isConstructor() ? aClass.getName() : methodSignature.getName(); List<Pair<PsiMethod, PsiSubstitutor>> pairs = aClass.findMethodsAndTheirSubstitutorsByName(name, checkBases); for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) { PsiMethod method = pair.first; PsiSubstitutor substitutor = pair.second; MethodSignature foundMethodSignature = method.getSignature(substitutor); if (methodSignature.equals(foundMethodSignature)) return method; } return null; }
@Override public int computeHashCode(final MethodSignature signature) { int result = signature.isConstructor() ? 0 : signature.getName().hashCode(); PsiType[] parameterTypes = signature.getParameterTypes(); result += 37 * parameterTypes.length; PsiType firstParamType = parameterTypes.length == 0 ? null : parameterTypes[0]; if (firstParamType != null) { firstParamType = TypeConversionUtil.erasure(firstParamType, signature.getSubstitutor()); assert firstParamType != null : parameterTypes[0]; result = 31 * result + firstParamType.hashCode(); } return result; }
/** * Adds a method to the class which bridges from the service method to the corresponding method in * the filter interface. The next service (either another Bridge, or the terminator at the end of * the pipeline) is passed to the filter). */ private void addBridgeMethod(int position, MethodSignature ms, MethodSignature fms) { StringBuffer buffer = new StringBuffer(100); if (ms.getReturnType() != void.class) buffer.append("return "); buffer.append("_filter."); buffer.append(ms.getName()); buffer.append("("); boolean comma = false; int filterParameterCount = fms.getParameterTypes().length; for (int i = 0; i < position; i++) { if (comma) buffer.append(", "); buffer.append("$"); // Add one to the index to get the parameter symbol ($0 is the implicit // this parameter). buffer.append(i + 1); comma = true; } if (comma) buffer.append(", "); // _next is the variable in -this- Bridge that points to the -next- Bridge // or the terminator for the pipeline. The filter is expected to reinvoke the // method on the _next that's passed to it. buffer.append("_next"); for (int i = position + 1; i < filterParameterCount; i++) { buffer.append(", $"); buffer.append(i); } buffer.append(");"); // This should work, unless the exception types turn out to not be compatble. We still // don't do a check on that, and not sure that Javassist does either! _classFab.addMethod(Modifier.PUBLIC, ms, buffer.toString()); }