/******************************************************************************* * Copyright (c) 2000, 2009 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.core; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Stack; import org.eclipse.core.runtime.Assert; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMemberValuePair; import org.eclipse.jdt.core.ITypeParameter; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.ISourceElementRequestor; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Literal; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt; import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter; import org.eclipse.jdt.internal.core.util.Util; /** * A requestor for the fuzzy parser, used to compute the children of an ICompilationUnit. */ public class CompilationUnitStructureRequestor extends ReferenceInfoAdapter implements ISourceElementRequestor { /** * The handle to the compilation unit being parsed */ protected ICompilationUnit unit; /** * The info object for the compilation unit being parsed */ protected CompilationUnitElementInfo unitInfo; /** * The import container info - null until created */ protected ImportContainerInfo importContainerInfo= null; protected ImportContainer importContainer; /** * Hashtable of children elements of the compilation unit. Children are added to the table as * they are found by the parser. Keys are handles, values are corresponding info objects. */ protected Map newElements; /* * A table from a handle (with occurenceCount == 1) to the current occurence count for this handle */ private HashtableOfObjectToInt occurenceCounts; /** * Stack of parent scope info objects. The info on the top of the stack is the parent of the * next element found. For example, when we locate a method, the parent info object will be the * type the method is contained in. */ protected Stack infoStack; /* * Map from info to of ArrayList of IJavaElement representing the children * of the given info. */ protected HashMap children; /** * Stack of parent handles, corresponding to the info stack. We keep both, since info objects do * not have back pointers to handles. */ protected Stack handleStack; /** * The number of references reported thus far. Used to expand the arrays of reference kinds and * names. */ protected int referenceCount= 0; /** * Problem requestor which will get notified of discovered problems */ protected boolean hasSyntaxErrors= false; /* * The parser this requestor is using. */ protected Parser parser; protected HashtableOfObject fieldRefCache; protected HashtableOfObject messageRefCache; protected HashtableOfObject typeRefCache; protected HashtableOfObject unknownRefCache; protected CompilationUnitStructureRequestor(ICompilationUnit unit, CompilationUnitElementInfo unitInfo, Map newElements) { this.unit= unit; this.unitInfo= unitInfo; this.newElements= newElements; this.occurenceCounts= new HashtableOfObjectToInt(); } /** * @see ISourceElementRequestor */ public void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers) { JavaElement parentHandle= (JavaElement)this.handleStack.peek(); if (!(parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT)) { Assert.isTrue(false); // Should not happen } ICompilationUnit parentCU= (ICompilationUnit)parentHandle; //create the import container and its info if (this.importContainer == null) { this.importContainer= createImportContainer(parentCU); this.importContainerInfo= new ImportContainerInfo(); Object parentInfo= this.infoStack.peek(); addToChildren(parentInfo, this.importContainer); this.newElements.put(this.importContainer, this.importContainerInfo); } String elementName= JavaModelManager.getJavaModelManager().intern(new String(CharOperation.concatWith(tokens, '.'))); ImportDeclaration handle= createImportDeclaration(this.importContainer, elementName, onDemand); resolveDuplicates(handle); ImportDeclarationElementInfo info= new ImportDeclarationElementInfo(); info.setSourceRangeStart(declarationStart); info.setSourceRangeEnd(declarationEnd); info.setFlags(modifiers); addToChildren(this.importContainerInfo, handle); this.newElements.put(handle, info); } /* * Table of line separator position. This table is passed once at the end * of the parse action, so as to allow computation of normalized ranges. * * A line separator might corresponds to several characters in the source, * */ public void acceptLineSeparatorPositions(int[] positions) { // ignore line separator positions } /** * @see ISourceElementRequestor */ public void acceptPackage(ImportReference importReference) { Object parentInfo= this.infoStack.peek(); JavaElement parentHandle= (JavaElement)this.handleStack.peek(); PackageDeclaration handle= null; if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) { char[] name= CharOperation.concatWith(importReference.getImportName(), '.'); handle= createPackageDeclaration(parentHandle, new String(name)); } else { Assert.isTrue(false); // Should not happen } resolveDuplicates(handle); AnnotatableInfo info= new AnnotatableInfo(); info.setSourceRangeStart(importReference.declarationSourceStart); info.setSourceRangeEnd(importReference.declarationSourceEnd); addToChildren(parentInfo, handle); this.newElements.put(handle, info); if (importReference.annotations != null) { for (int i= 0, length= importReference.annotations.length; i < length; i++) { org.eclipse.jdt.internal.compiler.ast.Annotation annotation= importReference.annotations[i]; acceptAnnotation(annotation, info, handle); } } } public void acceptProblem(CategorizedProblem problem) { if ((problem.getID() & IProblem.Syntax) != 0) { this.hasSyntaxErrors= true; } } private void addToChildren(Object parentInfo, JavaElement handle) { ArrayList childrenList= (ArrayList)this.children.get(parentInfo); if (childrenList == null) this.children.put(parentInfo, childrenList= new ArrayList()); childrenList.add(handle); } protected Annotation createAnnotation(JavaElement parent, String name) { return new Annotation(parent, name); } protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) { String fieldName= JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name)); return new SourceField(parent, fieldName); } protected ImportContainer createImportContainer(ICompilationUnit parent) { return (ImportContainer)parent.getImportContainer(); } protected ImportDeclaration createImportDeclaration(ImportContainer parent, String name, boolean onDemand) { return new ImportDeclaration(parent, name, onDemand); } protected Initializer createInitializer(JavaElement parent) { return new Initializer(parent, 1); } protected SourceMethod createMethodHandle(JavaElement parent, MethodInfo methodInfo) { String selector= JavaModelManager.getJavaModelManager().intern(new String(methodInfo.name)); String[] parameterTypeSigs= convertTypeNamesToSigs(methodInfo.parameterTypes); return new SourceMethod(parent, selector, parameterTypeSigs); } protected PackageDeclaration createPackageDeclaration(JavaElement parent, String name) { return new PackageDeclaration((CompilationUnit)parent, name); } protected SourceType createTypeHandle(JavaElement parent, TypeInfo typeInfo) { String nameString= new String(typeInfo.name); return new SourceType(parent, nameString); } protected TypeParameter createTypeParameter(JavaElement parent, String name) { return new TypeParameter(parent, name); } /** * Convert these type names to signatures. * * @see Signature */ protected static String[] convertTypeNamesToSigs(char[][] typeNames) { if (typeNames == null) return CharOperation.NO_STRINGS; int n= typeNames.length; if (n == 0) return CharOperation.NO_STRINGS; JavaModelManager manager= JavaModelManager.getJavaModelManager(); String[] typeSigs= new String[n]; for (int i= 0; i < n; ++i) { typeSigs[i]= manager.intern(Signature.createTypeSignature(typeNames[i], false)); } return typeSigs; } protected IAnnotation acceptAnnotation(org.eclipse.jdt.internal.compiler.ast.Annotation annotation, AnnotatableInfo parentInfo, JavaElement parentHandle) { String nameString= new String(CharOperation.concatWith(annotation.type.getTypeName(), '.')); Annotation handle= createAnnotation(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates resolveDuplicates(handle); AnnotationInfo info= new AnnotationInfo(); // populate the maps here as getValue(...) below may need them this.newElements.put(handle, info); this.handleStack.push(handle); info.setSourceRangeStart(annotation.sourceStart()); info.nameStart= annotation.type.sourceStart(); info.nameEnd= annotation.type.sourceEnd(); MemberValuePair[] memberValuePairs= annotation.memberValuePairs(); int membersLength= memberValuePairs.length; if (membersLength == 0) { info.members= Annotation.NO_MEMBER_VALUE_PAIRS; } else { info.members= getMemberValuePairs(memberValuePairs); } if (parentInfo != null) { IAnnotation[] annotations= parentInfo.annotations; int length= annotations.length; System.arraycopy(annotations, 0, annotations= new IAnnotation[length + 1], 0, length); annotations[length]= handle; parentInfo.annotations= annotations; } info.setSourceRangeEnd(annotation.declarationSourceEnd); this.handleStack.pop(); return handle; } /** * @see ISourceElementRequestor */ public void enterCompilationUnit() { this.infoStack= new Stack(); this.children= new HashMap(); this.handleStack= new Stack(); this.infoStack.push(this.unitInfo); this.handleStack.push(this.unit); } /** * @see ISourceElementRequestor */ public void enterConstructor(MethodInfo methodInfo) { enterMethod(methodInfo); } /** * @see ISourceElementRequestor */ public void enterField(FieldInfo fieldInfo) { TypeInfo parentInfo= (TypeInfo)this.infoStack.peek(); JavaElement parentHandle= (JavaElement)this.handleStack.peek(); SourceField handle= null; if (parentHandle.getElementType() == IJavaElement.TYPE) { handle= createField(parentHandle, fieldInfo); } else { Assert.isTrue(false); // Should not happen } resolveDuplicates(handle); addToChildren(parentInfo, handle); parentInfo.childrenCategories.put(handle, fieldInfo.categories); this.infoStack.push(fieldInfo); this.handleStack.push(handle); } /** * @see ISourceElementRequestor */ public void enterInitializer(int declarationSourceStart, int modifiers) { Object parentInfo= this.infoStack.peek(); JavaElement parentHandle= (JavaElement)this.handleStack.peek(); Initializer handle= null; if (parentHandle.getElementType() == IJavaElement.TYPE) { handle= createInitializer(parentHandle); } else { Assert.isTrue(false); // Should not happen } resolveDuplicates(handle); addToChildren(parentInfo, handle); this.infoStack.push(new int[] { declarationSourceStart, modifiers }); this.handleStack.push(handle); } /** * @see ISourceElementRequestor */ public void enterMethod(MethodInfo methodInfo) { TypeInfo parentInfo= (TypeInfo)this.infoStack.peek(); JavaElement parentHandle= (JavaElement)this.handleStack.peek(); SourceMethod handle= null; // translate nulls to empty arrays if (methodInfo.parameterTypes == null) { methodInfo.parameterTypes= CharOperation.NO_CHAR_CHAR; } if (methodInfo.parameterNames == null) { methodInfo.parameterNames= CharOperation.NO_CHAR_CHAR; } if (methodInfo.exceptionTypes == null) { methodInfo.exceptionTypes= CharOperation.NO_CHAR_CHAR; } if (parentHandle.getElementType() == IJavaElement.TYPE) { handle= createMethodHandle(parentHandle, methodInfo); } else { Assert.isTrue(false); // Should not happen } resolveDuplicates(handle); this.infoStack.push(methodInfo); this.handleStack.push(handle); addToChildren(parentInfo, handle); parentInfo.childrenCategories.put(handle, methodInfo.categories); } private SourceMethodElementInfo createMethodInfo(MethodInfo methodInfo, SourceMethod handle) { IJavaElement[] elements= getChildren(methodInfo); SourceMethodElementInfo info; if (methodInfo.isConstructor) { info= elements.length == 0 ? new SourceConstructorInfo() : new SourceConstructorWithChildrenInfo(elements); } else if (methodInfo.isAnnotation) { info= new SourceAnnotationMethodInfo(); } else { info= elements.length == 0 ? new SourceMethodInfo() : new SourceMethodWithChildrenInfo(elements); } info.setSourceRangeStart(methodInfo.declarationStart); int flags= methodInfo.modifiers; info.setNameSourceStart(methodInfo.nameSourceStart); info.setNameSourceEnd(methodInfo.nameSourceEnd); info.setFlags(flags); JavaModelManager manager= JavaModelManager.getJavaModelManager(); char[][] parameterNames= methodInfo.parameterNames; for (int i= 0, length= parameterNames.length; i < length; i++) parameterNames[i]= manager.intern(parameterNames[i]); info.setArgumentNames(parameterNames); char[] returnType= methodInfo.returnType == null ? new char[] { 'v', 'o', 'i', 'd' } : methodInfo.returnType; info.setReturnType(manager.intern(returnType)); char[][] exceptionTypes= methodInfo.exceptionTypes; info.setExceptionTypeNames(exceptionTypes); for (int i= 0, length= exceptionTypes.length; i < length; i++) exceptionTypes[i]= manager.intern(exceptionTypes[i]); this.newElements.put(handle, info); if (methodInfo.typeParameters != null) { for (int i= 0, length= methodInfo.typeParameters.length; i < length; i++) { TypeParameterInfo typeParameterInfo= methodInfo.typeParameters[i]; acceptTypeParameter(typeParameterInfo, info); } } if (methodInfo.annotations != null) { int length= methodInfo.annotations.length; this.unitInfo.annotationNumber+= length; for (int i= 0; i < length; i++) { org.eclipse.jdt.internal.compiler.ast.Annotation annotation= methodInfo.annotations[i]; acceptAnnotation(annotation, info, handle); } } return info; } /** * @see ISourceElementRequestor */ public void enterType(TypeInfo typeInfo) { Object parentInfo= this.infoStack.peek(); JavaElement parentHandle= (JavaElement)this.handleStack.peek(); SourceType handle= createTypeHandle(parentHandle, typeInfo); //NB: occurenceCount is computed in resolveDuplicates resolveDuplicates(handle); this.infoStack.push(typeInfo); this.handleStack.push(handle); if (parentHandle.getElementType() == IJavaElement.TYPE) ((TypeInfo)parentInfo).childrenCategories.put(handle, typeInfo.categories); addToChildren(parentInfo, handle); } private SourceTypeElementInfo createTypeInfo(TypeInfo typeInfo, SourceType handle) { SourceTypeElementInfo info= typeInfo.anonymousMember ? new SourceTypeElementInfo() { public boolean isAnonymousMember() { return true; } } : new SourceTypeElementInfo(); info.setHandle(handle); info.setSourceRangeStart(typeInfo.declarationStart); info.setFlags(typeInfo.modifiers); info.setNameSourceStart(typeInfo.nameSourceStart); info.setNameSourceEnd(typeInfo.nameSourceEnd); JavaModelManager manager= JavaModelManager.getJavaModelManager(); char[] superclass= typeInfo.superclass; info.setSuperclassName(superclass == null ? null : manager.intern(superclass)); char[][] superinterfaces= typeInfo.superinterfaces; for (int i= 0, length= superinterfaces == null ? 0 : superinterfaces.length; i < length; i++) superinterfaces[i]= manager.intern(superinterfaces[i]); info.setSuperInterfaceNames(superinterfaces); info.addCategories(handle, typeInfo.categories); this.newElements.put(handle, info); if (typeInfo.typeParameters != null) { for (int i= 0, length= typeInfo.typeParameters.length; i < length; i++) { TypeParameterInfo typeParameterInfo= typeInfo.typeParameters[i]; acceptTypeParameter(typeParameterInfo, info); } } if (typeInfo.annotations != null) { int length= typeInfo.annotations.length; this.unitInfo.annotationNumber+= length; for (int i= 0; i < length; i++) { org.eclipse.jdt.internal.compiler.ast.Annotation annotation= typeInfo.annotations[i]; acceptAnnotation(annotation, info, handle); } } if (typeInfo.childrenCategories != null) { Iterator iterator= typeInfo.childrenCategories.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry= (Map.Entry)iterator.next(); info.addCategories((IJavaElement)entry.getKey(), (char[][])entry.getValue()); } } return info; } protected void acceptTypeParameter(TypeParameterInfo typeParameterInfo, JavaElementInfo parentInfo) { JavaElement parentHandle= (JavaElement)this.handleStack.peek(); String nameString= new String(typeParameterInfo.name); TypeParameter handle= createTypeParameter(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates resolveDuplicates(handle); TypeParameterElementInfo info= new TypeParameterElementInfo(); info.setSourceRangeStart(typeParameterInfo.declarationStart); info.nameStart= typeParameterInfo.nameSourceStart; info.nameEnd= typeParameterInfo.nameSourceEnd; info.bounds= typeParameterInfo.bounds; if (parentInfo instanceof SourceTypeElementInfo) { SourceTypeElementInfo elementInfo= (SourceTypeElementInfo)parentInfo; ITypeParameter[] typeParameters= elementInfo.typeParameters; int length= typeParameters.length; System.arraycopy(typeParameters, 0, typeParameters= new ITypeParameter[length + 1], 0, length); typeParameters[length]= handle; elementInfo.typeParameters= typeParameters; } else { SourceMethodElementInfo elementInfo= (SourceMethodElementInfo)parentInfo; ITypeParameter[] typeParameters= elementInfo.typeParameters; int length= typeParameters.length; System.arraycopy(typeParameters, 0, typeParameters= new ITypeParameter[length + 1], 0, length); typeParameters[length]= handle; elementInfo.typeParameters= typeParameters; } this.newElements.put(handle, info); info.setSourceRangeEnd(typeParameterInfo.declarationEnd); } /** * @see ISourceElementRequestor */ public void exitCompilationUnit(int declarationEnd) { // set import container children if (this.importContainerInfo != null) { this.importContainerInfo.children= getChildren(this.importContainerInfo); } this.unitInfo.children= getChildren(this.unitInfo); this.unitInfo.setSourceLength(declarationEnd + 1); // determine if there were any parsing errors this.unitInfo.setIsStructureKnown(!this.hasSyntaxErrors); } /** * @see ISourceElementRequestor */ public void exitConstructor(int declarationEnd) { exitMethod(declarationEnd, null); } /** * @see ISourceElementRequestor */ public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) { JavaElement handle= (JavaElement)this.handleStack.peek(); FieldInfo fieldInfo= (FieldInfo)this.infoStack.peek(); IJavaElement[] elements= getChildren(fieldInfo); SourceFieldElementInfo info= elements.length == 0 ? new SourceFieldElementInfo() : new SourceFieldWithChildrenInfo(elements); info.setNameSourceStart(fieldInfo.nameSourceStart); info.setNameSourceEnd(fieldInfo.nameSourceEnd); info.setSourceRangeStart(fieldInfo.declarationStart); info.setFlags(fieldInfo.modifiers); char[] typeName= JavaModelManager.getJavaModelManager().intern(fieldInfo.type); info.setTypeName(typeName); this.newElements.put(handle, info); if (fieldInfo.annotations != null) { int length= fieldInfo.annotations.length; this.unitInfo.annotationNumber+= length; for (int i= 0; i < length; i++) { org.eclipse.jdt.internal.compiler.ast.Annotation annotation= fieldInfo.annotations[i]; acceptAnnotation(annotation, info, handle); } } info.setSourceRangeEnd(declarationSourceEnd); this.handleStack.pop(); this.infoStack.pop(); // remember initializer source if field is a constant if (initializationStart != -1) { int flags= info.flags; Object typeInfo; if (Flags.isStatic(flags) && Flags.isFinal(flags) || ((typeInfo= this.infoStack.peek()) instanceof TypeInfo && (Flags.isInterface(((TypeInfo)typeInfo).modifiers)))) { int length= declarationEnd - initializationStart; if (length > 0) { char[] initializer= new char[length]; System.arraycopy(this.parser.scanner.source, initializationStart, initializer, 0, length); info.initializationSource= initializer; } } } } /** * @see ISourceElementRequestor */ public void exitInitializer(int declarationEnd) { JavaElement handle= (JavaElement)this.handleStack.peek(); int[] initializerInfo= (int[])this.infoStack.peek(); IJavaElement[] elements= getChildren(initializerInfo); InitializerElementInfo info= elements.length == 0 ? new InitializerElementInfo() : new InitializerWithChildrenInfo(elements); info.setSourceRangeStart(initializerInfo[0]); info.setFlags(initializerInfo[1]); info.setSourceRangeEnd(declarationEnd); this.newElements.put(handle, info); this.handleStack.pop(); this.infoStack.pop(); } /** * @see ISourceElementRequestor */ public void exitMethod(int declarationEnd, Expression defaultValue) { SourceMethod handle= (SourceMethod)this.handleStack.peek(); MethodInfo methodInfo= (MethodInfo)this.infoStack.peek(); SourceMethodElementInfo info= createMethodInfo(methodInfo, handle); info.setSourceRangeEnd(declarationEnd); // remember default value of annotation method if (info.isAnnotationMethod() && defaultValue != null) { SourceAnnotationMethodInfo annotationMethodInfo= (SourceAnnotationMethodInfo)info; annotationMethodInfo.defaultValueStart= defaultValue.sourceStart; annotationMethodInfo.defaultValueEnd= defaultValue.sourceEnd; JavaElement element= (JavaElement)this.handleStack.peek(); org.eclipse.jdt.internal.core.MemberValuePair defaultMemberValuePair= new org.eclipse.jdt.internal.core.MemberValuePair(element.getElementName()); defaultMemberValuePair.value= getMemberValue(defaultMemberValuePair, defaultValue); annotationMethodInfo.defaultValue= defaultMemberValuePair; } this.handleStack.pop(); this.infoStack.pop(); } /** * @see ISourceElementRequestor */ public void exitType(int declarationEnd) { SourceType handle= (SourceType)this.handleStack.peek(); TypeInfo typeInfo= (TypeInfo)this.infoStack.peek(); SourceTypeElementInfo info= createTypeInfo(typeInfo, handle); info.setSourceRangeEnd(declarationEnd); info.children= getChildren(typeInfo); this.handleStack.pop(); this.infoStack.pop(); } /** * Resolves duplicate handles by incrementing the occurrence count of the handle being created. */ protected void resolveDuplicates(SourceRefElement handle) { int occurenceCount= this.occurenceCounts.get(handle); if (occurenceCount == -1) this.occurenceCounts.put(handle, 1); else { this.occurenceCounts.put(handle, ++occurenceCount); handle.occurrenceCount= occurenceCount; } } protected IMemberValuePair getMemberValuePair(MemberValuePair memberValuePair) { String memberName= new String(memberValuePair.name); org.eclipse.jdt.internal.core.MemberValuePair result= new org.eclipse.jdt.internal.core.MemberValuePair(memberName); result.value= getMemberValue(result, memberValuePair.value); return result; } protected IMemberValuePair[] getMemberValuePairs(MemberValuePair[] memberValuePairs) { int membersLength= memberValuePairs.length; IMemberValuePair[] members= new IMemberValuePair[membersLength]; for (int j= 0; j < membersLength; j++) { members[j]= getMemberValuePair(memberValuePairs[j]); } return members; } private IJavaElement[] getChildren(Object info) { ArrayList childrenList= (ArrayList)this.children.get(info); if (childrenList != null) { return (IJavaElement[])childrenList.toArray(new IJavaElement[childrenList.size()]); } return JavaElement.NO_ELEMENTS; } /* * Creates the value from the given expression, and sets the valueKind on the given memberValuePair */ protected Object getMemberValue(org.eclipse.jdt.internal.core.MemberValuePair memberValuePair, Expression expression) { if (expression instanceof NullLiteral) { return null; } else if (expression instanceof Literal) { ((Literal)expression).computeConstant(); return Util.getAnnotationMemberValue(memberValuePair, expression.constant); } else if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Annotation) { org.eclipse.jdt.internal.compiler.ast.Annotation annotation= (org.eclipse.jdt.internal.compiler.ast.Annotation)expression; Object handle= acceptAnnotation(annotation, null, (JavaElement)this.handleStack.peek()); memberValuePair.valueKind= IMemberValuePair.K_ANNOTATION; return handle; } else if (expression instanceof ClassLiteralAccess) { ClassLiteralAccess classLiteral= (ClassLiteralAccess)expression; char[] name= CharOperation.concatWith(classLiteral.type.getTypeName(), '.'); memberValuePair.valueKind= IMemberValuePair.K_CLASS; return new String(name); } else if (expression instanceof QualifiedNameReference) { char[] qualifiedName= CharOperation.concatWith(((QualifiedNameReference)expression).tokens, '.'); memberValuePair.valueKind= IMemberValuePair.K_QUALIFIED_NAME; return new String(qualifiedName); } else if (expression instanceof SingleNameReference) { char[] simpleName= ((SingleNameReference)expression).token; if (simpleName == RecoveryScanner.FAKE_IDENTIFIER) { memberValuePair.valueKind= IMemberValuePair.K_UNKNOWN; return null; } memberValuePair.valueKind= IMemberValuePair.K_SIMPLE_NAME; return new String(simpleName); } else if (expression instanceof ArrayInitializer) { memberValuePair.valueKind= -1; // modified below by the first call to getMemberValue(...) Expression[] expressions= ((ArrayInitializer)expression).expressions; int length= expressions == null ? 0 : expressions.length; Object[] values= new Object[length]; for (int i= 0; i < length; i++) { int previousValueKind= memberValuePair.valueKind; Object value= getMemberValue(memberValuePair, expressions[i]); if (previousValueKind != -1 && memberValuePair.valueKind != previousValueKind) { // values are heterogeneous, value kind is thus unknown memberValuePair.valueKind= IMemberValuePair.K_UNKNOWN; } values[i]= value; } if (memberValuePair.valueKind == -1) memberValuePair.valueKind= IMemberValuePair.K_UNKNOWN; return values; } else if (expression instanceof UnaryExpression) { // to deal with negative numerals (see bug - 248312) UnaryExpression unaryExpression= (UnaryExpression)expression; if ((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT == OperatorIds.MINUS) { if (unaryExpression.expression instanceof Literal) { Literal subExpression= (Literal)unaryExpression.expression; subExpression.computeConstant(); return Util.getNegativeAnnotationMemberValue(memberValuePair, subExpression.constant); } } memberValuePair.valueKind= IMemberValuePair.K_UNKNOWN; return null; } else { memberValuePair.valueKind= IMemberValuePair.K_UNKNOWN; return null; } } }