blob: a697b5f3b138300f3afc5574cffe60243a17e883 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. 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:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
*******************************************************************************/
/* -- ST-Origin --
* Source folder: org.eclipse.cdt.core/model
* Class: org.eclipse.cdt.internal.core.model.CModelBuilder2
* Version: 1.48
*/
package org.eclipse.ptp.internal.rdt.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.dom.ast.ASTSignatureUtil;
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.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.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.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.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.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
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.parser.Keywords;
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.cdt.internal.core.model.ASTStringUtil;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
/**
* Build TranslationUnit structure from an <code>IASTTranslationUnit</code>.
*
* @since 4.0
*/
public class CModelBuilder2 {
// 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
* @param monitor the progress monitor
*/
public CModelBuilder2(TranslationUnit unit, IProgressMonitor monitor) {
fTranslationUnit= unit;
fNewElements= new HashMap<ICElement, CElementInfo>();
fProgressMonitor= monitor;
}
/**
* Populates the underlying <code>TranslationUnit</code> with the
* structural contents of the given <code>IASTTranslationUnit</code>.
*
* @param ast
* @throws CoreException
* @throws DOMException
*/
public void parse(IASTTranslationUnit ast) throws CoreException, DOMException {
checkCanceled();
// long startTime= System.currentTimeMillis();
final CElementInfo elementInfo= getElementInfo(fTranslationUnit);
checkCanceled();
// startTime= System.currentTimeMillis();
buildModel(ast);
elementInfo.setIsStructureKnown(true);
// Util.debugLog("CModelBuilder2: building " //$NON-NLS-1$
// +"children="+ fTranslationUnit.getElementInfo().internalGetChildren().size() //$NON-NLS-1$
// +" time="+ (System.currentTimeMillis() - startTime) + "ms", //$NON-NLS-1$ //$NON-NLS-2$
// DebugLogConstants.MODEL, false);
}
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<ASTAccessVisibility>();
fEqualElements= new HashMap<ISourceReference, int[]>();
// includes
final IASTPreprocessorIncludeStatement[] includeDirectives= ast.getIncludeDirectives();
// Set<Include> allIncludes= new HashSet<Include>();
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>() {
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);
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 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 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 {
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) {
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);
final IASTEnumerator[] enumerators= enumSpecifier.getEnumerators();
for (final IASTEnumerator enumerator : enumerators) {
createEnumerator(element, enumerator);
}
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());
}
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(ASTSignatureUtil.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 IASTName baseName= baseSpecifier.getName();
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;
}
element.addSuperClass(ASTStringUtil.getSimpleName(baseName), 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() == ICPPASTDeclSpecifier.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) {
final IASTName[] names= ((ICPPASTQualifiedName)name).getNames();
if (isTemplate) {
for (IASTName name2 : names) {
if (name2 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 IASTName[] names= quName.getNames();
isConstructor= names.length >= 2 && simpleName.equals(ASTStringUtil.getSimpleName(names[names.length-2]));
} 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 IASTName[] names= quName.getNames();
if (names.length >= 2 && parent.getElementName().equals(ASTStringUtil.getSimpleName(names[names.length-2]))) {
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, simpleName);
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
* @throws CModelException
*/
private void setIdentifierPosition(SourceManipulation element, IASTName astName) throws CModelException {
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>ICPPASTVisibilityLabel</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;
}
}