/* * SonarQube Java * Copyright (C) 2012-2016 SonarSource SA * mailto:contact AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.java.resolve; import org.sonar.plugins.java.api.semantic.Symbol; import org.sonar.plugins.java.api.semantic.Type; import javax.annotation.Nullable; public class JavaType implements Type { public static final int BYTE = 1; public static final int CHAR = 2; public static final int SHORT = 3; public static final int INT = 4; public static final int LONG = 5; public static final int FLOAT = 6; public static final int DOUBLE = 7; public static final int BOOLEAN = 8; public static final int VOID = 9; public static final int CLASS = 10; public static final int ARRAY = 11; public static final int METHOD = 12; public static final int BOT = 13; public static final int UNKNOWN = 14; public static final int TYPEVAR = 15; public static final int WILDCARD = 16; public static final int DEFERRED = 17; public static final int PARAMETERIZED = 18; int tag; JavaType primitiveType = null; JavaType primitiveWrapperType = null; /** * Symbol, which defines this type. */ JavaSymbol.TypeJavaSymbol symbol; public JavaType(int tag, JavaSymbol.TypeJavaSymbol symbol) { this.tag = tag; this.symbol = symbol; } public boolean isTagged(int tag) { return tag == this.tag; } @Override public boolean isNumerical() { // JLS8 4.2 return tag <= DOUBLE; } public JavaSymbol.TypeJavaSymbol getSymbol() { symbol.complete(); return symbol; } @Override public boolean is(String fullyQualifiedName) { if (tag < CLASS) { // primitive type return fullyQualifiedName.equals(symbol.name); } else if (isTagged(ARRAY)) { return fullyQualifiedName.endsWith("[]") && ((ArrayJavaType) this).elementType.is(fullyQualifiedName.substring(0, fullyQualifiedName.length() - 2)); } else if (isTagged(TYPEVAR)) { return false; } return false; } @Override public boolean isSubtypeOf(String fullyQualifiedName) { if (isTagged(ARRAY)) { return "java.lang.Object".equals(fullyQualifiedName) || (fullyQualifiedName.endsWith("[]") && ((ArrayJavaType) this).elementType.isSubtypeOf(fullyQualifiedName.substring(0, fullyQualifiedName.length() - 2))); } else if (isTagged(TYPEVAR)) { return erasure().isSubtypeOf(fullyQualifiedName); } return false; } @Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; if (isTagged(ARRAY)) { //Handle covariance of arrays. if(supType.isTagged(ARRAY)) { return ((ArrayType) this).elementType().isSubtypeOf(((ArrayType) supType).elementType()); } if(supType.isTagged(WILDCARD)) { return ((WildCardType) superType).isSubtypeOfBound(this); } //Only possibility to be supertype of array without being an array is to be Object. return "java.lang.Object".equals(supType.fullyQualifiedName()); } return false; } /** * JLS8 4.6 */ @Override public JavaType erasure() { return this; } @Override public boolean isPrimitive() { return tag <= BOOLEAN; } @Override public boolean isPrimitive(Primitives primitive) { return tag == primitive.ordinal() + 1; } @Override public boolean isUnknown() { return false; } public boolean isPrimitiveWrapper() { if (!isTagged(CLASS)) { return false; } return is("java.lang.Byte") || is("java.lang.Character") || is("java.lang.Short") || is("java.lang.Integer") || is("java.lang.Long") || is("java.lang.Float") || is("java.lang.Double") || is("java.lang.Boolean"); } @Override public String toString() { return symbol == null ? "" : symbol.toString(); } @Nullable public JavaType primitiveType() { return primitiveType; } @Nullable public JavaType primitiveWrapperType() { return primitiveWrapperType; } @Override public boolean isArray() { return isTagged(ARRAY); } public boolean isParameterized() { return isTagged(PARAMETERIZED); } @Override public boolean isClass() { return isTagged(CLASS) || isTagged(PARAMETERIZED); } @Override public boolean isVoid() { return isTagged(VOID); } @Override public String fullyQualifiedName() { return symbol.getFullyQualifiedName(); } @Override public String name() { return symbol.name; } @Override public Symbol.TypeSymbol symbol() { return getSymbol(); } }