1 /******************************************************************************* 2 * Copyright (c) 2000, 2017 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 * Stephan Herrmann - Contribution for 14 * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault 15 *******************************************************************************/ 16 package org.eclipse.jdt.internal.compiler.ast; 17 18 import org.eclipse.jdt.core.compiler.CharOperation; 19 import org.eclipse.jdt.internal.compiler.ASTVisitor; 20 import org.eclipse.jdt.internal.compiler.lookup.*; 21 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; 22 23 public class ArrayQualifiedTypeReference extends QualifiedTypeReference { 24 int dimensions; 25 private Annotation[][] annotationsOnDimensions; // jsr308 style type annotations on dimensions 26 public int extendedDimensions; 27 ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss)28 public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) { 29 30 super( sources , poss); 31 this.dimensions = dim ; 32 this.annotationsOnDimensions = null; 33 } 34 ArrayQualifiedTypeReference(char[][] sources, int dim, Annotation[][] annotationsOnDimensions, long[] poss)35 public ArrayQualifiedTypeReference(char[][] sources, int dim, Annotation[][] annotationsOnDimensions, long[] poss) { 36 this(sources, dim, poss); 37 this.annotationsOnDimensions = annotationsOnDimensions; 38 if (annotationsOnDimensions != null) 39 this.bits |= ASTNode.HasTypeAnnotations; 40 } 41 42 @Override dimensions()43 public int dimensions() { 44 45 return this.dimensions; 46 } 47 48 @Override extraDimensions()49 public int extraDimensions() { 50 return this.extendedDimensions; 51 } 52 53 /** 54 @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getAnnotationsOnDimensions(boolean) 55 */ 56 @Override getAnnotationsOnDimensions(boolean useSourceOrder)57 public Annotation[][] getAnnotationsOnDimensions(boolean useSourceOrder) { 58 if (useSourceOrder || this.annotationsOnDimensions == null || this.annotationsOnDimensions.length == 0 || this.extendedDimensions == 0 || this.extendedDimensions == this.dimensions) 59 return this.annotationsOnDimensions; 60 Annotation [][] externalAnnotations = new Annotation[this.dimensions][]; 61 final int baseDimensions = this.dimensions - this.extendedDimensions; 62 System.arraycopy(this.annotationsOnDimensions, baseDimensions, externalAnnotations, 0, this.extendedDimensions); 63 System.arraycopy(this.annotationsOnDimensions, 0, externalAnnotations, this.extendedDimensions, baseDimensions); 64 return externalAnnotations; 65 } 66 67 @Override setAnnotationsOnDimensions(Annotation [][] annotationsOnDimensions)68 public void setAnnotationsOnDimensions(Annotation [][] annotationsOnDimensions) { 69 this.annotationsOnDimensions = annotationsOnDimensions; 70 } 71 72 /** 73 * @return char[][] 74 */ 75 @Override getParameterizedTypeName()76 public char [][] getParameterizedTypeName(){ 77 int dim = this.dimensions; 78 char[] dimChars = new char[dim*2]; 79 for (int i = 0; i < dim; i++) { 80 int index = i*2; 81 dimChars[index] = '['; 82 dimChars[index+1] = ']'; 83 } 84 int length = this.tokens.length; 85 char[][] qParamName = new char[length][]; 86 System.arraycopy(this.tokens, 0, qParamName, 0, length-1); 87 qParamName[length-1] = CharOperation.concat(this.tokens[length-1], dimChars); 88 return qParamName; 89 } 90 91 @Override getTypeBinding(Scope scope)92 protected TypeBinding getTypeBinding(Scope scope) { 93 94 if (this.resolvedType != null) 95 return this.resolvedType; 96 if (this.dimensions > 255) { 97 scope.problemReporter().tooManyDimensions(this); 98 } 99 LookupEnvironment env = scope.environment(); 100 try { 101 env.missingClassFileLocation = this; 102 TypeBinding leafComponentType = super.getTypeBinding(scope); 103 if (leafComponentType != null) { 104 return this.resolvedType = scope.createArrayType(leafComponentType, this.dimensions); 105 } 106 return null; 107 } catch (AbortCompilation e) { 108 e.updateContext(this, scope.referenceCompilationUnit().compilationResult); 109 throw e; 110 } finally { 111 env.missingClassFileLocation = null; 112 } 113 } 114 115 @Override internalResolveType(Scope scope, int location)116 protected TypeBinding internalResolveType(Scope scope, int location) { 117 TypeBinding internalResolveType = super.internalResolveType(scope, location); 118 internalResolveType = ArrayTypeReference.maybeMarkArrayContentsNonNull(scope, internalResolveType, this.sourceStart, this.dimensions, null); 119 120 return internalResolveType; 121 } 122 123 @Override printExpression(int indent, StringBuffer output)124 public StringBuffer printExpression(int indent, StringBuffer output){ 125 126 super.printExpression(indent, output); 127 if ((this.bits & IsVarArgs) != 0) { 128 for (int i= 0 ; i < this.dimensions - 1; i++) { 129 if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[i] != null) { 130 output.append(' '); 131 printAnnotations(this.annotationsOnDimensions[i], output); 132 output.append(' '); 133 } 134 output.append("[]"); //$NON-NLS-1$ 135 } 136 if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[this.dimensions - 1] != null) { 137 output.append(' '); 138 printAnnotations(this.annotationsOnDimensions[this.dimensions - 1], output); 139 output.append(' '); 140 } 141 output.append("..."); //$NON-NLS-1$ 142 } else { 143 for (int i= 0 ; i < this.dimensions; i++) { 144 if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[i] != null) { 145 output.append(" "); //$NON-NLS-1$ 146 printAnnotations(this.annotationsOnDimensions[i], output); 147 output.append(" "); //$NON-NLS-1$ 148 } 149 output.append("[]"); //$NON-NLS-1$ 150 } 151 } 152 return output; 153 } 154 155 @Override traverse(ASTVisitor visitor, BlockScope scope)156 public void traverse(ASTVisitor visitor, BlockScope scope) { 157 if (visitor.visit(this, scope)) { 158 if (this.annotations != null) { 159 int annotationsLevels = this.annotations.length; 160 for (int i = 0; i < annotationsLevels; i++) { 161 int annotationsLength = this.annotations[i] == null ? 0 : this.annotations[i].length; 162 for (int j = 0; j < annotationsLength; j++) 163 this.annotations[i][j].traverse(visitor, scope); 164 } 165 } 166 if (this.annotationsOnDimensions != null) { 167 for (int i = 0, max = this.annotationsOnDimensions.length; i < max; i++) { 168 Annotation[] annotations2 = this.annotationsOnDimensions[i]; 169 for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) { 170 Annotation annotation = annotations2[j]; 171 annotation.traverse(visitor, scope); 172 } 173 } 174 } 175 } 176 visitor.endVisit(this, scope); 177 } 178 179 @Override traverse(ASTVisitor visitor, ClassScope scope)180 public void traverse(ASTVisitor visitor, ClassScope scope) { 181 if (visitor.visit(this, scope)) { 182 if (this.annotations != null) { 183 int annotationsLevels = this.annotations.length; 184 for (int i = 0; i < annotationsLevels; i++) { 185 int annotationsLength = this.annotations[i] == null ? 0 : this.annotations[i].length; 186 for (int j = 0; j < annotationsLength; j++) 187 this.annotations[i][j].traverse(visitor, scope); 188 } 189 } 190 if (this.annotationsOnDimensions != null) { 191 for (int i = 0, max = this.annotationsOnDimensions.length; i < max; i++) { 192 Annotation[] annotations2 = this.annotationsOnDimensions[i]; 193 for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) { 194 Annotation annotation = annotations2[j]; 195 annotation.traverse(visitor, scope); 196 } 197 } 198 } 199 } 200 visitor.endVisit(this, scope); 201 } 202 } 203