blob: a022efb61049117741165d352c6befd1c40d0991 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2015 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:
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Thomas Corbat (IFS)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTClassVirtSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
/**
* c++ specific composite type specifier
*/
public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
implements ICPPASTCompositeTypeSpecifier {
private int fKey;
private IASTName fName;
private CPPClassScope fScope;
private IASTDeclaration[] fAllDeclarations;
private IASTDeclaration[] fActiveDeclarations;
private int fDeclarationsPos = -1;
private ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier[] baseSpecs;
private int baseSpecsPos = -1;
private boolean fAmbiguitiesResolved;
private ICPPASTClassVirtSpecifier virtSpecifier;
public CPPASTCompositeTypeSpecifier() {
}
public CPPASTCompositeTypeSpecifier(int k, IASTName n) {
this.fKey = k;
setName(n);
}
public void setAmbiguitiesResolved() {
if (!fAmbiguitiesResolved && fScope != null) {
fScope.createImplicitMembers();
}
fAmbiguitiesResolved= true;
}
@Override
public CPPASTCompositeTypeSpecifier copy() {
return copy(CopyStyle.withoutLocations);
}
@Override
public CPPASTCompositeTypeSpecifier copy(CopyStyle style) {
CPPASTCompositeTypeSpecifier copy =
new CPPASTCompositeTypeSpecifier(fKey, fName == null ? null : fName.copy(style));
for (IASTDeclaration member : getMembers())
copy.addMemberDeclaration(member == null ? null : member.copy(style));
for (ICPPASTBaseSpecifier baseSpecifier : getBaseSpecifiers())
copy.addBaseSpecifier(baseSpecifier == null ? null : baseSpecifier.copy(style));
copy.setVirtSpecifier(virtSpecifier == null ? null : virtSpecifier.copy(style));
return super.copy(copy, style);
}
@Override
public ICPPASTBaseSpecifier[] getBaseSpecifiers() {
if (baseSpecs == null)
return ICPPASTBaseSpecifier.EMPTY_BASESPECIFIER_ARRAY;
baseSpecs = ArrayUtil.trimAt(ICPPASTBaseSpecifier.class, baseSpecs, baseSpecsPos);
return baseSpecs;
}
@Override
public void addBaseSpecifier(ICPPASTBaseSpecifier baseSpec) {
assertNotFrozen();
if (baseSpec != null) {
baseSpec.setParent(this);
baseSpec.setPropertyInParent(BASE_SPECIFIER);
baseSpecs = ArrayUtil.appendAt(ICPPASTBaseSpecifier.class, baseSpecs, ++baseSpecsPos,
baseSpec);
}
}
@Override
public int getKey() {
return fKey;
}
@Override
public void setKey(int key) {
assertNotFrozen();
fKey = key;
}
@Override
public IASTName getName() {
return fName;
}
@Override
public void setName(IASTName name) {
assertNotFrozen();
this.fName = name;
if (name != null) {
name.setParent(this);
name.setPropertyInParent(TYPE_NAME);
}
}
@Override
public IASTDeclaration[] getMembers() {
IASTDeclaration[] active= fActiveDeclarations;
if (active == null) {
active = ASTQueries.extractActiveDeclarations(fAllDeclarations, fDeclarationsPos + 1);
fActiveDeclarations= active;
}
return active;
}
@Override
public final IASTDeclaration[] getDeclarations(boolean includeInactive) {
if (includeInactive) {
fAllDeclarations= ArrayUtil.trimAt(IASTDeclaration.class, fAllDeclarations,
fDeclarationsPos);
return fAllDeclarations;
}
return getMembers();
}
@Override
public void addMemberDeclaration(IASTDeclaration decl) {
if (decl == null)
return;
// ignore inactive visibility labels
if (decl instanceof ICPPASTVisibilityLabel && !decl.isActive())
return;
assertNotFrozen();
decl.setParent(this);
decl.setPropertyInParent(decl instanceof ICPPASTVisibilityLabel ? VISIBILITY_LABEL : MEMBER_DECLARATION);
fAllDeclarations = ArrayUtil.appendAt(IASTDeclaration.class, fAllDeclarations,
++fDeclarationsPos, decl);
fActiveDeclarations= null;
}
@Override
public final void addDeclaration(IASTDeclaration decl) {
addMemberDeclaration(decl);
}
@Override
public ICPPClassScope getScope() {
if (fScope == null) {
fScope = new CPPClassScope(this);
if (fAmbiguitiesResolved) {
fScope.createImplicitMembers();
}
}
return fScope;
}
@Override
public boolean accept(ASTVisitor action) {
if (action.shouldVisitDeclSpecifiers) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
default: break;
}
}
if (!acceptByAttributeSpecifiers(action))
return false;
if (fName != null && !fName.accept(action))
return false;
if (virtSpecifier != null && !virtSpecifier.accept(action))
return false;
ICPPASTBaseSpecifier[] bases = getBaseSpecifiers();
for (int i = 0; i < bases.length; i++) {
if (!bases[i].accept(action))
return false;
}
IASTDeclaration[] decls = getDeclarations(action.includeInactiveNodes);
for (int i = 0; i < decls.length; i++) {
if (!decls[i].accept(action))
return false;
}
if (action.shouldVisitDeclSpecifiers && action.leave(this) == ASTVisitor.PROCESS_ABORT)
return false;
return true;
}
@Override
public int getRoleForName(IASTName name) {
if (name == this.fName)
return r_definition;
return r_unclear;
}
@Override
public void replace(IASTNode child, IASTNode other) {
assert child.isActive() == other.isActive();
for (int i = 0; i <= fDeclarationsPos; ++i) {
if (fAllDeclarations[i] == child) {
other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent());
fAllDeclarations[i] = (IASTDeclaration) other;
fActiveDeclarations= null;
return;
}
}
super.replace(child, other);
}
@Override
public boolean isFinal() {
return virtSpecifier != null;
}
@Override
@Deprecated
public void setFinal(boolean value) {
assertNotFrozen();
// Do nothing here. Use setVirtSpecifier() instead.
}
@Override
public ICPPASTClassVirtSpecifier getVirtSpecifier() {
return virtSpecifier;
}
@Override
public void setVirtSpecifier(ICPPASTClassVirtSpecifier virtSpecifier) {
assertNotFrozen();
this.virtSpecifier = virtSpecifier;
if (virtSpecifier != null) {
virtSpecifier.setParent(this);
virtSpecifier.setPropertyInParent(CLASS_VIRT_SPECIFIER);
}
}
}