aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorbcorso <bcorso@google.com>2019-11-13 07:49:10 -0800
committerChris Povirk <beigetangerine@gmail.com>2019-11-13 13:47:34 -0500
commit7db5511b899278f2f6daa4ea6f3e748bb7b84f64 (patch)
tree737387f97060387c203bfcc74af4307c3134f08a /common
parent37dac1e64194764d54245d31f9d1bc13f9508a61 (diff)
downloadauto-7db5511b899278f2f6daa4ea6f3e748bb7b84f64.tar.gz
Optimize MoreTypes.nonObjectSuperclass
This CL tries to avoid using expensive method calls like Elements#getTypeElement, TypeElement#getKind(), and Types#directSupertypes. Of all of these, TypeElement#getKind() had the largest cost because it requires symbol completion. In addition, getKind() was being called on unnecessarily on all supertypes, even though only the first type can possibly be an ElementKind.CLASS. RELNOTES=N/A ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=280196697
Diffstat (limited to 'common')
-rw-r--r--common/src/main/java/com/google/auto/common/MoreTypes.java53
-rw-r--r--common/src/test/java/com/google/auto/common/MoreTypesTest.java9
2 files changed, 35 insertions, 27 deletions
diff --git a/common/src/main/java/com/google/auto/common/MoreTypes.java b/common/src/main/java/com/google/auto/common/MoreTypes.java
index a1a24f4a..73905bba 100644
--- a/common/src/main/java/com/google/auto/common/MoreTypes.java
+++ b/common/src/main/java/com/google/auto/common/MoreTypes.java
@@ -17,7 +17,6 @@ package com.google.auto.common;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
import static javax.lang.model.type.TypeKind.ARRAY;
import static javax.lang.model.type.TypeKind.DECLARED;
import static javax.lang.model.type.TypeKind.EXECUTABLE;
@@ -28,8 +27,6 @@ import static javax.lang.model.type.TypeKind.WILDCARD;
import com.google.common.base.Equivalence;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.HashSet;
@@ -875,34 +872,36 @@ public final class MoreTypes {
* Returns the non-object superclass of the type with the proper type parameters.
* An absent Optional is returned if there is no non-Object superclass.
*/
- public static Optional<DeclaredType> nonObjectSuperclass(final Types types, Elements elements,
+ // TODO(user): Remove unused parameter Elements?
+ public static Optional<DeclaredType> nonObjectSuperclass(Types types, Elements elements,
DeclaredType type) {
checkNotNull(types);
- checkNotNull(elements);
+ checkNotNull(elements); // This is no longer used, but here to avoid changing the API.
checkNotNull(type);
- final TypeMirror objectType =
- elements.getTypeElement(Object.class.getCanonicalName()).asType();
- // It's guaranteed there's only a single CLASS superclass because java doesn't have multiple
- // class inheritance.
- TypeMirror superclass =
- getOnlyElement(
- FluentIterable.from(types.directSupertypes(type))
- .filter(
- new Predicate<TypeMirror>() {
- @Override
- public boolean apply(TypeMirror input) {
- return input.getKind().equals(TypeKind.DECLARED)
- && MoreElements.asType(MoreTypes.asDeclared(input).asElement())
- .getKind()
- .equals(ElementKind.CLASS)
- && !types.isSameType(objectType, input);
- }
- }),
- null);
- return superclass != null
- ? Optional.of(MoreTypes.asDeclared(superclass))
- : Optional.<DeclaredType>absent();
+ TypeMirror superclassType = asTypeElement(type).getSuperclass();
+ if (!isType(superclassType)) { // type is Object or an interface
+ return Optional.absent();
+ }
+
+ DeclaredType superclass = asDeclared(superclassType);
+ if (isObjectType(superclass)) {
+ return Optional.absent();
+ }
+
+ if (superclass.getTypeArguments().isEmpty()) {
+ return Optional.of(superclass);
+ }
+
+ // In the case where the super class has type parameters, TypeElement#getSuperclass gives
+ // SuperClass<T> rather than SuperClass<Foo>, so use Types#directSupertypes instead. The javadoc
+ // for Types#directSupertypes guarantees that a super class, if it exists, comes before any
+ // interfaces. Thus, we can just get the first element in the list.
+ return Optional.of(asDeclared(types.directSupertypes(type).get(0)));
+ }
+
+ private static boolean isObjectType(DeclaredType type) {
+ return asTypeElement(type).getQualifiedName().contentEquals("java.lang.Object");
}
/**
diff --git a/common/src/test/java/com/google/auto/common/MoreTypesTest.java b/common/src/test/java/com/google/auto/common/MoreTypesTest.java
index 84bcb9d3..5b8d33f8 100644
--- a/common/src/test/java/com/google/auto/common/MoreTypesTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreTypesTest.java
@@ -281,6 +281,7 @@ public class MoreTypesTest {
private static class ChildA extends Parent<Number> {}
private static class ChildB extends Parent<String> {}
private static class GenericChild<T> extends Parent<T> {}
+ private interface InterfaceType {}
@Test
public void asElement_throws() {
@@ -317,7 +318,15 @@ public class MoreTypesTest {
TypeElement genericChild = elements.getTypeElement(GenericChild.class.getCanonicalName());
TypeMirror genericChildOfNumber = types.getDeclaredType(genericChild, numberType);
TypeMirror genericChildOfInteger = types.getDeclaredType(genericChild, integerType);
+ TypeMirror objectType =
+ elements.getTypeElement(Object.class.getCanonicalName()).asType();
+ TypeMirror interfaceType =
+ elements.getTypeElement(InterfaceType.class.getCanonicalName()).asType();
+ assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) objectType))
+ .isAbsent();
+ assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) interfaceType))
+ .isAbsent();
assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) parent.asType()))
.isAbsent();