Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2013 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation /
 
 package org.eclipse.jdt.internal.compiler.ast;
 
Node representing a structured Javadoc comment
 
 public class Javadoc extends ASTNode {
 
 	public TypeReference[] exceptionReferences// @throws, @exception
 	public JavadocReturnStatement returnStatement// @return
 	public Expression[] seeReferences// @see
 	public long[] inheritedPositions = null;
 	// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
 	// Store param references for tag with invalid syntax
 	// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=153399
 	// Store value tag positions
 	public long valuePositions = -1;
 
 	public Javadoc(int sourceStartint sourceEnd) {
 		this. = sourceStart;
 		this. = sourceEnd;
 	}
Returns whether a type can be seen at a given visibility level or not.

Parameters:
visibility Level of visiblity allowed to see references
modifiers modifiers of java element to be seen
Returns:
true if the type can be seen, false otherwise
 
 	boolean canBeSeen(int visibilityint modifiers) {
 		if (modifiers < 0) return true;
 		switch (modifiers & .) {
 				return true;
 				return (visibility != .);
 				return (visibility == . || visibility == .);
 				return (visibility == .);
 		}
 		return true;
 	}
 
 	/*
 	 * Search node with a given staring position in javadoc objects arrays.
 	 */
 	public ASTNode getNodeStartingAt(int start) {
 		int length = 0;
 		// parameters array
 		if (this. != null) {
 			length = this..length;
 			for (int i=0; i<lengthi++) {
 				if (param.sourceStart==start) {
 					return param;
 				}
 			}
 		}
 		// array of invalid syntax tags parameters
 		if (this. != null) {
 			length = this..length;
 			for (int i=0; i<lengthi++) {
 				if (param.sourceStart==start) {
 					return param;
 				}
 			}
 		}
 		// type parameters array
 		if (this. != null) {
 			length = this..length;
 			for (int i=0; i<lengthi++) {
 				if (param.sourceStart==start) {
 					return param;
 				}
 			}
 		}
		// thrown exception array
		if (this. != null) {
			length = this..length;
			for (int i=0; i<lengthi++) {
				TypeReference typeRef = this.[i];
				if (typeRef.sourceStart==start) {
					return typeRef;
				}
			}
		}
		// references array
		if (this. != null) {
			length = this..length;
			for (int i=0; i<lengthi++) {
				if (expression.sourceStart==start) {
					return expression;
else if (expression instanceof JavadocAllocationExpression) {
					// if binding is valid then look at arguments
					if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
						if (allocationExpr.arguments != null) {
							for (int j=0, l=allocationExpr.arguments.lengthj<lj++) {
								if (allocationExpr.arguments[j]. == start) {
									return allocationExpr.arguments[j];
								}
							}
						}
					}
else if (expression instanceof JavadocMessageSend) {
					// if binding is valid then look at arguments
					if (messageSend.binding != null && messageSend.binding.isValidBinding()) {
						if (messageSend.arguments != null) {
							for (int j=0, l=messageSend.arguments.lengthj<lj++) {
								if (messageSend.arguments[j]. == start) {
									return messageSend.arguments[j];
								}
							}
						}
					}
				}
			}
		}
		return null;
	}
	/*
	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
	 */
	public StringBuffer print(int indentStringBuffer output) {
		printIndent(indentoutput).append("/**\n"); //$NON-NLS-1$
		if (this. != null) {
			for (int i = 0, length = this..lengthi < lengthi++) {
				printIndent(indent + 1, output).append(" * @param "); //$NON-NLS-1$
				this.[i].print(indentoutput).append('\n');
			}
		}
		if (this. != null) {
			for (int i = 0, length = this..lengthi < lengthi++) {
				printIndent(indent + 1, output).append(" * @param <"); //$NON-NLS-1$
				this.[i].print(indentoutput).append(">\n"); //$NON-NLS-1$
			}
		}
		if (this. != null) {
			printIndent(indent + 1, output).append(" * @"); //$NON-NLS-1$
			this..print(indentoutput).append('\n');
		}
		if (this. != null) {
			for (int i = 0, length = this..lengthi < lengthi++) {
				printIndent(indent + 1, output).append(" * @throws "); //$NON-NLS-1$
				this.[i].print(indentoutput).append('\n');
			}
		}
		if (this. != null) {
			for (int i = 0, length = this..lengthi < lengthi++) {
				printIndent(indent + 1, output).append(" * @see "); //$NON-NLS-1$
				this.[i].print(indentoutput).append('\n');
			}
		}
		printIndent(indentoutput).append(" */\n"); //$NON-NLS-1$
		return output;
	}
	/*
	 * Resolve type javadoc
	 */
	public void resolve(ClassScope scope) {
		if ((this. & .) == 0) {
			return;
		}
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247037, @inheritDoc tag cannot
		// be used in the documentation comment for a class or interface.
		if (this. != null) {
			int length = this..length;
			for (int i = 0; i < length; ++i) {
				int start = (int) (this.[i] >>> 32);
				int end = (intthis.[i];
			}
		}
		// @param tags
		int paramTagsSize = this. == null ? 0 : this..length;
		for (int i = 0; i < paramTagsSizei++) {
			scope.problemReporter().javadocUnexpectedTag(param.tagSourceStartparam.tagSourceEnd);
		}
		// @return tags
		if (this. != null) {
		}
		// @throws/@exception tags
		int throwsTagsLength = this. == null ? 0 : this..length;
		for (int i = 0; i < throwsTagsLengthi++) {
			TypeReference typeRef = this.[i];
			int startend;
			if (typeRef instanceof JavadocSingleTypeReference) {
				start = singleRef.tagSourceStart;
				end = singleRef.tagSourceEnd;
else if (typeRef instanceof JavadocQualifiedTypeReference) {
				start = qualifiedRef.tagSourceStart;
				end = qualifiedRef.tagSourceEnd;
else {
				start = typeRef.sourceStart;
				end = typeRef.sourceEnd;
			}
		}
		// @see tags
		int seeTagsLength = this. == null ? 0 : this..length;
		for (int i = 0; i < seeTagsLengthi++) {
		}
		// @value tag
		boolean source15 = scope.compilerOptions(). >= .;
		if (!source15 && this. != -1) {
			scope.problemReporter().javadocUnexpectedTag((int)(this.>>>32), (intthis.);
		}
	}
	/*
	 * Resolve compilation unit javadoc
	 */
	public void resolve(CompilationUnitScope unitScope) {
		if ((this. & .) == 0) {
			return;
		}
		// Do nothing - This is to mimic the SDK's javadoc tool behavior, which neither
		// sanity checks nor generates documentation using comments at the CU scope 
		// (unless the unit happens to be package-info.java - in which case we don't come here.) 
	}
	/*
	 * Resolve method javadoc
	 */
	public void resolve(MethodScope methScope) {
		if ((this. & .) == 0) {
			return;
		}
		// get method declaration
		AbstractMethodDeclaration methDecl = methScope.referenceMethod();
		boolean overriding = methDecl == null /* field declaration */ || methDecl.binding == null /* compiler error */
false :
			!methDecl.binding.isStatic() && ((methDecl.binding.modifiers & (. | .)) != 0);
		// @see tags
		int seeTagsLength = this. == null ? 0 : this..length;
		boolean superRef = false;
		for (int i = 0; i < seeTagsLengthi++) {
			// Resolve reference
			resolveReference(this.[i], methScope);
			// see whether we can have a super reference
			if (methDecl != null && !superRef) {
				if (!methDecl.isConstructor()) {
					if (overriding && this.[iinstanceof JavadocMessageSend) {
						// if binding is valid then look if we have a reference to an overriden method/constructor
						if (messageSend.binding != null && messageSend.binding.isValidBinding() && messageSend.actualReceiverType instanceof ReferenceBinding) {
							ReferenceBinding methodReceiverType = (ReferenceBindingmessageSend.actualReceiverType;
							TypeBinding superType = methDecl.binding.declaringClass.findSuperTypeOriginatingFrom(methodReceiverType);
							if (superType != null && superType.original() != methDecl.binding.declaringClass && CharOperation.equals(messageSend.selectormethDecl.selector)) {
								if (methScope.environment().methodVerifier().doesMethodOverride(methDecl.bindingmessageSend.binding.original())) {
									superRef = true;
								}
							}
						}
					}
else if (this.[iinstanceof JavadocAllocationExpression) {
					// if binding is valid then look if we have a reference to an overriden method/constructor
					if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
						ReferenceBinding allocType = (ReferenceBindingallocationExpr.resolvedType.original();
						ReferenceBinding superType = (ReferenceBindingmethDecl.binding.declaringClass.findSuperTypeOriginatingFrom(allocType);
						if (superType != null && superType.original() != methDecl.binding.declaringClass) {
							MethodBinding superConstructor = methScope.getConstructor(superTypemethDecl.binding.parametersallocationExpr);
							if (superConstructor.isValidBinding() && superConstructor.original() == allocationExpr.binding.original()) {
								if (superConstructor.areParametersEqual(methDecl.binding)) {
									superRef = true;
								}
							}
						}						
					}
				}
			}
		}
		// Look at @Override annotations
		if (!superRef && methDecl != null && methDecl.annotations != null) {
			int length = methDecl.annotations.length;
			for (int i=0; i<length && !superRefi++) {
				superRef = (methDecl.binding.tagBits & .) != 0;
			}
		}
		// Store if a reference exists to an overriden method/constructor or the method is in a local type,
		boolean reportMissing = methDecl == null || !((overriding && this. != null) || superRef || (methDecl.binding.declaringClass != null && methDecl.binding.declaringClass.isLocalType()));
		if (!overriding && this. != null) {
			int length = this..length;
			for (int i = 0; i < length; ++i) {
				int start = (int) (this.[i] >>> 32);
				int end = (intthis.[i];
				methScope.problemReporter().javadocUnexpectedTag(startend);
			}
		}
		// @param tags
		CompilerOptions compilerOptions = methScope.compilerOptions();
		resolveParamTags(methScopereportMissingcompilerOptions.reportUnusedParameterIncludeDocCommentReference /* considerParamRefAsUsage*/);
		resolveTypeParameterTags(methScopereportMissing && compilerOptions.reportMissingJavadocTagsMethodTypeParameters);
		// @return tags
		if (this. == null) {
			if (reportMissing && methDecl != null) {
				if (methDecl.isMethod()) {
					MethodDeclaration meth = (MethodDeclarationmethDecl;
					if (meth.binding.returnType != .) {
						// method with return should have @return tag
						methScope.problemReporter().javadocMissingReturnTag(meth.returnType.sourceStartmeth.returnType.sourceEndmethDecl.binding.modifiers);
					}
				}
			}
else {
			this..resolve(methScope);
		}
		// @throws/@exception tags
		resolveThrowsTags(methScopereportMissing);
		// @value tag
		boolean source15 = compilerOptions.sourceLevel >= .;
		if (!source15 && methDecl != null && this. != -1) {
			methScope.problemReporter().javadocUnexpectedTag((int)(this.>>>32), (intthis.);
		}
		// Resolve param tags with invalid syntax
		int length = this. == null ? 0 : this..length;
		for (int i = 0; i < lengthi++) {
			this.[i].resolve(methScopefalsefalse);
		}
	}
	private void resolveReference(Expression referenceScope scope) {
		// Perform resolve
		int problemCount = scope.referenceContext().compilationResult().;
		switch (scope.kind) {
				reference.resolveType((MethodScope)scope);
				break;
				reference.resolveType((ClassScope)scope);
				break;
		}
		boolean hasProblems = scope.referenceContext().compilationResult(). > problemCount;
		// Verify field references
		boolean source15 = scope.compilerOptions(). >= .;
		int scopeModifiers = -1;
		if (reference instanceof JavadocFieldReference) {
			JavadocFieldReference fieldRef = (JavadocFieldReferencereference;
			// Verify if this is a method reference
			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
			if (fieldRef.methodBinding != null) {
				// cannot refer to method for @value tag
				if (fieldRef.tagValue == .) {
					if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStartfieldRef.sourceEndscopeModifiers);
				}
				else if (fieldRef.actualReceiverType != null) {
					if (scope.enclosingSourceType().isCompatibleWith(fieldRef.actualReceiverType)) {
						fieldRef.bits |= .;
					}
					ReferenceBinding resolvedType = (ReferenceBindingfieldRef.actualReceiverType;
					if (CharOperation.equals(resolvedType.sourceName(), fieldRef.token)) {
						fieldRef.methodBinding = scope.getConstructor(resolvedType.fieldRef);
else {
						fieldRef.methodBinding = scope.findMethod(resolvedTypefieldRef.token.fieldRef);
					}
				}
			}
			// Verify whether field ref should be static or not (for @value tags)
			else if (source15 && fieldRef.binding != null && fieldRef.binding.isValidBinding()) {
				if (fieldRef.tagValue == . && !fieldRef.binding.isStatic()) {
					if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStartfieldRef.sourceEndscopeModifiers);
				}
			}
			// Verify type references
			if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.actualReceiverType instanceof ReferenceBinding) {
				ReferenceBinding resolvedType = (ReferenceBindingfieldRef.actualReceiverType;
				verifyTypeReference(fieldReffieldRef.receiverscopesource15resolvedTypefieldRef.binding.modifiers);
			}
			// That's it for field references
			return;
		}
		// Verify type references
		if (!hasProblems && (reference instanceof JavadocSingleTypeReference || reference instanceof JavadocQualifiedTypeReference) && reference.resolvedType instanceof ReferenceBinding) {
			ReferenceBinding resolvedType = (ReferenceBindingreference.resolvedType;
			verifyTypeReference(referencereferencescopesource15resolvedTyperesolvedType.modifiers);
		}
		// Verify that message reference are not used for @value tags
		if (reference instanceof JavadocMessageSend) {
			JavadocMessageSend msgSend = (JavadocMessageSendreference;
			// tag value
			if (source15 && msgSend.tagValue == .) { // cannot refer to method for @value tag
				if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
				scope.problemReporter().javadocInvalidValueReference(msgSend.sourceStartmsgSend.sourceEndscopeModifiers);
			}
			// Verify type references
			if (!hasProblems && msgSend.binding != null && msgSend.binding.isValidBinding() && msgSend.actualReceiverType instanceof ReferenceBinding) {
				ReferenceBinding resolvedType = (ReferenceBindingmsgSend.actualReceiverType;
				verifyTypeReference(msgSendmsgSend.receiverscopesource15resolvedTypemsgSend.binding.modifiers);
			}
		}
		// Verify that constructor reference are not used for @value tags
		else if (reference instanceof JavadocAllocationExpression) {
			// tag value
			if (source15 && alloc.tagValue == .) { // cannot refer to method for @value tag
				if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
				scope.problemReporter().javadocInvalidValueReference(alloc.sourceStartalloc.sourceEndscopeModifiers);
			}
			// Verify type references
			if (!hasProblems && alloc.binding != null && alloc.binding.isValidBinding() && alloc.resolvedType instanceof ReferenceBinding) {
				ReferenceBinding resolvedType = (ReferenceBindingalloc.resolvedType;
				verifyTypeReference(allocalloc.typescopesource15resolvedTypealloc.binding.modifiers);
			}
		}
		// Verify that there's no type variable reference
		// (javadoc does not accept them and this is not a referenced bug or requested enhancement)
		if (reference.resolvedType != null && reference.resolvedType.isTypeVariable()) {
			scope.problemReporter().javadocInvalidReference(reference.sourceStartreference.sourceEnd);
		}
	}
	/*
	 * Resolve @param tags while method scope
	 */
	private void resolveParamTags(MethodScope scopeboolean reportMissingboolean considerParamRefAsUsage) {
		int paramTagsSize = this. == null ? 0 : this..length;
		// If no referenced method (field initializer for example) then report a problem for each param tag
		if (methodDecl == null) {
			for (int i = 0; i < paramTagsSizei++) {
				scope.problemReporter().javadocUnexpectedTag(param.tagSourceStartparam.tagSourceEnd);
			}
			return;
		}
		// If no param tags then report a problem for each method argument
		int argumentsSize = methodDecl.arguments == null ? 0 : methodDecl.arguments.length;
		if (paramTagsSize == 0) {
			if (reportMissing) {
				for (int i = 0; i < argumentsSizei++) {
					Argument arg = methodDecl.arguments[i];
					scope.problemReporter().javadocMissingParamTag(arg.namearg.sourceStartarg.sourceEndmethodDecl.binding.modifiers);
				}
			}
else {
			LocalVariableBinding[] bindings = new LocalVariableBinding[paramTagsSize];
			int maxBindings = 0;
			// Scan all @param tags
			for (int i = 0; i < paramTagsSizei++) {
				param.resolve(scopetrueconsiderParamRefAsUsage);
				if (param.binding != null && param.binding.isValidBinding()) {
					// Verify duplicated tags
					boolean found = false;
					for (int j = 0; j < maxBindings && !foundj++) {
						if (bindings[j] == param.binding) {
							scope.problemReporter().javadocDuplicatedParamTag(param.tokenparam.sourceStartparam.sourceEndmethodDecl.binding.modifiers);
							found = true;
						}
					}
					if (!found) {
						bindings[maxBindings++] = (LocalVariableBindingparam.binding;
					}
				}
			}
			// Look for undocumented arguments
			if (reportMissing) {
				for (int i = 0; i < argumentsSizei++) {
					Argument arg = methodDecl.arguments[i];
					boolean found = false;
					for (int j = 0; j < maxBindings && !foundj++) {
						LocalVariableBinding binding = bindings[j];
						if (arg.binding == binding) {
							found = true;
						}
					}
					if (!found) {
						scope.problemReporter().javadocMissingParamTag(arg.namearg.sourceStartarg.sourceEndmethodDecl.binding.modifiers);
					}
				}
			}
		}
	}
	/*
	 * Resolve @param tags for type parameters
	 */
	private void resolveTypeParameterTags(Scope scopeboolean reportMissing) {
		int paramTypeParamLength = this. == null ? 0 : this..length;
		// Get declaration infos
		TypeParameter[] parameters = null;
		TypeVariableBinding[] typeVariables = null;
		int modifiers = -1;
		switch (scope.kind) {
				AbstractMethodDeclaration methodDeclaration = ((MethodScope)scope).referenceMethod();
				// If no referenced method (field initializer for example) then report a problem for each param tag
				if (methodDeclaration == null) {
					for (int i = 0; i < paramTypeParamLengthi++) {
						scope.problemReporter().javadocUnexpectedTag(param.tagSourceStartparam.tagSourceEnd);
					}
					return;
				}
				parameters = methodDeclaration.typeParameters();
				typeVariables = methodDeclaration.binding.typeVariables;
				modifiers = methodDeclaration.binding.modifiers;
				break;
				TypeDeclaration typeDeclaration = ((ClassScopescope).;
				parameters = typeDeclaration.typeParameters;
				typeVariables = typeDeclaration.binding.typeVariables;
				modifiers = typeDeclaration.binding.modifiers;
				break;
		}
		// If no type variables then report a problem for each param type parameter tag
		if (typeVariables == null || typeVariables.length == 0) {
			for (int i = 0; i < paramTypeParamLengthi++) {
				scope.problemReporter().javadocUnexpectedTag(param.tagSourceStartparam.tagSourceEnd);
			}
			return;
		}
		// If no param tags then report a problem for each declaration type parameter
		if (parameters != null) {
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, avoid secondary errors when <= 1.4 
			reportMissing = reportMissing && scope.compilerOptions(). >= .;
			int typeParametersLength = parameters.length;
			if (paramTypeParamLength == 0) {
				if (reportMissing) {
					for (int i = 0, l=typeParametersLengthi<li++) {
						scope.problemReporter().javadocMissingParamTag(parameters[i].parameters[i].parameters[i].modifiers);
					}
				}
			// Otherwise verify that all param tags match type parameters
else if (typeVariables.length == typeParametersLength) {
				TypeVariableBinding[] bindings = new TypeVariableBinding[paramTypeParamLength];
				// Scan all @param tags
				for (int i = 0; i < paramTypeParamLengthi++) {
					TypeBinding paramBindind = param.internalResolveType(scope);
					if (paramBindind != null && paramBindind.isValidBinding()) {
						if (paramBindind.isTypeVariable()) {
							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888
								TypeVariableBinding typeVariableBinding = (TypeVariableBindingparamBindind;
								typeVariableBinding.modifiers |= .;
							}
							// Verify duplicated tags
							boolean duplicate = false;
							for (int j = 0; j < i && !duplicatej++) {
								if (bindings[j] == param.resolvedType) {
									scope.problemReporter().javadocDuplicatedParamTag(param.tokenparam.sourceStartparam.sourceEndmodifiers);
									duplicate = true;
								}
							}
							if (!duplicate) {
								bindings[i] = (TypeVariableBindingparam.resolvedType;
							}
else {
							scope.problemReporter().javadocUndeclaredParamTagName(param.tokenparam.sourceStartparam.sourceEndmodifiers);
						}
					}
				}
				// Look for undocumented type parameters
				for (int i = 0; i < typeParametersLengthi++) {
					TypeParameter parameter = parameters[i];
					boolean found = false;
					for (int j = 0; j < paramTypeParamLength && !foundj++) {
						if (parameter.binding == bindings[j]) {
							found = true;
							bindings[j] = null;
						}
					}
					if (!found && reportMissing) {
						scope.problemReporter().javadocMissingParamTag(parameter.nameparameter.sourceStartparameter.sourceEndmodifiers);
					}
				}
				// Report invalid param
				for (int i=0; i<paramTypeParamLengthi++) {
					if (bindings[i] != null) {
						scope.problemReporter().javadocUndeclaredParamTagName(param.tokenparam.sourceStartparam.sourceEndmodifiers);
					}
				}
			}
		}
	}
	/*
	 * Resolve @throws/@exception tags while method scope
	 */
	private void resolveThrowsTags(MethodScope methScopeboolean reportMissing) {
		int throwsTagsLength = this. == null ? 0 : this..length;
		// If no referenced method (field initializer for example) then report a problem for each throws tag
		if (md == null) {
			for (int i = 0; i < throwsTagsLengthi++) {
				TypeReference typeRef = this.[i];
				int start = typeRef.sourceStart;
				int end = typeRef.sourceEnd;
				if (typeRef instanceof JavadocQualifiedTypeReference) {
else if (typeRef instanceof JavadocSingleTypeReference) {
				}
				methScope.problemReporter().javadocUnexpectedTag(startend);
			}
			return;
		}
		// If no throws tags then report a problem for each method thrown exception
		int boundExceptionLength = (md.binding == null) ? 0 : md.binding.thrownExceptions.length;
		int thrownExceptionLength = md.thrownExceptions == null ? 0 : md.thrownExceptions.length;
		if (throwsTagsLength == 0) {
			if (reportMissing) {
				for (int i = 0; i < boundExceptionLengthi++) {
					ReferenceBinding exceptionBinding = md.binding.thrownExceptions[i];
					if (exceptionBinding != null && exceptionBinding.isValidBinding()) { // flag only valid class name
						int j=i;
						while (j<thrownExceptionLength && exceptionBinding != md.thrownExceptions[j].j++;
						if (j<thrownExceptionLength) {
							methScope.problemReporter().javadocMissingThrowsTag(md.thrownExceptions[j], md.binding.modifiers);
						}
					}
				}
			}
else {
			int maxRef = 0;
			TypeReference[] typeReferences = new TypeReference[throwsTagsLength];
			// Scan all @throws tags
			for (int i = 0; i < throwsTagsLengthi++) {
				TypeReference typeRef = this.[i];
				typeRef.resolve(methScope);
				TypeBinding typeBinding = typeRef.resolvedType;
				if (typeBinding != null && typeBinding.isValidBinding() && typeBinding.isClass()) {
					// accept only valid class binding
					typeReferences[maxRef++] = typeRef;
				}
			}
			// Look for undocumented thrown exception
			for (int i = 0; i < boundExceptionLengthi++) {
				ReferenceBinding exceptionBinding = md.binding.thrownExceptions[i];
				if (exceptionBinding != nullexceptionBinding = (ReferenceBindingexceptionBinding.erasure();
				boolean found = false;
				for (int j = 0; j < maxRef && !foundj++) {
					if (typeReferences[j] != null) {
						TypeBinding typeBinding = typeReferences[j].;
						if (exceptionBinding == typeBinding) {
							found = true;
							typeReferences[j] = null;
						}
					}
				}
				if (!found && reportMissing) {
					if (exceptionBinding != null && exceptionBinding.isValidBinding()) { // flag only valid class name
						int k=i;
						while (k<thrownExceptionLength && exceptionBinding != md.thrownExceptions[k].k++;
						if (k<thrownExceptionLength) {
							methScope.problemReporter().javadocMissingThrowsTag(md.thrownExceptions[k], md.binding.modifiers);
						}
					}
				}
			}
			// Verify additional @throws tags
			for (int i = 0; i < maxRefi++) {
				TypeReference typeRef = typeReferences[i];
				if (typeRef != null) {
					boolean compatible = false;
					// thrown exceptions subclasses are accepted
					for (int j = 0; j<thrownExceptionLength && !compatiblej++) {
						TypeBinding exceptionBinding = md.thrownExceptions[j].;
						if (exceptionBinding != null) {
							compatible = typeRef.resolvedType.isCompatibleWith(exceptionBinding);
						}
					}
					//  If not compatible only complain on unchecked exception
					if (!compatible && !typeRef.resolvedType.isUncheckedException(false)) {
						methScope.problemReporter().javadocInvalidThrowsClassName(typeRefmd.binding.modifiers);
					}
				}
			}
		}
	}
	private void verifyTypeReference(Expression referenceExpression typeReferenceScope scopeboolean source15ReferenceBinding resolvedTypeint modifiers) {
		if (resolvedType.isValidBinding()) {
			int scopeModifiers = -1;
			// reference must have enough visibility to be used
				scope.problemReporter().javadocHiddenReference(typeReference.sourceStartreference.sourceEndscopemodifiers);
				return;
			}
			// type reference must have enough visibility to be used
			if (reference != typeReference) {
				if (!canBeSeen(scope.problemReporter()..resolvedType.modifiers)) {
					scope.problemReporter().javadocHiddenReference(typeReference.sourceStarttypeReference.sourceEndscoperesolvedType.modifiers);
					return;
				}
			}
			// member types
			if (resolvedType.isMemberType()) {
				ReferenceBinding topLevelType = resolvedType;
				// rebuild and store (in reverse order) compound name to handle embedded inner class
				int packageLength = topLevelType.fPackage.compoundName.length;
				int depth = resolvedType.depth();
				int idx = depth + packageLength;
				char[][] computedCompoundName = new char[idx+1][];
				computedCompoundName[idx] = topLevelType.sourceName;
				while (topLevelType.enclosingType() != null) {
					topLevelType = topLevelType.enclosingType();
					computedCompoundName[--idx] = topLevelType.sourceName;
				}
				// add package information
				for (int i = packageLength; --i >= 0;) {
					computedCompoundName[--idx] = topLevelType.fPackage.compoundName[i];
				}
				ClassScope topLevelScope = scope.classScope();
				// when scope is not on compilation unit type, then inner class may not be visible...
				if (topLevelScope.parent.kind != . ||
					!CharOperation.equals(topLevelType.sourceNametopLevelScope.referenceContext.name)) {
					topLevelScope = topLevelScope.outerMostClassScope();
					if (typeReference instanceof JavadocSingleTypeReference) {
						// inner class single reference can only be done in same unit
						if ((!source15 && depth == 1) || topLevelType != topLevelScope.referenceContext.binding) {
							// search for corresponding import
							boolean hasValidImport = false;
							if (source15) {
								CompilationUnitScope unitScope = topLevelScope.compilationUnitScope();
								ImportBinding[] imports = unitScope.imports;
								int length = imports == null ? 0 : imports.length;
								mainLoop: for (int i=0; i<lengthi++) {
									char[][] compoundName = imports[i].;
									int compoundNameLength = compoundName.length;
									if ((imports[i]. && compoundNameLength == computedCompoundName.length-1) 
											|| (compoundNameLength == computedCompoundName.length)) {
										for (int j = compoundNameLength; --j >= 0;) {
											if (CharOperation.equals(imports[i].[j], computedCompoundName[j])) {
												if (j == 0) {
													hasValidImport = true;
													ImportReference importReference = imports[i].;
													if (importReference != null) {
														importReference.bits |= .;
													}
													break mainLoop;
												}
else {
												break;
											}
										}
									}
								}
								if (!hasValidImport) {
									if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
									scope.problemReporter().javadocInvalidMemberTypeQualification(typeReference.sourceStarttypeReference.sourceEndscopeModifiers);
								}
else {
								if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
								scope.problemReporter().javadocInvalidMemberTypeQualification(typeReference.sourceStarttypeReference.sourceEndscopeModifiers);
								return;
							}
						}
					}
				}
				if (typeReference instanceof JavadocQualifiedTypeReference && !scope.isDefinedInSameUnit(resolvedType)) {
					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=222188
					// partially qualified references from a different CU should be warned
					char[][] typeRefName = ((JavadocQualifiedTypeReferencetypeReference).getTypeName();
					int skipLength = 0;
					if (topLevelScope.getCurrentPackage() == resolvedType.getPackage()
							&& typeRefName.length < computedCompoundName.length) {
						// https://bugs.eclipse.org/bugs/show_bug.cgi?id=221539: references can be partially qualified
						// in same package and hence if the package name is not given, ignore package name check
						skipLength = resolvedType.fPackage.compoundName.length;
					}
					boolean valid = true;
					if (typeRefName.length == computedCompoundName.length - skipLength) {
						checkQualification: for (int i = 0; i < typeRefName.lengthi++) {
							if (!CharOperation.equals(typeRefName[i], computedCompoundName[i + skipLength])) {
								valid = false;
								break checkQualification;
							}
						}
else {
						valid = false;
					}
					// report invalid reference
					if (!valid) {
						if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
						scope.problemReporter().javadocInvalidMemberTypeQualification(typeReference.sourceStarttypeReference.sourceEndscopeModifiers);
						return;
					}
				}
			}
			/*
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=286918
			 *
			 * We are concerned only about the Single type references (i.e. without any package) If they are not in default package,
			 * then report an error. References with qualified yet incorrect names would have already been taken care of.
			 */
			if (scope.referenceCompilationUnit().isPackageInfo() && typeReference instanceof JavadocSingleTypeReference) {
				if (resolvedType.fPackage.compoundName.length > 0) {
					scope.problemReporter().javadocInvalidReference(typeReference.sourceStarttypeReference.sourceEnd);
					return// Not really needed - just in case more code added in future
				}
			}
		}
	}
	public void traverse(ASTVisitor visitorBlockScope scope) {
		if (visitor.visit(thisscope)) {
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
			if (this. != null) {
				this..traverse(visitorscope);
			}
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
		}
		visitor.endVisit(thisscope);
	}
	public void traverse(ASTVisitor visitorClassScope scope) {
		if (visitor.visit(thisscope)) {
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
			if (this. != null) {
				this..traverse(visitorscope);
			}
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
			if (this. != null) {
				for (int i = 0, length = this..lengthi < lengthi++) {
					this.[i].traverse(visitorscope);
				}
			}
		}
		visitor.endVisit(thisscope);
	}