From 0aa860ee97029939017674a6ed15269cf277f4f4 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 30 Jan 2008 17:09:15 +0000 Subject: [PATCH] Index based name resolution for classes in namespaces (bug 217102) --- .../tests/IndexCPPBindingResolutionBugs.java | 34 ++++++++++++- .../dom/parser/cpp/CPPASTTranslationUnit.java | 26 ++++++++-- .../dom/parser/cpp/CPPNamespaceScope.java | 48 ++++++++++++++++++- .../core/dom/parser/cpp/CPPSemantics.java | 23 +++++---- .../cdt/internal/core/index/CIndex.java | 22 +++++++++ .../actions/OpenDeclarationsAction.java | 2 +- 6 files changed, 140 insertions(+), 15 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java index 50aa9178088..f62bfe5388a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java @@ -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()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index ec6cd949dbb..27b6d703ce5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -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 fMappedScopes= new HashMap(); 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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java index de247711a25..f398ef9c90a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java @@ -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]; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index 62f24d0323a..afce7934644 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -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 ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java index c5508efcc18..4de0e3cc80e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java @@ -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 result= new ArrayList(); + 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 result= new LinkedList(); int fragCount= 0; for (int i = 0; i < fPrimaryFragmentCount; i++) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java index aed2a3a3fa9..ef6f8327f83 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java @@ -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