Coverage Summary for Class: TypeVisitor (com.google.common.reflect)

Class Class, % Method, % Line, %
TypeVisitor 100% (1/1) 42.9% (3/7) 74.1% (20/27)


1 /* 2  * Copyright (C) 2013 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5  * in compliance with the License. You may obtain a copy of the License at 6  * 7  * http://www.apache.org/licenses/LICENSE-2.0 8  * 9  * Unless required by applicable law or agreed to in writing, software distributed under the License 10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11  * or implied. See the License for the specific language governing permissions and limitations under 12  * the License. 13  */ 14  15 package com.google.common.reflect; 16  17 import com.google.common.collect.Sets; 18 import java.lang.reflect.GenericArrayType; 19 import java.lang.reflect.ParameterizedType; 20 import java.lang.reflect.Type; 21 import java.lang.reflect.TypeVariable; 22 import java.lang.reflect.WildcardType; 23 import java.util.Set; 24 import org.checkerframework.checker.nullness.qual.Nullable; 25  26 /** 27  * Based on what a {@link Type} is, dispatch it to the corresponding {@code visit*} method. By 28  * default, no recursion is done for type arguments or type bounds. But subclasses can opt to do 29  * recursion by calling {@link #visit} for any {@code Type} while visitation is in progress. For 30  * example, this can be used to reject wildcards or type variables contained in a type as in: 31  * 32  * <pre>{@code 33  * new TypeVisitor() { 34  * protected void visitParameterizedType(ParameterizedType t) { 35  * visit(t.getOwnerType()); 36  * visit(t.getActualTypeArguments()); 37  * } 38  * protected void visitGenericArrayType(GenericArrayType t) { 39  * visit(t.getGenericComponentType()); 40  * } 41  * protected void visitTypeVariable(TypeVariable<?> t) { 42  * throw new IllegalArgumentException("Cannot contain type variable."); 43  * } 44  * protected void visitWildcardType(WildcardType t) { 45  * throw new IllegalArgumentException("Cannot contain wildcard type."); 46  * } 47  * }.visit(type); 48  * }</pre> 49  * 50  * <p>One {@code Type} is visited at most once. The second time the same type is visited, it's 51  * ignored by {@link #visit}. This avoids infinite recursion caused by recursive type bounds. 52  * 53  * <p>This class is <em>not</em> thread safe. 54  * 55  * @author Ben Yu 56  */ 57 @ElementTypesAreNonnullByDefault 58 abstract class TypeVisitor { 59  60  private final Set<Type> visited = Sets.newHashSet(); 61  62  /** 63  * Visits the given types. Null types are ignored. This allows subclasses to call {@code 64  * visit(parameterizedType.getOwnerType())} safely without having to check nulls. 65  */ 66  public final void visit(@Nullable Type... types) { 67  for (Type type : types) { 68  if (type == null || !visited.add(type)) { 69  // null owner type, or already visited; 70  continue; 71  } 72  boolean succeeded = false; 73  try { 74  if (type instanceof TypeVariable) { 75  visitTypeVariable((TypeVariable<?>) type); 76  } else if (type instanceof WildcardType) { 77  visitWildcardType((WildcardType) type); 78  } else if (type instanceof ParameterizedType) { 79  visitParameterizedType((ParameterizedType) type); 80  } else if (type instanceof Class) { 81  visitClass((Class<?>) type); 82  } else if (type instanceof GenericArrayType) { 83  visitGenericArrayType((GenericArrayType) type); 84  } else { 85  throw new AssertionError("Unknown type: " + type); 86  } 87  succeeded = true; 88  } finally { 89  if (!succeeded) { // When the visitation failed, we don't want to ignore the second. 90  visited.remove(type); 91  } 92  } 93  } 94  } 95  96  void visitClass(Class<?> t) {} 97  98  void visitGenericArrayType(GenericArrayType t) {} 99  100  void visitParameterizedType(ParameterizedType t) {} 101  102  void visitTypeVariable(TypeVariable<?> t) {} 103  104  void visitWildcardType(WildcardType t) {} 105 }