blob: 2495e588bd33d65276817250f2e338bee2530d0e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2014 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
* Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
* Thomas Corbat (IFS)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
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.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
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.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
/**
* Represents a class template.
*/
public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClassTemplate,
ICPPInternalClassTemplate, ICPPInternalClassTypeMixinHost {
private ICPPClassTemplatePartialSpecialization[] partialSpecializations;
private ICPPDeferredClassInstance fDeferredInstance;
private boolean addedPartialSpecializationsOfIndex;
private ICPPBase[] bases;
public CPPClassTemplate(IASTName name) {
super(name);
}
@Override
public void checkForDefinition() {
// Ambiguity resolution ensures that definitions are resolved.
}
@Override
public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec) {
partialSpecializations = ArrayUtil.append(
ICPPClassTemplatePartialSpecialization.class, partialSpecializations, spec);
}
@Override
public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() {
if (definition != null) {
IASTNode node = definition.getParent();
if (node instanceof ICPPASTQualifiedName)
node = node.getParent();
if (node instanceof ICPPASTCompositeTypeSpecifier)
return (ICPPASTCompositeTypeSpecifier) node;
}
return null;
}
@Override
public ICPPClassScope getCompositeScope() {
if (definition == null) {
checkForDefinition();
}
if (definition != null) {
IASTNode parent = definition.getParent();
while (parent instanceof IASTName)
parent = parent.getParent();
if (parent instanceof ICPPASTCompositeTypeSpecifier) {
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) parent;
return compSpec.getScope();
}
}
// Forward declarations must be backed up from the index.
ICPPClassTemplate ib = getIndexBinding();
if (ib != null) {
IScope scope = ib.getCompositeScope();
if (scope instanceof ICPPClassScope)
return (ICPPClassScope) scope;
}
return null;
}
@Override
public int getKey() {
if (definition != null) {
ICPPASTCompositeTypeSpecifier cts= getCompositeTypeSpecifier();
if (cts != null) {
return cts.getKey();
}
IASTNode n= definition.getParent();
if (n instanceof ICPPASTElaboratedTypeSpecifier) {
return ((ICPPASTElaboratedTypeSpecifier) n).getKind();
}
}
if (declarations != null && declarations.length > 0) {
IASTNode n = declarations[0].getParent();
if (n instanceof ICPPASTElaboratedTypeSpecifier) {
return ((ICPPASTElaboratedTypeSpecifier) n).getKind();
}
}
return ICPPASTElaboratedTypeSpecifier.k_class;
}
@Override
public ICPPClassTemplatePartialSpecialization[] getPartialSpecializations() {
if (!addedPartialSpecializationsOfIndex) {
addedPartialSpecializationsOfIndex= true;
ICPPClassTemplate ib = getIndexBinding();
if (ib != null) {
IIndexFileSet fs = getTemplateName().getTranslationUnit().getIndexFileSet();
for (ICPPClassTemplatePartialSpecialization spec : ib.getPartialSpecializations()) {
if (spec instanceof IIndexBinding && fs.containsDeclaration((IIndexBinding) spec)) {
addPartialSpecialization(spec);
}
}
}
}
partialSpecializations = ArrayUtil.trim(ICPPClassTemplatePartialSpecialization.class, partialSpecializations);
return partialSpecializations;
}
@Override
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef || type instanceof IIndexBinding)
return type.isSameType(this);
return false;
}
@Override
public ICPPBase[] getBases() {
if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
}
@Override
public IField[] getFields() {
return ClassTypeHelper.getFields(this);
}
@Override
public ICPPField[] getDeclaredFields() {
return ClassTypeHelper.getDeclaredFields(this);
}
@Override
public ICPPMethod[] getMethods() {
return ClassTypeHelper.getMethods(this);
}
@Override
public ICPPMethod[] getAllDeclaredMethods() {
return ClassTypeHelper.getAllDeclaredMethods(this);
}
@Override
public ICPPMethod[] getDeclaredMethods() {
return ClassTypeHelper.getDeclaredMethods(this);
}
@Override
public ICPPConstructor[] getConstructors() {
return ClassTypeHelper.getConstructors(this);
}
@Override
public IBinding[] getFriends() {
return ClassTypeHelper.getFriends(this);
}
@Override
public ICPPClassType[] getNestedClasses() {
return ClassTypeHelper.getNestedClasses(this);
}
@Override
public ICPPUsingDeclaration[] getUsingDeclarations() {
return ClassTypeHelper.getUsingDeclarations(this);
}
@Override
public IField findField(String name) {
return ClassTypeHelper.findField(this, name);
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
}
return null;
}
/* For debug purposes only */
@Override
public String toString() {
return ASTTypeUtil.getType(this);
}
@Override
public boolean isAnonymous() {
return false;
}
@Override
public final ICPPDeferredClassInstance asDeferredInstance() {
if (fDeferredInstance == null) {
fDeferredInstance= CPPTemplates.createDeferredInstance(this);
}
return fDeferredInstance;
}
@Override
public ICPPTemplateArgument getDefaultArgFromIndex(int paramPos) throws DOMException {
ICPPClassTemplate ib = getIndexBinding();
if (ib != null) {
ICPPTemplateParameter[] params = ib.getTemplateParameters();
if (paramPos < params.length) {
ICPPTemplateParameter param = params[paramPos];
return param.getDefaultValue();
}
}
return null;
}
@Override
public boolean isFinal() {
ICPPASTCompositeTypeSpecifier typeSpecifier = getCompositeTypeSpecifier();
if (typeSpecifier != null) {
return typeSpecifier.isFinal();
}
return false;
}
@Override
public int getVisibility(IBinding member) {
return ClassTypeHelper.getVisibility(this, member);
}
}