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 }