diff options
author | bcorso <bcorso@google.com> | 2019-11-13 07:49:10 -0800 |
---|---|---|
committer | Chris Povirk <beigetangerine@gmail.com> | 2019-11-13 13:47:34 -0500 |
commit | 7db5511b899278f2f6daa4ea6f3e748bb7b84f64 (patch) | |
tree | 737387f97060387c203bfcc74af4307c3134f08a /common | |
parent | 37dac1e64194764d54245d31f9d1bc13f9508a61 (diff) | |
download | auto-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.java | 53 | ||||
-rw-r--r-- | common/src/test/java/com/google/auto/common/MoreTypesTest.java | 9 |
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(); |