From 4321e9a476c3393e118b3bf826af324a92ebad1e Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Wed, 19 Jul 2006 03:44:26 +0000 Subject: [PATCH] Add base classes to PDOM. --- .../cdt/internal/pdom/tests/ClassTests.java | 51 ++++++++++ .../resources/pdomtests/classTests/class.cpp | 13 +++ .../cdt/core/parser/util/ArrayUtil.java | 9 ++ .../eclipse/cdt/internal/core/pdom/PDOM.java | 3 +- .../core/pdom/dom/cpp/PDOMCPPBase.java | 99 +++++++++++++++++++ .../core/pdom/dom/cpp/PDOMCPPClassType.java | 71 +++++++++++-- .../core/pdom/dom/cpp/PDOMCPPLinkage.java | 21 +++- 7 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java create mode 100644 core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java new file mode 100644 index 00000000000..7d1074d383b --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2006 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.pdom.tests; + +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.internal.core.pdom.PDOM; + +/** + * @author Doug Schaefer + * + */ +public class ClassTests extends PDOMTestBase { + + protected ICProject project; + + protected void setUp() throws Exception { + project = createProject("classTests"); + } + + public void test1() throws Exception { + PDOM pdom = (PDOM)CCorePlugin.getPDOMManager().getPDOM(project); + + IBinding[] Bs = pdom.findBindings(Pattern.compile("B")); + assertEquals(1, Bs.length); + ICPPClassType B = (ICPPClassType)Bs[0]; + ICPPMethod[] Bmethods = B.getAllDeclaredMethods(); + assertEquals(1, Bmethods.length); + ICPPMethod Bf = Bmethods[0]; + assertEquals("f", Bf.getName()); + IASTName [] Bf_refs = pdom.getReferences(Bf); + assertEquals(1, Bf_refs.length); + IASTFileLocation loc = Bf_refs[0].getFileLocation(); + assertEquals(offset(95, 84), loc.getNodeOffset()); + } +} diff --git a/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp b/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp new file mode 100644 index 00000000000..1b0968ee2d8 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp @@ -0,0 +1,13 @@ +class A { +public: + void f() { + } +}; + +class B : public A { +}; + +int main() { + B b; + b.f(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index 0e01ad02938..d52ee277f19 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -283,4 +283,13 @@ public class ArrayUtil { return array; } + public static void reverse(Object [] array) { + for (int left = 0, right = array.length - 1; + left < right; ++left, --right) { + Object tmp = array[left]; + array[left] = array[right]; + array[right] = tmp; + } + } + } 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 2c7c19ca292..1192759b7c0 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 @@ -54,7 +54,7 @@ public class PDOM extends PlatformObject private Database db; - public static final int VERSION = 8; + public static final int VERSION = 9; // 0 - the beginning of it all // 1 - first change to kick off upgrades // 2 - added file inclusions @@ -64,6 +64,7 @@ public class PDOM extends PlatformObject // 6 - function style macros. // 7 - class key // 8 - enumerators + // 9 - base classes public static final int LINKAGES = Database.DATA_AREA; public static final int FILE_INDEX = Database.DATA_AREA + 4; 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 new file mode 100644 index 00000000000..a8a032452fe --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2006 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom.dom.cpp; + +import org.eclipse.cdt.core.CCorePlugin; +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.internal.core.pdom.PDOM; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.core.runtime.CoreException; + +/** + * @author Doug Schaefer + */ +public class PDOMCPPBase implements ICPPBase { + + private static final int BASECLASS = 0; + private static final int NEXTBASE = 4; + private static final int FLAGS = 8; + + protected static final int RECORD_SIZE = 9; + + protected final PDOM pdom; + protected final int record; + + public PDOMCPPBase(PDOM pdom, int record) { + this.pdom = pdom; + this.record = record; + } + + public PDOMCPPBase(PDOM pdom, PDOMCPPClassType baseClass, boolean isVirtual, int visibility) throws CoreException { + this.pdom = pdom; + Database db = pdom.getDB(); + this.record = db.malloc(RECORD_SIZE); + + int baserec = baseClass != null ? baseClass.getRecord() : 0; + db.putInt(record + BASECLASS, baserec); + + byte flags = (byte)(visibility | (isVirtual ? 4 : 0)); + db.putByte(record + FLAGS, flags); + } + + public int getRecord() { + return record; + } + + public void setNextBase(PDOMCPPBase nextBase) throws CoreException { + int rec = nextBase != null ? nextBase.getRecord() : 0; + pdom.getDB().putInt(record + NEXTBASE, rec); + } + + public PDOMCPPBase getNextBase() throws CoreException { + int rec = pdom.getDB().getInt(record + NEXTBASE); + return rec != 0 ? new PDOMCPPBase(pdom, rec) : null; + } + + private int getFlags() throws CoreException { + return pdom.getDB().getByte(record + FLAGS); + } + + public IBinding getBaseClass() throws DOMException { + try { + int rec = pdom.getDB().getInt(record + BASECLASS); + return rec != 0 ? new PDOMCPPClassType(pdom, rec) : null; + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } + + public int getVisibility() throws DOMException { + try { + return getFlags() & 0x3; + } catch (CoreException e) { + CCorePlugin.log(e); + return 0; + } + + } + + public boolean isVirtual() throws DOMException { + try { + return (getFlags() & 0x4) != 0; + } catch (CoreException e) { + CCorePlugin.log(e); + return false; + } + } + +} 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 2370a05491c..9b31027786b 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 @@ -11,6 +11,11 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; @@ -25,6 +30,7 @@ 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.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMMember; @@ -40,9 +46,10 @@ import org.eclipse.core.runtime.CoreException; public class PDOMCPPClassType extends PDOMMemberOwner implements ICPPClassType, ICPPClassScope { - private static final int KEY = PDOMMemberOwner.RECORD_SIZE + 0; // byte + private static final int FIRSTBASE = PDOMMemberOwner.RECORD_SIZE + 0; + private static final int KEY = PDOMMemberOwner.RECORD_SIZE + 4; // byte - protected static final int RECORD_SIZE = PDOMMemberOwner.RECORD_SIZE + 1; + protected static final int RECORD_SIZE = PDOMMemberOwner.RECORD_SIZE + 5; public PDOMCPPClassType(PDOM pdom, PDOMNode parent, IASTName name) throws CoreException { @@ -67,6 +74,22 @@ public class PDOMCPPClassType extends PDOMMemberOwner implements ICPPClassType, return PDOMCPPLinkage.CPPCLASSTYPE; } + public PDOMCPPBase getFirstBase() throws CoreException { + int rec = pdom.getDB().getInt(record + FIRSTBASE); + return rec != 0 ? new PDOMCPPBase(pdom, rec) : null; + } + + private void setFirstBase(PDOMCPPBase base) throws CoreException { + int rec = base != null ? base.getRecord() : 0; + pdom.getDB().putInt(record + FIRSTBASE, rec); + } + + public void addBase(PDOMCPPBase base) throws CoreException { + PDOMCPPBase firstBase = getFirstBase(); + base.setNextBase(firstBase); + setFirstBase(base); + } + public boolean isSameType(IType type) { if (type instanceof PDOMBinding) return record == ((PDOMBinding)type).getRecord(); @@ -82,14 +105,50 @@ public class PDOMCPPClassType extends PDOMMemberOwner implements ICPPClassType, public IField findField(String name) throws DOMException { throw new PDOMNotImplementedError(); } - + + private void visitAllDeclaredMethods(Set visited, List methods) throws CoreException { + if (visited.contains(this)) + return; + visited.add(this); + + // Get my members + for (PDOMMember member = getFirstMember(); member != null; member = member.getNextMember()) { + if (member instanceof ICPPMethod) + methods.add(member); + } + + // Visit my base classes + for (PDOMCPPBase base = getFirstBase(); base != null; base = base.getNextBase()) { + IBinding baseClass = base.getBaseClass(); + if (baseClass != null && baseClass instanceof PDOMCPPClassType) + ((PDOMCPPClassType)baseClass).visitAllDeclaredMethods(visited, methods); + } + } + public ICPPMethod[] getAllDeclaredMethods() throws DOMException { - throw new PDOMNotImplementedError(); + List methods = new ArrayList(); + Set visited = new HashSet(); + try { + visitAllDeclaredMethods(visited, methods); + return (ICPPMethod[])methods.toArray(new ICPPMethod[methods.size()]); + } catch (CoreException e) { + CCorePlugin.log(e); + return new ICPPMethod[0]; + } } public ICPPBase[] getBases() throws DOMException { - // TODO - return new ICPPBase[0]; + try { + List list = new ArrayList(); + for (PDOMCPPBase base = getFirstBase(); base != null; base = base.getNextBase()) + list.add(base); + ICPPBase[] bases = (ICPPBase[])list.toArray(new ICPPBase[list.size()]); + ArrayUtil.reverse(bases); + return bases; + } catch (CoreException e) { + CCorePlugin.log(e); + return new ICPPBase[0]; + } } public ICPPConstructor[] getConstructors() throws DOMException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index b76c22d6cab..0234e1438d7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IParameter; 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.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; @@ -36,6 +37,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBlockScope; @@ -160,9 +162,24 @@ public class PDOMCPPLinkage extends PDOMLinkage { } } - // Add in the name - if (pdomBinding != null) + // final processing + if (pdomBinding != null) { + // Add in the name new PDOMName(pdom, name, file, pdomBinding); + + // Check if is a base specifier + if (pdomBinding instanceof ICPPClassType && name.getParent() instanceof ICPPASTBaseSpecifier) { + ICPPASTBaseSpecifier baseNode = (ICPPASTBaseSpecifier)name.getParent(); + ICPPASTCompositeTypeSpecifier ownerNode = (ICPPASTCompositeTypeSpecifier)baseNode.getParent(); + IBinding ownerBinding = adaptBinding(ownerNode.getName().resolveBinding()); + if (ownerBinding != null && ownerBinding instanceof PDOMCPPClassType) { + PDOMCPPClassType ownerClass = (PDOMCPPClassType)ownerBinding; + PDOMCPPBase pdomBase = new PDOMCPPBase(pdom, (PDOMCPPClassType)pdomBinding, + baseNode.isVirtual(), baseNode.getVisibility()); + ownerClass.addBase(pdomBase); + } + } + } return pdomBinding; }