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