1 /* 2 * Copyright (C) 2007-2010 Júlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2016 The JavaParser Team. 4 * 5 * This file is part of JavaParser. 6 * 7 * JavaParser can be used either under the terms of 8 * a) the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * b) the terms of the Apache License 12 * 13 * You should have received a copy of both licenses in LICENCE.LGPL and 14 * LICENCE.APACHE. Please refer to those files for details. 15 * 16 * JavaParser is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Lesser General Public License for more details. 20 */ 21 22 package com.github.javaparser.resolution.types; 23 24 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; 25 26 import java.util.List; 27 import java.util.Map; 28 29 /** 30 * A wildcard can be: 31 * - unbounded (?) 32 * - have a lower bound (? super Number) 33 * - have an upper bound (? extends Number) 34 * It is not possible to have both a lower and an upper bound at the same time. 35 * 36 * @author Federico Tomassetti 37 */ 38 public class ResolvedWildcard implements ResolvedType { 39 40 public static ResolvedWildcard UNBOUNDED = new ResolvedWildcard(null, null); 41 42 private BoundType type; 43 private ResolvedType boundedType; 44 ResolvedWildcard(BoundType type, ResolvedType boundedType)45 private ResolvedWildcard(BoundType type, ResolvedType boundedType) { 46 if (type == null && boundedType != null) { 47 throw new IllegalArgumentException(); 48 } 49 if (type != null && boundedType == null) { 50 throw new IllegalArgumentException(); 51 } 52 this.type = type; 53 this.boundedType = boundedType; 54 } 55 superBound(ResolvedType type)56 public static ResolvedWildcard superBound(ResolvedType type) { 57 return new ResolvedWildcard(BoundType.SUPER, type); 58 } 59 extendsBound(ResolvedType type)60 public static ResolvedWildcard extendsBound(ResolvedType type) { 61 return new ResolvedWildcard(BoundType.EXTENDS, type); 62 } 63 64 @Override toString()65 public String toString() { 66 return "WildcardUsage{" + 67 "type=" + type + 68 ", boundedType=" + boundedType + 69 '}'; 70 } 71 isWildcard()72 public boolean isWildcard() { 73 return true; 74 } 75 asWildcard()76 public ResolvedWildcard asWildcard() { 77 return this; 78 } 79 80 @Override equals(Object o)81 public boolean equals(Object o) { 82 if (this == o) return true; 83 if (!(o instanceof ResolvedWildcard)) return false; 84 85 ResolvedWildcard that = (ResolvedWildcard) o; 86 87 if (boundedType != null ? !boundedType.equals(that.boundedType) : that.boundedType != null) return false; 88 if (type != that.type) return false; 89 90 return true; 91 } 92 93 @Override hashCode()94 public int hashCode() { 95 int result = type != null ? type.hashCode() : 0; 96 result = 31 * result + (boundedType != null ? boundedType.hashCode() : 0); 97 return result; 98 } 99 100 @Override describe()101 public String describe() { 102 if (type == null) { 103 return "?"; 104 } else if (type == BoundType.SUPER) { 105 return "? super " + boundedType.describe(); 106 } else if (type == BoundType.EXTENDS) { 107 return "? extends " + boundedType.describe(); 108 } else { 109 throw new UnsupportedOperationException(); 110 } 111 } 112 isSuper()113 public boolean isSuper() { 114 return type == BoundType.SUPER; 115 } 116 isExtends()117 public boolean isExtends() { 118 return type == BoundType.EXTENDS; 119 } 120 isBounded()121 public boolean isBounded() { 122 return isSuper() || isExtends(); 123 } 124 getBoundedType()125 public ResolvedType getBoundedType() { 126 if (boundedType == null) { 127 throw new IllegalStateException(); 128 } 129 return boundedType; 130 } 131 132 @Override isAssignableBy(ResolvedType other)133 public boolean isAssignableBy(ResolvedType other) { 134 if (boundedType == null) { 135 //return other.isReferenceType() && other.asReferenceType().getQualifiedName().equals(Object.class.getCanonicalName()); 136 return false; 137 } else if (type == BoundType.SUPER) { 138 return boundedType.isAssignableBy(other); 139 } else if (type == BoundType.EXTENDS) { 140 return false; 141 } else { 142 throw new RuntimeException(); 143 } 144 } 145 146 @Override replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes)147 public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { 148 if (replaced == null) { 149 throw new IllegalArgumentException(); 150 } 151 if (boundedType == null) { 152 return this; 153 } 154 ResolvedType boundedTypeReplaced = boundedType.replaceTypeVariables(tpToReplace, replaced, inferredTypes); 155 if (boundedTypeReplaced == null) { 156 throw new RuntimeException(); 157 } 158 if (boundedTypeReplaced != boundedType) { 159 return new ResolvedWildcard(type, boundedTypeReplaced); 160 } else { 161 return this; 162 } 163 } 164 165 @Override mention(List<ResolvedTypeParameterDeclaration> typeParameters)166 public boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) { 167 return boundedType != null && boundedType.mention(typeParameters); 168 } 169 isUpperBounded()170 public boolean isUpperBounded() { 171 return isSuper(); 172 } 173 isLowerBounded()174 public boolean isLowerBounded() { 175 return isExtends(); 176 } 177 178 public enum BoundType { 179 SUPER, 180 EXTENDS 181 } 182 183 } 184