diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 7695d9d62a7..27c905ad703 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -8683,4 +8683,107 @@ public class AST2CPPTests extends AST2BaseTest { fb= bh.assertNonProblem("g()", 1); assertTrue(fb.isDeleted()); } + + // namespace ns { + // struct S {}; + // } + // + // namespace m { + // void h(ns::S); + // } + // + // namespace ns { + // inline namespace a { + // using namespace m; + // struct A {}; + // void fa(S s); + // } + // inline namespace b { + // struct B {}; + // void fb(S s); + // void gb(a::A); + // } + // void f(S s); + // void g(a::A); + // void g(b::B); + // } + // + // ns::S s; + // ns::A a0; + // ns::B b0; + // ns::a::A a; + // ns::b::B b; + // + // void ok() { + // fa(s); fb(s); f(s); + // ns::h(s); + // g(a); + // gb(a); + // } + public void testInlineNamespace_305980a() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + } + + // namespace ns { + // inline namespace m { + // int a; + // } + // } + // void test() { + // ns::m::a; + // ns::a; + // } + public void testInlineNamespace_305980b() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + } + + // namespace out { + // void f(int); + // } + // namespace out2 { + // void g(int); + // } + // using namespace out; + // inline namespace in { + // inline namespace in2 { + // void f(char); + // using namespace out2; + // } + // } + // void test() { + // ::f(1); + // ::g(1); + // } + public void testInlineNamespace_305980c() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction fo= bh.assertNonProblem("f(int)", 1); + IFunction g= bh.assertNonProblem("g(int)", 1); + IFunction fi= bh.assertNonProblem("f(char)", 1); + + IFunction ref= bh.assertNonProblem("f(1)", 1); + assertSame(fi, ref); + ref= bh.assertNonProblem("g(1)", 1); + assertSame(g, ref); + } + + // namespace ns { + // inline namespace m { + // void f(); + // } + // } + // void ns::f() {} + public void testInlineNamespace_305980d() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction f1= bh.assertNonProblem("f();", 1); + IFunction f2= bh.assertNonProblem("f() {", 1); + assertSame(f1, f2); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 72942eda1db..b3ebd6351f7 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -63,6 +63,7 @@ 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.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; @@ -5009,4 +5010,40 @@ public class AST2TemplateTests extends AST2BaseTest { tu = validateCopy(tu); assertEquals(1, tu.getDeclarations().length); } + + // namespace N { + // inline namespace M { + // template void f(T&) { } + // + // } + // template void f(char&); + // template<> void f(short&) {} + // } + // + // template void N::f(int&); + // template<> void N::f(long&) {} + public void testInlineNamespaces_305980() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + ICPPFunctionTemplate ft= bh.assertNonProblem("f(T&)", 1); + ICPPNamespace M= (ICPPNamespace) ft.getOwner(); + + ICPPTemplateInstance inst; + inst= bh.assertNonProblem("f", 0); + assertSame(ft, inst.getTemplateDefinition()); + assertSame(M, inst.getOwner()); + + inst= bh.assertNonProblem("f", 0); + assertSame(ft, inst.getTemplateDefinition()); + assertSame(M, inst.getOwner()); + + inst= bh.assertNonProblem("f", 0); + assertSame(ft, inst.getTemplateDefinition()); + assertSame(M, inst.getOwner()); + + inst= bh.assertNonProblem("f", 0); + assertSame(ft, inst.getTemplateDefinition()); + assertSame(M, inst.getOwner()); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java index e0da0d650b7..3f098b03fac 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IIndexFragmentFileSet; import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; +import org.eclipse.cdt.internal.core.index.IIndexScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -148,4 +149,8 @@ public class EmptyIndexFragment implements IIndexFragment { public void clearResultCache() { } + + public IIndexScope[] getInlineNamespaces() { + return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY; + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java index 8101d0cfbb9..40cff12b865 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java @@ -19,6 +19,7 @@ import java.util.Set; import junit.framework.TestSuite; +import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; @@ -1408,6 +1409,185 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti getBindingFromASTName("m(a)", 1, IFunction.class); } + // namespace ns { + // struct S {}; + // } + // namespace m { + // void h(ns::S); + // } + // namespace ns { + // inline namespace a { + // using namespace m; + // struct A {}; + // void fa(S s); + // } + // inline namespace b { + // struct B {}; + // void fb(S s); + // void gb(a::A); + // } + // void f(S s); + // void g(a::A); + // void g(b::B); + // } + + // ns::S s; + // ns::A a0; + // ns::B b0; + // ns::a::A a; + // ns::b::B b; + // + // void ok() { + // fa(s); fb(s); f(s); + // g(a); + // gb(a); + // } + public void testInlineNamespace_305980a() throws Exception { + IFunction f= getBindingFromASTName("fa(s)", 2); + f= getBindingFromASTName("fb(s)", 2); + f= getBindingFromASTName("f(s)", 1); + f= getBindingFromASTName("g(a)", 1); + f= getBindingFromASTName("gb(a)", 2); + } + + // namespace ns { + // struct S {}; + // } + // namespace m { + // void h(ns::S); + // } + // namespace ns { + // inline namespace a { + // using namespace m; + // struct A {}; + // void fa(S s); + // } + // inline namespace b { + // struct B {}; + // void fb(S s); + // void gb(a::A); + // } + // void f(S s); + // void g(a::A); + // void g(b::B); + // } + + // namespace ns {} + // namespace m {} + // ns::S s; + // ns::A a0; + // ns::B b0; + // ns::a::A a; + // ns::b::B b; + // + // void ok() { + // fa(s); fb(s); f(s); + // g(a); + // gb(a); + // } + public void testInlineNamespace_305980am() throws Exception { + IFunction f= getBindingFromASTName("fa(s)", 2); + f= getBindingFromASTName("fb(s)", 2); + f= getBindingFromASTName("f(s)", 1); + f= getBindingFromASTName("g(a)", 1); + f= getBindingFromASTName("gb(a)", 2); + } + + // namespace ns { + // inline namespace m { + // int a; + // } + // } + + // void test() { + // ns::m::a; //1 + // ns::a; //2 + // } + public void testInlineNamespace_305980b() throws Exception { + IVariable v1= getBindingFromASTName("a; //1", 1); + IVariable v2= getBindingFromASTName("a; //2", 1); + assertEquals(v1, v2); + } + + // namespace ns { + // inline namespace m { + // int a; + // } + // } + + // namespace ns { + // void test() { + // m::a; //1 + // a; //2 + // } + // } + // void test() { + // ns::m::a; //3 + // ns::a; //4 + // } + public void testInlineNamespace_305980bm() throws Exception { + IVariable v1= getBindingFromASTName("a; //1", 1); + IVariable v2= getBindingFromASTName("a; //2", 1); + IVariable v3= getBindingFromASTName("a; //3", 1); + IVariable v4= getBindingFromASTName("a; //4", 1); + assertEquals(v1, v2); + assertEquals(v2, v3); + assertEquals(v3, v4); + } + + // namespace out { + // void f(int); + // } + // namespace out2 { + // void g(int); + // } + // using namespace out; + // inline namespace in { + // inline namespace in2 { + // void f(char); + // using namespace out2; + // } + // } + + // #include "header.h" + // void test() { + // ::f(1); + // ::g(1); + // } + public void testInlineNamespace_305980c() throws Exception { + IFunction ref= getBindingFromASTName("f(1)", 1); + assertEquals("void (char)", ASTTypeUtil.getType(ref.getType())); + getBindingFromASTName("g(1)", 1); + } + + // namespace out { + // void f(int); + // } + // namespace out2 { + // void g(int); + // } + // using namespace out; + // inline namespace in { + // inline namespace in2 { + // void f(char); + // using namespace out2; + // } + // } + + // #include "header.h" + // namespace out {} + // namespace out2 {} + // namespace in {} + // void test() { + // ::f(1); + // ::g(1); + // } + public void testInlineNamespace_305980cm() throws Exception { + IFunction ref= getBindingFromASTName("f(1)", 1); + assertEquals("void (char)", ASTTypeUtil.getType(ref.getType())); + getBindingFromASTName("g(1)", 1); + } + /* CPP assertion helpers */ /* ##################################################################### */ diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java index 06545fad1ba..37d3b1fcc02 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java @@ -36,6 +36,7 @@ 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.ICPPMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; @@ -1292,4 +1293,50 @@ public class IndexUpdateTests extends IndexTestBase { } assertEquals(id1, id2); } + + // namespace ns { + // namespace m {} + // } + + // inline namespace ns { + // inline namespace m {} + // } + + // namespace ns { + // namespace m {} + // } + public void testInlineNamespaces_305980() throws Exception { + setupFile(3, true); + fIndex.acquireReadLock(); + try { + final ICPPNamespace ns = (ICPPNamespace) findBinding("ns"); + assertFalse(ns.isInline()); + final ICPPNamespace m = (ICPPNamespace) findBinding("ns::m"); + assertFalse(ns.isInline()); + } finally { + fIndex.releaseReadLock(); + } + + updateFile(); + fIndex.acquireReadLock(); + try { + final ICPPNamespace ns = (ICPPNamespace) findBinding("ns"); + assertTrue(ns.isInline()); + final ICPPNamespace m = (ICPPNamespace) findBinding("ns::m"); + assertTrue(ns.isInline()); + } finally { + fIndex.releaseReadLock(); + } + + updateFile(); + fIndex.acquireReadLock(); + try { + final ICPPNamespace ns = (ICPPNamespace) findBinding("ns"); + assertFalse(ns.isInline()); + final ICPPNamespace m = (ICPPNamespace) findBinding("ns::m"); + assertFalse(ns.isInline()); + } finally { + fIndex.releaseReadLock(); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java index 7bde01482cf..5ca387226c9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java @@ -252,7 +252,15 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IAdaptabl * @since 5.1 */ IIndexFileSet getIndexFileSet(); - + + /** + * Return the set of files in the index that are superseded by this AST, + * or null if not available. + * Applies only, if AST was created with an index. + * @since 5.3 + */ + IIndexFileSet getASTFileSet(); + /** * In case the AST was created in a way that supports comment parsing, * all comments of the translation unit are returned. Otherwise an diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNamespaceDefinition.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNamespaceDefinition.java index 6b3fc6565a7..de671f9ede4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNamespaceDefinition.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNamespaceDefinition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * 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 @@ -7,6 +7,7 @@ * * Contributors: * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -54,6 +55,18 @@ public interface ICPPASTNamespaceDefinition extends IASTDeclaration, IASTNameOwn */ public void setName(IASTName name); + /** + * Specify whether the namespace definition is inline. + * @since 5.3 + */ + public void setIsInline(boolean isInline); + + /** + * Returns whether this namespace definition is inline. + * @since 5.3 + */ + public boolean isInline(); + /** * A translation unit contains an ordered sequence of declarations. * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespace.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespace.java index ed96e011c77..b55f11eedda 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespace.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespace.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * 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 @@ -7,6 +7,7 @@ * * Contributors: * Andrew Niefer (IBM Corporation) - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -32,4 +33,10 @@ public interface ICPPNamespace extends ICPPBinding { * @throws DOMException */ public IBinding[] getMemberBindings() throws DOMException; + + /** + * Returns whether this is an inline namespace. + * @since 5.3 + */ + public boolean isInline(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java index ac0164e330e..46146ae960f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * 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 @@ -11,7 +11,6 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; -import org.eclipse.cdt.core.dom.ast.DOMException; /** * A namespace scope is either a block-scope or a namespace-scope or global scope. @@ -21,14 +20,25 @@ import org.eclipse.cdt.core.dom.ast.DOMException; */ public interface ICPPNamespaceScope extends ICPPScope { + /** + * @since 5.3 + */ + ICPPNamespaceScope[] EMPTY_NAMESPACE_SCOPE_ARRAY = {}; + /** * Add a directive that nominates another namespace to this scope. */ - public void addUsingDirective(ICPPUsingDirective usingDirective) throws DOMException; + public void addUsingDirective(ICPPUsingDirective usingDirective); /** * Get the using directives that have been added to this scope to nominate other * namespaces during lookup. */ - public ICPPUsingDirective[] getUsingDirectives() throws DOMException; + public ICPPUsingDirective[] getUsingDirectives(); + + /** + * Returns the inline namespaces that are members of this scope. + * @since 5.3 + */ + public ICPPNamespaceScope[] getInlineNamespaces(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java index 42f14c99c32..9cc4978e387 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -393,4 +394,11 @@ public interface IIndex { * linkages, or in multiple fragments only one of the files will be returned. */ public IIndexFile[] getAllFiles() throws CoreException; + + /** + * Returns the global inline c++ namespaces. + * @throws CoreException + * @since 5.3 + */ + public IScope[] getInlineNamespaces() throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java index 2fcee3e6f0a..1fff5b334fa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2008, 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 @@ -23,7 +23,7 @@ import org.eclipse.core.runtime.CoreException; */ public interface IIndexFileSet { IIndexFileSet EMPTY = new IndexFileSet(); - + /** * Returns whether the given file is part of this file set. * @since 5.1 @@ -43,6 +43,12 @@ public interface IIndexFileSet { */ IBinding[] filterFileLocalBindings(IBinding[] bindings); + /** + * Returns an index file set with the inverse meaning. + * @since 5.3 + */ + IIndexFileSet invert(); + /** * Adds a file to this set. * @noreference This method is not intended to be referenced by clients. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java index f517aa2cf80..16b7fa48b77 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems, Inc. and others. + * 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 @@ -9,7 +9,6 @@ * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) *******************************************************************************/ - package org.eclipse.cdt.core.index; import org.eclipse.cdt.core.dom.IName; @@ -72,6 +71,12 @@ public interface IIndexName extends IName { */ public boolean couldBePolymorphicMethodCall() throws CoreException; + /** + * Returns whether this name specifies an inline namespace. + * @since 5.3 + */ + public boolean isInlineNamespaceDefinition() throws CoreException; + /** * Returns whether this name is a read-reference to a variable or field. * The notion of a read-reference may not strictly reflect what your compiler generates, diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java index 30196c00ea0..19409d9da36 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java @@ -36,9 +36,11 @@ import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider; import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver; import org.eclipse.cdt.internal.core.parser.scanner.ISkippedIndexedFilesListener; import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent; +import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; import org.eclipse.core.runtime.CoreException; @@ -61,6 +63,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat private IIndex fIndex; private boolean fIsHeader= true; private IIndexFileSet fIndexFileSet; + private IIndexFileSet fASTFileSet; private INodeFactory fNodeFactory; private boolean fForContentAssist; @@ -300,6 +303,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat this.fIndex = index; if (index != null) { fIndexFileSet= index.createFileSet(); + fASTFileSet= index.createFileSet(); } } @@ -364,6 +368,26 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat return fIndexFileSet; } + public void replacingFile(InternalFileContentProvider provider, InternalFileContent fc) { + if (fASTFileSet != null) { + if (provider instanceof IndexBasedFileContentProvider) { + try { + IIndexFile file= ((IndexBasedFileContentProvider) provider).findIndexFile(fc); + if (file != null) { + fASTFileSet.add(file); + } + } catch (CoreException e) { + // Ignore, tracking of replaced files fails. + } + } + } + } + + public final IIndexFileSet getASTFileSet() { + return fASTFileSet; + } + + /* * (non-Javadoc) * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamespaceDefinition.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamespaceDefinition.java index 851be7cbf47..c7c68830420 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamespaceDefinition.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamespaceDefinition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * 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 @@ -35,6 +35,7 @@ public class CPPASTNamespaceDefinition extends ASTNode implements private IASTDeclaration[] fAllDeclarations; private IASTDeclaration[] fActiveDeclarations; private int fLastDeclaration=-1; + private boolean fIsInline; public CPPASTNamespaceDefinition() { } @@ -45,6 +46,7 @@ public class CPPASTNamespaceDefinition extends ASTNode implements public CPPASTNamespaceDefinition copy() { CPPASTNamespaceDefinition copy = new CPPASTNamespaceDefinition(fName == null ? null : fName.copy()); + copy.fIsInline= fIsInline; for(IASTDeclaration declaration : getDeclarations()) copy.addDeclaration(declaration == null ? null : declaration.copy()); copy.setOffsetAndLength(this); @@ -64,6 +66,15 @@ public class CPPASTNamespaceDefinition extends ASTNode implements } } + public void setIsInline(boolean isInline) { + assertNotFrozen(); + fIsInline= isInline; + } + + public boolean isInline() { + return fIsInline; + } + public final void addDeclaration(IASTDeclaration decl) { if (decl != null) { decl.setParent(this); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java index 3f0a98bb8fe..aea25ed1f52 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * 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 @@ -66,6 +66,9 @@ public class CPPNamespace extends PlatformObject implements ICPPNamespace, ICPPI public boolean isGloballyQualified() throws DOMException { throw new DOMException(this); } + public boolean isInline() { + return false; + } } private static final char[] EMPTY_CHAR_ARRAY = {}; @@ -205,8 +208,8 @@ public class CPPNamespace extends PlatformObject implements ICPPNamespace, ICPPI namespaceDef.getTranslationUnit().accept(collector); namespaceDefinitions = collector.getNamespaces(); - for (int i = 0; i < namespaceDefinitions.length; i++) { - namespaceDefinitions[i].setBinding(this); + for (IASTName namespaceDefinition : namespaceDefinitions) { + namespaceDefinition.setBinding(this); } } @@ -327,12 +330,12 @@ public class CPPNamespace extends PlatformObject implements ICPPNamespace, ICPPI public IBinding[] getMemberBindings() { if (namespaceDefinitions != null) { NamespaceMemberCollector collector = new NamespaceMemberCollector(); - for (int i = 0; i < namespaceDefinitions.length; i++) { - IASTNode parent = namespaceDefinitions[i].getParent(); + for (IASTName namespaceDefinition : namespaceDefinitions) { + IASTNode parent = namespaceDefinition.getParent(); if (parent instanceof ICPPASTNamespaceDefinition) { IASTDeclaration[] decls = ((ICPPASTNamespaceDefinition)parent).getDeclarations(); - for (int j = 0; j < decls.length; j++) { - decls[j].accept(collector); + for (IASTDeclaration decl : decls) { + decl.accept(collector); } } } @@ -341,6 +344,14 @@ public class CPPNamespace extends PlatformObject implements ICPPNamespace, ICPPI return IBinding.EMPTY_BINDING_ARRAY; } + public boolean isInline() { + final ICPPNamespaceScope nsScope = getNamespaceScope(); + if (nsScope instanceof CPPNamespaceScope) { + return ((CPPNamespaceScope) nsScope).isInlineNamepace(); + } + return false; + } + public ILinkage getLinkage() { return Linkage.CPP_LINKAGE; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceAlias.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceAlias.java index 1bf5182a2b8..32ed7b07638 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceAlias.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceAlias.java @@ -1,12 +1,12 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 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: - * IBM Corporation - initial API and implementation + * Andrew Niefer (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -25,17 +25,12 @@ import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.core.runtime.PlatformObject; -/** - * @author aniefer - */ public class CPPNamespaceAlias extends PlatformObject implements ICPPNamespaceAlias, ICPPInternalBinding { private ICPPNamespace namespace; private IASTName alias; - /** - * - */ - public CPPNamespaceAlias( IASTName aliasName, ICPPNamespace namespace ) { + + public CPPNamespaceAlias(IASTName aliasName, ICPPNamespace namespace) { super(); this.namespace = namespace; this.alias = aliasName; @@ -104,4 +99,8 @@ public class CPPNamespaceAlias extends PlatformObject implements ICPPNamespaceAl public IBinding getOwner() throws DOMException { return CPPVisitor.findDeclarationOwner(alias, false); } + + public boolean isInline() { + return false; + } } 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 43b4694a0a9..2eb1ea268c5 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, 2009 IBM Corporation and others. + * 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 @@ -11,6 +11,12 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.EScopeKind; @@ -21,19 +27,32 @@ 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.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; -import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexFileSet; +import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScopeMapper.InlineNamespaceDirective; import org.eclipse.cdt.internal.core.index.IIndexScope; +import org.eclipse.core.runtime.CoreException; /** * Implementation of namespace scopes, including global scope. */ -public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ - ICPPUsingDirective[] usings = null; +public class CPPNamespaceScope extends CPPScope implements ICPPInternalNamespaceScope { + private static final ICPPInternalNamespaceScope[] NO_NAMESPACE_SCOPES = new ICPPInternalNamespaceScope[0]; + + private List fUsingDirectives = null; + + private boolean fIsInline; + private boolean fIsInlineInitialized; + private ICPPNamespaceScope[] fEnclosingNamespaceSet; + private List fInlineNamespaceDefinitions; + private ICPPInternalNamespaceScope[] fInlineNamespaces; - public CPPNamespaceScope( IASTNode physicalNode ) { - super( physicalNode ); + public CPPNamespaceScope(IASTNode physicalNode) { + super(physicalNode); } public EScopeKind getKind() { @@ -46,15 +65,30 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope#getUsingDirectives() */ - public ICPPUsingDirective[] getUsingDirectives() throws DOMException { + public ICPPUsingDirective[] getUsingDirectives() { + initUsingDirectives(); populateCache(); - return (ICPPUsingDirective[]) ArrayUtil.trim( ICPPUsingDirective.class, usings, true ); + return fUsingDirectives.toArray(new ICPPUsingDirective[fUsingDirectives.size()]); } + + private void initUsingDirectives() { + if (fUsingDirectives == null) { + fUsingDirectives= new ArrayList(1); + // Insert a using directive for every inline namespace found in the index + for(ICPPInternalNamespaceScope inline: getIndexInlineNamespaces()) { + if (!(inline instanceof CPPNamespaceScope)) { + fUsingDirectives.add(new InlineNamespaceDirective(this, inline)); + } + } + } + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope#addUsingDirective(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective) */ public void addUsingDirective(ICPPUsingDirective directive) { - usings = (ICPPUsingDirective[]) ArrayUtil.append( ICPPUsingDirective.class, usings, directive ); + initUsingDirectives(); + fUsingDirectives.add(directive); } /* (non-Javadoc) @@ -109,4 +143,165 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ getPhysicalNode().accept(visitor); return result[0]; } + + public boolean isInlineNamepace() { + if (!fIsInlineInitialized) { + fIsInline= computeIsInline(); + fIsInlineInitialized= true; + } + return fIsInline; + } + + public boolean computeIsInline() { + final IASTNode node= getPhysicalNode(); + if (!(node instanceof ICPPASTNamespaceDefinition)) { + return false; + } + + if (((ICPPASTNamespaceDefinition) node).isInline()) + return true; + + IASTTranslationUnit tu= node.getTranslationUnit(); + if (tu != null) { + final IIndex index= tu.getIndex(); + IIndexFileSet fileSet= tu.getASTFileSet(); + if (index != null && fileSet != null) { + fileSet= fileSet.invert(); + ICPPNamespace nsBinding = getNamespaceIndexBinding(index); + if (nsBinding != null && nsBinding.isInline()) { + try { + IIndexName[] names = index.findDefinitions(nsBinding); + for (IIndexName name : names) { + if (name.isInlineNamespaceDefinition() && fileSet.contains(name.getFile())) { + return true; + } + } + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + } + } + return false; + } + + public ICPPNamespaceScope[] getEnclosingNamespaceSet() { + if (fEnclosingNamespaceSet == null) { + return fEnclosingNamespaceSet= computeEnclosingNamespaceSet(this); + } + return fEnclosingNamespaceSet; + } + + public ICPPInternalNamespaceScope[] getInlineNamespaces() { + if (getKind() == EScopeKind.eLocal) + return NO_NAMESPACE_SCOPES; + + if (fInlineNamespaces == null) { + fInlineNamespaces= computeInlineNamespaces(); + } + return fInlineNamespaces; + } + + ICPPInternalNamespaceScope[] computeInlineNamespaces() { + populateCache(); + Set result= null; + if (fInlineNamespaceDefinitions != null) { + result= new HashSet(fInlineNamespaceDefinitions.size()); + for (ICPPASTNamespaceDefinition nsdef : fInlineNamespaceDefinitions) { + final IScope scope = nsdef.getScope(); + if (scope instanceof ICPPInternalNamespaceScope) { + result.add((ICPPInternalNamespaceScope) scope); + } + } + } + + for (ICPPInternalNamespaceScope inline : getIndexInlineNamespaces()) { + if (result == null) + result = new HashSet(); + result.add(inline); + } + + if (result == null) { + return NO_NAMESPACE_SCOPES; + } + return result.toArray(new ICPPInternalNamespaceScope[result.size()]); + } + + private ICPPInternalNamespaceScope[] getIndexInlineNamespaces() { + IASTTranslationUnit tu= getPhysicalNode().getTranslationUnit(); + if (tu instanceof CPPASTTranslationUnit) { + CPPASTTranslationUnit cpptu= (CPPASTTranslationUnit) tu; + IIndex index= tu.getIndex(); + if (index != null) { + IScope[] inlineScopes= null; + ICPPNamespace namespace= getNamespaceIndexBinding(index); + try { + if (namespace != null) { + ICPPNamespaceScope scope = namespace.getNamespaceScope(); + inlineScopes= scope.getInlineNamespaces(); + } else if (getKind() == EScopeKind.eGlobal) { + inlineScopes= index.getInlineNamespaces(); + } + } catch (DOMException e) { + } catch (CoreException e) { + } + if (inlineScopes != null) { + List result= null; + for (IScope scope : inlineScopes) { + if (scope instanceof IIndexScope) { + scope= cpptu.mapToASTScope((IIndexScope) scope); + } + if (scope instanceof ICPPInternalNamespaceScope) { + if (result == null) { + result= new ArrayList(); + } + result.add((ICPPInternalNamespaceScope) scope); + } + } + if (result != null) { + return result.toArray(new ICPPInternalNamespaceScope[result.size()]); + } + } + } + } + return NO_NAMESPACE_SCOPES; + } + + /** + * Called while populating scope. + */ + public void addInlineNamespace(ICPPASTNamespaceDefinition nsDef) { + if (fInlineNamespaceDefinitions == null) { + fInlineNamespaceDefinitions= new ArrayList(); + } + fInlineNamespaceDefinitions.add(nsDef); + } + + + public static ICPPNamespaceScope[] computeEnclosingNamespaceSet(ICPPInternalNamespaceScope nsScope) { + if (nsScope.isInlineNamepace()) { + try { + IScope parent= nsScope.getParent(); + if (parent instanceof ICPPInternalNamespaceScope) { + return ((ICPPInternalNamespaceScope) parent).getEnclosingNamespaceSet(); + } + } catch (DOMException e) { + CCorePlugin.log(e); + } + } + + Set result= new HashSet(); + result.add(nsScope); + addInlineNamespaces(nsScope, result); + return result.toArray(new ICPPNamespaceScope[result.size()]); + } + + private static void addInlineNamespaces(ICPPInternalNamespaceScope nsScope, Set result) { + ICPPInternalNamespaceScope[] inlineNss = nsScope.getInlineNamespaces(); + for (ICPPInternalNamespaceScope inlineNs : inlineNss) { + if (result.add(inlineNs)) { + addInlineNamespaces(inlineNs, result); + } + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java index 25d5d997b0a..8fd5fb47976 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java @@ -164,8 +164,8 @@ abstract public class CPPScope implements ICPPASTInternalScope { } catch (CoreException e) { CCorePlugin.log(e); } - } else if (physicalNode instanceof ICPPASTNamespaceDefinition) { - ICPPNamespace nsbinding= getNamespaceIndexBinding((ICPPASTNamespaceDefinition)physicalNode, index); + } else { + ICPPNamespace nsbinding= getNamespaceIndexBinding(index); if (nsbinding != null) { return nsbinding.getNamespaceScope().getBinding(name, forceResolve, fileSet); } @@ -175,14 +175,17 @@ abstract public class CPPScope implements ICPPASTInternalScope { return binding; } - private ICPPNamespace getNamespaceIndexBinding(ICPPASTNamespaceDefinition nsdef, IIndex index) { + protected ICPPNamespace getNamespaceIndexBinding(IIndex index) { if (fIndexNamespace == UNINITIALIZED) { fIndexNamespace= null; - IASTName nsname = nsdef.getName(); - IBinding nsbinding= nsname.resolveBinding(); - if (nsbinding != null) { - fIndexNamespace= (ICPPNamespace) index.adaptBinding(nsbinding); - } + IASTNode node= getPhysicalNode(); + if (node instanceof ICPPASTNamespaceDefinition) { + IASTName nsname = ((ICPPASTNamespaceDefinition) node).getName(); + IBinding nsbinding= nsname.resolveBinding(); + if (nsbinding != null) { + fIndexNamespace= (ICPPNamespace) index.adaptBinding(nsbinding); + } + } } return fIndexNamespace; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java index 6ccecac7e23..479d90d1ad5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2008, 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 @@ -48,15 +48,40 @@ import org.eclipse.cdt.internal.core.index.IIndexScope; * scopes that can be reopened, i.e. namespaces. */ public class CPPScopeMapper { + + /** + * Used for implicit inline directives for inline namespaces found in the index. + */ + public static final class InlineNamespaceDirective implements ICPPUsingDirective { + private final ICPPInternalNamespaceScope fContainer; + private final ICPPInternalNamespaceScope fNominated; + + public InlineNamespaceDirective(ICPPInternalNamespaceScope container, ICPPInternalNamespaceScope inline) { + fContainer= container; + fNominated= inline; + } + public IScope getContainingScope() { + return fContainer; + } + public ICPPNamespaceScope getNominatedScope() throws DOMException { + return fNominated; + } + public int getPointOfDeclaration() { + return 0; + } + } + /** * Wrapper for namespace-scopes from the index. */ - private class NamespaceScopeWrapper implements ICPPNamespaceScope { + private class NamespaceScopeWrapper implements ICPPInternalNamespaceScope { private final ICPPNamespaceScope fScope; private ArrayList fUsingDirectives; + private ICPPNamespaceScope[] fEnclosingNamespaceSet; public NamespaceScopeWrapper(ICPPNamespaceScope scope) { fScope= scope; + assert fScope instanceof IIndexScope; } public EScopeKind getKind() { @@ -90,19 +115,50 @@ public class CPPScopeMapper { return fScope.getScopeName(); } - public void addUsingDirective(ICPPUsingDirective usingDirective) throws DOMException { - if (fUsingDirectives == null) { - fUsingDirectives= new ArrayList(1); - } + public void addUsingDirective(ICPPUsingDirective usingDirective) { + initUsingDirectives(); fUsingDirectives.add(usingDirective); } - public ICPPUsingDirective[] getUsingDirectives() throws DOMException { + private void initUsingDirectives() { if (fUsingDirectives == null) { - return ICPPUsingDirective.EMPTY_ARRAY; + fUsingDirectives= new ArrayList(1); + // Insert a using directive for every inline namespace + for (ICPPInternalNamespaceScope inline: getInlineNamespaces()) { + fUsingDirectives.add(new InlineNamespaceDirective(this, inline)); + } } + } + + public ICPPUsingDirective[] getUsingDirectives() { + initUsingDirectives(); return fUsingDirectives.toArray(new ICPPUsingDirective[fUsingDirectives.size()]); } + + public ICPPNamespaceScope[] getEnclosingNamespaceSet() { + if (fEnclosingNamespaceSet == null) + return fEnclosingNamespaceSet= CPPNamespaceScope.computeEnclosingNamespaceSet(this); + + return fEnclosingNamespaceSet; + } + + public boolean isInlineNamepace() { + IIndexBinding binding = ((IIndexScope) fScope).getScopeBinding(); + if (binding instanceof ICPPNamespace && ((ICPPNamespace) binding).isInline()) + return true; + + return false; + } + + public ICPPInternalNamespaceScope[] getInlineNamespaces() { + // Obtain the inline namespaces from the index and map them to the ast + ICPPNamespaceScope[] pre = fScope.getInlineNamespaces(); + ICPPInternalNamespaceScope[] result= new ICPPInternalNamespaceScope[pre.length]; + for (int i = 0; i < result.length; i++) { + result[i]= (ICPPInternalNamespaceScope) mapToASTScope((IIndexScope) pre[i]); + } + return result; + } } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 1305ab3699d..e58904a2beb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -1810,6 +1810,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.t_inline: if (supportExtendedTemplateSyntax && LT(2) == IToken.t_template) return templateDeclaration(option); + if (LT(2) == IToken.t_namespace) { + return namespaceDefinitionOrAlias(); + } break; case IToken.tSEMI: IToken t= consume(); @@ -1858,8 +1861,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * request a backtrack */ protected IASTDeclaration namespaceDefinitionOrAlias() throws BacktrackException, EndOfFileException { - final int offset= consume().getOffset(); + final int offset= LA().getOffset(); int endOffset; + boolean isInline= false; + + if (LT(1) == IToken.t_inline) { + consume(); + isInline= true; + } + consume(IToken.t_namespace); // optional name IASTName name = null; @@ -1875,6 +1885,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (LT(1) == IToken.tLBRACE) { ICPPASTNamespaceDefinition ns = nodeFactory.newNamespaceDefinition(name); + ns.setIsInline(isInline); declarationListInBraces(ns, offset, DeclarationOptions.GLOBAL); return ns; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalNamespaceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalNamespaceScope.java new file mode 100644 index 00000000000..139889242e6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalNamespaceScope.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; + +/** + * For namespace scopes from the AST or mapped index namespace scopes. + */ +public interface ICPPInternalNamespaceScope extends ICPPNamespaceScope { + + /** + * Returns the enclosing namespace set (7.3.1-9) + */ + public ICPPNamespaceScope[] getEnclosingNamespaceSet(); + + /** + * Returns whether this namespace scope is inline. + */ + public boolean isInlineNamepace(); + + /** + * Returns the inline namespace scopes mapped back to the AST. + */ + public ICPPInternalNamespaceScope[] getInlineNamespaces(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java index bf07b6f43e0..33ef875bb64 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java @@ -168,9 +168,6 @@ class BaseClassLookup { infoMap.put(baseClassScope, result); try { IBinding[] members= CPPSemantics.getBindingsFromScope(baseClassScope, fileSet, data); - if (data.typesOnly) { - CPPSemantics.removeObjects(members); - } if (members != null && members.length > 0 && members[0] != null) { if (data.prefixLookup) { matches= members; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index aea2c713f08..d2d3f70e753 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -20,6 +20,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -175,6 +176,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespaceScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding; @@ -188,6 +190,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalNamespaceScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; @@ -533,9 +536,8 @@ public class CPPSemantics { private static void doKoenigLookup(LookupData data) throws DOMException { data.ignoreUsingDirectives = true; data.forceQualified = true; - ObjectSet associated = getAssociatedScopes(data); - for (int i = 0; i < associated.size(); i++) { - final ICPPScope scope = associated.keyAt(i); + Set associated = getAssociatedScopes(data); + for (ICPPNamespaceScope scope : associated) { if (!data.visited.containsKey(scope)) { lookup(data, scope); } @@ -637,12 +639,12 @@ public class CPPSemantics { return data; } - static private ObjectSet getAssociatedScopes(LookupData data) { + static private Set getAssociatedScopes(LookupData data) { if (!data.hasFunctionArguments()) - return ObjectSet.emptySet(); + return Collections.emptySet(); IType[] ps = data.getFunctionArgumentTypes(); - ObjectSet namespaces = new ObjectSet(2); + Set namespaces = new HashSet(2); ObjectSet classes = new ObjectSet(2); for (IType p : ps) { p = getUltimateType(p, true); @@ -654,16 +656,14 @@ public class CPPSemantics { return namespaces; } - static private void getAssociatedScopes(IType t, ObjectSet namespaces, + static private void getAssociatedScopes(IType t, Set namespaces, ObjectSet classes, CPPASTTranslationUnit tu) throws DOMException { // 3.4.2-2 if (t instanceof ICPPClassType) { ICPPClassType ct= (ICPPClassType) t; if (!classes.containsKey(ct)) { classes.put(ct); - ICPPScope scope = getContainingNamespaceScope((IBinding) t, tu); - if (scope != null) - namespaces.put(scope); + getAssociatedNamespaceScopes(getContainingNamespaceScope((IBinding) t, tu), namespaces); ICPPClassType cls = (ICPPClassType) t; ICPPBase[] bases = cls.getBases(); @@ -676,9 +676,7 @@ public class CPPSemantics { } } } else if (t instanceof IEnumeration) { - ICPPScope scope = getContainingNamespaceScope((IBinding) t, tu); - if (scope!=null) - namespaces.put(scope); + getAssociatedNamespaceScopes(getContainingNamespaceScope((IBinding) t, tu), namespaces); } else if (t instanceof IFunctionType) { IFunctionType ft = (IFunctionType) t; @@ -693,16 +691,32 @@ public class CPPSemantics { } return; } - + static private ICPPNamespaceScope getContainingNamespaceScope(IBinding binding, CPPASTTranslationUnit tu) throws DOMException { - if (binding == null) return null; + if (binding == null) + return null; IScope scope = binding.getScope(); + if (scope instanceof IIndexScope) { + scope= tu.mapToASTScope((IIndexScope) scope); + } while (scope != null && !(scope instanceof ICPPNamespaceScope)) { scope = getParentScope(scope, tu); } return (ICPPNamespaceScope) scope; } + + public static void getAssociatedNamespaceScopes(ICPPNamespaceScope scope, Set namespaces) { + if (scope == null || !namespaces.add(scope)) + return; + + if (scope instanceof ICPPInternalNamespaceScope) { + final ICPPInternalNamespaceScope internalScope = (ICPPInternalNamespaceScope) scope; + for (ICPPNamespaceScope mem : internalScope.getEnclosingNamespaceSet()) { + namespaces.add(mem); + } + } + } static ICPPScope getLookupScope(IASTName name, LookupData data) throws DOMException { IASTNode parent = name.getParent(); @@ -875,56 +889,44 @@ public class CPPSemantics { } if (!data.usingDirectivesOnly && !(data.ignoreMembers && scope instanceof ICPPClassScope)) { - IBinding[] bindings= getBindingsFromScope(scope, fileSet, data); - if (data.typesOnly) { - removeObjects(bindings); - } - mergeResults(data, bindings, true); + mergeResults(data, getBindingsFromScope(scope, fileSet, data), true); - // store using-directives found in this block or namespace for later use. - if ((!data.hasResults() || !data.qualified() || data.contentAssist) && scope instanceof ICPPNamespaceScope) { + // Nominate using-directives found in this block or namespace. + if (scope instanceof ICPPNamespaceScope) { final ICPPNamespaceScope blockScope= (ICPPNamespaceScope) scope; - if (!(blockScope instanceof ICPPBlockScope)) { - data.visited.put(blockScope); // namespace has been searched. - if (data.tu != null) { - data.tu.handleAdditionalDirectives(blockScope); - } + + if (data.qualified() && blockScope.getKind() != EScopeKind.eLocal) { + lookupInlineNamespaces(data, fileSet, blockScope); } - ICPPUsingDirective[] uds= blockScope.getUsingDirectives(); - if (uds != null && uds.length > 0) { - HashSet handled= new HashSet(); - for (final ICPPUsingDirective ud : uds) { - if (declaredBefore(ud, data.astName, false)) { - storeUsingDirective(data, blockScope, ud, handled); - } - } + if (data.contentAssist || !data.hasResults() || !data.qualified()) { + // Nominate namespaces + nominateNamespaces(data, blockScope); } } } - // lookup in nominated namespaces + // Lookup in nominated namespaces if (!data.ignoreUsingDirectives && scope instanceof ICPPNamespaceScope && !(scope instanceof ICPPBlockScope)) { if (!data.hasResults() || !data.qualified() || data.contentAssist) { - lookupInNominated(data, (ICPPNamespaceScope) scope); + lookupInNominated(data, fileSet, (ICPPNamespaceScope) scope); } } - if ((!data.contentAssist && (data.problem != null || data.hasResults())) || - (friendInLocalClass && !(scope instanceof ICPPClassScope))) { + if (friendInLocalClass && !(scope instanceof ICPPClassScope)) + return; + if (!data.contentAssist && data.hasResultOrProblem()) return; - } + // Lookup in base classes if (!data.usingDirectivesOnly && scope instanceof ICPPClassScope) { BaseClassLookup.lookupInBaseClasses(data, (ICPPClassScope) scope, fileSet); + if (!data.contentAssist && data.hasResultOrProblem()) + return; } - if (!data.contentAssist && (data.problem != null || data.hasResults())) - return; - - // if still not found, loop and check our containing scope if (data.qualified() && !(scope instanceof ICPPTemplateScope)) { if (data.ignoreUsingDirectives || data.usingDirectives.isEmpty()) - break; + return; data.usingDirectivesOnly = true; } @@ -937,6 +939,37 @@ public class CPPSemantics { } } + private static void lookupInlineNamespaces(LookupData data, IIndexFileSet fileSet, ICPPNamespaceScope namespace) throws DOMException { + if (namespace instanceof ICPPInternalNamespaceScope) { + ICPPInternalNamespaceScope ns= (ICPPInternalNamespaceScope) namespace; + for (ICPPInternalNamespaceScope inline : ns.getInlineNamespaces()) { + mergeResults(data, getBindingsFromScope(inline, fileSet, data), true); + lookupInlineNamespaces(data, fileSet, inline); + nominateNamespaces(data, inline); + } + } + } + + private static void nominateNamespaces(LookupData data, final ICPPNamespaceScope blockScope) + throws DOMException { + final boolean isBlockScope = blockScope.getKind() == EScopeKind.eLocal; + if (!isBlockScope) { + data.visited.put(blockScope); // Mark as searched. + if (data.tu != null) { + data.tu.handleAdditionalDirectives(blockScope); + } + } + ICPPUsingDirective[] uds= blockScope.getUsingDirectives(); + if (uds != null && uds.length > 0) { + HashSet handled= new HashSet(); + for (final ICPPUsingDirective ud : uds) { + if (declaredBefore(ud, data.astName, false)) { + storeUsingDirective(data, blockScope, ud, handled); + } + } + } + } + private static boolean lookupDestructor(LookupData data, IScope start) throws DOMException { IASTName typeDtorName= data.astName; final char[] typeDtorChars= typeDtorName.getSimpleID(); @@ -1018,7 +1051,7 @@ public class CPPSemantics { private static boolean dependsOnTemplateFieldReference(IASTName astName) { if (astName.getPropertyInParent() != IASTFieldReference.FIELD_NAME) return false; - + final boolean[] result= {false}; final IASTExpression fieldOwner = ((IASTFieldReference) astName.getParent()).getFieldOwner(); fieldOwner.accept(new ASTVisitor() { @@ -1109,15 +1142,17 @@ public class CPPSemantics { } }); return result[0]; - } + } + + static IBinding[] getBindingsFromScope(ICPPScope scope, final IIndexFileSet fileSet, LookupData data) throws DOMException { + IBinding[] bindings; - static IBinding[] getBindingsFromScope(ICPPScope scope, final IIndexFileSet fileSet, LookupData data) throws DOMException { // For internal scopes we need to check the point of declaration if (scope instanceof ICPPASTInternalScope) { final IASTName astName = data.astName; final ICPPASTInternalScope internalScope = (ICPPASTInternalScope) scope; - IBinding[] bindings= internalScope.getBindings(astName, true, data.prefixLookup, fileSet, data.checkPointOfDecl); - + bindings= internalScope.getBindings(astName, true, data.prefixLookup, fileSet, data.checkPointOfDecl); + // Bug 103857: Members declared after the point of completion cannot be // found in the partial AST, we look them up in the index if (data.checkWholeClassScope && scope instanceof ICPPClassScope) { @@ -1134,15 +1169,20 @@ public class CPPSemantics { } } } - return bindings; - } + } else { + // For index scopes the point of declaration is ignored. + bindings= scope.getBindings(data.astName, true, data.prefixLookup, fileSet); + } - // For index scopes the point of declaration is ignored. - return scope.getBindings(data.astName, true, data.prefixLookup, fileSet); + if (data.typesOnly) { + return removeObjects(bindings); + } + return bindings; } - static void removeObjects(final IBinding[] bindings) { + private static IBinding[] removeObjects(final IBinding[] bindings) { final int length = bindings.length; + IBinding[] copy= null; int pos= 0; for (int i = 0; i < length; i++) { final IBinding binding= bindings[i]; @@ -1153,12 +1193,21 @@ public class CPPSemantics { check= delegates[0]; } if (check instanceof IType || check instanceof ICPPNamespace) { - bindings[pos++]= binding; + if (copy != null) { + copy[pos]= binding; + } + pos++; + } else { + if (copy == null) { + copy= new IBinding[length-1]; + System.arraycopy(bindings, 0, copy, 0, pos); + } } } - while (pos < length) { - bindings[pos++]= null; - } + if (pos == 0) + return IBinding.EMPTY_BINDING_ARRAY; + + return copy == null ? bindings : copy; } private static ICPPTemplateScope enclosingTemplateScope(IASTNode node) { @@ -1342,22 +1391,23 @@ public class CPPSemantics { if (scope instanceof ICPPNamespaceScope) { final ICPPNamespaceScope nsscope = (ICPPNamespaceScope) scope; final ICPPASTUsingDirective usingDirective = (ICPPASTUsingDirective) item; - try { - nsscope.addUsingDirective(new CPPUsingDirective(usingDirective)); - } catch (DOMException e) { - // directive is not cached. + nsscope.addUsingDirective(new CPPUsingDirective(usingDirective)); + } + } else if (item instanceof ICPPASTNamespaceDefinition) { + final ICPPASTNamespaceDefinition nsDef = (ICPPASTNamespaceDefinition) item; + final boolean isUnnamed = nsDef.getName().getLookupKey().length == 0; + final boolean isInline = nsDef.isInline(); + if (isUnnamed || isInline) { + if (scope instanceof CPPNamespaceScope) { + final CPPNamespaceScope nsscope = (CPPNamespaceScope) scope; + nsscope.addUsingDirective(new CPPUsingDirective(nsDef)); + if (isInline) { + nsscope.addInlineNamespace(nsDef); + } } } - } else if (item instanceof ICPPASTNamespaceDefinition && - ((ICPPASTNamespaceDefinition) item).getName().getLookupKey().length == 0) { - if (scope instanceof ICPPNamespaceScope) { - final ICPPNamespaceScope nsscope = (ICPPNamespaceScope) scope; - final ICPPASTNamespaceDefinition nsdef= (ICPPASTNamespaceDefinition) item; - try { - nsscope.addUsingDirective(new CPPUsingDirective(nsdef)); - } catch (DOMException e) { - // directive is not cached. - } + if (!isUnnamed) { + populateCache(scope, item); } } else { populateCache(scope, item); @@ -1577,8 +1627,9 @@ public class CPPSemantics { * Perform lookup in nominated namespaces that appear in the given scope. For unqualified lookups the method assumes * that transitive directives have been stored in the lookup-data. For qualified lookups the transitive directives * are considered if the lookup of the original directive returns empty. + * @param fileSet */ - static private void lookupInNominated(LookupData data, ICPPNamespaceScope scope) throws DOMException { + static private void lookupInNominated(LookupData data, IIndexFileSet fileSet, ICPPNamespaceScope scope) throws DOMException { List allNominated= data.usingDirectives.remove(scope); while (allNominated != null) { for (ICPPNamespaceScope nominated : allNominated) { @@ -1588,15 +1639,10 @@ public class CPPSemantics { data.visited.put(nominated); boolean found = false; - IBinding[] bindings= nominated.getBindings(data.astName, true, data.prefixLookup); + IBinding[] bindings= getBindingsFromScope(nominated, fileSet, data); if (bindings != null && bindings.length > 0) { - if (data.typesOnly) { - removeObjects(bindings); - } - if (bindings[0] != null) { - mergeResults(data, bindings, true); - found = true; - } + mergeResults(data, bindings, true); + found = true; } // in the qualified lookup we have to nominate the transitive directives only when diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 865de1d4003..4b550831c52 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -319,6 +319,10 @@ public class LookupData { return false; } + public boolean hasResultOrProblem() { + return problem != null || hasResults(); + } + public boolean hasResults() { if (foundItems == null) return false; 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 85fcec9cf69..11276d4cc40 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.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; @@ -638,4 +640,33 @@ public class CIndex implements IIndex { } return result.values().toArray(new IIndexFile[result.size()]); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.index.IIndex#getInlineNamespaces() + */ + public IIndexScope[] getInlineNamespaces() throws CoreException { + if (SPECIALCASE_SINGLES && fFragments.length == 1) { + return fFragments[0].getInlineNamespaces(); + } + + IIndexFragmentBinding[][] preresult = new IIndexFragmentBinding[fPrimaryFragmentCount][]; + try { + for (int i = 0; i < fPrimaryFragmentCount; i++) { + IIndexScope[] raw = fFragments[i].getInlineNamespaces(); + IIndexFragmentBinding[] arr = preresult[i] = new IIndexFragmentBinding[raw.length]; + for (int j=0; j fSubSets= new HashMap(); public IndexFileSet() { @@ -40,13 +41,18 @@ public class IndexFileSet implements IIndexFileSet { } public boolean containsDeclaration(IIndexBinding binding) { + return containsDeclaration(binding, false); + } + + boolean containsDeclaration(IIndexBinding binding, boolean inverse) { for (Map.Entry entry : fSubSets.entrySet()) { try { IIndexFragmentName[] names = entry.getKey().findNames(binding, IIndexFragment.FIND_DECLARATIONS_DEFINITIONS); for (IIndexFragmentName name : names) { try { - if (entry.getValue().contains((IIndexFragmentFile) name.getFile())) { + final boolean foundDecl = entry.getValue().contains((IIndexFragmentFile) name.getFile()); + if (foundDecl != inverse) { return true; } } catch (CoreException e) { @@ -61,10 +67,18 @@ public class IndexFileSet implements IIndexFileSet { } public IBinding[] filterFileLocalBindings(IBinding[] bindings) { + return filterFileLocalBindings(bindings, false); + } + + public IBinding[] filterFileLocalBindings(IBinding[] bindings, boolean invert) { if (bindings == null || bindings.length == 0) { return bindings; } BitSet ok= new BitSet(bindings.length); + if (invert) { + ok.set(0, bindings.length); + } + for (int i = 0; i < bindings.length; i++) { IBinding binding = bindings[i]; if (binding != null) { @@ -90,10 +104,16 @@ public class IndexFileSet implements IIndexFileSet { } } } - if (ok.cardinality() == bindings.length) { + + if (invert) { + ok.flip(0, bindings.length); + } + final int cardinality = ok.cardinality(); + if (cardinality == bindings.length) { return bindings; } - IBinding[] result= new IBinding[ok.cardinality()]; + + IBinding[] result= new IBinding[cardinality]; int j= ok.nextSetBit(0); for (int i = 0; i < result.length; i++) { result[i]= bindings[j]; @@ -103,14 +123,48 @@ public class IndexFileSet implements IIndexFileSet { } public boolean contains(IIndexFile file) throws CoreException { + return contains(file, false); + } + + public boolean contains(IIndexFile file, boolean invert) throws CoreException { if (!(file instanceof IIndexFragmentFile)) - return false; + return invert; IIndexFragmentFile ifile= (IIndexFragmentFile) file; IIndexFragmentFileSet subSet= fSubSets.get(ifile.getIndexFragment()); - if (subSet != null) { - return subSet.contains(ifile); + if (subSet != null && subSet.contains(ifile)) { + return !invert; } - return false; + return invert; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.index.IIndexFileSet#invert() + */ + public IIndexFileSet invert() { + if (fInverse == null) { + fInverse= new IIndexFileSet() { + public IIndexFileSet invert() { + return IndexFileSet.this; + } + + public IBinding[] filterFileLocalBindings(IBinding[] bindings) { + return IndexFileSet.this.filterFileLocalBindings(bindings, true); + } + + public boolean containsDeclaration(IIndexBinding binding) { + return IndexFileSet.this.containsDeclaration(binding, true); + } + + public boolean contains(IIndexFile file) throws CoreException { + return IndexFileSet.this.contains(file, true); + } + + public void add(IIndexFile indexFile) { + Assert.isLegal(false); + } + }; + } + return fInverse; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespace.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespace.java index 0bb7f4c7cd5..f3e575e0e8a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespace.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespace.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Symbian Software Systems and others. + * Copyright (c) 2006, 2010 Symbian Software Systems 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 Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; @@ -37,4 +38,12 @@ class CompositeCPPNamespace extends CompositeCPPBinding implements ICPPNamespace public ICPPNamespaceScope getNamespaceScope() throws DOMException { return new CompositeCPPNamespaceScope(cf, namespaces); } + + public boolean isInline() { + for (ICPPNamespace namespace : namespaces) { + if (namespace.isInline()) + return true; + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceAlias.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceAlias.java index 95a072d1e66..a0914dd9dba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceAlias.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceAlias.java @@ -1,12 +1,12 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Symbian Software Systems and others. + * Copyright (c) 2007, 2010 Symbian Software Systems 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 Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; @@ -39,4 +39,8 @@ class CompositeCPPNamespaceAlias extends CompositeCPPBinding implements ICPPName IIndexFragmentBinding ns = (IIndexFragmentBinding) ((ICPPNamespaceAlias)rbinding).getBinding(); return cf.getCompositeBinding(ns); } + + public boolean isInline() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceScope.java index 072161d3a00..b0b400f80c2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPNamespaceScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Symbian Software Systems and others. + * Copyright (c) 2007, 2010 Symbian Software Systems 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 @@ -38,11 +38,11 @@ class CompositeCPPNamespaceScope extends CompositeScope implements ICPPNamespace return EScopeKind.eNamespace; } - public void addUsingDirective(ICPPUsingDirective directive) throws DOMException { + public void addUsingDirective(ICPPUsingDirective directive) { fail(); } - public ICPPUsingDirective[] getUsingDirectives() throws DOMException { + public ICPPUsingDirective[] getUsingDirectives() { return new ICPPUsingDirective[0]; // same behavior as PDOMCPPNamespace } @@ -82,9 +82,9 @@ class CompositeCPPNamespaceScope extends CompositeScope implements ICPPNamespace @Override public IIndexName getScopeName() { - for(int i=0; i postProcesses = new LinkedList(); @@ -396,6 +403,14 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return pdomBinding; } + @Override + public void addChild(PDOMNode node) throws CoreException { + super.addChild(node); + if (node instanceof PDOMCPPNamespace) { + ((PDOMCPPNamespace) node).addToList(record + FIRST_NAMESPACE_CHILD_OFFSET); + } + } + private PDOMBinding createSpecialization(PDOMNode parent, PDOMBinding orig, IBinding special) throws CoreException, DOMException { PDOMBinding result= null; @@ -594,6 +609,22 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return result; } + @Override + public PDOMCPPNamespace[] getInlineNamespaces() { + final Long key = record + CACHE_BASES; + PDOMCPPNamespace[] result= (PDOMCPPNamespace[]) getPDOM().getCachedResult(key); + if (result == null) { + List nslist = PDOMCPPNamespace.collectInlineNamespaces(getDB(), getLinkage(), record+FIRST_NAMESPACE_CHILD_OFFSET); + if (nslist == null) { + result= new PDOMCPPNamespace[0]; + } else { + result= nslist.toArray(new PDOMCPPNamespace[nslist.size()]); + } + getPDOM().putCachedResult(key, result, true); + } + return result; + } + /** * Find the equivalent binding, or binding place holder within this PDOM */ @@ -814,13 +845,13 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { PDOMCPPBase pdomBase = new PDOMCPPBase(this, pdomName, baseNode.isVirtual(), baseNode.getVisibility()); ownerClass.addBase(pdomBase); - pdomName.setIsBaseSpecifier(true); + pdomName.setIsBaseSpecifier(); } else if (derivedClassBinding instanceof PDOMCPPClassSpecialization) { PDOMCPPClassSpecialization ownerClass = (PDOMCPPClassSpecialization) derivedClassBinding; PDOMCPPBase pdomBase = new PDOMCPPBase(this, pdomName, baseNode.isVirtual(), baseNode.getVisibility()); ownerClass.addBase(pdomBase); - pdomName.setIsBaseSpecifier(true); + pdomName.setIsBaseSpecifier(); } } } else if (parentNode instanceof ICPPASTUsingDirective) { @@ -860,7 +891,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } else if (parentNode instanceof ICPPASTElaboratedTypeSpecifier) { ICPPASTElaboratedTypeSpecifier elaboratedSpecifier = (ICPPASTElaboratedTypeSpecifier)parentNode; if (elaboratedSpecifier.isFriend()) { - pdomName.setIsFriendSpecifier(true); + pdomName.setIsFriendSpecifier(); PDOMName enclClassName = (PDOMName) pdomName.getEnclosingDefinition(); if (enclClassName != null) { PDOMBinding enclClassBinding = enclClassName.getBinding(); @@ -874,7 +905,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { IASTSimpleDeclaration grandparentNode = (IASTSimpleDeclaration) parentNode.getParent(); if (grandparentNode.getDeclSpecifier() instanceof ICPPASTDeclSpecifier) { if (((ICPPASTDeclSpecifier) grandparentNode.getDeclSpecifier()).isFriend()) { - pdomName.setIsFriendSpecifier(true); + pdomName.setIsFriendSpecifier(); PDOMName enclClassName = (PDOMName) pdomName.getEnclosingDefinition(); if (enclClassName != null) { PDOMBinding enclClassBinding = enclClassName.getBinding(); @@ -885,6 +916,11 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } } } + } else if (parentNode instanceof ICPPASTNamespaceDefinition) { + ICPPASTNamespaceDefinition nsdef= (ICPPASTNamespaceDefinition) parentNode; + if (nsdef.isInline()) { + pdomName.setIsInlineNamespace(); + } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespace.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespace.java index a90b94bd49a..8e6af112efd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespace.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespace.java @@ -36,6 +36,7 @@ import org.eclipse.cdt.internal.core.index.IIndexScope; import org.eclipse.cdt.internal.core.model.ASTStringUtil; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; @@ -49,18 +50,40 @@ import org.eclipse.core.runtime.CoreException; class PDOMCPPNamespace extends PDOMCPPBinding implements ICPPNamespace, ICPPNamespaceScope, IIndexScope { - private static final int INDEX_OFFSET = PDOMBinding.RECORD_SIZE + 0; + private static final int INDEX_OFFSET = PDOMCPPBinding.RECORD_SIZE; + private static final int FIRST_NAMESPACE_CHILD_OFFSET = INDEX_OFFSET + Database.PTR_SIZE; + private static final int NEXT_NAMESPACE_SIBBLING_OFFSET = FIRST_NAMESPACE_CHILD_OFFSET + Database.PTR_SIZE; + private static final int FLAG_OFFSET = NEXT_NAMESPACE_SIBBLING_OFFSET + Database.PTR_SIZE; @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMBinding.RECORD_SIZE + 4; + protected static final int RECORD_SIZE = FLAG_OFFSET + 1; + + private static int INLINE_FLAG= 0x1; + + private int fFlag= -1; + private ICPPNamespaceScope[] fInlineNamespaces; public PDOMCPPNamespace(PDOMLinkage linkage, PDOMNode parent, ICPPNamespace namespace) throws CoreException { super(linkage, parent, namespace.getNameCharArray()); + updateFlag(namespace); } public PDOMCPPNamespace(PDOMLinkage linkage, long record) throws CoreException { super(linkage, record); } + + @Override + public void update(PDOMLinkage linkage, IBinding newBinding) throws CoreException { + updateFlag((ICPPNamespace) newBinding); + } + + private void updateFlag(ICPPNamespace namespace) throws CoreException { + int flag= 0; + if (namespace.isInline()) + flag |= INLINE_FLAG; + + getDB().putByte(record + FLAG_OFFSET, (byte) flag); + } public EScopeKind getKind() { return EScopeKind.eNamespace; @@ -104,14 +127,25 @@ class PDOMCPPNamespace extends PDOMCPPBinding @Override public void addChild(PDOMNode child) throws CoreException { - getIndex().insert(child.getRecord()); + final long childRec = child.getRecord(); + getIndex().insert(childRec); + if (child instanceof PDOMCPPNamespace) { + ((PDOMCPPNamespace) child).addToList(record + FIRST_NAMESPACE_CHILD_OFFSET); + } } - public ICPPNamespaceScope getNamespaceScope() throws DOMException { + public void addToList(final long listRecord) throws CoreException { + final Database db= getDB(); + final long nextRec= db.getRecPtr(listRecord); + db.putRecPtr(record + NEXT_NAMESPACE_SIBBLING_OFFSET, nextRec); + db.putRecPtr(listRecord, record); + } + + public ICPPNamespaceScope getNamespaceScope() { return this; } - public ICPPUsingDirective[] getUsingDirectives() throws DOMException { + public ICPPUsingDirective[] getUsingDirectives() { return new ICPPUsingDirective[0]; } @@ -203,7 +237,7 @@ class PDOMCPPNamespace extends PDOMCPPBinding return result; } - public void addUsingDirective(ICPPUsingDirective directive) throws DOMException { fail(); } + public void addUsingDirective(ICPPUsingDirective directive) { fail(); } public IIndexBinding getScopeBinding() { return this; @@ -217,4 +251,49 @@ class PDOMCPPNamespace extends PDOMCPPBinding } return ASTStringUtil.join(names, String.valueOf(Keywords.cpCOLONCOLON)); } + + public ICPPNamespaceScope[] getInlineNamespaces() { + if (fInlineNamespaces == null) { + List nslist = collectInlineNamespaces(getDB(), getLinkage(), record+FIRST_NAMESPACE_CHILD_OFFSET); + if (nslist == null) { + fInlineNamespaces= new PDOMCPPNamespace[0]; + } else { + fInlineNamespaces= nslist.toArray(new PDOMCPPNamespace[nslist.size()]); + } + } + return fInlineNamespaces; + } + + public static List collectInlineNamespaces(Database db, + PDOMLinkage linkage, long listRecord) { + List nslist= null; + try { + long rec= db.getRecPtr(listRecord); + while (rec != 0) { + PDOMCPPNamespace ns= new PDOMCPPNamespace(linkage, rec); + if (ns.isInline()) { + if (nslist == null) { + nslist= new ArrayList(); + } + nslist.add(ns); + } + rec= db.getRecPtr(rec + NEXT_NAMESPACE_SIBBLING_OFFSET); + } + } catch (CoreException e) { + CCorePlugin.log(e); + } + return nslist; + } + + public boolean isInline() { + if (fFlag == -1) { + try { + fFlag= getDB().getByte(record + FLAG_OFFSET); + } catch (CoreException e) { + CCorePlugin.log(e); + fFlag= 0; + } + } + return (fFlag & INLINE_FLAG) != 0; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespaceAlias.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespaceAlias.java index 23865cbda75..9395d567685 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespaceAlias.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPNamespaceAlias.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 QNX Software Systems and others. + * Copyright (c) 2006, 2010 QNX Software Systems 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 @@ -101,4 +101,7 @@ class PDOMCPPNamespaceAlias extends PDOMCPPBinding implements ICPPNamespaceAlias return null; } + public boolean isInline() { + return false; + } }