| /******************************************************************************* |
| * 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); |
| } |
| } |
| } |