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