blob: 63c983b1b115cecea81aa76dc6d6bcb0500b5b74 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2014 Wind River Systems, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStaticAssertDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeTransformationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.IContributedModelBuilder;
import org.eclipse.cdt.core.model.INamespace;
import org.eclipse.cdt.core.model.IProblemRequestor;
import org.eclipse.cdt.core.model.ISourceReference;
import org.eclipse.cdt.core.model.IStructure;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.ParseError;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
/**
* Build TranslationUnit structure from an {@code IASTTranslationUnit}.
*
* @since 4.0
*/
public class CModelBuilder2 implements IContributedModelBuilder {
private final static boolean DEBUG = Util.isActive(DebugLogConstants.MODEL);
private final TranslationUnit fTranslationUnit;
private final Map<ICElement, CElementInfo> fNewElements;
private final IProgressMonitor fProgressMonitor;
private ASTAccessVisibility fCurrentVisibility;
private Stack<ASTAccessVisibility> fVisibilityStack;
private HashMap<ISourceReference, int[]> fEqualElements;
/**
* Create a model builder for the given translation unit.
*
* @param tu the translation unit (must be a {@link TranslationUnit}
* @param newElements element cache
* @param monitor the progress monitor
*/
public CModelBuilder2(ITranslationUnit tu, Map<ICElement, CElementInfo> newElements, IProgressMonitor monitor) {
fTranslationUnit = (TranslationUnit) tu;
fNewElements = newElements;
fProgressMonitor = monitor;
}
@Override
public void parse(boolean quickParseMode) throws Exception {
final IIndexManager indexManager = CCorePlugin.getIndexManager();
IIndex index = indexManager.getIndex(fTranslationUnit.getCProject(),
IIndexManager.ADD_EXTENSION_FRAGMENTS_EDITOR);
try {
if (index != null) {
try {
index.acquireReadLock();
} catch (InterruptedException e) {
index = null;
}
}
checkCanceled();
long startTime = System.currentTimeMillis();
final CElementInfo elementInfo = getElementInfo(fTranslationUnit);
int parseFlags = quickParseMode ? ITranslationUnit.AST_SKIP_ALL_HEADERS
: ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
if (!(elementInfo instanceof ASTHolderTUInfo)) {
parseFlags |= ITranslationUnit.AST_SKIP_FUNCTION_BODIES;
} else {
parseFlags |= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT;
}
parseFlags |= ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS;
parseFlags |= ITranslationUnit.AST_PARSE_INACTIVE_CODE;
final IASTTranslationUnit ast;
try {
ast = fTranslationUnit.getAST(index, parseFlags, fProgressMonitor);
if (DEBUG) {
Util.debugLog("CModelBuilder2: parsing " //$NON-NLS-1$
+ fTranslationUnit.getElementName() + " mode=" //$NON-NLS-1$
+ (quickParseMode ? "skip all " : "skip indexed ") //$NON-NLS-1$ //$NON-NLS-2$
+ " time=" + (System.currentTimeMillis() - startTime) + "ms", //$NON-NLS-1$ //$NON-NLS-2$
DebugLogConstants.MODEL, false);
}
} catch (ParseError e) {
checkCanceled();
throw e;
}
if (ast == null) {
return;
}
checkCanceled();
startTime = System.currentTimeMillis();
buildModel(ast);
elementInfo.setIsStructureKnown(true);
if (DEBUG) {
Util.debugLog("CModelBuilder2: building " //$NON-NLS-1$
+ "children=" + elementInfo.internalGetChildren().size() //$NON-NLS-1$
+ " time=" + (System.currentTimeMillis() - startTime) + "ms", //$NON-NLS-1$ //$NON-NLS-2$
DebugLogConstants.MODEL, false);
}
if (elementInfo instanceof ASTHolderTUInfo) {
((ASTHolderTUInfo) elementInfo).fAST = ast;
// preserve index lock for AST receiver
index = null;
}
} finally {
if (index != null) {
index.releaseReadLock();
}
}
}
private boolean isCanceled() {
return fProgressMonitor != null && fProgressMonitor.isCanceled();
}
private void checkCanceled() {
if (fProgressMonitor != null && fProgressMonitor.isCanceled()) {
if (DEBUG)
Util.debugLog("CModelBuilder2: cancelled ", DebugLogConstants.MODEL, false); //$NON-NLS-1$
throw new OperationCanceledException();
}
}
/**
* Build the model from the given AST.
* @param ast
* @throws CModelException
* @throws DOMException
*/
private void buildModel(IASTTranslationUnit ast) throws CModelException, DOMException {
fVisibilityStack = new Stack<>();
fEqualElements = new HashMap<>();
// includes
final IASTPreprocessorIncludeStatement[] includeDirectives = ast.getIncludeDirectives();
for (IASTPreprocessorIncludeStatement includeDirective : includeDirectives) {
if (isLocalToFile(includeDirective)) {
createInclusion(fTranslationUnit, includeDirective);
}
}
// Macros
final IASTPreprocessorMacroDefinition[] macroDefinitions = ast.getMacroDefinitions();
for (IASTPreprocessorMacroDefinition macroDefinition : macroDefinitions) {
if (isLocalToFile(macroDefinition)) {
createMacro(fTranslationUnit, macroDefinition);
}
}
// Declarations
final IASTDeclaration[] declarations = ast.getDeclarations(true);
for (IASTDeclaration declaration : declarations) {
if (isLocalToFile(declaration)) {
createDeclaration(fTranslationUnit, declaration);
}
}
fEqualElements.clear();
// Sort by offset
final List<ICElement> children = getElementInfo(fTranslationUnit).internalGetChildren();
Collections.sort(children, new Comparator<ICElement>() {
@Override
public int compare(ICElement o1, ICElement o2) {
final SourceManipulationInfo info1 = getSourceManipulationInfo((SourceManipulation) o1);
final SourceManipulationInfo info2 = getSourceManipulationInfo((SourceManipulation) o2);
int delta = info1.getStartPos() - info2.getStartPos();
if (delta == 0) {
delta = info1.getIdStartPos() - info2.getIdStartPos();
}
return delta;
}
});
if (isCanceled()) {
return;
}
// Report problems
IProblemRequestor problemRequestor = fTranslationUnit.getProblemRequestor();
if (problemRequestor != null && problemRequestor.isActive()) {
problemRequestor.beginReporting();
final IASTProblem[] ppProblems = ast.getPreprocessorProblems();
IASTProblem[] problems = ppProblems;
for (IASTProblem problem : problems) {
if (isLocalToFile(problem)) {
problemRequestor.acceptProblem(problem);
}
}
problems = CPPVisitor.getProblems(ast);
for (IASTProblem problem : problems) {
if (isLocalToFile(problem)) {
problemRequestor.acceptProblem(problem);
}
}
problemRequestor.endReporting();
}
}
private boolean isLocalToFile(IASTNode node) {
return node.isPartOfTranslationUnitFile();
}
private Include createInclusion(Parent parent, IASTPreprocessorIncludeStatement inclusion) throws CModelException {
// Create element
final IASTName name = inclusion.getName();
Include element = new Include(parent, ASTStringUtil.getSimpleName(name), inclusion.isSystemInclude());
element.setFullPathName(inclusion.getPath());
setIndex(element);
element.setActive(inclusion.isActive());
element.setResolved(inclusion.isResolved());
// Add to parent
parent.addChild(element);
// Set positions
setIdentifierPosition(element, name);
setBodyPosition(element, inclusion);
return element;
}
private void setIndex(SourceManipulation element) {
int[] idx = fEqualElements.get(element);
if (idx == null) {
idx = new int[] { 0 };
fEqualElements.put(element, idx);
} else {
element.setIndex(++idx[0]);
}
}
private Macro createMacro(Parent parent, IASTPreprocessorMacroDefinition macro) throws CModelException {
// Create element
final IASTName name = macro.getName();
Macro element = new Macro(parent, ASTStringUtil.getSimpleName(name));
setIndex(element);
element.setActive(macro.isActive());
// Add to parent
parent.addChild(element);
// Set positions
setIdentifierPosition(element, name);
setBodyPosition(element, macro);
if (macro instanceof IASTPreprocessorFunctionStyleMacroDefinition) {
element.setFunctionStyle(true);
}
return element;
}
private void createDeclaration(Parent parent, IASTDeclaration declaration) throws CModelException, DOMException {
if (declaration instanceof IASTFunctionDefinition) {
createFunctionDefinition(parent, (IASTFunctionDefinition) declaration, false);
} else if (declaration instanceof IASTSimpleDeclaration) {
createSimpleDeclarations(parent, (IASTSimpleDeclaration) declaration, false);
} else if (declaration instanceof ICPPASTVisibilityLabel) {
handleVisibilityLabel((ICPPASTVisibilityLabel) declaration);
} else if (declaration instanceof ICPPASTNamespaceDefinition) {
createNamespace(parent, (ICPPASTNamespaceDefinition) declaration);
} else if (declaration instanceof ICPPASTNamespaceAlias) {
// TODO [cmodel] namespace alias?
} else if (declaration instanceof ICPPASTTemplateDeclaration) {
createTemplateDeclaration(parent, (ICPPASTTemplateDeclaration) declaration);
} else if (declaration instanceof ICPPASTTemplateSpecialization) {
// TODO [cmodel] template specialization?
} else if (declaration instanceof ICPPASTExplicitTemplateInstantiation) {
// TODO [cmodel] explicit template instantiation?
} else if (declaration instanceof ICPPASTAliasDeclaration) {
// TODO [cmodel] alias declaration?
} else if (declaration instanceof ICPPASTUsingDeclaration) {
createUsingDeclaration(parent, (ICPPASTUsingDeclaration) declaration);
} else if (declaration instanceof ICPPASTUsingDirective) {
createUsingDirective(parent, (ICPPASTUsingDirective) declaration);
} else if (declaration instanceof ICPPASTLinkageSpecification) {
createLinkageSpecification(parent, (ICPPASTLinkageSpecification) declaration);
} else if (declaration instanceof IASTASMDeclaration) {
// TODO [cmodel] asm declaration?
} else if (declaration instanceof IASTProblemDeclaration) {
// TODO [cmodel] problem declaration?
} else if (declaration instanceof ICPPASTStaticAssertDeclaration) {
// ignore
} else {
assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$
}
}
private void createTemplateDeclaration(Parent parent, ICPPASTTemplateDeclaration templateDeclaration)
throws CModelException, DOMException {
IASTDeclaration declaration = templateDeclaration.getDeclaration();
if (declaration instanceof IASTFunctionDefinition) {
CElement element = createFunctionDefinition(parent, (IASTFunctionDefinition) declaration, true);
String[] parameterTypes = ASTStringUtil
.getTemplateParameterArray(templateDeclaration.getTemplateParameters());
// set the template parameters
if (element instanceof FunctionTemplate) {
FunctionTemplate functionTemplate = (FunctionTemplate) element;
functionTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof MethodTemplate) {
MethodTemplate methodTemplate = (MethodTemplate) element;
methodTemplate.setTemplateParameterTypes(parameterTypes);
}
// set the body position
if (element instanceof SourceManipulation) {
setBodyPosition((SourceManipulation) element, templateDeclaration);
}
} else if (declaration instanceof IASTSimpleDeclaration) {
CElement[] elements = createSimpleDeclarations(parent, (IASTSimpleDeclaration) declaration, true);
String[] parameterTypes = ASTStringUtil
.getTemplateParameterArray(templateDeclaration.getTemplateParameters());
for (CElement element : elements) {
// set the template parameters
if (element instanceof StructureTemplate) {
StructureTemplate classTemplate = (StructureTemplate) element;
classTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof StructureTemplateDeclaration) {
StructureTemplateDeclaration classTemplate = (StructureTemplateDeclaration) element;
classTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof VariableTemplate) {
VariableTemplate varTemplate = (VariableTemplate) element;
varTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof FunctionTemplateDeclaration) {
FunctionTemplateDeclaration functionTemplate = (FunctionTemplateDeclaration) element;
functionTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof MethodTemplateDeclaration) {
MethodTemplateDeclaration methodTemplate = (MethodTemplateDeclaration) element;
methodTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof FunctionTemplate) {
FunctionTemplate functionTemplate = (FunctionTemplate) element;
functionTemplate.setTemplateParameterTypes(parameterTypes);
} else if (element instanceof MethodTemplate) {
MethodTemplate methodTemplate = (MethodTemplate) element;
methodTemplate.setTemplateParameterTypes(parameterTypes);
}
// set the body position
if (element instanceof SourceManipulation) {
setBodyPosition((SourceManipulation) element, templateDeclaration);
}
}
} else if (declaration instanceof ICPPASTAliasDeclaration) {
createDeclaration(parent, declaration);
} else if (declaration instanceof ICPPASTTemplateDeclaration) {
// strange: template decl inside template decl
createTemplateDeclaration(parent, (ICPPASTTemplateDeclaration) declaration);
} else if (declaration instanceof IASTProblemDeclaration) {
// ignore problem declarations (or create special elements for debugging?)
} else {
assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$
}
}
/**
* Handle extern "C" and related kinds.
*
* @param parent
* @param declaration
* @throws CModelException
* @throws DOMException
*/
private void createLinkageSpecification(Parent parent, ICPPASTLinkageSpecification linkageDeclaration)
throws CModelException, DOMException {
IASTDeclaration[] declarations = linkageDeclaration.getDeclarations(true);
for (IASTDeclaration declaration : declarations) {
if (linkageDeclaration.getFileLocation() != null || isLocalToFile(declaration)) {
createDeclaration(parent, declaration);
}
}
}
private CElement[] createSimpleDeclarations(Parent parent, IASTSimpleDeclaration declaration, boolean isTemplate)
throws CModelException, DOMException {
final IASTDeclSpecifier declSpecifier = declaration.getDeclSpecifier();
final IASTDeclarator[] declarators = declaration.getDeclarators();
final CElement[] elements;
boolean isCompositeType = declSpecifier instanceof IASTCompositeTypeSpecifier
|| declSpecifier instanceof IASTEnumerationSpecifier;
if (declarators.length == 0) {
elements = new CElement[1];
final CElement element = createSimpleDeclaration(parent, declSpecifier, null, isTemplate);
elements[0] = element;
} else {
if (isCompositeType) {
createSimpleDeclaration(parent, declSpecifier, null, isTemplate);
}
elements = new CElement[declarators.length];
for (int i = 0; i < declarators.length; i++) {
final IASTDeclarator declarator = declarators[i];
final CElement element = createSimpleDeclaration(parent, declSpecifier, declarator, isTemplate);
if (!isTemplate && element instanceof SourceManipulation && declarators.length > 1) {
setBodyPosition((SourceManipulation) element, declarator);
}
elements[i] = element;
}
}
return elements;
}
private CElement createSimpleDeclaration(Parent parent, IASTDeclSpecifier declSpecifier, IASTDeclarator declarator,
boolean isTemplate) throws CModelException, DOMException {
if (declSpecifier instanceof IASTCompositeTypeSpecifier) {
if (declarator != null) {
return createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate);
}
return createCompositeType(parent, (IASTCompositeTypeSpecifier) declSpecifier, isTemplate);
} else if (declSpecifier instanceof IASTElaboratedTypeSpecifier) {
if (declarator != null) {
return createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate);
}
return createElaboratedTypeDeclaration(parent, (IASTElaboratedTypeSpecifier) declSpecifier, isTemplate);
} else if (declSpecifier instanceof IASTEnumerationSpecifier) {
if (declarator != null) {
return createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate);
}
return createEnumeration(parent, (IASTEnumerationSpecifier) declSpecifier);
} else if (declSpecifier instanceof IASTNamedTypeSpecifier) {
if (declarator != null) {
return createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate);
}
} else if (declSpecifier instanceof IASTSimpleDeclSpecifier) {
if (declarator != null) {
return createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate);
}
} else if (declSpecifier instanceof ICPPASTTypeTransformationSpecifier) {
if (declarator != null) {
return createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate);
}
} else {
assert false : "TODO: " + declSpecifier.getClass().getName(); //$NON-NLS-1$
}
return null;
}
private CElement createTypedefOrFunctionOrVariable(Parent parent, IASTDeclSpecifier declSpecifier,
IASTDeclarator declarator, boolean isTemplate) throws CModelException {
assert declarator != null;
if (declSpecifier.getStorageClass() == IASTDeclSpecifier.sc_typedef) {
return createTypeDef(parent, declSpecifier, declarator);
}
IASTDeclarator typeRelevant = ASTQueries.findTypeRelevantDeclarator(declarator);
if (typeRelevant instanceof IASTFunctionDeclarator) {
return createFunctionDeclaration(parent, declSpecifier, (IASTFunctionDeclarator) typeRelevant, isTemplate);
}
return createVariable(parent, declSpecifier, declarator, isTemplate);
}
private void createNamespace(Parent parent, ICPPASTNamespaceDefinition declaration)
throws CModelException, DOMException {
// create element
final String type = Keywords.NAMESPACE;
final IASTName name = declaration.getName();
final String nsName = ASTStringUtil.getQualifiedName(name);
final Namespace element = new Namespace(parent, nsName);
setIndex(element);
element.setActive(declaration.isActive());
// add to parent
parent.addChild(element);
// set positions
if (name != null && nsName.length() > 0) {
setIdentifierPosition(element, name);
} else {
final IASTFileLocation nsLocation = declaration.getFileLocation();
if (nsLocation != null) {
// Note: don't want to call element.setIdPos(), because we want the SourceManipulationInfo
// lookup to go through the local 'fNewElements' cache.
getSourceManipulationInfo(element).setIdPos(nsLocation.getNodeOffset(), type.length());
}
}
setBodyPosition(element, declaration);
element.setTypeName(type);
IASTDeclaration[] nsDeclarations = declaration.getDeclarations(true);
for (IASTDeclaration nsDeclaration : nsDeclarations) {
if (declaration.getFileLocation() != null || isLocalToFile(nsDeclaration)) {
createDeclaration(element, nsDeclaration);
}
}
}
private StructureDeclaration createElaboratedTypeDeclaration(Parent parent,
IASTElaboratedTypeSpecifier elaboratedTypeSpecifier, boolean isTemplate) throws CModelException {
// create element
final String type;
final int kind;
switch (elaboratedTypeSpecifier.getKind()) {
case IASTElaboratedTypeSpecifier.k_struct:
kind = (isTemplate) ? ICElement.C_TEMPLATE_STRUCT_DECLARATION : ICElement.C_STRUCT_DECLARATION;
type = Keywords.STRUCT;
break;
case IASTElaboratedTypeSpecifier.k_union:
kind = (isTemplate) ? ICElement.C_TEMPLATE_UNION_DECLARATION : ICElement.C_UNION_DECLARATION;
type = Keywords.UNION;
break;
case ICPPASTElaboratedTypeSpecifier.k_class:
kind = (isTemplate) ? ICElement.C_TEMPLATE_CLASS_DECLARATION : ICElement.C_CLASS_DECLARATION;
type = Keywords.CLASS;
break;
case IASTElaboratedTypeSpecifier.k_enum:
// do we need a C_ENUM_DECLARATION?
kind = ICElement.C_CLASS_DECLARATION;
type = Keywords.ENUM;
break;
default:
kind = ICElement.C_CLASS_DECLARATION;
type = ""; //$NON-NLS-1$
break;
}
final IASTName astClassName = elaboratedTypeSpecifier.getName();
final String className = ASTStringUtil.getSimpleName(astClassName);
StructureDeclaration element;
if (isTemplate) {
element = new StructureTemplateDeclaration(parent, kind, className);
} else {
element = new StructureDeclaration(parent, className, kind);
}
setIndex(element);
element.setActive(elaboratedTypeSpecifier.isActive());
StructureInfo info = (StructureInfo) getElementInfo(element);
info.setTypeName(type);
// add to parent
parent.addChild(element);
// set positions
if (className.length() > 0) {
setIdentifierPosition(info, astClassName);
} else {
final IASTFileLocation classLocation = getMinFileLocation(elaboratedTypeSpecifier.getNodeLocations());
if (classLocation != null) {
info.setIdPos(classLocation.getNodeOffset(), type.length());
}
}
setBodyPosition(info, elaboratedTypeSpecifier);
return element;
}
private Enumeration createEnumeration(Parent parent, IASTEnumerationSpecifier enumSpecifier)
throws CModelException {
// create element
final String type = Keywords.ENUM;
final IASTName astEnumName = enumSpecifier.getName();
final String enumName = ASTStringUtil.getSimpleName(astEnumName);
final Enumeration element = new Enumeration(parent, enumName);
setIndex(element);
element.setActive(enumSpecifier.isActive());
// add to parent
parent.addChild(element);
EnumerationInfo info = (EnumerationInfo) getElementInfo(element);
// set enumeration position
if (astEnumName != null && enumName.length() > 0) {
setIdentifierPosition(info, astEnumName);
} else {
final IASTFileLocation enumLocation = enumSpecifier.getFileLocation();
info.setIdPos(enumLocation.getNodeOffset(), type.length());
}
// add enumerators
final IASTEnumerator[] enumerators = enumSpecifier.getEnumerators();
for (final IASTEnumerator enumerator : enumerators) {
createEnumerator(element, enumerator);
}
setBodyPosition(info, enumSpecifier);
info.setTypeName(type);
return element;
}
private Enumerator createEnumerator(Parent enumarator, IASTEnumerator enumDef) throws CModelException {
final IASTName astEnumName = enumDef.getName();
final Enumerator element = new Enumerator(enumarator, ASTStringUtil.getSimpleName(astEnumName));
setIndex(element);
element.setActive(enumDef.isActive());
IASTExpression initialValue = enumDef.getValue();
if (initialValue != null) {
element.setConstantExpression(ASTStringUtil.getExpressionString(initialValue));
}
// add to parent
enumarator.addChild(element);
// set positions
setIdentifierPosition(element, astEnumName);
setBodyPosition(element, enumDef);
return element;
}
private Structure createCompositeType(Parent parent, IASTCompositeTypeSpecifier compositeTypeSpecifier,
boolean isTemplate) throws CModelException, DOMException {
// create element
final String type;
final int kind;
final ASTAccessVisibility defaultVisibility;
switch (compositeTypeSpecifier.getKey()) {
case IASTCompositeTypeSpecifier.k_struct:
kind = (isTemplate) ? ICElement.C_TEMPLATE_STRUCT : ICElement.C_STRUCT;
type = Keywords.STRUCT;
defaultVisibility = ASTAccessVisibility.PUBLIC;
break;
case IASTCompositeTypeSpecifier.k_union:
kind = (isTemplate) ? ICElement.C_TEMPLATE_UNION : ICElement.C_UNION;
type = Keywords.UNION;
defaultVisibility = ASTAccessVisibility.PUBLIC;
break;
case ICPPASTCompositeTypeSpecifier.k_class:
kind = (isTemplate) ? ICElement.C_TEMPLATE_CLASS : ICElement.C_CLASS;
type = Keywords.CLASS;
defaultVisibility = ASTAccessVisibility.PRIVATE;
break;
default:
kind = ICElement.C_CLASS;
type = ""; //$NON-NLS-1$
defaultVisibility = ASTAccessVisibility.PUBLIC;
break;
}
final IASTName astClassName = compositeTypeSpecifier.getName();
final String className = ASTStringUtil.getSimpleName(astClassName);
final Structure element;
if (!isTemplate) {
Structure classElement = new Structure(parent, kind, className);
element = classElement;
} else {
StructureTemplate classTemplate = new StructureTemplate(parent, kind, className);
element = classTemplate;
}
setIndex(element);
element.setActive(compositeTypeSpecifier.isActive());
if (compositeTypeSpecifier instanceof ICPPASTCompositeTypeSpecifier) {
// store super classes names
final ICPPASTCompositeTypeSpecifier cppCompositeTypeSpecifier = (ICPPASTCompositeTypeSpecifier) compositeTypeSpecifier;
ICPPASTBaseSpecifier[] baseSpecifiers = cppCompositeTypeSpecifier.getBaseSpecifiers();
for (final ICPPASTBaseSpecifier baseSpecifier : baseSpecifiers) {
final ICPPASTNameSpecifier nameSpec = baseSpecifier.getNameSpecifier();
final ASTAccessVisibility visibility;
switch (baseSpecifier.getVisibility()) {
case ICPPASTBaseSpecifier.v_public:
visibility = ASTAccessVisibility.PUBLIC;
break;
case ICPPASTBaseSpecifier.v_protected:
visibility = ASTAccessVisibility.PROTECTED;
break;
case ICPPASTBaseSpecifier.v_private:
visibility = ASTAccessVisibility.PRIVATE;
break;
default:
visibility = ASTAccessVisibility.PUBLIC;
}
if (nameSpec instanceof IASTName) {
element.addSuperClass(ASTStringUtil.getSimpleName((IASTName) nameSpec), visibility);
} else {
element.addSuperClass(new String(nameSpec.toCharArray()), visibility);
}
}
}
StructureInfo info = (StructureInfo) getElementInfo(element);
info.setTypeName(type);
// add to parent
parent.addChild(element);
// set positions
if (!isTemplate) {
setBodyPosition(info, compositeTypeSpecifier);
}
if (className.length() > 0) {
setIdentifierPosition(info, astClassName);
} else {
final IASTFileLocation classLocation = getMinFileLocation(compositeTypeSpecifier.getNodeLocations());
if (classLocation != null) {
info.setIdPos(classLocation.getNodeOffset(), type.length());
}
}
// add members
pushDefaultVisibility(defaultVisibility);
try {
final IASTDeclaration[] memberDeclarations = compositeTypeSpecifier.getDeclarations(true);
for (IASTDeclaration member : memberDeclarations) {
if (compositeTypeSpecifier.getFileLocation() != null || isLocalToFile(member)) {
createDeclaration(element, member);
}
}
} finally {
popDefaultVisibility();
}
return element;
}
private TypeDef createTypeDef(Parent parent, IASTDeclSpecifier declSpecifier, IASTDeclarator declarator)
throws CModelException {
IASTDeclarator nestedDeclarator = declarator;
while (nestedDeclarator.getNestedDeclarator() != null) {
nestedDeclarator = nestedDeclarator.getNestedDeclarator();
}
final IASTName astTypedefName = nestedDeclarator.getName();
if (astTypedefName == null) {
return null;
}
// create the element
String name = ASTStringUtil.getSimpleName(astTypedefName);
final TypeDef element = new TypeDef(parent, name);
setIndex(element);
element.setActive(declarator.isActive());
String typeName = ASTStringUtil.getSignatureString(declSpecifier, declarator);
element.setTypeName(typeName);
// add to parent
parent.addChild(element);
// set positions
final SourceManipulationInfo info = getSourceManipulationInfo(element);
if (name.length() > 0) {
setIdentifierPosition(info, astTypedefName);
} else {
setIdentifierPosition(info, declSpecifier);
}
if (declSpecifier instanceof IASTCompositeTypeSpecifier) {
setBodyPosition(info, astTypedefName);
} else {
setBodyPosition(info, declSpecifier.getParent());
}
return element;
}
private VariableDeclaration createVariable(Parent parent, IASTDeclSpecifier specifier, IASTDeclarator declarator,
boolean isTemplate) throws CModelException {
IASTDeclarator nestedDeclarator = declarator;
while (nestedDeclarator.getNestedDeclarator() != null) {
nestedDeclarator = nestedDeclarator.getNestedDeclarator();
}
final IASTName astVariableName = nestedDeclarator.getName();
if (astVariableName == null) {
return null;
}
final String variableName = ASTStringUtil.getQualifiedName(astVariableName);
final VariableDeclaration element;
final SourceManipulationInfo info;
if (declarator instanceof IASTFieldDeclarator || parent instanceof IStructure
|| CModelBuilder2.getScope(astVariableName) instanceof ICPPClassScope) {
// field
Field newElement = new Field(parent, variableName);
setIndex(newElement);
final FieldInfo fieldInfo = (FieldInfo) getElementInfo(newElement);
if (specifier instanceof ICPPASTDeclSpecifier) {
final ICPPASTDeclSpecifier cppSpecifier = (ICPPASTDeclSpecifier) specifier;
fieldInfo.setMutable(cppSpecifier.getStorageClass() == IASTDeclSpecifier.sc_mutable);
}
fieldInfo.setTypeName(ASTStringUtil.getSignatureString(specifier, declarator));
fieldInfo.setVisibility(getCurrentVisibility());
fieldInfo.setConst(specifier.isConst());
fieldInfo.setVolatile(specifier.isVolatile());
element = newElement;
info = fieldInfo;
} else {
if (isTemplate) {
// template variable
VariableTemplate newElement = new VariableTemplate(parent, variableName);
element = newElement;
} else {
if (specifier.getStorageClass() == IASTDeclSpecifier.sc_extern) {
// variable declaration
VariableDeclaration newElement = new VariableDeclaration(parent, variableName);
element = newElement;
} else {
// variable
Variable newElement = new Variable(parent, variableName);
element = newElement;
}
}
setIndex(element);
VariableInfo varInfo = (VariableInfo) getElementInfo(element);
varInfo.setTypeName(ASTStringUtil.getSignatureString(specifier, declarator));
varInfo.setConst(specifier.isConst());
varInfo.setVolatile(specifier.isVolatile());
info = varInfo;
}
element.setActive(declarator.isActive());
// TODO [cmodel] correctly resolve isStatic
element.setStatic(specifier.getStorageClass() == IASTDeclSpecifier.sc_static);
// add to parent
parent.addChild(element);
// set positions
setIdentifierPosition(info, astVariableName);
if (!isTemplate) {
if (specifier instanceof IASTCompositeTypeSpecifier) {
setBodyPosition(info, astVariableName);
} else {
setBodyPosition(info, specifier.getParent());
}
}
return element;
}
private FunctionDeclaration createFunctionDefinition(Parent parent, IASTFunctionDefinition functionDeclaration,
boolean isTemplate) throws CModelException, DOMException {
final IASTFunctionDeclarator declarator = functionDeclaration.getDeclarator();
IASTDeclarator nestedDeclarator = declarator;
while (nestedDeclarator.getNestedDeclarator() != null) {
nestedDeclarator = nestedDeclarator.getNestedDeclarator();
}
final IASTName name = nestedDeclarator.getName();
if (name == null) {
// Something is wrong, skip this element
return null;
}
final IASTDeclSpecifier declSpecifier = functionDeclaration.getDeclSpecifier();
final String simpleName = ASTStringUtil.getSimpleName(name);
final String[] parameterTypes = ASTStringUtil.getParameterSignatureArray(declarator);
final String returnType = ASTStringUtil.getReturnTypeString(declSpecifier, declarator);
final FunctionDeclaration element;
final FunctionInfo info;
if (declarator instanceof ICPPASTFunctionDeclarator) {
final ICPPASTFunctionDeclarator cppFunctionDeclarator = (ICPPASTFunctionDeclarator) declarator;
final IASTName simpleAstName;
if (name instanceof ICPPASTQualifiedName) {
final ICPPASTQualifiedName quName = (ICPPASTQualifiedName) name;
simpleAstName = quName.getLastName();
} else {
simpleAstName = name;
}
IScope scope = null;
// try to avoid expensive resolution of scope and binding
boolean isMethod = parent instanceof IStructure;
if (!isMethod && name instanceof ICPPASTQualifiedName) {
if (isTemplate) {
final ICPPASTNameSpecifier[] segments = ((ICPPASTQualifiedName) name).getAllSegments();
for (ICPPASTNameSpecifier segment : segments) {
if (segment instanceof ICPPASTTemplateId) {
isMethod = true;
break;
}
}
}
if (!isMethod) {
scope = CPPVisitor.getContainingScope(simpleAstName);
isMethod = scope instanceof ICPPClassScope || simpleAstName.resolveBinding() instanceof ICPPMethod;
}
}
if (isMethod) {
// method
final MethodDeclaration methodElement;
final String methodName;
if (parent instanceof IStructure) {
methodName = ASTStringUtil.getSimpleName(name);
} else {
methodName = ASTStringUtil.getQualifiedName(name);
}
if (isTemplate) {
methodElement = new MethodTemplate(parent, methodName);
} else {
methodElement = new Method(parent, methodName);
}
element = methodElement;
// establish identity attributes before getElementInfo()
methodElement.setParameterTypes(parameterTypes);
methodElement.setReturnType(returnType);
methodElement.setConst(cppFunctionDeclarator.isConst());
setIndex(element);
final MethodInfo methodInfo = (MethodInfo) getElementInfo(methodElement);
info = methodInfo;
ICPPMethod methodBinding = null;
if (scope != null) {
final IBinding binding = simpleAstName.resolveBinding();
if (binding instanceof ICPPMethod) {
methodBinding = (ICPPMethod) binding;
}
}
if (methodBinding != null) {
methodInfo.setVirtual(methodBinding.isVirtual());
methodInfo.setInline(methodBinding.isInline());
methodInfo.setFriend(((ICPPASTDeclSpecifier) declSpecifier).isFriend());
methodInfo.setVolatile(cppFunctionDeclarator.isVolatile());
methodInfo.setVisibility(adaptVisibilityConstant(methodBinding.getVisibility()));
methodInfo.setPureVirtual(false);
methodElement.setConstructor(methodBinding instanceof ICPPConstructor);
methodElement.setDestructor(methodBinding.isDestructor());
} else {
if (declSpecifier instanceof ICPPASTDeclSpecifier) {
final ICPPASTDeclSpecifier cppDeclSpecifier = (ICPPASTDeclSpecifier) declSpecifier;
methodInfo.setVirtual(cppDeclSpecifier.isVirtual());
methodInfo.setInline(cppDeclSpecifier.isInline());
methodInfo.setFriend(cppDeclSpecifier.isFriend());
}
methodInfo.setVolatile(cppFunctionDeclarator.isVolatile());
methodInfo.setVisibility(getCurrentVisibility());
methodInfo.setPureVirtual(false);
final boolean isConstructor;
if (scope != null) {
isConstructor = CPPVisitor.isConstructor(scope, declarator);
} else if (parent instanceof IStructure) {
isConstructor = parent.getElementName().equals(simpleName);
} else if (name instanceof ICPPASTQualifiedName) {
final ICPPASTQualifiedName quName = (ICPPASTQualifiedName) name;
final ICPPASTNameSpecifier[] qualifier = quName.getQualifier();
if (qualifier.length == 0)
isConstructor = false;
else {
ICPPASTNameSpecifier nameSpec = qualifier[qualifier.length - 1];
isConstructor = nameSpec instanceof IASTName
&& simpleName.equals(ASTStringUtil.getSimpleName((IASTName) nameSpec));
}
} else {
isConstructor = false;
}
methodElement.setConstructor(isConstructor);
methodElement.setDestructor(simpleName.charAt(0) == '~');
}
} else {
String functionName = ASTStringUtil.getQualifiedName(name);
// strip namespace qualifier if parent is same namespace
if (name instanceof ICPPASTQualifiedName && parent instanceof INamespace) {
final ICPPASTQualifiedName quName = (ICPPASTQualifiedName) name;
final ICPPASTNameSpecifier[] qualifier = quName.getQualifier();
if (qualifier.length >= 1) {
ICPPASTNameSpecifier nameSpec = qualifier[qualifier.length - 1];
if (nameSpec instanceof IASTName
&& parent.getElementName().equals(ASTStringUtil.getSimpleName((IASTName) nameSpec))) {
functionName = simpleName;
}
}
}
if (isTemplate) {
// template function
element = new FunctionTemplate(parent, functionName);
} else {
// function
element = new Function(parent, functionName);
}
element.setParameterTypes(parameterTypes);
element.setReturnType(returnType);
setIndex(element);
info = (FunctionInfo) getElementInfo(element);
info.setConst(cppFunctionDeclarator.isConst());
}
} else {
final String functionName = ASTStringUtil.getQualifiedName(name);
element = new Function(parent, functionName);
element.setParameterTypes(parameterTypes);
element.setReturnType(returnType);
setIndex(element);
info = (FunctionInfo) getElementInfo(element);
}
element.setActive(functionDeclaration.isActive());
// TODO [cmodel] correctly resolve isStatic
info.setStatic(declSpecifier.getStorageClass() == IASTDeclSpecifier.sc_static);
// add to parent
parent.addChild(element);
// set positions
setIdentifierPosition(info, name);
if (!isTemplate) {
setBodyPosition(info, functionDeclaration);
}
return element;
}
private FunctionDeclaration createFunctionDeclaration(Parent parent, IASTDeclSpecifier declSpecifier,
IASTFunctionDeclarator declarator, boolean isTemplate) throws CModelException {
IASTDeclarator nestedDeclarator = declarator;
while (nestedDeclarator.getNestedDeclarator() != null) {
nestedDeclarator = nestedDeclarator.getNestedDeclarator();
}
final IASTName name = nestedDeclarator.getName();
if (name == null) {
// Something is wrong, skip this element
return null;
}
final String functionName = ASTStringUtil.getSimpleName(name);
final String[] parameterTypes = ASTStringUtil.getParameterSignatureArray(declarator);
final String returnType = ASTStringUtil.getReturnTypeString(declSpecifier, declarator);
final FunctionDeclaration element;
final FunctionInfo info;
if (declarator instanceof ICPPASTFunctionDeclarator) {
final ICPPASTFunctionDeclarator cppFunctionDeclarator = (ICPPASTFunctionDeclarator) declarator;
if (parent instanceof IStructure) {
// method
final MethodDeclaration methodElement;
if (isTemplate) {
methodElement = new MethodTemplateDeclaration(parent, functionName);
} else {
methodElement = new MethodDeclaration(parent, functionName);
}
element = methodElement;
// establish identity attributes before getElementInfo()
methodElement.setParameterTypes(parameterTypes);
methodElement.setReturnType(returnType);
methodElement.setConst(cppFunctionDeclarator.isConst());
setIndex(element);
final MethodInfo methodInfo = (MethodInfo) getElementInfo(methodElement);
info = methodInfo;
if (declSpecifier instanceof ICPPASTDeclSpecifier) {
final ICPPASTDeclSpecifier cppDeclSpecifier = (ICPPASTDeclSpecifier) declSpecifier;
methodInfo.setVirtual(cppDeclSpecifier.isVirtual());
methodInfo.setInline(cppDeclSpecifier.isInline());
methodInfo.setFriend(cppDeclSpecifier.isFriend());
}
methodInfo.setVolatile(cppFunctionDeclarator.isVolatile());
methodInfo.setVisibility(getCurrentVisibility());
methodInfo.setPureVirtual(cppFunctionDeclarator.isPureVirtual());
methodElement.setConstructor(functionName.equals(parent.getElementName()));
methodElement.setDestructor(functionName.charAt(0) == '~');
} else {
if (isTemplate) {
element = new FunctionTemplateDeclaration(parent, functionName);
} else {
element = new FunctionDeclaration(parent, functionName);
}
element.setParameterTypes(parameterTypes);
element.setReturnType(returnType);
setIndex(element);
info = (FunctionInfo) getElementInfo(element);
info.setConst(cppFunctionDeclarator.isConst());
}
} else if (declarator instanceof IASTStandardFunctionDeclarator) {
if (isTemplate) {
element = new FunctionTemplateDeclaration(parent, functionName);
} else {
element = new FunctionDeclaration(parent, functionName);
}
element.setParameterTypes(parameterTypes);
element.setReturnType(returnType);
setIndex(element);
info = (FunctionInfo) getElementInfo(element);
} else {
assert false;
return null;
}
element.setActive(declarator.isActive());
// TODO [cmodel] correctly resolve isStatic
info.setStatic(declSpecifier.getStorageClass() == IASTDeclSpecifier.sc_static);
// add to parent
parent.addChild(element);
// hook up the offsets
setIdentifierPosition(info, name);
if (!isTemplate) {
setBodyPosition(info, declarator.getParent());
}
return element;
}
private Using createUsingDirective(Parent parent, ICPPASTUsingDirective usingDirDeclaration)
throws CModelException {
// create the element
IASTName name = usingDirDeclaration.getQualifiedName();
Using element = new Using(parent, ASTStringUtil.getQualifiedName(name), true);
setIndex(element);
element.setActive(usingDirDeclaration.isActive());
// add to parent
parent.addChild(element);
// set positions
setIdentifierPosition(element, name);
setBodyPosition(element, usingDirDeclaration);
return element;
}
private Using createUsingDeclaration(Parent parent, ICPPASTUsingDeclaration usingDeclaration)
throws CModelException {
// create the element
IASTName name = usingDeclaration.getName();
Using element = new Using(parent, ASTStringUtil.getSimpleName(name), false);
setIndex(element);
element.setActive(usingDeclaration.isActive());
// add to parent
parent.addChild(element);
// set positions
setIdentifierPosition(element, name);
setBodyPosition(element, usingDeclaration);
return element;
}
private CElementInfo getElementInfo(CElement cElement) {
CElementInfo info = fNewElements.get(cElement);
if (info == null) {
info = cElement.createElementInfo();
fNewElements.put(cElement, info);
}
return info;
}
private SourceManipulationInfo getSourceManipulationInfo(SourceManipulation cElement) {
return (SourceManipulationInfo) getElementInfo(cElement);
}
/**
* Utility method to set the body position of an element from an AST node.
*
* @param element
* @param astNode
* @throws CModelException
*/
private void setBodyPosition(SourceManipulation element, IASTNode astNode) throws CModelException {
setBodyPosition(getSourceManipulationInfo(element), astNode);
}
/**
* Utility method to set the body position of an element from an AST node.
*
* @param info
* @param astNode
*/
private void setBodyPosition(SourceManipulationInfo info, IASTNode astNode) {
final IASTFileLocation location = astNode.getFileLocation();
if (location != null) {
info.setPos(location.getNodeOffset(), location.getNodeLength());
info.setLines(location.getStartingLineNumber(), location.getEndingLineNumber());
} else {
final IASTNodeLocation[] locations = astNode.getNodeLocations();
final IASTFileLocation minLocation = getMinFileLocation(locations);
if (minLocation != null) {
final IASTFileLocation maxLocation = getMaxFileLocation(locations);
if (maxLocation != null) {
final int startOffset = minLocation.getNodeOffset();
final int endOffset = maxLocation.getNodeOffset() + maxLocation.getNodeLength();
info.setPos(startOffset, endOffset - startOffset);
final int startLine = minLocation.getStartingLineNumber();
final int endLine = maxLocation.getEndingLineNumber();
info.setLines(startLine, endLine);
}
}
}
}
/**
* Utility method to set the identifier position of an element from an AST name.
*
* @param element
* @param astName
*/
private void setIdentifierPosition(SourceManipulation element, IASTName astName) {
setIdentifierPosition(getSourceManipulationInfo(element), astName);
}
/**
* Utility method to set the identifier position of an element from an AST name.
*
* @param info
* @param astName
*/
private void setIdentifierPosition(SourceManipulationInfo info, IASTNode astName) {
final IASTFileLocation location = astName.getFileLocation();
if (location != null) {
info.setIdPos(location.getNodeOffset(), location.getNodeLength());
} else {
final IASTNodeLocation[] locations = astName.getNodeLocations();
final IASTFileLocation minLocation = getMinFileLocation(locations);
if (minLocation != null) {
final IASTFileLocation maxLocation = getMaxFileLocation(locations);
if (maxLocation != null) {
final int startOffset = minLocation.getNodeOffset();
final int endOffset = maxLocation.getNodeOffset() + maxLocation.getNodeLength();
info.setIdPos(startOffset, endOffset - startOffset);
}
}
}
}
private static IASTFileLocation getMaxFileLocation(IASTNodeLocation[] locations) {
if (locations == null || locations.length == 0) {
return null;
}
final IASTNodeLocation nodeLocation = locations[locations.length - 1];
return nodeLocation.asFileLocation();
}
private static IASTFileLocation getMinFileLocation(IASTNodeLocation[] locations) {
if (locations == null || locations.length == 0) {
return null;
}
final IASTNodeLocation nodeLocation = locations[0];
return nodeLocation.asFileLocation();
}
/**
* Handle the special "declaration" visibility label
* @param visibilityLabel
*/
private void handleVisibilityLabel(ICPPASTVisibilityLabel visibilityLabel) {
setCurrentVisibility(adaptVisibilityConstant(visibilityLabel.getVisibility()));
}
/**
* Convert the given <code>ICPPASTVisiblityLabel</code> visibility constant
* into an <code>ASTAccessVisibility</code>.
*
* @param visibility
* @return the corresponding <code>ASTAccessVisibility</code>
*/
private ASTAccessVisibility adaptVisibilityConstant(int visibility) {
switch (visibility) {
case ICPPASTVisibilityLabel.v_public:
return ASTAccessVisibility.PUBLIC;
case ICPPASTVisibilityLabel.v_protected:
return ASTAccessVisibility.PROTECTED;
case ICPPASTVisibilityLabel.v_private:
return ASTAccessVisibility.PRIVATE;
}
assert false : "Unknown visibility"; //$NON-NLS-1$
return ASTAccessVisibility.PUBLIC;
}
private void setCurrentVisibility(ASTAccessVisibility visibility) {
fCurrentVisibility = visibility;
}
private ASTAccessVisibility getCurrentVisibility() {
if (fCurrentVisibility == null) {
return ASTAccessVisibility.PUBLIC;
}
return fCurrentVisibility;
}
/**
* Pop the default visibility from the outer scope.
*/
private void popDefaultVisibility() {
if (!fVisibilityStack.isEmpty()) {
setCurrentVisibility(fVisibilityStack.pop());
}
}
/**
* Push given visibility as default class/struct/union visibility.
*
* @param visibility
*/
private void pushDefaultVisibility(ASTAccessVisibility visibility) {
fVisibilityStack.push(getCurrentVisibility());
setCurrentVisibility(visibility);
}
/**
* Determine the scope for given name.
*
* @param astName
* @return the scope or <code>null</code>
*/
private static IScope getScope(IASTName astName) {
IBinding binding = astName.resolveBinding();
if (binding != null) {
try {
return binding.getScope();
} catch (DOMException e) {
return null;
}
}
return null;
}
}