1 /* 2 * Copyright 2019 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.auto.factory.processor; 17 18 import static com.google.common.base.Preconditions.checkNotNull; 19 20 import com.google.common.collect.ImmutableSet; 21 import java.util.HashSet; 22 import java.util.Set; 23 import javax.lang.model.element.Element; 24 import javax.lang.model.type.ArrayType; 25 import javax.lang.model.type.DeclaredType; 26 import javax.lang.model.type.IntersectionType; 27 import javax.lang.model.type.TypeMirror; 28 import javax.lang.model.type.TypeVariable; 29 import javax.lang.model.type.UnionType; 30 import javax.lang.model.type.WildcardType; 31 import javax.lang.model.util.SimpleTypeVisitor8; 32 33 final class TypeVariables { TypeVariables()34 private TypeVariables() {} 35 getReferencedTypeVariables(TypeMirror type)36 static ImmutableSet<TypeVariable> getReferencedTypeVariables(TypeMirror type) { 37 checkNotNull(type); 38 return type.accept(ReferencedTypeVariables.INSTANCE, new HashSet<>()); 39 } 40 41 private static final class ReferencedTypeVariables 42 extends SimpleTypeVisitor8<ImmutableSet<TypeVariable>, Set<Element>> { 43 44 private static final ReferencedTypeVariables INSTANCE = new ReferencedTypeVariables(); 45 ReferencedTypeVariables()46 ReferencedTypeVariables() { 47 super(ImmutableSet.of()); 48 } 49 50 @Override visitArray(ArrayType t, Set<Element> visited)51 public ImmutableSet<TypeVariable> visitArray(ArrayType t, Set<Element> visited) { 52 return t.getComponentType().accept(this, visited); 53 } 54 55 @Override visitDeclared(DeclaredType t, Set<Element> visited)56 public ImmutableSet<TypeVariable> visitDeclared(DeclaredType t, Set<Element> visited) { 57 if (!visited.add(t.asElement())) { 58 return ImmutableSet.of(); 59 } 60 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 61 for (TypeMirror typeArgument : t.getTypeArguments()) { 62 typeVariables.addAll(typeArgument.accept(this, visited)); 63 } 64 return typeVariables.build(); 65 } 66 67 @Override visitTypeVariable(TypeVariable t, Set<Element> visited)68 public ImmutableSet<TypeVariable> visitTypeVariable(TypeVariable t, Set<Element> visited) { 69 if (!visited.add(t.asElement())) { 70 return ImmutableSet.of(); 71 } 72 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 73 typeVariables.add(t); 74 typeVariables.addAll(t.getLowerBound().accept(this, visited)); 75 typeVariables.addAll(t.getUpperBound().accept(this, visited)); 76 return typeVariables.build(); 77 } 78 79 @Override visitUnion(UnionType t, Set<Element> visited)80 public ImmutableSet<TypeVariable> visitUnion(UnionType t, Set<Element> visited) { 81 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 82 for (TypeMirror unionType : t.getAlternatives()) { 83 typeVariables.addAll(unionType.accept(this, visited)); 84 } 85 return typeVariables.build(); 86 } 87 88 @Override visitIntersection(IntersectionType t, Set<Element> visited)89 public ImmutableSet<TypeVariable> visitIntersection(IntersectionType t, Set<Element> visited) { 90 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 91 for (TypeMirror intersectionType : t.getBounds()) { 92 typeVariables.addAll(intersectionType.accept(this, visited)); 93 } 94 return typeVariables.build(); 95 } 96 97 @Override visitWildcard(WildcardType t, Set<Element> visited)98 public ImmutableSet<TypeVariable> visitWildcard(WildcardType t, Set<Element> visited) { 99 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 100 TypeMirror extendsBound = t.getExtendsBound(); 101 if (extendsBound != null) { 102 typeVariables.addAll(extendsBound.accept(this, visited)); 103 } 104 TypeMirror superBound = t.getSuperBound(); 105 if (superBound != null) { 106 typeVariables.addAll(superBound.accept(this, visited)); 107 } 108 return typeVariables.build(); 109 } 110 } 111 } 112