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 - Contributions for
14  *								bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding
15  *								bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
16  *								Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
17  *								Bug 416181 - [1.8][compiler][null] Invalid assignment is not rejected by the compiler
18  *								Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
19  *								Bug 434600 - Incorrect null analysis error reporting on type parameters
20  *								Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E"
21  *								Bug 456508 - Unexpected RHS PolyTypeBinding for: <code-snippet>
22  *								Bug 466713 - Null Annotations: NullPointerException using <int @Nullable []> as Type Param
23  *        Andy Clement - Contributions for
24  *                          Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
25  *******************************************************************************/
26 package org.eclipse.jdt.internal.compiler.ast;
27 
28 import org.eclipse.jdt.core.compiler.CharOperation;
29 import org.eclipse.jdt.internal.compiler.ASTVisitor;
30 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
31 import org.eclipse.jdt.internal.compiler.impl.Constant;
32 import org.eclipse.jdt.internal.compiler.lookup.*;
33 
34 /**
35  * Syntactic representation of a reference to a generic type.
36  * Note that it might also have a dimension.
37  */
38 public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeReference {
39 
40 	public TypeReference[][] typeArguments;
41 	ReferenceBinding[] typesPerToken;
42 
43 	/**
44 	 * @param tokens
45 	 * @param dim
46 	 * @param positions
47 	 */
ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions)48 	public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions) {
49 
50 		super(tokens, dim, positions);
51 		this.typeArguments = typeArguments;
52 		annotationSearch: for (int i = 0, max = typeArguments.length; i < max; i++) {
53 			TypeReference[] typeArgumentsOnTypeComponent = typeArguments[i];
54 			if (typeArgumentsOnTypeComponent != null) {
55 				for (int j = 0, max2 = typeArgumentsOnTypeComponent.length; j < max2; j++) {
56 					if ((typeArgumentsOnTypeComponent[j].bits & ASTNode.HasTypeAnnotations) != 0) {
57 						this.bits |= ASTNode.HasTypeAnnotations;
58 						break annotationSearch;
59 					}
60 				}
61 			}
62 		}
63 	}
ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, Annotation[][] annotationsOnDimensions, long[] positions)64 	public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, Annotation[][] annotationsOnDimensions, long[] positions) {
65 		this(tokens, typeArguments, dim, positions);
66 		setAnnotationsOnDimensions(annotationsOnDimensions);
67 		if (annotationsOnDimensions != null) {
68 			this.bits |= ASTNode.HasTypeAnnotations;
69 		}
70 	}
71 	@Override
checkBounds(Scope scope)72 	public void checkBounds(Scope scope) {
73 		if (this.resolvedType == null || !this.resolvedType.isValidBinding()) return;
74 
75 		checkBounds(
76 			(ReferenceBinding) this.resolvedType.leafComponentType(),
77 			scope,
78 			this.typeArguments.length - 1);
79 	}
checkBounds(ReferenceBinding type, Scope scope, int index)80 	public void checkBounds(ReferenceBinding type, Scope scope, int index) {
81 		// recurse on enclosing type if any, and assuming explictly  part of the reference (index>0)
82 		if (index > 0) {
83 			ReferenceBinding enclosingType = this.typesPerToken[index-1];
84 			if (enclosingType != null)
85 				checkBounds(enclosingType, scope, index - 1);
86 		}
87 		if (type.isParameterizedTypeWithActualArguments()) {
88 			ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type;
89 			ReferenceBinding currentType = parameterizedType.genericType();
90 			TypeVariableBinding[] typeVariables = currentType.typeVariables();
91 			if (typeVariables != null) { // argTypes may be null in error cases
92 				parameterizedType.boundCheck(scope, this.typeArguments[index]);
93 			}
94 		}
95 	}
96 	@Override
augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs)97 	public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
98 		int totalDimensions = this.dimensions() + additionalDimensions;
99 		Annotation [][] allAnnotations = getMergedAnnotationsOnDimensions(additionalDimensions, additionalAnnotations);
100 		ParameterizedQualifiedTypeReference pqtr = new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, totalDimensions, allAnnotations, this.sourcePositions);
101 		pqtr.annotations = this.annotations;
102 		pqtr.bits |= (this.bits & ASTNode.HasTypeAnnotations);
103 		if (!isVarargs)
104 			pqtr.extendedDimensions = additionalDimensions;
105 		return pqtr;
106 	}
107 	@Override
isParameterizedTypeReference()108 	public boolean isParameterizedTypeReference() {
109 		return true;
110 	}
111 
112 	@Override
hasNullTypeAnnotation(AnnotationPosition position)113     public boolean hasNullTypeAnnotation(AnnotationPosition position) {
114 		if (super.hasNullTypeAnnotation(position))
115 			return true;
116 		if (position == AnnotationPosition.ANY) {
117 	    	if (this.resolvedType != null && !this.resolvedType.hasNullTypeAnnotations())
118 	    		return false; // shortcut
119 	    	if (this.typeArguments != null) {
120 	    		for (int i = 0; i < this.typeArguments.length; i++) {
121 	    			TypeReference[] arguments = this.typeArguments[i];
122 	    			if (arguments != null) {
123 		    			for (int j = 0; j < arguments.length; j++) {
124 		    				if (arguments[j].hasNullTypeAnnotation(position))
125 		    					return true;
126 		    			}
127 					}
128 				}
129 	    	}
130 		}
131     	return false;
132     }
133 
134 	/**
135 	 * @return char[][]
136 	 */
137 	@Override
getParameterizedTypeName()138 	public char [][] getParameterizedTypeName(){
139 		int length = this.tokens.length;
140 		char[][] qParamName = new char[length][];
141 		for (int i = 0; i < length; i++) {
142 			TypeReference[] arguments = this.typeArguments[i];
143 			if (arguments == null) {
144 				qParamName[i] = this.tokens[i];
145 			} else {
146 				StringBuffer buffer = new StringBuffer(5);
147 				buffer.append(this.tokens[i]);
148 				buffer.append('<');
149 				for (int j = 0, argLength =arguments.length; j < argLength; j++) {
150 					if (j > 0) buffer.append(',');
151 					buffer.append(CharOperation.concatWith(arguments[j].getParameterizedTypeName(), '.'));
152 				}
153 				buffer.append('>');
154 				int nameLength = buffer.length();
155 				qParamName[i] = new char[nameLength];
156 				buffer.getChars(0, nameLength, qParamName[i], 0);
157 			}
158 		}
159 		int dim = this.dimensions;
160 		if (dim > 0) {
161 			char[] dimChars = new char[dim*2];
162 			for (int i = 0; i < dim; i++) {
163 				int index = i*2;
164 				dimChars[index] = '[';
165 				dimChars[index+1] = ']';
166 			}
167 			qParamName[length-1] = CharOperation.concat(qParamName[length-1], dimChars);
168 		}
169 		return qParamName;
170 	}
171 
172 	@Override
getTypeArguments()173 	public TypeReference[][] getTypeArguments() {
174 		return this.typeArguments;
175 	}
176 
177     @Override
getTypeBinding(Scope scope)178 	protected TypeBinding getTypeBinding(Scope scope) {
179         return null; // not supported here - combined with resolveType(...)
180     }
181 
182     /*
183      * No need to check for reference to raw type per construction
184      */
internalResolveType(Scope scope, boolean checkBounds, int location)185 	private TypeBinding internalResolveType(Scope scope, boolean checkBounds, int location) {
186 		// handle the error here
187 		this.constant = Constant.NotAConstant;
188 		if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved
189 			if (this.resolvedType != null) { // is a shared type reference which was already resolved
190 				if (this.resolvedType.isValidBinding()) {
191 					return this.resolvedType;
192 				} else {
193 					switch (this.resolvedType.problemId()) {
194 						case ProblemReasons.NotFound :
195 						case ProblemReasons.NotVisible :
196 						case ProblemReasons.InheritedNameHidesEnclosingName :
197 							TypeBinding type = this.resolvedType.closestMatch();
198 							return type;
199 						default :
200 							return null;
201 					}
202 				}
203 			}
204 		}
205 		this.bits |= ASTNode.DidResolve;
206 		TypeBinding type = internalResolveLeafType(scope, checkBounds);
207 		createArrayType(scope);
208 		resolveAnnotations(scope, location);
209 		if(this.dimensions > 0) {
210 			this.resolvedType = ArrayTypeReference.maybeMarkArrayContentsNonNull(scope, this.resolvedType, this.sourceStart, this.dimensions, null);
211 		}
212 
213 		if (this.typeArguments != null)
214 			// relevant null annotations are on the inner most type:
215 			checkIllegalNullAnnotations(scope, this.typeArguments[this.typeArguments.length-1]);
216 		return type == null ? type : this.resolvedType;
217 	}
internalResolveLeafType(Scope scope, boolean checkBounds)218 	private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) {
219 		boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
220 		Binding binding = scope.getPackage(this.tokens);
221 		if (binding != null && !binding.isValidBinding()) {
222 			this.resolvedType = (ReferenceBinding) binding;
223 			reportInvalidType(scope);
224 			// be resilient, still attempt resolving arguments
225 			for (int i = 0, max = this.tokens.length; i < max; i++) {
226 				TypeReference[] args = this.typeArguments[i];
227 				if (args != null) {
228 					int argLength = args.length;
229 					for (int j = 0; j < argLength; j++) {
230 						TypeReference typeArgument = args[j];
231 						if (isClassScope) {
232 							typeArgument.resolveType((ClassScope) scope);
233 						} else {
234 							typeArgument.resolveType((BlockScope) scope, checkBounds);
235 						}
236 					}
237 				}
238 			}
239 			return null;
240 		}
241 
242 		PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding;
243 		rejectAnnotationsOnPackageQualifiers(scope, packageBinding);
244 
245 		boolean typeIsConsistent = true;
246 		ReferenceBinding qualifyingType = null;
247 		int max = this.tokens.length;
248 		this.typesPerToken = new ReferenceBinding[max];
249 		for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length; i < max; i++) {
250 			findNextTypeBinding(i, scope, packageBinding);
251 			if (!(this.resolvedType.isValidBinding())) {
252 				reportInvalidType(scope);
253 				// be resilient, still attempt resolving arguments
254 				for (int j = i; j < max; j++) {
255 				    TypeReference[] args = this.typeArguments[j];
256 				    if (args != null) {
257 						int argLength = args.length;
258 						for (int k = 0; k < argLength; k++) {
259 						    TypeReference typeArgument = args[k];
260 						    if (isClassScope) {
261 						    	typeArgument.resolveType((ClassScope) scope);
262 						    } else {
263 						    	typeArgument.resolveType((BlockScope) scope);
264 						    }
265 						}
266 				    }
267 				}
268 				return null;
269 			}
270 			ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
271 			if (qualifyingType == null) {
272 				qualifyingType = currentType.enclosingType(); // if member type
273 				if (qualifyingType != null && currentType.hasEnclosingInstanceContext()) {
274 					qualifyingType = scope.environment().convertToParameterizedType(qualifyingType);
275 				}
276 			} else {
277 				if (this.annotations != null)
278 					rejectAnnotationsOnStaticMemberQualififer(scope, currentType, this.annotations[i-1]);
279 				if (typeIsConsistent && currentType.isStatic()
280 						&& (qualifyingType.isParameterizedTypeWithActualArguments() || qualifyingType.isGenericType())) {
281 					scope.problemReporter().staticMemberOfParameterizedType(this, currentType, qualifyingType, i);
282 					typeIsConsistent = false;
283 					qualifyingType = qualifyingType.actualType(); // avoid raw/parameterized enclosing of static member
284 				}
285 				ReferenceBinding enclosingType = currentType.enclosingType();
286 				if (enclosingType != null && TypeBinding.notEquals(enclosingType.erasure(), qualifyingType.erasure())) { // qualifier != declaring/enclosing
287 					qualifyingType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype
288 				}
289 			}
290 
291 			// check generic and arity
292 		    TypeReference[] args = this.typeArguments[i];
293 		    if (args != null) {
294 			    TypeReference keep = null;
295 			    if (isClassScope) {
296 			    	keep = ((ClassScope) scope).superTypeReference;
297 			    	((ClassScope) scope).superTypeReference = null;
298 			    }
299 				int argLength = args.length;
300 				boolean isDiamond = argLength == 0 && (i == (max -1)) && ((this.bits & ASTNode.IsDiamond) != 0);
301 				TypeBinding[] argTypes = new TypeBinding[argLength];
302 				boolean argHasError = false;
303 				ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original();
304 				for (int j = 0; j < argLength; j++) {
305 				    TypeReference arg = args[j];
306 				    TypeBinding argType = isClassScope
307 						? arg.resolveTypeArgument((ClassScope) scope, currentOriginal, j)
308 						: arg.resolveTypeArgument((BlockScope) scope, currentOriginal, j);
309 					if (argType == null) {
310 						argHasError = true;
311 					} else {
312 						argTypes[j] = argType;
313 					}
314 				}
315 				if (argHasError) {
316 					return null;
317 				}
318 				if (isClassScope) {
319 					((ClassScope) scope).superTypeReference = keep;
320 					if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this))
321 						return null;
322 				}
323 
324 			    TypeVariableBinding[] typeVariables = currentOriginal.typeVariables();
325 				if (typeVariables == Binding.NO_TYPE_VARIABLES) { // check generic
326 					if (scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5) { // below 1.5, already reported as syntax error
327 						scope.problemReporter().nonGenericTypeCannotBeParameterized(i, this, currentType, argTypes);
328 						return null;
329 					}
330 					this.resolvedType =  (qualifyingType != null && qualifyingType.isParameterizedType())
331 						? scope.environment().createParameterizedType(currentOriginal, null, qualifyingType)
332 						: currentType;
333 					return this.resolvedType;
334 				} else if (argLength != typeVariables.length) {
335 					if (!isDiamond) { // check arity
336 						scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes, i);
337 						return null;
338 					}
339 				}
340 				// check parameterizing (non-)static member type of raw type
341 				if (typeIsConsistent) {
342 					if (!currentType.hasEnclosingInstanceContext()) {
343 						if (qualifyingType != null && qualifyingType.isRawType())
344 							this.typesPerToken[i-1] = qualifyingType = qualifyingType.actualType(); // revert rawification of enclosing, since its generics are inaccessible
345 					} else {
346 						ReferenceBinding actualEnclosing = currentType.enclosingType();
347 						if (actualEnclosing != null && actualEnclosing.isRawType()) {
348 							scope.problemReporter().rawMemberTypeCannotBeParameterized(
349 									this, scope.environment().createRawType(currentOriginal, actualEnclosing), argTypes);
350 							typeIsConsistent = false;
351 						}
352 					}
353 				}
354 				ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType(currentOriginal, argTypes, qualifyingType);
355 				// check argument type compatibility for non <> cases - <> case needs no bounds check, we will scream foul if needed during inference.
356 				if (!isDiamond) {
357 					if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
358 						parameterizedType.boundCheck(scope, args);
359 					else
360 						scope.deferBoundCheck(this);
361 				} else {
362 		    		parameterizedType.arguments = ParameterizedSingleTypeReference.DIAMOND_TYPE_ARGUMENTS;
363 				}
364 				qualifyingType = parameterizedType;
365 		    } else {
366 				ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original();
367 				if (isClassScope)
368 					if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this))
369 						return null;
370 				if (currentOriginal.isGenericType()) {
371 	   			    if (typeIsConsistent && qualifyingType != null && qualifyingType.isParameterizedType() && currentOriginal.hasEnclosingInstanceContext()) {
372 						scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.environment().createParameterizedType(currentOriginal, null, qualifyingType), i);
373 						typeIsConsistent = false;
374 					}
375 	   			    qualifyingType = scope.environment().createRawType(currentOriginal, qualifyingType); // raw type
376 				} else {
377 					qualifyingType = scope.environment().maybeCreateParameterizedType(currentOriginal, qualifyingType);
378 				}
379 			}
380 			if (isTypeUseDeprecated(qualifyingType, scope))
381 				reportDeprecatedType(qualifyingType, scope, i);
382 			this.resolvedType = qualifyingType;
383 			this.typesPerToken[i] = qualifyingType;
384 			recordResolution(scope.environment(), this.resolvedType);
385 		}
386 		return this.resolvedType;
387 	}
createArrayType(Scope scope)388 	private void createArrayType(Scope scope) {
389 		if (this.dimensions > 0) {
390 			if (this.dimensions > 255)
391 				scope.problemReporter().tooManyDimensions(this);
392 			this.resolvedType = scope.createArrayType(this.resolvedType, this.dimensions);
393 		}
394 	}
395 
396 	@Override
printExpression(int indent, StringBuffer output)397 	public StringBuffer printExpression(int indent, StringBuffer output) {
398 		int length = this.tokens.length;
399 		for (int i = 0; i < length - 1; i++) {
400 			if (this.annotations != null && this.annotations[i] != null) {
401 				printAnnotations(this.annotations[i], output);
402 				output.append(' ');
403 			}
404 			output.append(this.tokens[i]);
405 			TypeReference[] typeArgument = this.typeArguments[i];
406 			if (typeArgument != null) {
407 				output.append('<');
408 				int typeArgumentLength = typeArgument.length;
409 				if (typeArgumentLength > 0) {
410 					int max = typeArgumentLength - 1;
411 					for (int j = 0; j < max; j++) {
412 						typeArgument[j].print(0, output);
413 						output.append(", ");//$NON-NLS-1$
414 					}
415 					typeArgument[max].print(0, output);
416 				}
417 				output.append('>');
418 			}
419 			output.append('.');
420 		}
421 		if (this.annotations != null && this.annotations[length - 1] != null) {
422 			output.append(" "); //$NON-NLS-1$
423 			printAnnotations(this.annotations[length - 1], output);
424 			output.append(' ');
425 		}
426 		output.append(this.tokens[length - 1]);
427 		TypeReference[] typeArgument = this.typeArguments[length - 1];
428 		if (typeArgument != null) {
429 			output.append('<');
430 			int typeArgumentLength = typeArgument.length;
431 			if (typeArgumentLength > 0) {
432 				int max = typeArgumentLength - 1;
433 				for (int j = 0; j < max; j++) {
434 					typeArgument[j].print(0, output);
435 					output.append(", ");//$NON-NLS-1$
436 				}
437 				typeArgument[max].print(0, output);
438 			}
439 			output.append('>');
440 		}
441 		Annotation [][] annotationsOnDimensions = this.getAnnotationsOnDimensions();
442 		if ((this.bits & IsVarArgs) != 0) {
443 			for (int i= 0 ; i < this.dimensions - 1; i++) {
444 				if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) {
445 					output.append(" "); //$NON-NLS-1$
446 					printAnnotations(annotationsOnDimensions[i], output);
447 					output.append(" "); //$NON-NLS-1$
448 				}
449 				output.append("[]"); //$NON-NLS-1$
450 			}
451 			if (annotationsOnDimensions != null && annotationsOnDimensions[this.dimensions - 1] != null) {
452 				output.append(" "); //$NON-NLS-1$
453 				printAnnotations(annotationsOnDimensions[this.dimensions - 1], output);
454 				output.append(" "); //$NON-NLS-1$
455 			}
456 			output.append("..."); //$NON-NLS-1$
457 		} else {
458 			for (int i= 0 ; i < this.dimensions; i++) {
459 				if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) {
460 					output.append(" "); //$NON-NLS-1$
461 					printAnnotations(annotationsOnDimensions[i], output);
462 					output.append(" "); //$NON-NLS-1$
463 				}
464 				output.append("[]"); //$NON-NLS-1$
465 			}
466 		}
467 		return output;
468 	}
469 
470 	@Override
resolveType(BlockScope scope, boolean checkBounds, int location)471 	public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
472 	    return internalResolveType(scope, checkBounds, location);
473 	}
474 	@Override
resolveType(ClassScope scope, int location)475 	public TypeBinding resolveType(ClassScope scope, int location) {
476 	    return internalResolveType(scope, false, location);
477 	}
478 	@Override
traverse(ASTVisitor visitor, BlockScope scope)479 	public void traverse(ASTVisitor visitor, BlockScope scope) {
480 		if (visitor.visit(this, scope)) {
481 			if (this.annotations != null) {
482 				int annotationsLevels = this.annotations.length;
483 				for (int i = 0; i < annotationsLevels; i++) {
484 					int annotationsLength = this.annotations[i] == null ? 0 : this.annotations[i].length;
485 					for (int j = 0; j < annotationsLength; j++)
486 						this.annotations[i][j].traverse(visitor, scope);
487 				}
488 			}
489 			Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true);
490 			if (annotationsOnDimensions != null) {
491 				for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
492 					Annotation[] annotations2 = annotationsOnDimensions[i];
493 					for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) {
494 						Annotation annotation = annotations2[j];
495 						annotation.traverse(visitor, scope);
496 					}
497 				}
498 			}
499 			for (int i = 0, max = this.typeArguments.length; i < max; i++) {
500 				if (this.typeArguments[i] != null) {
501 					for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
502 						this.typeArguments[i][j].traverse(visitor, scope);
503 					}
504 				}
505 			}
506 		}
507 		visitor.endVisit(this, scope);
508 	}
509 
510 	@Override
traverse(ASTVisitor visitor, ClassScope scope)511 	public void traverse(ASTVisitor visitor, ClassScope scope) {
512 		if (visitor.visit(this, scope)) {
513 			if (this.annotations != null) {
514 				int annotationsLevels = this.annotations.length;
515 				for (int i = 0; i < annotationsLevels; i++) {
516 					int annotationsLength = this.annotations[i] == null ? 0 : this.annotations[i].length;
517 					for (int j = 0; j < annotationsLength; j++)
518 						this.annotations[i][j].traverse(visitor, scope);
519 				}
520 			}
521 			Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true);
522 			if (annotationsOnDimensions != null) {
523 				for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
524 					Annotation[] annotations2 = annotationsOnDimensions[i];
525 					for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) {
526 						Annotation annotation = annotations2[j];
527 						annotation.traverse(visitor, scope);
528 					}
529 				}
530 			}
531 			for (int i = 0, max = this.typeArguments.length; i < max; i++) {
532 				if (this.typeArguments[i] != null) {
533 					for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
534 						this.typeArguments[i][j].traverse(visitor, scope);
535 					}
536 				}
537 			}
538 		}
539 		visitor.endVisit(this, scope);
540 	}
541 
542 }
543