1 /******************************************************************************* 2 * Copyright (c) 2000, 2016 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types; 15 16 import org.eclipse.core.runtime.Assert; 17 18 import org.eclipse.jdt.core.dom.ITypeBinding; 19 20 21 public final class ArrayType extends TType { 22 private TType fElementType; 23 private int fDimensions; 24 25 private TType fErasure; 26 ArrayType(TypeEnvironment environment)27 protected ArrayType(TypeEnvironment environment) { 28 super(environment); 29 } 30 ArrayType(TypeEnvironment environment, String key)31 protected ArrayType(TypeEnvironment environment, String key) { 32 super(environment, key); 33 } 34 initialize(ITypeBinding binding, TType elementType)35 protected void initialize(ITypeBinding binding, TType elementType) { 36 Assert.isTrue(binding.isArray()); 37 super.initialize(binding); 38 fElementType= elementType; 39 fDimensions= binding.getDimensions(); 40 if (fElementType.isStandardType() || fElementType.isGenericType() || fElementType.isPrimitiveType()) { 41 fErasure= this; 42 } else { 43 fErasure= getEnvironment().create(binding.getErasure()); 44 } 45 } 46 initialize(TType elementType, int dimensions)47 protected void initialize(TType elementType, int dimensions) { 48 fElementType= elementType; 49 fDimensions= dimensions; 50 if (fElementType.isStandardType() || fElementType.isGenericType() || fElementType.isPrimitiveType()) { 51 fErasure= this; 52 } else { 53 fErasure= getEnvironment().createArrayType(elementType.getErasure(), dimensions); 54 } 55 } 56 getElementType()57 public TType getElementType() { 58 return fElementType; 59 } 60 61 /** 62 * Returns the component type of this array. 63 * If getDimensions() is 1, the component type is the element type. 64 * If getDimensions() is > 1, the component type is an array type 65 * with element type getElementType() and dimensions getDimensions() - 1. 66 * 67 * @return the component type 68 */ getComponentType()69 public TType getComponentType() { 70 if (fDimensions > 1) 71 return getEnvironment().createArrayType(fElementType, fDimensions - 1); 72 else 73 return fElementType; 74 } 75 getDimensions()76 public int getDimensions() { 77 return fDimensions; 78 } 79 80 @Override getKind()81 public int getKind() { 82 return ARRAY_TYPE; 83 } 84 85 @Override getSubTypes()86 public TType[] getSubTypes() { 87 TType[] subTypes= fElementType.getSubTypes(); 88 TType[] result= new TType[subTypes.length]; 89 for (int i= 0; i < subTypes.length; i++) { 90 result[i]= getEnvironment().createArrayType(subTypes[i], fDimensions); 91 } 92 return result; 93 } 94 95 @Override getErasure()96 public TType getErasure() { 97 return fErasure; 98 } 99 100 @Override doEquals(TType other)101 public boolean doEquals(TType other) { 102 ArrayType arrayType= (ArrayType)other; 103 return fElementType.equals(arrayType.fElementType) && fDimensions == arrayType.fDimensions; 104 } 105 106 @Override hashCode()107 public int hashCode() { 108 return fElementType.hashCode() << ARRAY_TYPE_SHIFT; 109 } 110 111 @Override doCanAssignTo(TType lhs)112 protected boolean doCanAssignTo(TType lhs) { 113 switch (lhs.getKind()) { 114 case NULL_TYPE: return false; 115 case VOID_TYPE: return false; 116 case PRIMITIVE_TYPE: return false; 117 118 case ARRAY_TYPE: return canAssignToArrayType((ArrayType)lhs); 119 120 case GENERIC_TYPE: return false; 121 case STANDARD_TYPE: return isArrayLhsCompatible(lhs); 122 case PARAMETERIZED_TYPE: return false; 123 case RAW_TYPE: return false; 124 125 case UNBOUND_WILDCARD_TYPE: 126 case EXTENDS_WILDCARD_TYPE: 127 case SUPER_WILDCARD_TYPE: 128 return ((WildcardType)lhs).checkAssignmentBound(this); 129 130 case TYPE_VARIABLE: return false; 131 case CAPTURE_TYPE: 132 return ((CaptureType)lhs).checkLowerBound(this); 133 } 134 return false; 135 } 136 canAssignToArrayType(ArrayType lhs)137 private boolean canAssignToArrayType(ArrayType lhs) { 138 if (fDimensions == lhs.fDimensions) { 139 // primitive type don't have any conversion for arrays. 140 if (fElementType.getKind() == PRIMITIVE_TYPE || lhs.fElementType.getKind() == PRIMITIVE_TYPE) 141 return fElementType.isTypeEquivalentTo(lhs.fElementType); 142 return fElementType.canAssignTo(lhs.fElementType); 143 } 144 if (fDimensions < lhs.fDimensions) 145 return false; 146 return isArrayLhsCompatible(lhs.fElementType); 147 } 148 isArrayLhsCompatible(TType lhsElementType)149 private boolean isArrayLhsCompatible(TType lhsElementType) { 150 return lhsElementType.isJavaLangObject() || lhsElementType.isJavaLangCloneable() || lhsElementType.isJavaIoSerializable(); 151 } 152 153 @Override getPlainPrettySignature()154 protected String getPlainPrettySignature() { 155 StringBuilder result= new StringBuilder(fElementType.getPlainPrettySignature()); 156 for (int i= 0; i < fDimensions; i++) { 157 result.append("[]"); //$NON-NLS-1$ 158 } 159 return result.toString(); 160 } 161 162 @Override getName()163 public String getName() { 164 StringBuilder result= new StringBuilder(fElementType.getName()); 165 for (int i= 0; i < fDimensions; i++) { 166 result.append("[]"); //$NON-NLS-1$ 167 } 168 return result.toString(); 169 } 170 171 } 172