
com.google.gwt.inject.rebind.reflect.MethodLiteral Maven / Gradle / Ivy
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.inject.rebind.reflect;
import com.google.gwt.dev.util.Preconditions;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.user.client.rpc.core.java.util.Collections;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.MoreTypes;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.google.gwt.inject.rebind.util.SourceWriteUtil.join;
/**
* Generic method and constructor representation that preserves the member's
* parametrization and allows common operations on methods and constructors
* where appropriate.
*
* @see TypeLiteral
*/
public abstract class MethodLiteral
extends MemberLiteral {
/**
* Creates a new {@code MethodLiteral} based on the passed method and its
* declaring type.
*
* @param method method for which the literal is constructed
* @param declaringType type declaring the passed method
* @return new method literal
*/
public static MethodLiteral get(Method method, TypeLiteral declaringType) {
Preconditions.checkArgument(method.getDeclaringClass().equals(declaringType.getRawType()),
"declaringType (%s) must be the type literal where method was declared (%s)!",
declaringType, method.getDeclaringClass());
return new ConcreteMethodLiteral(method, declaringType);
}
/**
* Creates a new {@code MethodLiteral} based on the passed constructor and
* its declaring type.
*
* @param constructor constructor for which the literal is constructed
* @param declaringType type declaring the constructor
* @return new method literal
*/
public static MethodLiteral> get(Constructor> constructor,
TypeLiteral declaringType) {
Preconditions.checkArgument(
constructor.getDeclaringClass().equals(declaringType.getRawType()),
"declaringType (%s) must be the type literal where constructor was declared (%s)!",
declaringType, constructor.getDeclaringClass());
return new ConstructorLiteral(constructor, declaringType);
}
/**
* Cache of parameter keys.
*/
private List> parameterKeys;
/**
* Cache of parameter types.
*/
private List> parameterTypes;
protected MethodLiteral(M member, TypeLiteral declaringType) {
super(member, declaringType);
}
/**
* Returns this method's parameter keys, if appropriate parametrized with the
* declaring class's type parameters.
*
* @return parameter keys
*/
public List> getParameterKeys() {
if (parameterKeys == null) {
compileParameterKeys();
}
return parameterKeys;
}
/**
* Returns this method's parameter types, if appropriate parametrized with
* the declaring class's type parameters.
*
* @return parameter types
*/
public List> getParameterTypes() {
if (parameterTypes == null) {
parameterTypes = getDeclaringType().getParameterTypes(getMember());
}
return parameterTypes;
}
/**
* Returns this method's parameter types without any type parametrization
* applied.
*
* For example, {@code <T> void foo(T t)} will return a list with a single
* entry, a {@link TypeVariable} with name {@code T} and bounded by
* {@code java.lang.Object}.
*
* @return raw parameter types
*/
public abstract List getRawParameterTypes();
/**
* Returns this method's exception types, if appropriate parametrized with
* the declaring class's type parameters.
*
* @return exception types
*/
public List> getExceptionTypes() {
return getDeclaringType().getExceptionTypes(getMember());
}
/**
* Returns this method's type parameters.
*
* @return type parameters
*/
public TypeVariable>[] getTypeParameters() {
return getMember().getTypeParameters();
}
/**
* Returns this method's return type, if appropriate parametrized with the
* declaring class's type parameters.
*
* @return return type
*/
public abstract TypeLiteral> getReturnType();
/**
* Returns {@code true} if this method literal is based on a constructor.
*/
public abstract boolean isConstructor();
protected abstract Annotation[][] getParameterAnnotations();
private void compileParameterKeys() {
parameterKeys = new ArrayList>(getParameterTypes().size());
int i = 0;
for (TypeLiteral> parameterType : getParameterTypes()) {
Annotation bindingAnnotation = getBindingAnnotation(getParameterAnnotations()[i]);
if (bindingAnnotation != null) {
parameterKeys.add(Key.get(parameterType, bindingAnnotation));
} else {
parameterKeys.add(Key.get(parameterType));
}
i++;
}
}
/**
* Returns the method's declaring type and name in the format used in
* javadoc, e.g. {@code com.bar.Foo#baz(com.bar.Foo, com.bar.Bar)}, with
* resolved type parameters.
*
* @return string representation for this method including the declaring type
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getName()).append("(");
List parameters = new ArrayList();
for (Type parameterType : getRawParameterTypes()) {
// TODO(schmitt): We are not respecting varargs here.
parameters.add(MoreTypes.typeToString(parameterType));
}
sb.append(join(", ", parameters)).append(")");
return String.format("%s#%s", getDeclaringType(), sb.toString());
}
/**
* Constructor-specific implementation of {@link MethodLiteral}.
*/
private static class ConstructorLiteral extends MethodLiteral> {
ConstructorLiteral(Constructor> constructor, TypeLiteral declaringType) {
super(constructor, declaringType);
}
@Override
public TypeLiteral> getReturnType() {
return getDeclaringType();
}
@Override
public boolean isConstructor() {
return true;
}
@Override
protected Annotation[][] getParameterAnnotations() {
return getMember().getParameterAnnotations();
}
@Override
public List getRawParameterTypes() {
return Arrays.asList(getMember().getGenericParameterTypes());
}
}
/**
* Method-specific implementation of {@link MethodLiteral}.
*/
private static class ConcreteMethodLiteral extends MethodLiteral {
ConcreteMethodLiteral(Method method, TypeLiteral typeLiteral) {
super(method, typeLiteral);
}
@Override
public TypeLiteral> getReturnType() {
return getDeclaringType().getReturnType(getMember());
}
@Override
public boolean isConstructor() {
return false;
}
@Override
protected Annotation[][] getParameterAnnotations() {
return getMember().getParameterAnnotations();
}
@Override
public List getRawParameterTypes() {
return Arrays.asList(getMember().getGenericParameterTypes());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy