mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Index based name resolution for classes in namespaces (bug 217102)
This commit is contained in:
parent
ddc6109778
commit
0aa860ee97
6 changed files with 140 additions and 15 deletions
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2007 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2006, 2008 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
|
||||
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.ITypedef;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
|
@ -675,5 +676,36 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
|
|||
assertTrue(tAST.isSameType(tIndex));
|
||||
assertTrue(tIndex.isSameType(tAST));
|
||||
}
|
||||
|
||||
// namespace FOO {
|
||||
// namespace BAR {
|
||||
// class Bar;
|
||||
// }
|
||||
// class Foo {
|
||||
// BAR::Bar * Test(BAR::Bar * bar);
|
||||
// };
|
||||
// }
|
||||
|
||||
// #include "header.h"
|
||||
// namespace FOO {
|
||||
// using BAR::Bar;
|
||||
//
|
||||
// Bar* Foo::Test(Bar* pBar) {
|
||||
// return pBar;
|
||||
// }
|
||||
// }
|
||||
public void testAdvanceUsingDeclaration_Bug217102() throws Exception {
|
||||
IBinding cl = getBindingFromASTName("Bar* Foo", 3);
|
||||
assertTrue(cl instanceof ICPPDelegate);
|
||||
cl= ((ICPPDelegate) cl).getBinding();
|
||||
assertEquals("Bar", cl.getName());
|
||||
assertTrue(cl instanceof ICPPClassType);
|
||||
assertEquals("BAR", cl.getScope().getScopeName().toString());
|
||||
|
||||
cl = getBindingFromASTName("Bar* pBar", 3);
|
||||
cl= ((ICPPDelegate) cl).getBinding();
|
||||
assertEquals("Bar", cl.getName());
|
||||
assertTrue(cl instanceof ICPPClassType);
|
||||
assertEquals("BAR", cl.getScope().getScopeName().toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.IName;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
|
@ -54,7 +56,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
|
@ -63,6 +65,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.GCCBuiltinSymbolProvider.CPPBuiltinParameter;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexScope;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
|
@ -80,11 +83,12 @@ public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslat
|
|||
|
||||
private IASTDeclaration[] decls = new IASTDeclaration[32];
|
||||
private ICPPNamespace binding = null;
|
||||
private ICPPScope scope = null;
|
||||
private CPPNamespaceScope scope = null;
|
||||
private ILocationResolver resolver;
|
||||
private IIndex index;
|
||||
private IIndexFileSet fIndexFileSet;
|
||||
private boolean fIsHeader;
|
||||
private HashMap<IIndexScope, IScope> fMappedScopes= new HashMap<IIndexScope, IScope>();
|
||||
|
||||
public IASTTranslationUnit getTranslationUnit() {
|
||||
return this;
|
||||
|
@ -105,7 +109,7 @@ public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslat
|
|||
return (IASTDeclaration[]) ArrayUtil.trim( IASTDeclaration.class, decls );
|
||||
}
|
||||
|
||||
public IScope getScope() {
|
||||
public CPPNamespaceScope getScope() {
|
||||
if (scope == null) {
|
||||
scope = new CPPNamespaceScope(this);
|
||||
addBuiltinOperators(scope);
|
||||
|
@ -527,4 +531,20 @@ public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslat
|
|||
public void setIsHeaderUnit(boolean headerUnit) {
|
||||
fIsHeader= headerUnit;
|
||||
}
|
||||
|
||||
// bug 217102: namespace scopes from the index have to be mapped back to the AST.
|
||||
IScope mapToASTScope(IIndexScope scope) {
|
||||
if (scope instanceof ICPPNamespaceScope) {
|
||||
IScope result= fMappedScopes.get(scope);
|
||||
if (result == null) {
|
||||
result= getScope().findNamespaecScope(scope);
|
||||
if (result == null) {
|
||||
result= scope;
|
||||
}
|
||||
fMappedScopes.put(scope, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2006 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2008 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
|
||||
|
@ -15,10 +15,15 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.IName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexScope;
|
||||
|
||||
/**
|
||||
* @author aniefer
|
||||
|
@ -53,4 +58,45 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IScope findNamespaecScope(IIndexScope scope) {
|
||||
final String[] qname= scope.getScopeBinding().getQualifiedName();
|
||||
final IScope[] result= {null};
|
||||
final CPPASTVisitor visitor= new CPPASTVisitor () {
|
||||
private int depth= 0;
|
||||
{
|
||||
shouldVisitNamespaces= shouldVisitDeclarations= true;
|
||||
}
|
||||
@Override
|
||||
public int visit( IASTDeclaration declaration ){
|
||||
if( declaration instanceof ICPPASTLinkageSpecification )
|
||||
return PROCESS_CONTINUE;
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
@Override
|
||||
public int visit(ICPPASTNamespaceDefinition namespace) {
|
||||
final String name = namespace.getName().toString();
|
||||
if (name.length() == 0) {
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
if (qname[depth].equals(name)) {
|
||||
if (++depth == qname.length) {
|
||||
result[0]= namespace.getScope();
|
||||
return PROCESS_ABORT;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
@Override
|
||||
public int leave(ICPPASTNamespaceDefinition namespace) {
|
||||
if (namespace.getName().toCharArray().length > 0) {
|
||||
--depth;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
};
|
||||
getPhysicalNode().accept(visitor);
|
||||
return result[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -858,14 +858,14 @@ public class CPPSemantics {
|
|||
IType p = ps[i];
|
||||
p = getUltimateType( p, true );
|
||||
try {
|
||||
getAssociatedScopes( p, namespaces, classes, data.astName.getTranslationUnit());
|
||||
getAssociatedScopes( p, namespaces, classes, (CPPASTTranslationUnit) data.astName.getTranslationUnit());
|
||||
} catch ( DOMException e ) {
|
||||
}
|
||||
}
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
static private void getAssociatedScopes( IType t, ObjectSet namespaces, ObjectSet classes, IASTTranslationUnit tu) throws DOMException{
|
||||
static private void getAssociatedScopes( IType t, ObjectSet namespaces, ObjectSet classes, CPPASTTranslationUnit tu) throws DOMException{
|
||||
//3.4.2-2
|
||||
if( t instanceof ICPPClassType ){
|
||||
if( !classes.containsKey( t ) ){
|
||||
|
@ -905,7 +905,7 @@ public class CPPSemantics {
|
|||
return;
|
||||
}
|
||||
|
||||
static private ICPPNamespaceScope getContainingNamespaceScope( IBinding binding, IASTTranslationUnit tu) throws DOMException{
|
||||
static private ICPPNamespaceScope getContainingNamespaceScope( IBinding binding, CPPASTTranslationUnit tu) throws DOMException{
|
||||
if( binding == null ) return null;
|
||||
IScope scope = binding.getScope();
|
||||
while( scope != null && !(scope instanceof ICPPNamespaceScope) ){
|
||||
|
@ -1146,7 +1146,7 @@ public class CPPSemantics {
|
|||
if( blockItem != null )
|
||||
node = blockItem;
|
||||
|
||||
ICPPScope parentScope = (ICPPScope) getParentScope(scope, node.getTranslationUnit());
|
||||
ICPPScope parentScope = (ICPPScope) getParentScope(scope, (CPPASTTranslationUnit) node.getTranslationUnit());
|
||||
if( parentScope instanceof ICPPTemplateScope ){
|
||||
IASTNode parent = node.getParent();
|
||||
while( parent != null && !(parent instanceof ICPPASTTemplateDeclaration) ){
|
||||
|
@ -1165,11 +1165,16 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
private static IScope getParentScope(IScope scope, IASTTranslationUnit unit) throws DOMException {
|
||||
private static IScope getParentScope(IScope scope, CPPASTTranslationUnit unit) throws DOMException {
|
||||
IScope parentScope= scope.getParent();
|
||||
// the index cannot return the translation unit as parent scope
|
||||
if (parentScope == null && scope instanceof IIndexScope && unit != null) {
|
||||
parentScope= unit.getScope();
|
||||
if (unit != null) {
|
||||
if (parentScope == null && scope instanceof IIndexScope) {
|
||||
parentScope= unit.getScope();
|
||||
}
|
||||
else if (parentScope instanceof IIndexScope) {
|
||||
parentScope= unit.mapToASTScope((IIndexScope) parentScope);
|
||||
}
|
||||
}
|
||||
return parentScope;
|
||||
}
|
||||
|
@ -1403,7 +1408,7 @@ public class CPPSemantics {
|
|||
|
||||
//namespace are searched at most once
|
||||
if( !data.visited.containsKey( temp ) ){
|
||||
enclosing = getClosestEnclosingScope( scope, temp, data.astName.getTranslationUnit());
|
||||
enclosing = getClosestEnclosingScope( scope, temp, (CPPASTTranslationUnit) data.astName.getTranslationUnit());
|
||||
|
||||
//data.usingDirectives is a map from enclosing scope to a IScope[]
|
||||
//of namespaces to consider when we reach that enclosing scope
|
||||
|
@ -1418,7 +1423,7 @@ public class CPPSemantics {
|
|||
|
||||
}
|
||||
|
||||
static private ICPPScope getClosestEnclosingScope( IScope scope1, IScope scope2, IASTTranslationUnit tu) throws DOMException{
|
||||
static private ICPPScope getClosestEnclosingScope( IScope scope1, IScope scope2, CPPASTTranslationUnit tu) throws DOMException{
|
||||
ObjectSet set = new ObjectSet( 2 );
|
||||
IScope parent = scope1;
|
||||
while( parent != null ){
|
||||
|
|
|
@ -28,8 +28,10 @@ import java.util.regex.Pattern;
|
|||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ILinkage;
|
||||
import org.eclipse.cdt.core.dom.IName;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
|
@ -120,6 +122,26 @@ public class CIndex implements IIndex {
|
|||
}
|
||||
|
||||
public IIndexName[] findNames(IBinding binding, int flags) throws CoreException {
|
||||
if (binding instanceof ICPPUsingDeclaration) {
|
||||
IBinding[] bindings= null;
|
||||
try {
|
||||
bindings = ((ICPPUsingDeclaration)binding).getDelegates();
|
||||
} catch (DOMException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
if (bindings == null || bindings.length == 0) {
|
||||
return new IIndexName[0];
|
||||
}
|
||||
if (bindings.length > 1) {
|
||||
ArrayList<IIndexName> result= new ArrayList<IIndexName>();
|
||||
for (int i = 0; i < bindings.length; i++) {
|
||||
IBinding b = bindings[i];
|
||||
result.addAll(Arrays.asList(findNames(b, flags)));
|
||||
}
|
||||
return result.toArray(new IIndexName[result.size()]);
|
||||
}
|
||||
binding= bindings[0];
|
||||
}
|
||||
LinkedList<IIndexFragmentName> result= new LinkedList<IIndexFragmentName>();
|
||||
int fragCount= 0;
|
||||
for (int i = 0; i < fPrimaryFragmentCount; i++) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2007 IBM Corporation and others.
|
||||
* Copyright (c) 2000, 2008 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
|
||||
|
|
Loading…
Add table
Reference in a new issue