| /******************************************************************************* |
| * Copyright (c) 2005, 2011 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 - Initial API and implementation |
| * Markus Schorn (Wind River Systems) |
| * Bryan Wilkinson (QNX) |
| * Andrew Ferguson (Symbian) |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.core.dom.parser.cpp; |
| |
| import org.eclipse.cdt.core.dom.IName; |
| import org.eclipse.cdt.core.dom.ast.DOMException; |
| import org.eclipse.cdt.core.dom.ast.EScopeKind; |
| import org.eclipse.cdt.core.dom.ast.IASTName; |
| import org.eclipse.cdt.core.dom.ast.IBinding; |
| import org.eclipse.cdt.core.dom.ast.IProblemBinding; |
| import org.eclipse.cdt.core.dom.ast.IScope; |
| import org.eclipse.cdt.core.dom.ast.IType; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; |
| import org.eclipse.cdt.core.index.IIndexFileSet; |
| import org.eclipse.cdt.core.parser.util.ArrayUtil; |
| import org.eclipse.cdt.core.parser.util.CharArrayUtils; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; |
| |
| /** |
| * Base class for all specialization scopes |
| * For safe usage in index bindings, all fields need to be final or volatile. |
| */ |
| public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializationScope { |
| final private ICPPClassSpecialization specialClass; |
| private volatile ICPPBase[] fBases; // Used by the pdom bindings, needs to be volatile. |
| |
| public AbstractCPPClassSpecializationScope(ICPPClassSpecialization specialization) { |
| this.specialClass= specialization; |
| } |
| |
| public ICPPClassType getOriginalClassType() { |
| return specialClass.getSpecializedBinding(); |
| } |
| |
| public final IBinding getBinding(IASTName name, boolean resolve) { |
| return getBinding(name, resolve, IIndexFileSet.EMPTY); |
| } |
| |
| public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) { |
| return getBindings(name, resolve, prefix, IIndexFileSet.EMPTY); |
| } |
| |
| public IBinding getBinding(IASTName name, boolean forceResolve, IIndexFileSet fileSet) { |
| char[] c = name.getLookupKey(); |
| |
| if (CharArrayUtils.equals(c, specialClass.getNameCharArray()) |
| && !CPPClassScope.shallReturnConstructors(name, false)) { |
| return specialClass; |
| } |
| |
| ICPPClassType specialized = specialClass.getSpecializedBinding(); |
| IScope classScope = specialized.getCompositeScope(); |
| IBinding[] bindings = classScope != null ? classScope.getBindings(name, forceResolve, false) : null; |
| |
| if (bindings == null) |
| return null; |
| |
| IBinding[] specs = new IBinding[0]; |
| for (IBinding binding : bindings) { |
| specs = (IBinding[]) ArrayUtil.append(IBinding.class, specs, specialClass.specializeMember(binding)); |
| } |
| specs = (IBinding[]) ArrayUtil.trim(IBinding.class, specs); |
| return CPPSemantics.resolveAmbiguities(name, specs); |
| } |
| |
| final public IBinding[] getBindings(IASTName name, boolean forceResolve, boolean prefixLookup, |
| IIndexFileSet fileSet) { |
| return getBindings(name, forceResolve, prefixLookup, fileSet, true); |
| } |
| |
| public IBinding[] getBindings(IASTName name, boolean forceResolve, boolean prefixLookup, |
| IIndexFileSet fileSet, boolean checkPointOfDecl) { |
| ICPPClassType specialized = specialClass.getSpecializedBinding(); |
| IScope classScope = specialized.getCompositeScope(); |
| if (classScope == null) |
| return IBinding.EMPTY_BINDING_ARRAY; |
| |
| IBinding[] bindings; |
| if (classScope instanceof ICPPASTInternalScope) { |
| bindings= ((ICPPASTInternalScope) classScope).getBindings(name, forceResolve, prefixLookup, fileSet, checkPointOfDecl); |
| } else { |
| bindings= classScope.getBindings(name, forceResolve, prefixLookup, fileSet); |
| } |
| IBinding[] result= null; |
| for (IBinding binding : bindings) { |
| if (binding == specialized) { |
| binding= specialClass; |
| } else { |
| binding= specialClass.specializeMember(binding); |
| } |
| result = (IBinding[]) ArrayUtil.append(IBinding.class, result, binding); |
| } |
| return (IBinding[]) ArrayUtil.trim(IBinding.class, result); |
| } |
| |
| public ICPPClassSpecialization getClassType() { |
| return specialClass; |
| } |
| |
| public ICPPBase[] getBases() { |
| if (fBases == null) { |
| ICPPBase[] result = null; |
| ICPPBase[] bases = specialClass.getSpecializedBinding().getBases(); |
| if (bases.length == 0) { |
| fBases= bases; |
| } else { |
| final ICPPTemplateParameterMap tpmap = specialClass.getTemplateParameterMap(); |
| for (ICPPBase base : bases) { |
| IBinding origClass = base.getBaseClass(); |
| if (origClass instanceof ICPPTemplateParameter && ((ICPPTemplateParameter) origClass).isParameterPack()) { |
| IType[] specClasses= CPPTemplates.instantiateTypes(new IType[]{new CPPParameterPackType((IType) origClass)}, tpmap, -1, specialClass); |
| if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) { |
| result= (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, base); |
| } else { |
| for (IType specClass : specClasses) { |
| ICPPBase specBase = base.clone(); |
| specClass = SemanticUtil.getUltimateType(specClass, false); |
| if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) { |
| specBase.setBaseClass((IBinding) specClass); |
| result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBase); |
| } |
| } |
| } |
| continue; |
| } |
| if (origClass instanceof IType) { |
| ICPPBase specBase = base.clone(); |
| IType specClass= CPPTemplates.instantiateType((IType) origClass, tpmap, -1, specialClass); |
| specClass = SemanticUtil.getUltimateType(specClass, false); |
| if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) { |
| specBase.setBaseClass((IBinding) specClass); |
| } |
| result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBase); |
| } |
| } |
| result= (ICPPBase[]) ArrayUtil.trim(ICPPBase.class, result); |
| fBases= result; |
| return result; |
| } |
| } |
| return fBases; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <T extends IBinding> T[] specializeMembers(T[] array) { |
| if (array == null || array.length == 0) |
| return array; |
| |
| T[] newArray= array.clone(); |
| for (int i = 0; i < newArray.length; i++) { |
| newArray[i]= (T) specialClass.specializeMember(array[i]); |
| } |
| return newArray; |
| } |
| |
| public ICPPField[] getDeclaredFields() { |
| ICPPField[] fields= specialClass.getSpecializedBinding().getDeclaredFields(); |
| return specializeMembers(fields); |
| } |
| |
| public ICPPMethod[] getImplicitMethods() { |
| ICPPClassScope origClassScope= (ICPPClassScope) specialClass.getSpecializedBinding().getCompositeScope(); |
| if (origClassScope == null) { |
| return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; |
| } |
| ICPPMethod[] methods= origClassScope.getImplicitMethods(); |
| return specializeMembers(methods); |
| } |
| |
| public IName getScopeName() { |
| if (specialClass instanceof ICPPInternalBinding) |
| return (IASTName) ((ICPPInternalBinding) specialClass).getDefinition(); |
| return null; |
| } |
| |
| public ICPPConstructor[] getConstructors() { |
| ICPPConstructor[] ctors= specialClass.getSpecializedBinding().getConstructors(); |
| return specializeMembers(ctors); |
| } |
| |
| public ICPPMethod[] getDeclaredMethods() { |
| ICPPMethod[] bindings = specialClass.getSpecializedBinding().getDeclaredMethods(); |
| return specializeMembers(bindings); |
| } |
| |
| public ICPPClassType[] getNestedClasses() { |
| ICPPClassType[] bindings = specialClass.getSpecializedBinding().getNestedClasses(); |
| return specializeMembers(bindings); |
| } |
| |
| public IBinding[] getFriends() { |
| // not yet supported |
| return IBinding.EMPTY_BINDING_ARRAY; |
| } |
| |
| public IScope getParent() throws DOMException { |
| IBinding binding= specialClass.getOwner(); |
| if (binding instanceof ICPPClassType) { |
| return ((ICPPClassType) binding).getCompositeScope(); |
| } |
| if (binding instanceof ICPPNamespace) { |
| return ((ICPPNamespace) binding).getNamespaceScope(); |
| } |
| return getOriginalClassType().getScope(); |
| } |
| |
| public IBinding[] find(String name) { |
| return CPPSemantics.findBindings(this, name, false); |
| } |
| |
| @Override |
| public String toString() { |
| IName name = getScopeName(); |
| return name != null ? name.toString() : String.valueOf(specialClass); |
| } |
| |
| public EScopeKind getKind() { |
| return EScopeKind.eClassType; |
| } |
| } |