From 03b82b0928028e1ba2db6ca3579d4d65255301f0 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 6 Aug 2008 14:19:12 +0000 Subject: [PATCH] Complete implementation of ICPPClassType, bug 98171. --- .../index/tests/EmptyIndexFragment.java | 3 +- .../tests/IndexBindingResolutionTestBase.java | 11 +- .../tests/IndexCBindingResolutionBugs.java | 6 +- .../tests/IndexCBindingResolutionTest.java | 8 +- .../tests/IndexCPPBindingResolutionBugs.java | 202 +++++++++- .../tests/IndexCPPBindingResolutionTest.java | 6 +- .../tests/IndexCPPTemplateResolutionTest.java | 9 +- .../pdom/tests/CPPClassTemplateTests.java | 4 +- .../cdt/core/dom/ast/cpp/ICPPBase.java | 34 +- .../AbstractCPPClassSpecializationScope.java | 90 +++-- .../core/dom/parser/cpp/CPPBaseClause.java | 19 +- .../parser/cpp/CPPClassSpecialization.java | 362 ++++++++---------- .../core/dom/parser/cpp/CPPClassTemplate.java | 30 +- .../core/dom/parser/cpp/CPPClassType.java | 86 ++--- .../dom/parser/cpp/CPPSpecialization.java | 12 +- .../cpp/CPPTemplateTemplateParameter.java | 27 +- ...assTypeMixin.java => ClassTypeHelper.java} | 87 ++--- .../cpp/ICPPClassSpecializationScope.java | 27 +- .../cpp/ICPPInternalClassTypeMixinHost.java | 4 +- .../internal/core/index/IIndexFragment.java | 6 +- .../composite/AbstractCompositeFactory.java | 16 +- .../index/composite/ICompositesFactory.java | 6 + .../cpp/CompositeCPPClassInstance.java | 23 +- .../cpp/CompositeCPPClassSpecialization.java | 133 +++++-- .../CompositeCPPClassSpecializationScope.java | 23 ++ .../composite/cpp/CompositeCPPClassType.java | 9 +- .../composite/cpp/CompositeInstanceCache.java | 56 ++- .../eclipse/cdt/internal/core/pdom/PDOM.java | 11 +- .../cdt/internal/core/pdom/PDOMProxy.java | 3 +- .../core/pdom/dom/cpp/PDOMCPPBase.java | 4 +- .../dom/cpp/PDOMCPPClassSpecialization.java | 211 +++++----- .../core/pdom/dom/cpp/PDOMCPPClassType.java | 245 +++++------- .../core/pdom/dom/cpp/PDOMClassUtil.java | 17 +- .../core/pdom/dom/cpp/PDOMInstanceCache.java | 6 +- 34 files changed, 1057 insertions(+), 739 deletions(-) rename core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/{ClassTypeMixin.java => ClassTypeHelper.java} (85%) 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 5a9aab7e9e3..78a6dbb3f8c 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 @@ -136,6 +136,7 @@ public class EmptyIndexFragment implements IIndexFragment { return null; } - public void putCachedResult(Object key, Object newMap) { + public Object putCachedResult(Object key, Object value, boolean replace) { + return value; } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java index 7f10c9864c9..cb4c3365cf0 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java @@ -113,8 +113,15 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase { /* * @see IndexBindingResolutionTestBase#getBindingFromASTName(Class, String, int) */ - protected IBinding getBindingFromASTName(String section, int len) { - return getBindingFromASTName(section, len, IBinding.class); + protected T getBindingFromASTName(String section, int len) { + IASTName name= findName(section, len); + assertNotNull("name not found for \""+section+"\"", name); + assertEquals(section.substring(0, len), name.getRawSignature()); + + IBinding binding = name.resolveBinding(); + assertNotNull("No binding for "+name.getRawSignature(), binding); + assertFalse("Binding is a ProblemBinding for name "+name.getRawSignature(), IProblemBinding.class.isAssignableFrom(name.resolveBinding().getClass())); + return (T) binding; } /** diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionBugs.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionBugs.java index d4395274638..b7f8a04ba6d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionBugs.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionBugs.java @@ -36,14 +36,16 @@ public class IndexCBindingResolutionBugs extends IndexBindingResolutionTestBase public static class SingleProject extends IndexCBindingResolutionBugs { public SingleProject() {setStrategy(new SinglePDOMTestStrategy(false));} + public static TestSuite suite() {return suite(SingleProject.class);} } public static class ProjectWithDepProj extends IndexCBindingResolutionBugs { public ProjectWithDepProj() {setStrategy(new ReferencedProject(false));} + public static TestSuite suite() {return suite(ProjectWithDepProj.class);} } public static void addTests(TestSuite suite) { - suite.addTest(suite(SingleProject.class)); - suite.addTest(suite(ProjectWithDepProj.class)); + suite.addTest(SingleProject.suite()); + suite.addTest(ProjectWithDepProj.suite()); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java index f39c379ca03..780bd51aecd 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 Symbian Software Systems and others. + * Copyright (c) 2007, 2008 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 @@ -37,14 +37,16 @@ public class IndexCBindingResolutionTest extends IndexBindingResolutionTestBase public static class SingleProject extends IndexCBindingResolutionTest { public SingleProject() {setStrategy(new SinglePDOMTestStrategy(false));} + public static TestSuite suite() {return suite(SingleProject.class);} } public static class ProjectWithDepProj extends IndexCBindingResolutionTest { public ProjectWithDepProj() {setStrategy(new ReferencedProject(false));} + public static TestSuite suite() {return suite(ProjectWithDepProj.class);} } public static void addTests(TestSuite suite) { - suite.addTest(suite(SingleProject.class)); - suite.addTest(suite(ProjectWithDepProj.class)); + suite.addTest(SingleProject.suite()); + suite.addTest(ProjectWithDepProj.suite()); } public IndexCBindingResolutionTest() { 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 7ca51ad3aba..adf0d52b936 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 @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.index.tests; +import java.util.Arrays; import java.util.regex.Pattern; import junit.framework.TestSuite; @@ -30,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; 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.ICPPField; @@ -58,15 +60,17 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas public static class SingleProject extends IndexCPPBindingResolutionBugs { public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true));} + public static TestSuite suite() {return suite(SingleProject.class);} } public static class ProjectWithDepProj extends IndexCPPBindingResolutionBugs { public ProjectWithDepProj() {setStrategy(new ReferencedProject(true));} + public static TestSuite suite() {return suite(ProjectWithDepProj.class);} } public static void addTests(TestSuite suite) { - suite.addTest(suite(SingleProject.class)); - suite.addTest(suite(ProjectWithDepProj.class)); + suite.addTest(SingleProject.suite()); + suite.addTest(ProjectWithDepProj.suite()); } public static TestSuite suite() { @@ -870,4 +874,198 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas getBindingFromASTName("test2(x)", 5, ICPPFunction.class); getBindingFromASTName("test3(x)", 5, ICPPFunction.class); } + + // class A { + // A(); + // void l(); + // void e; + // class M {}; + // }; + // class B { + // B(); + // void m(); + // void f; + // class N {}; + // }; + // class C : B { + // C(); + // void n(); + // int g; + // class O {}; + // }; + // template class CT : B { + // CT(); + // void n(); + // T g; + // class O {}; + // }; + // template<> class CT : A { + // CT(); CT(int); + // void o(); + // int h; + // class P {}; + // }; + // template class Container { + // class C : B { + // C(); + // void n(); + // int g; + // class O {}; + // }; + // template class CT : B { + // CT(); + // void n(); + // T g; + // class O {}; + // }; + // }; + // template<> class Container::C : A { + // C(); C(int); + // void o(); + // int h; + // class P {}; + // }; + // template<> template class Container::CT : A { + // CT(); CT(int); + // void o(); + // int h; + // class P {}; + // }; + + // C c; + // CT ct; + // CT ctinst; + // Container::C spec; + // Container::CT spect; + // Container::C espec; + // Container::CT espect; + public void testClassTypes_Bug98171() throws Exception { + // regular class + ICPPClassType ct= getBindingFromASTName("C", 1); + assertBindings(new String[] {"B"}, ct.getBases()); + assertBindings(new String[] {"n", "m", "B", "C"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"C", "C"}, ct.getConstructors()); + assertBindings(new String[] {"g"}, ct.getDeclaredFields()); + assertBindings(new String[] {"n", "C"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"f", "g"}, ct.getFields()); + assertBindings(new String[] {"m", "n", "C", "C", "~C", "B", "B", "~B", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"O"}, ct.getNestedClasses()); + + // class template + ct= getBindingFromASTName("CT", 2); + assertInstance(ct, ICPPClassTemplate.class); + assertBindings(new String[] {"B"}, ct.getBases()); + assertBindings(new String[] {"n", "m", "B", "CT"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"CT", "CT"}, ct.getConstructors()); + assertBindings(new String[] {"g"}, ct.getDeclaredFields()); + assertBindings(new String[] {"n", "CT"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"f", "g"}, ct.getFields()); + assertBindings(new String[] {"m", "n", "CT", "CT", "~CT", "B", "B", "~B", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"O"}, ct.getNestedClasses()); + + // class template instance + ct= getBindingFromASTName("CT", 7); + assertInstance(ct, ICPPTemplateInstance.class); + assertBindings(new String[] {"B"}, ct.getBases()); + assertBindings(new String[] {"n", "m", "B", "CT"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"CT", "CT"}, ct.getConstructors()); + assertBindings(new String[] {"g"}, ct.getDeclaredFields()); + assertBindings(new String[] {"n", "CT"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"f", "g"}, ct.getFields()); + assertBindings(new String[] {"m", "n", "CT", "CT", "~CT", "B", "B", "~B", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"O"}, ct.getNestedClasses()); + + // explicit class template instance + ct= getBindingFromASTName("CT", 8); + assertInstance(ct, ICPPTemplateInstance.class); + assertBindings(new String[] {"A"}, ct.getBases()); + assertBindings(new String[] {"o", "l", "A", "CT", "CT"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"CT", "CT", "CT"}, ct.getConstructors()); + assertBindings(new String[] {"h"}, ct.getDeclaredFields()); + assertBindings(new String[] {"o", "CT", "CT"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"e", "h"}, ct.getFields()); + assertBindings(new String[] {"l", "o", "CT", "CT", "CT", "~CT", "A", "A", "~A", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"P"}, ct.getNestedClasses()); + + // class specialization + ct= getBindingFromASTName("C spec", 1); + assertInstance(ct, ICPPClassSpecialization.class); + assertBindings(new String[] {"B"}, ct.getBases()); + assertBindings(new String[] {"n", "m", "B", "C"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"C", "C"}, ct.getConstructors()); + assertBindings(new String[] {"g"}, ct.getDeclaredFields()); + assertBindings(new String[] {"n", "C"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"f", "g"}, ct.getFields()); + assertBindings(new String[] {"m", "n", "C", "C", "~C", "B", "B", "~B", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"O"}, ct.getNestedClasses()); + + // class template specialization + ct= getBindingFromASTName("CT spect", 2); + assertInstance(ct, ICPPClassTemplate.class, ICPPClassSpecialization.class); + assertBindings(new String[] {"B"}, ct.getBases()); + assertBindings(new String[] {"n", "m", "B", "CT"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"CT", "CT"}, ct.getConstructors()); + assertBindings(new String[] {"g"}, ct.getDeclaredFields()); + assertBindings(new String[] {"n", "CT"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"f", "g"}, ct.getFields()); + assertBindings(new String[] {"m", "n", "CT", "CT", "~CT", "B", "B", "~B", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"O"}, ct.getNestedClasses()); + + // explicit class specialization + ct= getBindingFromASTName("C espec", 1); + assertInstance(ct, ICPPClassSpecialization.class); + assertBindings(new String[] {"A"}, ct.getBases()); + assertBindings(new String[] {"o", "l", "A", "C", "C"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"C", "C", "C"}, ct.getConstructors()); + assertBindings(new String[] {"h"}, ct.getDeclaredFields()); + assertBindings(new String[] {"o", "C", "C"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"e", "h"}, ct.getFields()); + assertBindings(new String[] {"l", "o", "C", "C", "C", "~C", "A", "A", "~A", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"P"}, ct.getNestedClasses()); + + // explicit class template specialization + ct= getBindingFromASTName("CT espect", 7); + assertInstance(ct, ICPPTemplateInstance.class); + assertBindings(new String[] {"A"}, ct.getBases()); + assertBindings(new String[] {"o", "l", "A", "CT", "CT"}, ct.getAllDeclaredMethods()); + assertBindings(new String[] {"CT", "CT", "CT"}, ct.getConstructors()); + assertBindings(new String[] {"h"}, ct.getDeclaredFields()); + assertBindings(new String[] {"o", "CT", "CT"}, ct.getDeclaredMethods()); + assertBindings(new String[] {"e", "h"}, ct.getFields()); + assertBindings(new String[] {"l", "o", "CT", "CT", "CT", "~CT", "A", "A", "~A", "operator =", "operator ="}, ct.getMethods()); + assertBindings(new String[] {"P"}, ct.getNestedClasses()); + } + + private void assertBindings(String[] expected, ICPPBase[] bases) throws DOMException { + IBinding[] bindings= new IBinding[bases.length]; + for (int i = 0; i < bindings.length; i++) { + bindings[i]= bases[i].getBaseClass(); + } + assertBindings(expected, bindings); + } + + private void assertBindings(String[] expected, IBinding[] binding) { + String[] actual= new String[binding.length]; + for (int i = 0; i < actual.length; i++) { + actual[i]= binding[i].getName(); + } + Arrays.sort(actual); + Arrays.sort(expected); + assertEquals(toString(expected), toString(actual)); + } + + private String toString(String[] actual) { + StringBuilder buf= new StringBuilder(); + buf.append('{'); + boolean isFirst= true; + for (String val : actual) { + if (!isFirst) { + buf.append(','); + } + buf.append(val); + isFirst= false; + } + buf.append('}'); + return buf.toString(); + } } 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 fa65f079490..d8fc7e18c87 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 @@ -53,14 +53,16 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti public static class SingleProject extends IndexCPPBindingResolutionTest { public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true));} + public static TestSuite suite() {return suite(SingleProject.class);} } public static class ProjectWithDepProj extends IndexCPPBindingResolutionTest { public ProjectWithDepProj() {setStrategy(new ReferencedProject(true));} + public static TestSuite suite() {return suite(ProjectWithDepProj.class);} } public static void addTests(TestSuite suite) { - suite.addTest(suite(SingleProject.class)); - suite.addTest(suite(ProjectWithDepProj.class)); + suite.addTest(SingleProject.suite()); + suite.addTest(ProjectWithDepProj.suite()); } // namespace ns { class A; enum E {E1}; typedef int T; } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 59fb94d0e57..abe8ddaf06c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -6,7 +6,8 @@ * 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.index.tests; @@ -62,15 +63,17 @@ import org.eclipse.core.runtime.CoreException; public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBase { public static class SingleProject extends IndexCPPTemplateResolutionTest { public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true));} + public static TestSuite suite() {return suite(SingleProject.class);} } public static class ProjectWithDepProj extends IndexCPPTemplateResolutionTest { public ProjectWithDepProj() {setStrategy(new ReferencedProject(true));} + public static TestSuite suite() {return suite(ProjectWithDepProj.class);} } public static void addTests(TestSuite suite) { - suite.addTest(suite(SingleProject.class)); - suite.addTest(suite(ProjectWithDepProj.class)); + suite.addTest(SingleProject.suite()); + suite.addTest(ProjectWithDepProj.suite()); } public IndexCPPTemplateResolutionTest() { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java index ee426827bab..765b73bacd5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 Symbian Software Systems and others. + * Copyright (c) 2007, 2008 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 @@ -231,7 +231,7 @@ public class CPPClassTemplateTests extends PDOMTestBase { // void bar() { // foo->f(*new A()); // } - public void _testFunctionPointer() throws Exception { + public void testFunctionPointer() throws Exception { IIndexFragmentBinding[] bs= pdom.findBindings(new char[][] {"foo".toCharArray()}, IndexFilter.ALL, NPM); assertEquals(1, bs.length); assertInstance(bs[0], ICPPVariable.class); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java index 43c224c9001..90e2a25d0c5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -18,16 +19,18 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBas /** * Represents the relationship between a class and one of its base classes. * - * @author Doug Schaefer + * @noimplement This interface is not intended to be implemented by clients. */ -public interface ICPPBase { +public interface ICPPBase extends Cloneable { public static final ICPPBase[] EMPTY_BASE_ARRAY = new ICPPBase[0]; + public static final int v_private = ICPPASTBaseSpecifier.v_private; + public static final int v_protected = ICPPASTBaseSpecifier.v_protected; + public static final int v_public = ICPPASTBaseSpecifier.v_public; + /** * The base class. Generally a ICPPClassType, but may be a ICPPTemplateParameter. - * In the case of typedefs, the binding being typedefed will be returned instead of - * the typedef itself. - * + * In the case of typedefs, the target type will be returned instead of the typedef itself. */ public IBinding getBaseClass() throws DOMException; @@ -43,16 +46,21 @@ public interface ICPPBase { */ public int getVisibility() throws DOMException; - public static final int v_private = ICPPASTBaseSpecifier.v_private; - - public static final int v_protected = ICPPASTBaseSpecifier.v_protected; - - public static final int v_public = ICPPASTBaseSpecifier.v_public; /** * Whether this is a virtual base class. - * */ public boolean isVirtual() throws DOMException; - + + /** + * @since 5.1 + */ + public ICPPBase clone(); + + /** + * Used internally to change cloned bases. + * + * @noreference This method is not intended to be referenced by clients. + */ + public void setBaseClass(IBinding baseClass); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java index 997bfa416e7..88961318028 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java @@ -18,16 +18,24 @@ import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.core.parser.util.ObjectMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; /** * Base class for all specialization scopes @@ -100,43 +108,77 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat public ICPPClassSpecialization getClassType() { return specialClass; } + + public ICPPBase[] getBases() throws DOMException { + ICPPBase[] result = null; + ICPPBase[] bases = specialClass.getSpecializedBinding().getBases(); + final ObjectMap argmap = specialClass.getArgumentMap(); + for (ICPPBase base : bases) { + ICPPBase specBase = base.clone(); + IBinding origClass = base.getBaseClass(); + if (origClass instanceof IType) { + IType specClass= CPPTemplates.instantiateType((IType) origClass, argmap, specialClass); + specClass = SemanticUtil.getUltimateType(specClass, false); + if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) { + specBase.setBaseClass((IBinding) specClass); + } + result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBase); + } + } + return (ICPPBase[]) ArrayUtil.trim(ICPPBase.class, result); + } + + @SuppressWarnings("unchecked") + private T[] specializeMembers(T[] array) { + if (array == null || array.length == 0) + return array; + T[] newArray= array.clone(); + for (int i = 0; i < newArray.length; i++) { + newArray[i]= (T) specialClass.specializeMember(array[i]); + } + return newArray; + } + + public ICPPField[] getDeclaredFields() throws DOMException { + ICPPField[] fields= specialClass.getSpecializedBinding().getDeclaredFields(); + return specializeMembers(fields); + } + public ICPPMethod[] getImplicitMethods() { - // Implicit methods shouldn't have implicit specializations - return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; + try { + ICPPClassScope origClassType= (ICPPClassScope) specialClass.getSpecializedBinding().getCompositeScope(); + ICPPMethod[] methods= origClassType.getImplicitMethods(); + return specializeMembers(methods); + } catch (DOMException e) { + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; + } } public IName getScopeName() { if (specialClass instanceof ICPPInternalBinding) return (IASTName) ((ICPPInternalBinding) specialClass).getDefinition(); - //TODO: get the scope name for non-internal bindings return null; } public ICPPConstructor[] getConstructors() throws DOMException { - ICPPClassType specialized = specialClass.getSpecializedBinding(); - ICPPConstructor[] bindings = specialized.getConstructors(); - - if (bindings == null) return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; - - ICPPConstructor[] specs = new ICPPConstructor[0]; - for (ICPPConstructor binding : bindings) { - specs = (ICPPConstructor[]) ArrayUtil.append(ICPPConstructor.class, specs, specialClass.specializeMember(binding)); - } - return (ICPPConstructor[]) ArrayUtil.trim(ICPPConstructor.class, specs); + ICPPConstructor[] ctors= specialClass.getSpecializedBinding().getConstructors(); + return specializeMembers(ctors); } - + public ICPPMethod[] getDeclaredMethods() throws DOMException { - ICPPClassType specialized = specialClass.getSpecializedBinding(); - ICPPMethod[] bindings = specialized.getDeclaredMethods(); - - if (bindings == null) return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; - - ICPPMethod[] specs = new ICPPMethod[0]; - for (ICPPMethod binding : bindings) { - specs = (ICPPMethod[]) ArrayUtil.append(ICPPMethod.class, specs, specialClass.specializeMember(binding)); - } - return (ICPPMethod[]) ArrayUtil.trim(ICPPMethod.class, specs); + ICPPMethod[] bindings = specialClass.getSpecializedBinding().getDeclaredMethods(); + return specializeMembers(bindings); + } + + public ICPPClassType[] getNestedClasses() throws DOMException { + ICPPClassType[] bindings = specialClass.getSpecializedBinding().getNestedClasses(); + return specializeMembers(bindings); + } + + public IBinding[] getFriends() throws DOMException { + // not yet supported + return IBinding.EMPTY_BINDING_ARRAY; } public IScope getParent() throws DOMException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java index 96fb9d08cf0..d2b4049d8d1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java @@ -6,13 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Corporation - initial API and implementation - * Bryan Wilkinson (QNX) + * IBM Corporation - initial API and implementation + * Bryan Wilkinson (QNX) + * Markus Schorn (Wind River Systems) *******************************************************************************/ - -/* - * Created on Dec 15, 2004 - */ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.IName; @@ -58,8 +55,12 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase { return (IName) node; } - public void setBaseClass(IBinding binding) throws DOMException { - throw new DOMException(this); + public void setBaseClass(IBinding binding) { + } + + @Override + public ICPPBase clone() { + return this; } } @@ -123,7 +124,7 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase { } @Override - public Object clone() { + public ICPPBase clone() { ICPPBase t = null; try { t = (ICPPBase) super.clone(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 211652f8877..f8448c63acc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -13,46 +13,45 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; -import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; -import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; +import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; -import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; -import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.index.IIndexType; /** * @author aniefer * */ -public class CPPClassSpecialization extends CPPSpecialization implements ICPPClassSpecialization { +public class CPPClassSpecialization extends CPPSpecialization + implements ICPPClassSpecialization, ICPPInternalClassTypeMixinHost { - private IScope specScope; + private CPPClassSpecializationScope specScope; private ObjectMap specializationMap= ObjectMap.EMPTY_MAP; + private boolean checked; public CPPClassSpecialization(ICPPClassType specialized, IBinding owner, ObjectMap argumentMap) { super(specialized, owner, argumentMap); @@ -74,189 +73,167 @@ public class CPPClassSpecialization extends CPPSpecialization implements ICPPCla } return result; } + + private class FindDefinitionAction extends CPPASTVisitor { + private char [] nameArray = CPPClassSpecialization.this.getNameCharArray(); + public IASTName result = null; - private ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier(){ - IASTNode definition = getDefinition(); - if( definition != null ){ - IASTNode node = definition; - while( node instanceof IASTName ) - node = node.getParent(); - if( node instanceof ICPPASTCompositeTypeSpecifier ) - return (ICPPASTCompositeTypeSpecifier)node; - } - return null; + { + shouldVisitNames = true; + shouldVisitDeclarations = true; + shouldVisitDeclSpecifiers = true; + shouldVisitDeclarators = true; + } + + @Override + public int visit( IASTName name ){ + if( name instanceof ICPPASTTemplateId ) + return PROCESS_SKIP; + if( name instanceof ICPPASTQualifiedName ) + return PROCESS_CONTINUE; + char [] c = name.toCharArray(); + + if( name.getParent() instanceof ICPPASTQualifiedName ){ + IASTName [] ns = ((ICPPASTQualifiedName)name.getParent()).getNames(); + if( ns[ ns.length - 1 ] != name ) + return PROCESS_CONTINUE; + name = (IASTName) name.getParent(); + } + + if( name.getParent() instanceof ICPPASTCompositeTypeSpecifier && + CharArrayUtils.equals( c, nameArray ) ) + { + IBinding binding = name.resolveBinding(); + if( binding == CPPClassSpecialization.this ){ + if( name instanceof ICPPASTQualifiedName ){ + IASTName [] ns = ((ICPPASTQualifiedName)name).getNames(); + name = ns[ ns.length - 1 ]; + } + result = name; + return PROCESS_ABORT; + } + } + return PROCESS_CONTINUE; + } + + @Override + public int visit( IASTDeclaration declaration ){ + if(declaration instanceof IASTSimpleDeclaration || declaration instanceof ICPPASTTemplateDeclaration) + return PROCESS_CONTINUE; + return PROCESS_SKIP; + } + @Override + public int visit( IASTDeclSpecifier declSpec ){ + return (declSpec instanceof ICPPASTCompositeTypeSpecifier ) ? PROCESS_CONTINUE : PROCESS_SKIP; + } + @Override + public int visit( IASTDeclarator declarator ) { return PROCESS_SKIP; } + } + + public void checkForDefinition() { + if( !checked && definition == null ) { + IBinding orig= getSpecializedBinding(); + IASTTranslationUnit tu= null; + while (orig != null) { + if (orig instanceof ICPPInternalBinding) { + IASTNode node= ((ICPPInternalBinding) orig).getDefinition(); + if (node != null) { + tu= node.getTranslationUnit(); + if (tu != null) + break; + } + } + if (!(orig instanceof ICPPSpecialization)) + break; + orig= ((ICPPSpecialization) orig).getSpecializedBinding(); + } + if (tu != null) { + FindDefinitionAction action= new FindDefinitionAction(); + tu.accept( action ); + definition = action.result; + } + checked = true; + } + return; + } + + public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() { + IASTNode definition= getDefinition(); + if (definition != null) { + IASTNode node= definition; + while (node instanceof IASTName) + node= node.getParent(); + if (node instanceof ICPPASTCompositeTypeSpecifier) + return (ICPPASTCompositeTypeSpecifier) node; + } + return null; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getBases() - */ public ICPPBase[] getBases() throws DOMException { - if( getDefinition() == null ){ - ICPPBase[] result = null; - ICPPBase[] bindings = (getSpecializedBinding()).getBases(); - for (ICPPBase binding : bindings) { - ICPPBase specBinding = (ICPPBase) ((ICPPInternalBase)binding).clone(); - IBinding base = binding.getBaseClass(); - if (base instanceof IType) { - IType specBase= specializeType((IType) base); - specBase = SemanticUtil.getUltimateType(specBase, false); - if (specBase instanceof IBinding && !(specBase instanceof IProblemBinding)) { - ((ICPPInternalBase)specBinding).setBaseClass((IBinding)specBase); - } - result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBinding); - } - } - return (ICPPBase[]) ArrayUtil.trim(ICPPBase.class, result); - } - - ICPPASTBaseSpecifier[] bases = getCompositeTypeSpecifier().getBaseSpecifiers(); - if (bases.length == 0) - return ICPPBase.EMPTY_BASE_ARRAY; - - ICPPBase[] bindings = new ICPPBase[bases.length]; - for (int i = 0; i < bases.length; i++) { - bindings[i] = new CPPBaseClause(bases[i]); - IBinding base = bindings[i].getBaseClass(); - if (base instanceof IType) { - IType specBase = specializeType((IType) base); - if (specBase instanceof ICPPClassType) { - ((CPPBaseClause) bindings[i]).setBaseClass((ICPPClassType) specBase); - } - } - } - return bindings; + ICPPClassSpecializationScope scope= getSpecializationScope(); + if (scope == null) + return ClassTypeHelper.getBases(this); + return scope.getBases(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getFields() - */ - public IField[] getFields() throws DOMException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#findField(java.lang.String) - */ - public IField findField(String name) throws DOMException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getDeclaredFields() - */ public ICPPField[] getDeclaredFields() throws DOMException { - // TODO Auto-generated method stub - return null; + ICPPClassSpecializationScope scope= getSpecializationScope(); + if (scope == null) + return ClassTypeHelper.getDeclaredFields(this); + + return scope.getDeclaredFields(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getMethods() - */ - public ICPPMethod[] getMethods() throws DOMException { - return CPPClassType.getMethods(this); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getAllDeclaredMethods() - */ - public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getDeclaredMethods() - */ public ICPPMethod[] getDeclaredMethods() throws DOMException { - IScope scope= getCompositeScope(); - if (scope instanceof CPPClassSpecializationScope) { - CPPClassSpecializationScope sscope= (CPPClassSpecializationScope) scope; - if (sscope.isFullyCached()) - return sscope.getDeclaredMethods(); - } - - IBinding binding = null; - ICPPMethod [] result = null; + ICPPClassSpecializationScope scope= getSpecializationScope(); + if (scope == null) + return ClassTypeHelper.getDeclaredMethods(this); - IASTDeclaration [] decls = getCompositeTypeSpecifier().getMembers(); - for (IASTDeclaration decl : decls) { - while( decl instanceof ICPPASTTemplateDeclaration ) - decl = ((ICPPASTTemplateDeclaration)decl).getDeclaration(); - if( decl instanceof IASTSimpleDeclaration ){ - IASTDeclarator [] dtors = ((IASTSimpleDeclaration)decl).getDeclarators(); - for (IASTDeclarator dtor : dtors) { - binding = dtor.getName().resolveBinding(); - if( binding instanceof ICPPMethod) - result = (ICPPMethod[]) ArrayUtil.append( ICPPMethod.class, result, binding ); - } - } else if( decl instanceof IASTFunctionDefinition ){ - IASTDeclarator dtor = ((IASTFunctionDefinition)decl).getDeclarator(); - dtor = CPPVisitor.findInnermostDeclarator(dtor); - binding = dtor.getName().resolveBinding(); - if( binding instanceof ICPPMethod ){ - result = (ICPPMethod[]) ArrayUtil.append( ICPPMethod.class, result, binding ); - } - } else if( decl instanceof ICPPASTUsingDeclaration ){ - IASTName n = ((ICPPASTUsingDeclaration)decl).getName(); - binding = n.resolveBinding(); - if( binding instanceof ICPPUsingDeclaration ){ - IBinding [] bs = ((ICPPUsingDeclaration)binding).getDelegates(); - for (IBinding element : bs) { - if( element instanceof ICPPMethod ) - result = (ICPPMethod[]) ArrayUtil.append( ICPPMethod.class, result, element ); - } - } else if( binding instanceof ICPPMethod ) { - result = (ICPPMethod[]) ArrayUtil.append( ICPPMethod.class, result, binding ); - } - } - } - return (ICPPMethod[]) ArrayUtil.trim( ICPPMethod.class, result ); + return scope.getDeclaredMethods(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getConstructors() - */ public ICPPConstructor[] getConstructors() throws DOMException { - IScope scope = getCompositeScope(); - if (scope instanceof CPPClassSpecializationScope) { - if (ASTInternal.isFullyCached(scope)) - return ((CPPClassSpecializationScope)scope).getConstructors(); - } - - if( ASTInternal.isFullyCached(scope)) - return ((CPPClassScope)scope).getConstructors( true ); - - IASTDeclaration [] members = getCompositeTypeSpecifier().getMembers(); - for (IASTDeclaration decl : members) { - if( decl instanceof ICPPASTTemplateDeclaration ) - decl = ((ICPPASTTemplateDeclaration)decl).getDeclaration(); - if( decl instanceof IASTSimpleDeclaration ){ - IASTDeclarator [] dtors = ((IASTSimpleDeclaration)decl).getDeclarators(); - for (IASTDeclarator dtor : dtors) { - if( dtor == null ) break; - dtor= CPPVisitor.findInnermostDeclarator(dtor); - ASTInternal.addName(scope, dtor.getName() ); - } - } else if( decl instanceof IASTFunctionDefinition ){ - IASTDeclarator dtor = ((IASTFunctionDefinition)decl).getDeclarator(); - dtor= CPPVisitor.findInnermostDeclarator(dtor); - ASTInternal.addName(scope, dtor.getName() ); - } - } - - return ((CPPClassScope)scope).getConstructors( true ); + ICPPClassSpecializationScope scope= getSpecializationScope(); + if (scope == null) + return ClassTypeHelper.getConstructors(this); + + return scope.getConstructors(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getFriends() - */ public IBinding[] getFriends() throws DOMException { - // TODO Auto-generated method stub - return IBinding.EMPTY_BINDING_ARRAY; + ICPPClassSpecializationScope scope= getSpecializationScope(); + if (scope == null) + return ClassTypeHelper.getFriends(this); + + return scope.getFriends(); } + + public ICPPClassType[] getNestedClasses() throws DOMException { + ICPPClassSpecializationScope scope= getSpecializationScope(); + if (scope == null) + return ClassTypeHelper.getNestedClasses(this); + + return scope.getNestedClasses(); + } + + + public IField[] getFields() throws DOMException { + return ClassTypeHelper.getFields(this); + } + + public IField findField(String name) throws DOMException { + return ClassTypeHelper.findField(this, name); + } + + public ICPPMethod[] getMethods() throws DOMException { + return ClassTypeHelper.getMethods(this); + } + + public ICPPMethod[] getAllDeclaredMethods() throws DOMException { + return ClassTypeHelper.getAllDeclaredMethods(this); + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.ICompositeType#getKey() @@ -272,21 +249,23 @@ public class CPPClassSpecialization extends CPPSpecialization implements ICPPCla * @see org.eclipse.cdt.core.dom.ast.ICompositeType#getCompositeScope() */ public IScope getCompositeScope() throws DOMException { + final IScope specScope= getSpecializationScope(); + if (specScope != null) + return specScope; + + return getCompositeTypeSpecifier().getScope(); + } + + private ICPPClassSpecializationScope getSpecializationScope() { + checkForDefinition(); + if (getDefinition() != null) + return null; + + //implicit specialization: must specialize bindings in scope if (specScope == null) { - ICPPClassScope scope = null; - if( getDefinition() != null ){ - scope = (ICPPClassScope) getCompositeTypeSpecifier().getScope(); - } - - if (scope != null && scope.getClassType() == this) { - //explicit specialization: can use composite type specifier scope - specScope = scope; - } else { - //implicit specialization: must specialize bindings in scope - specScope = new CPPClassSpecializationScope(this); - } + specScope = new CPPClassSpecializationScope(this); } - return specScope; + return specScope; } /* (non-Javadoc) @@ -306,11 +285,6 @@ public class CPPClassSpecialization extends CPPSpecialization implements ICPPCla return this; } - public ICPPClassType[] getNestedClasses() throws DOMException { - return ICPPClassType.EMPTY_CLASS_ARRAY; - } - - public boolean isAnonymous() throws DOMException { if (getNameCharArray().length > 0) return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index 9446e62a105..12ed02c11d4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -6,10 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Bryan Wilkinson (QNX) - * Markus Schorn (Wind River Systems) - * Andrew Ferguson (Symbian) + * IBM - Initial API and implementation + * Bryan Wilkinson (QNX) + * Markus Schorn (Wind River Systems) + * Andrew Ferguson (Symbian) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -106,11 +106,9 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements } private ICPPClassTemplatePartialSpecialization[] partialSpecializations = null; - private ClassTypeMixin mixin; public CPPClassTemplate(IASTName name) { super(name); - this.mixin= new ClassTypeMixin(this); } public void checkForDefinition() { @@ -197,43 +195,43 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements } public ICPPBase[] getBases() { - return mixin.getBases(); + return ClassTypeHelper.getBases(this); } public IField[] getFields() throws DOMException { - return mixin.getFields(); + return ClassTypeHelper.getFields(this); } public ICPPField[] getDeclaredFields() throws DOMException { - return mixin.getDeclaredFields(); + return ClassTypeHelper.getDeclaredFields(this); } public ICPPMethod[] getMethods() throws DOMException { - return CPPClassType.getMethods(this); + return ClassTypeHelper.getMethods(this); } public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - return mixin.getAllDeclaredMethods(); + return ClassTypeHelper.getAllDeclaredMethods(this); } public ICPPMethod[] getDeclaredMethods() throws DOMException { - return mixin.getDeclaredMethods(); + return ClassTypeHelper.getDeclaredMethods(this); } public ICPPConstructor[] getConstructors() throws DOMException { - return mixin.getConstructors(); + return ClassTypeHelper.getConstructors(this); } public IBinding[] getFriends() { - return mixin.getFriends(); + return ClassTypeHelper.getFriends(this); } public ICPPClassType[] getNestedClasses() { - return mixin.getNestedClasses(); + return ClassTypeHelper.getNestedClasses(this); } public IField findField(String name) throws DOMException { - return mixin.findField(name); + return ClassTypeHelper.findField(this, name); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 0e07fff09f0..42e322915de 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -49,7 +49,6 @@ import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; -import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -63,83 +62,60 @@ import org.eclipse.core.runtime.PlatformObject; */ public class CPPClassType extends PlatformObject implements ICPPInternalClassTypeMixinHost { - public static ICPPMethod[] getMethods(ICPPClassType ct) throws DOMException { - ObjectSet set = new ObjectSet(4); - set.addAll(ct.getDeclaredMethods()); - ICPPClassScope scope = (ICPPClassScope) ct.getCompositeScope(); - set.addAll( scope.getImplicitMethods() ); - ICPPBase [] bases = ct.getBases(); - for (ICPPBase base : bases) { - IBinding b = base.getBaseClass(); - if( b instanceof ICPPClassType ) - set.addAll( ((ICPPClassType)b).getMethods() ); + public static class CPPClassTypeProblem extends ProblemBinding implements ICPPClassType { + public CPPClassTypeProblem(IASTNode node, int id, char[] arg) { + super(node, id, arg); } - return set.keyArray(ICPPMethod.class); - } - - public static class CPPClassTypeProblem extends ProblemBinding implements ICPPClassType{ - public CPPClassTypeProblem( IASTNode node, int id, char[] arg ) { - super( node, id, arg ); - } - public ICPPBase[] getBases() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public IField[] getFields() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPField[] getDeclaredFields() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPMethod[] getMethods() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPMethod[] getDeclaredMethods() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPConstructor[] getConstructors() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPMethod[] getDeclaredConversionOperators() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public int getKey() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public IField findField(String name) throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public IScope getCompositeScope() throws DOMException { - throw new DOMException( this ); - } - @Override - public IScope getParent() throws DOMException { - throw new DOMException( this ); - } - @Override - public IBinding[] find(String name) throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public IBinding[] getFriends() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public String[] getQualifiedName() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public char[][] getQualifiedNameCharArray() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public boolean isGloballyQualified() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public ICPPClassType[] getNestedClasses() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } public boolean isAnonymous() throws DOMException { - throw new DOMException( this ); + throw new DOMException(this); } } @@ -203,7 +179,6 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp private IASTName [] declarations; private boolean checked = false; private ICPPClassType typeInIndex; - private ClassTypeMixin mixin; public CPPClassType( IASTName name, IBinding indexBinding ){ if( name instanceof ICPPASTQualifiedName ){ @@ -222,7 +197,6 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp if (indexBinding instanceof ICPPClassType && indexBinding instanceof IIndexBinding) { typeInIndex= (ICPPClassType) indexBinding; } - mixin= new ClassTypeMixin(this); } public IASTNode[] getDeclarations() { @@ -406,43 +380,43 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp } public ICPPBase [] getBases() { - return mixin.getBases(); + return ClassTypeHelper.getBases(this); } public IField[] getFields() throws DOMException { - return mixin.getFields(); + return ClassTypeHelper.getFields(this); } public ICPPField[] getDeclaredFields() throws DOMException { - return mixin.getDeclaredFields(); + return ClassTypeHelper.getDeclaredFields(this); } public ICPPMethod[] getMethods() throws DOMException { - return getMethods(this); + return ClassTypeHelper.getMethods(this); } public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - return mixin.getAllDeclaredMethods(); + return ClassTypeHelper.getAllDeclaredMethods(this); } public ICPPMethod[] getDeclaredMethods() throws DOMException { - return mixin.getDeclaredMethods(); + return ClassTypeHelper.getDeclaredMethods(this); } public ICPPConstructor[] getConstructors() throws DOMException { - return mixin.getConstructors(); + return ClassTypeHelper.getConstructors(this); } public IBinding[] getFriends() { - return mixin.getFriends(); + return ClassTypeHelper.getFriends(this); } public ICPPClassType[] getNestedClasses() { - return mixin.getNestedClasses(); + return ClassTypeHelper.getNestedClasses(this); } public IField findField(String name) throws DOMException { - return mixin.findField(name); + return ClassTypeHelper.findField(this, name); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java index ec84f5179ac..33a6d15c968 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java @@ -6,13 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Markus Schorn (Wind River Systems) - * + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ -/* - * Created on Apr 29, 2005 - */ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ILinkage; @@ -41,7 +37,7 @@ public abstract class CPPSpecialization extends PlatformObject implements ICPPSp private IBinding owner; private IBinding specialized; protected ObjectMap argumentMap; - private IASTNode definition; + protected IASTNode definition; private IASTNode[] declarations; public CPPSpecialization(IBinding specialized, IBinding owner, ObjectMap argumentMap) { @@ -50,7 +46,7 @@ public abstract class CPPSpecialization extends PlatformObject implements ICPPSp this.argumentMap = argumentMap; } - protected IType specializeType(IType type) throws DOMException { + public IType specializeType(IType type) throws DOMException { if (owner instanceof ICPPClassSpecialization) { return CPPTemplates.instantiateType(type, argumentMap, (ICPPClassSpecialization) owner); } else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java index 843766eca14..87d2b0f5a98 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java @@ -121,37 +121,32 @@ public class CPPTemplateTemplateParameter extends CPPTemplateParameter implement public ICPPBase[] getBases() { return ICPPBase.EMPTY_BASE_ARRAY; } - public IField[] getFields() throws DOMException { - return null; + return IField.EMPTY_FIELD_ARRAY; } - public IField findField(String name) throws DOMException { return null; } - public ICPPField[] getDeclaredFields() throws DOMException { - return null; + return ICPPField.EMPTY_CPPFIELD_ARRAY; } - public ICPPMethod[] getMethods() throws DOMException { - return null; + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; } - public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - return null; + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; } - public ICPPMethod[] getDeclaredMethods() throws DOMException { - return null; + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; } - public ICPPConstructor[] getConstructors() { return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; } - public IBinding[] getFriends() throws DOMException { - return null; + return IBinding.EMPTY_BINDING_ARRAY; + } + public ICPPClassType[] getNestedClasses() { + return ICPPClassType.EMPTY_CLASS_ARRAY; } public int getKey() throws DOMException { @@ -215,10 +210,6 @@ public class CPPTemplateTemplateParameter extends CPPTemplateParameter implement } return ICPPTemplateInstance.EMPTY_TEMPLATE_INSTANCE_ARRAY; } - - public ICPPClassType[] getNestedClasses() { - return ICPPClassType.EMPTY_CLASS_ARRAY; - } public IASTName getUnknownName() { return new CPPASTName(getNameCharArray()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeMixin.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java similarity index 85% rename from core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeMixin.java rename to core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java index 817adf2d4f7..b8eccf6183d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeMixin.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java @@ -48,20 +48,13 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; /** * Holds common implementation of methods for ICPPClassType implementations that have - * a corresponding textual definition in the source code. This functionality is then - * accessed via a delegate. + * a corresponding textual definition in the source code. * * @see CPPClassType * @see CPPClassTemplate */ -class ClassTypeMixin { - private ICPPInternalClassTypeMixinHost host; - - public ClassTypeMixin(ICPPInternalClassTypeMixinHost host) { - this.host= host; - } - - public IBinding[] getFriends() { +public class ClassTypeHelper { + public static IBinding[] getFriends(ICPPInternalClassTypeMixinHost host) { if( host.getDefinition() == null ){ host.checkForDefinition(); if( host.getDefinition() == null ){ @@ -103,7 +96,7 @@ class ClassTypeMixin { return resultSet.keyArray(IBinding.class); } - public ICPPBase [] getBases() { + public static ICPPBase[] getBases(ICPPInternalClassTypeMixinHost host) { if( host.getDefinition() == null ){ host.checkForDefinition(); if( host.getDefinition() == null ){ @@ -124,7 +117,7 @@ class ClassTypeMixin { return bindings; } - public ICPPField[] getDeclaredFields() throws DOMException { + public static ICPPField[] getDeclaredFields(ICPPInternalClassTypeMixinHost host) throws DOMException { if( host.getDefinition() == null ){ host.checkForDefinition(); if( host.getDefinition() == null ){ @@ -161,19 +154,10 @@ class ClassTypeMixin { } return (ICPPField[]) ArrayUtil.trim( ICPPField.class, result ); } - - public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - if( host.getDefinition() == null ){ - host.checkForDefinition(); - if( host.getDefinition() == null ){ - IASTNode[] declarations= host.getDeclarations(); - IASTNode node = (declarations != null && declarations.length > 0) ? declarations[0] : null; - return new ICPPMethod [] { new CPPMethod.CPPMethodProblem( node, IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, host.getNameCharArray() ) }; - } - } - - ICPPMethod[] methods = getDeclaredMethods(); - ICPPBase [] bases = getBases(); + + public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) throws DOMException { + ICPPMethod[] methods = ct.getDeclaredMethods(); + ICPPBase [] bases = ct.getBases(); for (ICPPBase base : bases) { IBinding b = base.getBaseClass(); if( b instanceof ICPPClassType ) @@ -181,8 +165,22 @@ class ClassTypeMixin { } return (ICPPMethod[]) ArrayUtil.trim( ICPPMethod.class, methods ); } - - public ICPPMethod[] getDeclaredMethods() throws DOMException { + + public static ICPPMethod[] getMethods(ICPPClassType ct) throws DOMException { + ObjectSet set = new ObjectSet(4); + set.addAll(ct.getDeclaredMethods()); + ICPPClassScope scope = (ICPPClassScope) ct.getCompositeScope(); + set.addAll(scope.getImplicitMethods()); + ICPPBase[] bases = ct.getBases(); + for (ICPPBase base : bases) { + IBinding b = base.getBaseClass(); + if (b instanceof ICPPClassType) + set.addAll(((ICPPClassType) b).getMethods()); + } + return set.keyArray(ICPPMethod.class); + } + + public static ICPPMethod[] getDeclaredMethods(ICPPInternalClassTypeMixinHost host) throws DOMException { if( host.getDefinition() == null ){ host.checkForDefinition(); if( host.getDefinition() == null ){ @@ -232,7 +230,7 @@ class ClassTypeMixin { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getConstructors() */ - public ICPPConstructor[] getConstructors() throws DOMException { + public static ICPPConstructor[] getConstructors(ICPPInternalClassTypeMixinHost host) throws DOMException { if( host.getDefinition() == null ){ host.checkForDefinition(); if( host.getDefinition() == null ){ @@ -267,7 +265,7 @@ class ClassTypeMixin { return ((CPPClassScope)scope).getConstructors( true ); } - public ICPPClassType[] getNestedClasses() { + public static ICPPClassType[] getNestedClasses(ICPPInternalClassTypeMixinHost host) { if( host.getDefinition() == null ){ host.checkForDefinition(); if( host.getDefinition() == null ){ @@ -300,18 +298,9 @@ class ClassTypeMixin { return (ICPPClassType[]) ArrayUtil.trim( ICPPClassType.class, result ); } - public IField[] getFields() throws DOMException { - if( host.getDefinition() == null ){ - host.checkForDefinition(); - if( host.getDefinition() == null ){ - IASTNode[] declarations= host.getDeclarations(); - IASTNode node = (declarations != null && declarations.length > 0) ? declarations[0] : null; - return new IField [] { new CPPField.CPPFieldProblem( node, IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, host.getNameCharArray() ) }; - } - } - - IField[] fields = getDeclaredFields(); - ICPPBase [] bases = getBases(); + public static IField[] getFields(ICPPClassType ct) throws DOMException { + IField[] fields = ct.getDeclaredFields(); + ICPPBase [] bases = ct.getBases(); for (ICPPBase base : bases) { IBinding b = base.getBaseClass(); if( b instanceof ICPPClassType ) @@ -320,17 +309,17 @@ class ClassTypeMixin { return (IField[]) ArrayUtil.trim( IField.class, fields ); } - public IField findField(String name) throws DOMException { - IBinding [] bindings = CPPSemantics.findBindings( host.getCompositeScope(), name, true ); + public static IField findField(ICPPClassType ct, String name) throws DOMException { + IBinding[] bindings = CPPSemantics.findBindings(ct.getCompositeScope(), name, true); IField field = null; for (IBinding binding : bindings) { - if( binding instanceof IField ){ - if( field == null ) + if (binding instanceof IField) { + if (field == null) { field = (IField) binding; - else { - IASTNode[] declarations= host.getDeclarations(); - IASTNode node = (declarations != null && declarations.length > 0) ? declarations[0] : null; - return new CPPField.CPPFieldProblem( node, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, name.toCharArray() ); + } else { + IASTNode[] decls= ASTInternal.getDeclarationsOfBinding(ct); + IASTNode node= (decls != null && decls.length > 0) ? decls[0] : null; + return new CPPField.CPPFieldProblem(node, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, name.toCharArray()); } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPClassSpecializationScope.java index 1a2535e182e..654c9dca3cd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPClassSpecializationScope.java @@ -11,10 +11,13 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; /** @@ -35,12 +38,32 @@ public interface ICPPClassSpecializationScope extends ICPPClassScope { ICPPClassSpecialization getClassType(); /** - * Computes constructors off specialized class. + * Computes the bases via the original class. + */ + ICPPBase[] getBases() throws DOMException; + + /** + * Computes the constructors via the original class. */ ICPPConstructor[] getConstructors() throws DOMException; /** - * Computes the declared methods off the specialized class. + * Computes the methods via the original class. */ ICPPMethod[] getDeclaredMethods() throws DOMException; + + /** + * Computes the fields via the original class. + */ + ICPPField[] getDeclaredFields() throws DOMException; + + /** + * Computes the friends via the original class. + */ + IBinding[] getFriends() throws DOMException; + + /** + * Computes the nested classes via the original class. + */ + ICPPClassType[] getNestedClasses() throws DOMException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalClassTypeMixinHost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalClassTypeMixinHost.java index 4c7cefcdd00..c4c7c4e8a7f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalClassTypeMixinHost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalClassTypeMixinHost.java @@ -6,7 +6,7 @@ * 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.dom.parser.cpp; @@ -14,7 +14,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; /** - * Internal interface for exposing internal methods to ClassTypeMixin + * Internal interface for exposing internal methods to {@link ClassTypeHelper} */ interface ICPPInternalClassTypeMixinHost extends ICPPClassType, ICPPInternalBinding { /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index 78354d8b236..53676cf664f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -257,9 +257,11 @@ public interface IIndexFragment { /** * Caches an object with the key, the cache must be cleared at latest when the fragment no - * longer holds a locks. + * longer holds a locks. + * @param replace if false an existing entry will not be replaced. + * @return the value that is actually stored. */ - void putCachedResult(Object key, Object value); + Object putCachedResult(Object key, Object value, boolean replace); /** * Returns a previously cached object, the cache is cleared at latest when the fragment no diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/AbstractCompositeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/AbstractCompositeFactory.java index 1c15412ac5e..47f210fd271 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/AbstractCompositeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/AbstractCompositeFactory.java @@ -6,7 +6,8 @@ * 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; @@ -57,6 +58,16 @@ public abstract class AbstractCompositeFactory implements ICompositesFactory { public final IIndexBinding[] getCompositeBindings(IIndexFragmentBinding[][] fragmentBindings) { return getCompositeBindings(mergeBindingArrays(fragmentBindings)); } + + public final IIndexFragmentBinding[] findEquivalentBindings(IBinding binding) { + CIndex cindex= (CIndex) index; + try { + return cindex.findEquivalentBindings(binding); + } catch (CoreException e) { + CCorePlugin.log(e); + return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + } /** * Convenience method for taking a group of binding arrays, and returning a single array @@ -84,8 +95,7 @@ public abstract class AbstractCompositeFactory implements ICompositesFactory { */ protected IIndexFragmentBinding findOneBinding(IBinding binding, boolean allowDeclaration) { try{ - CIndex cindex= (CIndex) index; - IIndexFragmentBinding[] ibs= cindex.findEquivalentBindings(binding); + IIndexFragmentBinding[] ibs= findEquivalentBindings(binding); IBinding def= null; IBinding dec= ibs.length>0 ? ibs[0] : null; for(int i=0; i 0) { + for (ICPPClassType ct : nested) { + if (ct instanceof ICPPClassSpecialization && + !(ct.getCompositeScope() instanceof ICPPClassSpecializationScope)) { + ICPPClassSpecialization cspec= (ICPPClassSpecialization) cf.getCompositeBinding((IIndexFragmentBinding) ct); + newMap.put(cspec.getSpecializedBinding(), cspec); + } + } + if (!newMap.isEmpty()) + break; + } + } + } + } catch (DOMException e) { + CCorePlugin.log(e); + } + specializationMap= (ObjectMap) frag.putCachedResult(key, newMap, false); } } - IBinding result= (IBinding) specializationMap.get(original); - if (result == null) { - result= CPPTemplates.createSpecialization(this, original, getArgumentMap()); - specializationMap.put(original, result); + synchronized (specializationMap) { + IBinding result= (IBinding) specializationMap.get(original); + if (result != null) + return result; } - return result; + IBinding newSpec= CPPTemplates.createSpecialization(this, original, getArgumentMap()); + synchronized (specializationMap) { + IBinding oldSpec= (IBinding) specializationMap.put(original, newSpec); + if (oldSpec != null) { + specializationMap.put(original, oldSpec); + return oldSpec; + } + } + return newSpec; } @Override public ICPPBase[] getBases() throws DOMException { IScope scope= getCompositeScope(); if (scope instanceof ICPPClassSpecializationScope) { - // this is an implicit specialization - final ICPPBase[] pdomBases = (getSpecializedBinding()).getBases(); - if (pdomBases != null) { - ICPPBase[] result = null; - for (ICPPBase origBase : pdomBases) { - ICPPBase specBase = (ICPPBase) ((ICPPInternalBase)origBase).clone(); - IBinding origClass = origBase.getBaseClass(); - if (origClass instanceof IType) { - IType specClass = CPPTemplates.instantiateType((IType) origClass, getArgumentMap(), this); - specClass = SemanticUtil.getUltimateType(specClass, true); - if (specClass instanceof IBinding) { - ((ICPPInternalBase)specBase).setBaseClass((IBinding) specClass); - } - result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBase); - } - } - - return (ICPPBase[]) ArrayUtil.trim(ICPPBase.class, result); - } - return ICPPBase.EMPTY_BASE_ARRAY; + return ((ICPPClassSpecializationScope) scope).getBases(); } return super.getBases(); } @@ -110,4 +128,51 @@ public class CompositeCPPClassSpecialization extends CompositeCPPClassType imple } return super.getDeclaredMethods(); } + + @Override + public ICPPField[] getDeclaredFields() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getDeclaredFields(); + } + return super.getDeclaredFields(); + } + + @Override + public IBinding[] getFriends() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getFriends(); + } + return super.getFriends(); + } + + @Override + public ICPPClassType[] getNestedClasses() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getNestedClasses(); + } + return super.getNestedClasses(); + } + + @Override + public IField findField(String name) throws DOMException { + return ClassTypeHelper.findField(this, name); + } + + @Override + public ICPPMethod[] getAllDeclaredMethods() throws DOMException { + return ClassTypeHelper.getAllDeclaredMethods(this); + } + + @Override + public IField[] getFields() throws DOMException { + return ClassTypeHelper.getFields(this); + } + + @Override + public ICPPMethod[] getMethods() throws DOMException { + return ClassTypeHelper.getMethods(this); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassSpecializationScope.java index 617290ef3fd..4ea171ea512 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassSpecializationScope.java @@ -7,6 +7,7 @@ * * Contributors: * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; @@ -14,9 +15,11 @@ import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexFileSet; @@ -90,4 +93,24 @@ public class CompositeCPPClassSpecializationScope extends CompositeScope impleme createDelegate(); return fDelegate.getDeclaredMethods(); } + + public ICPPBase[] getBases() throws DOMException { + createDelegate(); + return fDelegate.getBases(); + } + + public ICPPField[] getDeclaredFields() throws DOMException { + createDelegate(); + return fDelegate.getDeclaredFields(); + } + + public IBinding[] getFriends() throws DOMException { + createDelegate(); + return fDelegate.getFriends(); + } + + public ICPPClassType[] getNestedClasses() throws DOMException { + createDelegate(); + return fDelegate.getNestedClasses(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java index 4a1707a81e1..c5101fda7f8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java @@ -22,7 +22,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBase; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; @@ -50,7 +49,7 @@ class CompositeCPPClassType extends CompositeCPPBinding implements ICPPClassType return result; } - private class CPPBaseDelegate implements ICPPBase, ICPPInternalBase { + private class CPPBaseDelegate implements ICPPBase { private ICPPBase base; private IBinding baseClass; private boolean writable; @@ -84,16 +83,16 @@ class CompositeCPPClassType extends CompositeCPPBinding implements ICPPClassType return base.isVirtual(); } - public void setBaseClass(IBinding binding) throws DOMException { + public void setBaseClass(IBinding binding) { if(writable) { baseClass= binding; } else { - ((ICPPInternalBase)base).setBaseClass(binding); + base.setBaseClass(binding); } } @Override - public Object clone(){ + public ICPPBase clone(){ return new CPPBaseDelegate(base, true); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeInstanceCache.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeInstanceCache.java index b1b3d879aa0..76b6927449b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeInstanceCache.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeInstanceCache.java @@ -10,15 +10,18 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; -import java.util.ArrayList; +import java.util.HashMap; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; +import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; +import org.eclipse.core.runtime.CoreException; public class CompositeInstanceCache { @@ -26,43 +29,38 @@ public class CompositeInstanceCache { final IIndexFragment frag= fb.getFragment(); final Object key = CPPCompositesFactory.createInstanceCacheKey(cf, fb); Object cache= frag.getCachedResult(key); - if (cache instanceof CompositeInstanceCache) { + if (cache != null) { return (CompositeInstanceCache) cache; } CompositeInstanceCache newCache= new CompositeInstanceCache(); newCache.populate(cf, fb); - - cache= frag.getCachedResult(key); - if (cache instanceof CompositeInstanceCache) { - return (CompositeInstanceCache) cache; - } - frag.putCachedResult(key, newCache); - return newCache; + return (CompositeInstanceCache) frag.putCachedResult(key, newCache, false); } - private final ArrayList fList; + private final HashMap fMap; public CompositeInstanceCache() { - fList= new ArrayList(); + fMap= new HashMap(); } synchronized public final void addInstance(IType[] arguments, ICPPTemplateInstance instance) { - fList.add(arguments); - fList.add(instance); + try { + String key= IndexCPPSignatureUtil.getTemplateArgString(arguments, true); + fMap.put(key, instance); + } catch (CoreException e) { + CCorePlugin.log(e); + } catch (DOMException e) { + } } synchronized public final ICPPTemplateInstance getInstance(IType[] arguments) { - loop: for (int i=0; i < fList.size(); i+=2) { - final IType[] args = (IType[]) fList.get(i); - if (args.length == arguments.length) { - for (int j=0; j < args.length; j++) { - if (!CPPTemplates.isSameTemplateArgument(args[j], arguments[j])) { - continue loop; - } - } - return (ICPPTemplateInstance) fList.get(i+1); - } + try { + String key= IndexCPPSignatureUtil.getTemplateArgString(arguments, true); + return fMap.get(key); + } catch (CoreException e) { + CCorePlugin.log(e); + } catch (DOMException e) { } return null; } @@ -73,18 +71,14 @@ public class CompositeInstanceCache { for (ICPPTemplateInstance ti : insts) { if (ti instanceof IIndexFragmentBinding) { ICPPTemplateInstance comp= (ICPPTemplateInstance) cf.getCompositeBinding((IIndexFragmentBinding) ti); - fList.add(comp.getArguments()); - fList.add(comp); + IType[] args= comp.getArguments(); + addInstance(args, comp); } } } } synchronized public ICPPTemplateInstance[] getAllInstances() { - ICPPTemplateInstance[] result= new ICPPTemplateInstance[fList.size()/2]; - for (int i=0; i < fList.size(); i+=2) { - result[i/2]= (ICPPTemplateInstance) fList.get(i+1); - } - return result; + return fMap.values().toArray(new ICPPTemplateInstance[fMap.size()]); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 4c688c2faec..c3e9511d08a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -960,8 +960,17 @@ public class PDOM extends PlatformObject implements IPDOM { } public void putCachedResult(Object key, Object result) { + putCachedResult(key, result, true); + } + + public Object putCachedResult(Object key, Object result, boolean replace) { synchronized(fResultCache) { - fResultCache.put(key, result); + Object old= fResultCache.put(key, result); + if (old != null && !replace) { + fResultCache.put(key, old); + return old; + } + return result; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java index d8459c6e1db..d80b82d95a8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java @@ -256,6 +256,7 @@ public class PDOMProxy implements IPDOM { return null; } - public void putCachedResult(Object key, Object value) { + public Object putCachedResult(Object key, Object value, boolean replace) { + return value; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java index 4e18ec7e860..08b2a50f94c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java @@ -134,7 +134,7 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase { } @Override - public Object clone() { + public ICPPBase clone() { return new PDOMCPPBaseClone(this); } @@ -164,7 +164,7 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase { baseClass = binding; } @Override - public Object clone() { + public ICPPBase clone() { return new PDOMCPPBaseClone(this); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java index 3554ea3f769..225a35cdb50 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java @@ -35,14 +35,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; -import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBase; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.pdom.PDOM; @@ -99,20 +96,39 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements if (specializationMap == null) { final Integer key= record+PDOMCPPLinkage.CACHE_INSTANCE_SCOPE; Object cached= pdom.getCachedResult(key); - if (cached instanceof ObjectMap) { + if (cached != null) { specializationMap= (ObjectMap) cached; } else { final ObjectMap newMap= new ObjectMap(2); - pdom.putCachedResult(key, newMap); - specializationMap= newMap; + try { + PDOMClassUtil.NestedClassCollector visitor = new PDOMClassUtil.NestedClassCollector(); + PDOMCPPClassScope.acceptViaCache(this, visitor, false); + final ICPPClassType[] nested= visitor.getNestedClasses(); + for (ICPPClassType classType : nested) { + if (classType instanceof ICPPSpecialization) { + newMap.put(((ICPPSpecialization) classType).getSpecializedBinding(), classType); + } + } + } catch (CoreException e) { + CCorePlugin.log(e); + } + specializationMap= (ObjectMap) pdom.putCachedResult(key, newMap, false); } } - IBinding result= (IBinding) specializationMap.get(original); - if (result == null) { - result= CPPTemplates.createSpecialization(this, original, getArgumentMap()); - specializationMap.put(original, result); + synchronized (specializationMap) { + IBinding result= (IBinding) specializationMap.get(original); + if (result != null) + return result; } - return result; + IBinding newSpec= CPPTemplates.createSpecialization(this, original, getArgumentMap()); + synchronized (specializationMap) { + IBinding oldSpec= (IBinding) specializationMap.put(original, newSpec); + if (oldSpec != null) { + specializationMap.put(original, oldSpec); + return oldSpec; + } + } + return newSpec; } public IScope getCompositeScope() throws DOMException { @@ -129,34 +145,7 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements return fScope; } - public ICPPConstructor[] getConstructors() throws DOMException { - IScope scope= getCompositeScope(); - if (scope instanceof ICPPClassSpecializationScope) { - return ((ICPPClassSpecializationScope) scope).getConstructors(); - } - try { - PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector(); - PDOMCPPClassScope.acceptViaCache(this, visitor, false); - return visitor.getConstructors(); - } catch (CoreException e) { - CCorePlugin.log(e); - return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; - } - } - public ICPPMethod[] getDeclaredMethods() throws DOMException { - IScope scope= getCompositeScope(); - if (scope instanceof ICPPClassSpecializationScope) { - return ((ICPPClassSpecializationScope) scope).getDeclaredMethods(); - } - try { - PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(false); - PDOMCPPClassScope.acceptViaCache(this, methods, false); - return methods.getMethods(); - } catch (CoreException e) { - return new ICPPMethod[0]; - } - } public PDOMCPPBase getFirstBase() throws CoreException { int rec = pdom.getDB().getInt(record + FIRSTBASE); @@ -197,72 +186,112 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements } } - public IField findField(String name) throws DOMException { fail(); return null; } - public ICPPMethod[] getAllDeclaredMethods() throws DOMException { fail(); return null; } - + // implementation of class type public ICPPBase[] getBases() throws DOMException { IScope scope= getCompositeScope(); if (scope instanceof ICPPClassSpecializationScope) { - // this is an implicit specialization - final ICPPBase[] pdomBases = (getSpecializedBinding()).getBases(); - if (pdomBases != null) { - ICPPBase[] result = null; - for (ICPPBase origBase : pdomBases) { - ICPPBase specBase = (ICPPBase) ((ICPPInternalBase)origBase).clone(); - IBinding origClass = origBase.getBaseClass(); - if (origClass instanceof IType) { - IType specClass = CPPTemplates.instantiateType((IType) origClass, getArgumentMap(), this); - specClass = SemanticUtil.getUltimateType(specClass, true); - if (specClass instanceof IBinding) { - ((ICPPInternalBase)specBase).setBaseClass((IBinding) specClass); - } - result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBase); - } - } - - return (ICPPBase[]) ArrayUtil.trim(ICPPBase.class, result); - } - } else { - // this is an explicit specialization - Integer key= record + PDOMCPPLinkage.CACHE_BASES; - ICPPBase[] bases= (ICPPBase[]) pdom.getCachedResult(key); - if (bases != null) - return bases; - - try { - List list = new ArrayList(); - for (PDOMCPPBase base = getFirstBase(); base != null; base = base.getNextBase()) - list.add(base); - Collections.reverse(list); - bases = list.toArray(new ICPPBase[list.size()]); - pdom.putCachedResult(key, bases); - return bases; - } catch (CoreException e) { - CCorePlugin.log(e); - } - } + return ((ICPPClassSpecializationScope) scope).getBases(); + } + // this is an explicit specialization + Integer key= record + PDOMCPPLinkage.CACHE_BASES; + ICPPBase[] bases= (ICPPBase[]) pdom.getCachedResult(key); + if (bases != null) + return bases; + + try { + List list = new ArrayList(); + for (PDOMCPPBase base = getFirstBase(); base != null; base = base.getNextBase()) + list.add(base); + Collections.reverse(list); + bases = list.toArray(new ICPPBase[list.size()]); + pdom.putCachedResult(key, bases); + return bases; + } catch (CoreException e) { + CCorePlugin.log(e); + } return ICPPBase.EMPTY_BASE_ARRAY; } + public ICPPConstructor[] getConstructors() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getConstructors(); + } + try { + PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector(); + PDOMCPPClassScope.acceptViaCache(this, visitor, false); + return visitor.getConstructors(); + } catch (CoreException e) { + CCorePlugin.log(e); + return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; + } + } + + public ICPPMethod[] getDeclaredMethods() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getDeclaredMethods(); + } + try { + PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(false); + PDOMCPPClassScope.acceptViaCache(this, methods, false); + return methods.getMethods(); + } catch (CoreException e) { + CCorePlugin.log(e); + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; + } + } + public ICPPField[] getDeclaredFields() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getDeclaredFields(); + } try { PDOMClassUtil.FieldCollector visitor = new PDOMClassUtil.FieldCollector(); - accept(visitor); + PDOMCPPClassScope.acceptViaCache(this, visitor, false); return visitor.getFields(); } catch (CoreException e) { CCorePlugin.log(e); - return new ICPPField[0]; + return ICPPField.EMPTY_CPPFIELD_ARRAY; } } - //ICPPClassType unimplemented - public IField[] getFields() throws DOMException { fail(); return null; } - public IBinding[] getFriends() throws DOMException { fail(); return null; } - public ICPPClassType[] getNestedClasses() throws DOMException { fail(); return null; } + public ICPPClassType[] getNestedClasses() throws DOMException { + IScope scope= getCompositeScope(); + if (scope instanceof ICPPClassSpecializationScope) { + return ((ICPPClassSpecializationScope) scope).getNestedClasses(); + } + try { + PDOMClassUtil.NestedClassCollector visitor = new PDOMClassUtil.NestedClassCollector(); + PDOMCPPClassScope.acceptViaCache(this, visitor, false); + return visitor.getNestedClasses(); + } catch (CoreException e) { + CCorePlugin.log(e); + return ICPPClassType.EMPTY_CLASS_ARRAY; + } + } + + public IBinding[] getFriends() throws DOMException { + // not yet supported. + return IBinding.EMPTY_BINDING_ARRAY; + } public ICPPMethod[] getMethods() throws DOMException { - return CPPClassType.getMethods(this); + return ClassTypeHelper.getMethods(this); + } + + public ICPPMethod[] getAllDeclaredMethods() throws DOMException { + return ClassTypeHelper.getAllDeclaredMethods(this); + } + + public IField[] getFields() throws DOMException { + return ClassTypeHelper.getFields(this); + } + + public IField findField(String name) throws DOMException { + return ClassTypeHelper.findField(this, name); } public int getKey() throws DOMException { @@ -316,7 +345,13 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements } @Override - public Object clone() {fail();return null;} + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } @Override public void addChild(PDOMNode member) throws CoreException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java index f5cb62cd49b..4a873d3fec9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java @@ -16,12 +16,9 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.dom.IPDOMNode; import org.eclipse.cdt.core.dom.IPDOMVisitor; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; @@ -38,7 +35,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList; @@ -80,6 +77,17 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO super(pdom, bindingRecord); } + @Override + protected int getRecordSize() { + return RECORD_SIZE; + } + + @Override + public int getNodeType() { + return IIndexCPPBindingConstants.CPPCLASSTYPE; + } + + @Override public void update(PDOMLinkage linkage, IBinding newBinding) throws CoreException { if (newBinding instanceof ICPPClassType) { @@ -106,23 +114,33 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO } } + @Override + public boolean mayHaveChildren() { + return true; + } + @Override public void addChild(PDOMNode member) throws CoreException { pdom.removeCachedResult(record+PDOMCPPLinkage.CACHE_MEMBERS); PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + MEMBERLIST, getLinkageImpl()); list.addMember(member); } - + @Override - protected int getRecordSize() { - return RECORD_SIZE; + public void accept(IPDOMVisitor visitor) throws CoreException { + PDOMCPPClassScope.acceptViaCache(this, visitor, false); } - @Override - public int getNodeType() { - return IIndexCPPBindingConstants.CPPCLASSTYPE; + /** + * Called to populate the cache for the bindings in the class scope. + */ + public void acceptUncached(IPDOMVisitor visitor) throws CoreException { + super.accept(visitor); + PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + MEMBERLIST, getLinkageImpl()); + list.accept(visitor); } + private PDOMCPPBase getFirstBase() throws CoreException { int rec = pdom.getDB().getInt(record + FIRSTBASE); return rec != 0 ? new PDOMCPPBase(pdom, rec) : null; @@ -165,6 +183,40 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO } } + public IScope getCompositeScope() throws DOMException { + if (fScope == null) { + fScope= new PDOMCPPClassScope(this); + } + return fScope; + } + + public int getKey() throws DOMException { + try { + return pdom.getDB().getByte(record + KEY); + } catch (CoreException e) { + CCorePlugin.log(e); + return ICPPClassType.k_class; // or something + } + } + + public boolean isAnonymous() throws DOMException { + try { + return pdom.getDB().getByte(record + ANONYMOUS) != 0; + } catch (CoreException e) { + CCorePlugin.log(e); + return false; + } + } + + @Override + public boolean isGloballyQualified() throws DOMException { + try { + return getParentNode() instanceof PDOMLinkage; + } catch (CoreException e) { + return true; + } + } + public boolean isSameType(IType type) { if (type instanceof ITypedef) { return type.isSameType(this); @@ -212,65 +264,25 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO } } + public ICPPConstructor[] getConstructors() throws DOMException { + PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector(); + try { + PDOMCPPClassScope.acceptViaCache(this, visitor, false); + return visitor.getConstructors(); + } catch (CoreException e) { + CCorePlugin.log(e); + return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; + } + } + public ICPPMethod[] getDeclaredMethods() throws DOMException { try { PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(false); PDOMCPPClassScope.acceptViaCache(this, methods, false); return methods.getMethods(); - } catch (CoreException e) { - return new ICPPMethod[0]; - } - } - - public ICPPMethod[] getMethods() throws DOMException { - return CPPClassType.getMethods(this); - } - - static void acceptInHierarchy(IPDOMMemberOwner current, Set visited, IPDOMVisitor visitor) throws CoreException { - if (visited.contains(current)) - return; - visited.add(current); - - // Class is in its own scope - visitor.visit((IPDOMNode) current); - - // Get my members - current.accept(visitor); - - // Visit my base classes - if(current instanceof ICPPClassType) { - try { - ICPPBase[] bases= ((ICPPClassType) current).getBases(); - for(ICPPBase base : bases) { - IBinding baseClass = base.getBaseClass(); - if (baseClass != null && baseClass instanceof IPDOMMemberOwner) - acceptInHierarchy((IPDOMMemberOwner)baseClass, visited, visitor); - } - } catch(DOMException de) { - CCorePlugin.log(Util.createStatus(de)); - } - } - } - - public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - PDOMClassUtil.MethodCollector myMethods = new PDOMClassUtil.MethodCollector(false, true); - try { - acceptInHierarchy(this, new HashSet(), myMethods); - return myMethods.getMethods(); } catch (CoreException e) { CCorePlugin.log(e); - return new ICPPMethod[0]; - } - } - - public IField[] getFields() throws DOMException { - try { - PDOMClassUtil.FieldCollector visitor = new PDOMClassUtil.FieldCollector(); - acceptInHierarchy(this, new HashSet(), visitor); - return visitor.getFields(); - } catch (CoreException e) { - CCorePlugin.log(e); - return new IField[0]; + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; } } @@ -281,102 +293,49 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO return visitor.getFields(); } catch (CoreException e) { CCorePlugin.log(e); - return new ICPPField[0]; - } - } - - private static class NestedClassCollector implements IPDOMVisitor { - private List nestedClasses = new ArrayList(); - public boolean visit(IPDOMNode node) throws CoreException { - if (node instanceof ICPPClassType) - nestedClasses.add(node); - return false; - } - public void leave(IPDOMNode node) throws CoreException { - } - public ICPPClassType[] getNestedClasses() { - return nestedClasses.toArray(new ICPPClassType[nestedClasses.size()]); + return ICPPField.EMPTY_CPPFIELD_ARRAY; } } public ICPPClassType[] getNestedClasses() throws DOMException { try { - NestedClassCollector visitor = new NestedClassCollector(); + PDOMClassUtil.NestedClassCollector visitor = new PDOMClassUtil.NestedClassCollector(); PDOMCPPClassScope.acceptViaCache(this, visitor, false); return visitor.getNestedClasses(); } catch (CoreException e) { CCorePlugin.log(e); - return new ICPPClassType[0]; + return ICPPClassType.EMPTY_CLASS_ARRAY; } } + public IBinding[] getFriends() throws DOMException { + // not yet supported. + return IBinding.EMPTY_BINDING_ARRAY; + } + + public ICPPMethod[] getMethods() throws DOMException { + return ClassTypeHelper.getMethods(this); + } + + public ICPPMethod[] getAllDeclaredMethods() throws DOMException { + return ClassTypeHelper.getAllDeclaredMethods(this); + } + + public IField[] getFields() throws DOMException { + return ClassTypeHelper.getFields(this); + } + + public IField findField(String name) throws DOMException { + return ClassTypeHelper.findField(this, name); + } + @Override - public void accept(IPDOMVisitor visitor) throws CoreException { - PDOMCPPClassScope.acceptViaCache(this, visitor, false); - } - - /** - * Called to populate the cache for the bindings in the class scope. - */ - public void acceptUncached(IPDOMVisitor visitor) throws CoreException { - super.accept(visitor); - PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + MEMBERLIST, getLinkageImpl()); - list.accept(visitor); - } - - - public IScope getCompositeScope() throws DOMException { - if (fScope == null) { - fScope= new PDOMCPPClassScope(this); - } - return fScope; - } - - public int getKey() throws DOMException { + public Object clone() { try { - return pdom.getDB().getByte(record + KEY); - } catch (CoreException e) { - CCorePlugin.log(e); - return ICPPClassType.k_class; // or something + return super.clone(); + } catch (CloneNotSupportedException e) { } - } - - public boolean isAnonymous() throws DOMException { - try { - return pdom.getDB().getByte(record + ANONYMOUS) != 0; - } catch (CoreException e) { - CCorePlugin.log(e); - return false; - } - } - - @Override - public boolean isGloballyQualified() throws DOMException { - try { - return getParentNode() instanceof PDOMLinkage; - } catch (CoreException e) { - return true; - } - } - - public ICPPConstructor[] getConstructors() throws DOMException { - PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector(); - try { - PDOMCPPClassScope.acceptViaCache(this, visitor, false); - } catch (CoreException e) { - CCorePlugin.log(e); - } - return visitor.getConstructors(); - } - - @Override - public Object clone() {fail();return null;} - public IField findField(String name) throws DOMException {fail();return null;} - public IBinding[] getFriends() throws DOMException {fail();return null;} - - @Override - public boolean mayHaveChildren() { - return true; + return null; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMClassUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMClassUtil.java index 6b1e5b64537..def69d443be 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMClassUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMClassUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 QNX Software Systems and others. + * Copyright (c) 2007, 2008 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 @@ -16,6 +16,7 @@ import java.util.List; import org.eclipse.cdt.core.dom.IPDOMNode; import org.eclipse.cdt.core.dom.IPDOMVisitor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; @@ -92,4 +93,18 @@ class PDOMClassUtil { return methods.toArray(new ICPPMethod[methods.size()]); } } + + static class NestedClassCollector implements IPDOMVisitor { + private List nestedClasses = new ArrayList(); + public boolean visit(IPDOMNode node) throws CoreException { + if (node instanceof ICPPClassType) + nestedClasses.add(node); + return false; + } + public void leave(IPDOMNode node) throws CoreException { + } + public ICPPClassType[] getNestedClasses() { + return nestedClasses.toArray(new ICPPClassType[nestedClasses.size()]); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMInstanceCache.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMInstanceCache.java index b9fb1b23154..992843e6f99 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMInstanceCache.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMInstanceCache.java @@ -42,11 +42,7 @@ public class PDOMInstanceCache { CCorePlugin.log(e); } - cache= pdom.getCachedResult(key); - if (cache instanceof PDOMInstanceCache) { - return (PDOMInstanceCache) cache; - } - pdom.putCachedResult(key, newCache); + newCache= (PDOMInstanceCache) pdom.putCachedResult(key, newCache, false); return newCache; }