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 extends 42 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( 57 DeclaredType t, Set<Element> visited) { 58 if (!visited.add(t.asElement())) { 59 return ImmutableSet.of(); 60 } 61 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 62 for (TypeMirror typeArgument : t.getTypeArguments()) { 63 typeVariables.addAll(typeArgument.accept(this, visited)); 64 } 65 return typeVariables.build(); 66 } 67 68 @Override visitTypeVariable( TypeVariable t, Set<Element> visited)69 public ImmutableSet<TypeVariable> visitTypeVariable( 70 TypeVariable t, Set<Element> visited) { 71 if (!visited.add(t.asElement())) { 72 return ImmutableSet.of(); 73 } 74 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 75 typeVariables.add(t); 76 typeVariables.addAll(t.getLowerBound().accept(this, visited)); 77 typeVariables.addAll(t.getUpperBound().accept(this, visited)); 78 return typeVariables.build(); 79 } 80 81 @Override visitUnion( UnionType t, Set<Element> visited)82 public ImmutableSet<TypeVariable> visitUnion( 83 UnionType t, Set<Element> visited) { 84 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 85 for (TypeMirror unionType : t.getAlternatives()) { 86 typeVariables.addAll(unionType.accept(this, visited)); 87 } 88 return typeVariables.build(); 89 } 90 91 @Override visitIntersection( IntersectionType t, Set<Element> visited)92 public ImmutableSet<TypeVariable> visitIntersection( 93 IntersectionType t, Set<Element> visited) { 94 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 95 for (TypeMirror intersectionType : t.getBounds()) { 96 typeVariables.addAll(intersectionType.accept(this, visited)); 97 } 98 return typeVariables.build(); 99 } 100 101 @Override visitWildcard( WildcardType t, Set<Element> visited)102 public ImmutableSet<TypeVariable> visitWildcard( 103 WildcardType t, Set<Element> visited) { 104 ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); 105 TypeMirror extendsBound = t.getExtendsBound(); 106 if (extendsBound != null) { 107 typeVariables.addAll(extendsBound.accept(this, visited)); 108 } 109 TypeMirror superBound = t.getSuperBound(); 110 if (superBound != null) { 111 typeVariables.addAll(superBound.accept(this, visited)); 112 } 113 return typeVariables.build(); 114 } 115 } 116 } 117