blob: 20ca20dedd2de829d2017705f12b0c0a831cdc55 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
/**
* Models the scope represented by an unknown binding such (e.g.: template type parameter). Used within
* the context of templates, only.
* For safe usage in index bindings, all fields need to be final or used in a thread-safe manner otherwise.
*/
public class CPPUnknownScope implements ICPPInternalUnknownScope {
private final ICPPUnknownBinding binding;
private final IASTName scopeName;
/**
* This field needs to be protected when used in PDOMCPPUnknownScope,
* don't use it outside of {@link #getOrCreateBinding(IASTName, int)}
*/
private CharArrayObjectMap map;
public CPPUnknownScope(ICPPUnknownBinding binding, IASTName name) {
super();
this.scopeName = name;
this.binding = binding;
}
public EScopeKind getKind() {
return EScopeKind.eClassType;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#getScopeName()
*/
public IName getScopeName() {
return scopeName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#getParent()
*/
public IScope getParent() throws DOMException {
return binding.getScope();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String)
*/
public IBinding[] find(String name) {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#getPhysicalNode()
*/
public IASTNode getPhysicalNode() {
return scopeName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#addName(org.eclipse.cdt.core.dom.ast.IASTName)
*/
public void addName(IASTName name) {
}
public final IBinding getBinding(IASTName name, boolean resolve) {
return getBinding(name, resolve, IIndexFileSet.EMPTY);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean)
*/
public IBinding getBinding(final IASTName name, boolean resolve, IIndexFileSet fileSet) {
boolean type= false;
boolean function= false;
if (name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) {
type= true;
} else {
IASTName n= name;
IASTNode parent= name.getParent();
if (parent instanceof ICPPASTTemplateId) {
n= (IASTName) parent;
parent= n.getParent();
}
if (parent instanceof ICPPASTQualifiedName) {
ICPPASTQualifiedName qname= (ICPPASTQualifiedName) parent;
if (qname.getLastName() != n) {
type= true;
} else {
parent= qname.getParent();
}
}
if (!type) {
if (parent instanceof ICPPASTBaseSpecifier ||
parent instanceof ICPPASTConstructorChainInitializer) {
type= true;
} else if (parent instanceof ICPPASTNamedTypeSpecifier) {
ICPPASTNamedTypeSpecifier nts= (ICPPASTNamedTypeSpecifier) parent;
type= nts.isTypename();
} else if (parent instanceof ICPPASTUsingDeclaration) {
ICPPASTUsingDeclaration ud= (ICPPASTUsingDeclaration) parent;
type= ud.isTypename();
}
if (!type && parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
function= true;
}
}
}
int idx= type ? 0 : function ? 1 : 2;
IBinding result = getOrCreateBinding(name, idx);
return result;
}
protected IBinding getOrCreateBinding(final IASTName name, int idx) {
if (map == null)
map = new CharArrayObjectMap(2);
final char[] c = name.getLookupKey();
IBinding[] o = (IBinding[]) map.get(c);
if (o == null) {
o = new IBinding[3];
map.put(c, o);
}
IBinding result= o[idx];
if (result == null) {
switch (idx) {
case 0:
result= new CPPUnknownClass(binding, name.getSimpleID());
break;
case 1:
result= new CPPUnknownFunction(binding, name.getSimpleID());
break;
case 2:
result= new CPPUnknownBinding(binding, name.getSimpleID());
break;
}
o[idx]= result;
}
return result;
}
public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) {
return getBindings(name, resolve, prefix, IIndexFileSet.EMPTY);
}
public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) {
return getBindings(name, resolve, prefixLookup, fileSet, true);
}
public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet acceptLocalBindings, boolean checkPointOfDecl) {
if (prefixLookup) {
if (binding instanceof ICPPDeferredClassInstance) {
ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) binding;
IScope scope = instance.getClassTemplate().getCompositeScope();
if (scope != null) {
return scope.getBindings(name, resolve, prefixLookup, acceptLocalBindings);
}
}
return IBinding.EMPTY_BINDING_ARRAY;
}
return new IBinding[] {getBinding(name, resolve, acceptLocalBindings)};
}
public void addBinding(IBinding binding) {
// do nothing, this is part of template magic and not a normal scope
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope#getUnknownBinding()
*/
public ICPPBinding getScopeBinding() {
return binding;
}
/* (non-Javadoc)
* For debug purposes only
*/
@Override
public String toString() {
return scopeName.toString();
}
public void populateCache() {}
}