/** {@inheritDoc} */ @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { unwrapArgs(method.getParameterTypes(), args); if (!mixinHandlers.isEmpty()) { MethodSignature methodSignature = MethodSignature.forMethod(method); if (mixinHandlers.containsKey(methodSignature)) { return mixinHandlers.get(methodSignature).invoke(proxy, method, args); } } final InvocationHandler invocationHandler = handlers.get(MethodSignature.forMethod(method)); if (invocationHandler != null) { try { return invocationHandler.invoke(proxy, method, args); } catch (XPathExpressionException e) { throw new XBPathException(e, method, "??"); } } throw new IllegalArgumentException( "I don't known how to invoke method " + method + ". Did you forget to add a XB*-annotation or to register a mixin?"); }
public static boolean isReceiverType( PsiType functionalInterfaceType, PsiClass containingClass, @Nullable PsiMethod referencedMethod) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final MethodSignature function = LambdaUtil.getFunction(resolveResult.getElement()); if (function != null) { final int interfaceMethodParamsLength = function.getParameterTypes().length; if (interfaceMethodParamsLength > 0) { final PsiType firstParamType = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); boolean isReceiver = isReceiverType( firstParamType, containingClass, PsiUtil.resolveGenericsClassInType(firstParamType).getSubstitutor()); if (isReceiver) { if (referencedMethod == null) { if (interfaceMethodParamsLength == 1) return true; return false; } if (referencedMethod.getParameterList().getParametersCount() != interfaceMethodParamsLength - 1) { return false; } return true; } } } return false; }
@NotNull private static List<PsiMethod> findMethodsBySignature( @NotNull PsiClass aClass, @NotNull PsiMethod patternMethod, boolean checkBases, boolean stopOnFirst) { final PsiMethod[] methodsByName = aClass.findMethodsByName(patternMethod.getName(), checkBases); if (methodsByName.length == 0) return Collections.emptyList(); final List<PsiMethod> methods = new SmartList<PsiMethod>(); final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY); for (final PsiMethod method : methodsByName) { final PsiClass superClass = method.getContainingClass(); final PsiSubstitutor substitutor; if (checkBases && !aClass.equals(superClass)) { substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); } else { substitutor = PsiSubstitutor.EMPTY; } final MethodSignature signature = method.getSignature(substitutor); if (signature.equals(patternSignature)) { methods.add(method); if (stopOnFirst) { break; } } } return methods; }
@Override public final boolean permitsStaticMethod(Method method, Object[] args) { for (MethodSignature s : staticMethodSignatures()) { if (s.matches(method)) { return true; } } return false; }
@Nullable public static PsiMethod findMethodBySignature( GrTypeDefinition grType, PsiMethod patternMethod, boolean checkBases) { final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY); for (PsiMethod method : findMethodsByName(grType, patternMethod.getName(), checkBases, false)) { MethodSignature signature = getSignatureForInheritor(method, grType); if (patternSignature.equals(signature)) return method; } return null; }
private <T> Cursor<T> executeForCursor(SqlSession sqlSession, Object[] args) { Cursor<T> result; Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.<T>selectCursor(command.getName(), param, rowBounds); } else { result = sqlSession.<T>selectCursor(command.getName(), param); } return result; }
private <K, V> Map<K, V> executeForMap(SqlSession sqlSession, Object[] args) { Map<K, V> result; Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.<K, V>selectMap(command.getName(), param, method.getMapKey(), rowBounds); } else { result = sqlSession.<K, V>selectMap(command.getName(), param, method.getMapKey()); } return result; }
public static PsiType[] getErasedParameterTypes(MethodSignature signature) { PsiType[] parameterTypes = signature.getParameterTypes(); if (parameterTypes.length == 0) return PsiType.EMPTY_ARRAY; PsiSubstitutor substitutor = signature.getSubstitutor(); PsiType[] erasedTypes = new PsiType[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { erasedTypes[i] = TypeConversionUtil.erasure(substitutor.substitute(parameterTypes[i]), substitutor); } return erasedTypes; }
@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; }
private Map<MethodSignature, InvocationHandler> getDefaultInvokers( final Object defaultInvokerObject) { final ReflectionInvoker reflectionInvoker = new ReflectionInvoker(defaultInvokerObject); final Map<MethodSignature, InvocationHandler> invokers = new HashMap<MethodSignature, InvocationHandler>(); for (Method m : DOMAccess.class.getMethods()) { if (m.getAnnotation(XBWrite.class) == null) { invokers.put(MethodSignature.forMethod(m), reflectionInvoker); } } invokers.put(MethodSignature.forVoidMethod("toString"), reflectionInvoker); invokers.put(MethodSignature.forSingleParam("equals", Object.class), reflectionInvoker); invokers.put(MethodSignature.forVoidMethod("hashCode"), reflectionInvoker); return invokers; // Collections.unmodifiableMap(invokers); }
@Nullable private static List<MethodSignature> hasSubsignature(List<MethodSignature> signatures) { for (MethodSignature signature : signatures) { boolean subsignature = true; for (MethodSignature methodSignature : signatures) { if (!signature.equals(methodSignature)) { if (!MethodSignatureUtil.isSubsignature(signature, methodSignature)) { subsignature = false; break; } } } if (subsignature) return Collections.singletonList(signature); } return signatures; }
@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; }
private static PsiMethod[] findMethodsBySignature( GrTypeDefinition grType, PsiMethod patternMethod, boolean checkBases, boolean includeSynthetic) { ArrayList<PsiMethod> result = new ArrayList<PsiMethod>(); final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY); for (PsiMethod method : findMethodsByName(grType, patternMethod.getName(), checkBases, includeSynthetic)) { MethodSignature signature = getSignatureForInheritor(method, grType); if (patternSignature.equals(signature)) { result.add(method); } } return result.toArray(new PsiMethod[result.size()]); }
private void executeWithResultHandler(SqlSession sqlSession, Object[] args) { MappedStatement ms = sqlSession.getConfiguration().getMappedStatement(command.getName()); if (void.class.equals(ms.getResultMaps().get(0).getType())) { throw new BindingException( "method " + command.getName() + " needs either a @ResultMap annotation, a @ResultType annotation," + " or a resultType attribute in XML so a ResultHandler can be used as a parameter."); } Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); sqlSession.select(command.getName(), param, rowBounds, method.extractResultHandler(args)); } else { sqlSession.select(command.getName(), param, method.extractResultHandler(args)); } }
@Test public void getInterceptionHandler_whenCallIsNotRecognized_shouldReturnDoNothingHandler() throws Exception { MethodSignature methodSignature = MethodSignature.parse("java/lang/Object/unknownMethod()V"); Function<Object, Object> handler = shadowWrangler.getInterceptionHandler(methodSignature); assertThat(handler).isNotNull().isSameAs(ShadowWrangler.DO_NOTHING_HANDLER); assertThat(handler.call(null)).isNull(); }
public static boolean isSubsignature( MethodSignature superSignature, MethodSignature subSignature) { if (subSignature == superSignature) return true; if (!areSignaturesEqualLightweight(superSignature, subSignature)) return false; PsiSubstitutor unifyingSubstitutor = getSuperMethodSignatureSubstitutor(subSignature, superSignature); if (checkSignaturesEqualInner(superSignature, subSignature, unifyingSubstitutor)) return true; if (subSignature.getTypeParameters().length > 0) return false; final PsiType[] subParameterTypes = subSignature.getParameterTypes(); final PsiType[] superParameterTypes = superSignature.getParameterTypes(); for (int i = 0; i < subParameterTypes.length; i++) { PsiType type1 = subParameterTypes[i]; PsiType type2 = TypeConversionUtil.erasure(superParameterTypes[i]); if (!Comparing.equal(type1, type2)) return false; } return true; }
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { List<E> result; Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.<E>selectList(command.getName(), param, rowBounds); } else { result = sqlSession.<E>selectList(command.getName(), param); } // issue #510 Collections & arrays support if (!method.getReturnType().isAssignableFrom(result.getClass())) { if (method.getReturnType().isArray()) { return convertToArray(result); } else { return convertToDeclaredCollection(sqlSession.getConfiguration(), result); } } 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()); }
private static boolean checkSignaturesEqualInner( @NotNull MethodSignature subSignature, @NotNull MethodSignature superSignature, final PsiSubstitutor unifyingSubstitutor) { if (unifyingSubstitutor == null) return false; if (!areErasedParametersEqual(subSignature, superSignature)) return false; final PsiType[] subParameterTypes = subSignature.getParameterTypes(); final PsiType[] superParameterTypes = superSignature.getParameterTypes(); for (int i = 0; i < subParameterTypes.length; i++) { final PsiType type1 = unifyingSubstitutor.substitute(subParameterTypes[i]); final PsiType type2 = unifyingSubstitutor.substitute(superParameterTypes[i]); if (!Comparing.equal(type1, type2)) { return false; } } return true; }
@Test public void getInterceptionHandler_whenInterceptingElderOnLinkedHashMap_shouldReturnNonDoNothingHandler() throws Exception { MethodSignature methodSignature = MethodSignature.parse("java/util/LinkedHashMap/eldest()Ljava/lang/Object"); Function<Object, Object> handler = shadowWrangler.getInterceptionHandler(methodSignature); assertThat(handler).isNotSameAs(ShadowWrangler.DO_NOTHING_HANDLER); }
@Override public void genCyan( PWInterface pw, boolean printInMoreThanOneLine, CyanEnv cyanEnv, boolean genFunctions) { if (cyanEnv.getCreatingInstanceGenericPrototype()) { pw.print(cyanEnv.formalGenericParamToRealParam(methodName.getSymbolString())); } else { pw.print(methodName.getSymbolString()); } super.genCyan(pw, printInMoreThanOneLine, cyanEnv, genFunctions); }
@Nullable private static PsiSubstitutor getSuperMethodSignatureSubstitutorImpl( @NotNull MethodSignature methodSignature, @NotNull MethodSignature superSignature) { // normalize generic method declarations: correlate type parameters // todo: correlate type params by name? PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters(); PsiTypeParameter[] superTypeParameters = superSignature.getTypeParameters(); // both methods are parameterized and number of parameters mismatch if (methodTypeParameters.length != superTypeParameters.length) return null; PsiSubstitutor result = superSignature.getSubstitutor(); for (int i = 0; i < methodTypeParameters.length; i++) { PsiTypeParameter methodTypeParameter = methodTypeParameters[i]; PsiElementFactory factory = JavaPsiFacade.getInstance(methodTypeParameter.getProject()).getElementFactory(); result = result.put(superTypeParameters[i], factory.createType(methodTypeParameter)); } return result; }
@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; }
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; }
/** * @param methodSignature method signature * @param superMethodSignature super method signature * @return null if signatures do not match */ @Nullable public static PsiSubstitutor getSuperMethodSignatureSubstitutor( @NotNull MethodSignature methodSignature, @NotNull MethodSignature superMethodSignature) { PsiSubstitutor result = getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature); if (result == null) return null; PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters(); PsiTypeParameter[] superTypeParameters = superMethodSignature.getTypeParameters(); PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor(); // check bounds for (int i = 0; i < methodTypeParameters.length; i++) { PsiTypeParameter methodTypeParameter = methodTypeParameters[i]; PsiTypeParameter superTypeParameter = superTypeParameters[i]; final Set<PsiType> methodSupers = new HashSet<PsiType>(); for (PsiClassType methodSuper : methodTypeParameter.getSuperTypes()) { methodSupers.add(methodSubstitutor.substitute(methodSuper)); } final Set<PsiType> superSupers = new HashSet<PsiType>(); for (PsiClassType superSuper : superTypeParameter.getSuperTypes()) { superSupers.add( methodSubstitutor.substitute( PsiUtil.captureToplevelWildcards( result.substitute(superSuper), methodTypeParameter))); } methodSupers.remove( PsiType.getJavaLangObject( methodTypeParameter.getManager(), methodTypeParameter.getResolveScope())); superSupers.remove( PsiType.getJavaLangObject( superTypeParameter.getManager(), superTypeParameter.getResolveScope())); if (!methodSupers.equals(superSupers)) return null; } return result; }
private static boolean hasReceiver( @NotNull PsiMethodReferenceExpression methodRef, @NotNull PsiMethod method, PsiType functionalInterfaceType) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature( LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null; if (signature == null) { return false; } final PsiType[] parameterTypes = signature.getParameterTypes(); final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(methodRef); return (method.getParameterList().getParametersCount() + 1 == parameterTypes.length || method.isVarArgs() && parameterTypes.length > 0 && !method.hasModifierProperty(PsiModifier.STATIC)) && hasReceiver(parameterTypes, qualifierResolveResult, methodRef); }
private void fixupSignature(MethodSignature signature) throws IOException { int classNameIndex = signature.getClassNameIndex(); String dottedName = constantPool.getUtf8(classNameIndex).getString().replace("/", "."); signature.setClassNameIndex(getOrInsertUtf8(dottedName)); signature.setMethodNameIndex( getOrInsertString(signature.getMethodNameIndex())); // will be a String resource now signature.setClassNameIndex( getOrInsertString(signature.getClassNameIndex())); // will be a String resource now }
private Map<String, Integer> getOrInsertPrimitiveWrapperMethods(MethodSignature signature) throws IOException { Map<String, Integer> methodRefs = new HashMap<String, Integer>(); int valueOfString = getOrInsertUtf8("valueOf"); for (String paramType : signature.getParamTypes()) { char baseType = paramType.charAt(0); Class wrapperClass = getWrapperClass(baseType); if (wrapperClass != null) { int wrapperMethod = getOrInsertPrimitiveWrappeMethod(wrapperClass, baseType, valueOfString); methodRefs.put(paramType, wrapperMethod); } } return methodRefs; }
private Object rowCountResult(int rowCount) { final Object result; if (method.returnsVoid()) { result = null; } else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) { result = Integer.valueOf(rowCount); } else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) { result = Long.valueOf(rowCount); } else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) { result = Boolean.valueOf(rowCount > 0); } else { throw new BindingException( "Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType()); } return result; }