From 41d26bc51413199b08e787a9cb5d2223a810603e Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Fri, 25 Nov 2005 22:01:48 +0000 Subject: [PATCH] Moved the PDOM into the Core. Started introduction of ILanguage, the mechanism of language extensibility for the CDT. --- .../cdt/internal/pdom/tests/DBTest.java | 145 ++++++++ .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 4 + .../org/eclipse/cdt/core/model/ICProject.java | 3 + .../cdt/core/model/ITranslationUnit.java | 10 +- .../cdt/internal/core/model/CProject.java | 6 + .../internal/core/model/TranslationUnit.java | 71 ++-- .../cdt/core/dom/ICodeReaderFactory.java | 3 + .../org/eclipse/cdt/core/dom/IIndex.java | 35 ++ .../eclipse/cdt/core/dom/IIndexReader.java | 20 ++ .../eclipse/cdt/core/dom/IIndexWriter.java | 20 ++ .../org/eclipse/cdt/core/dom/ILanguage.java | 50 +++ .../cdt/core/dom/ast/IASTTranslationUnit.java | 12 +- .../cdt/core/dom/ast/gnu/c/GCCLanguage.java | 90 +++++ .../cdt/core/dom/ast/gnu/cpp/GPPLanguage.java | 89 +++++ .../dom/parser/c/CASTTranslationUnit.java | 4 +- .../internal/core/dom/parser/c/CVisitor.java | 4 +- .../dom/parser/cpp/CPPASTTranslationUnit.java | 4 +- .../core/dom/parser/cpp/CPPSemantics.java | 4 +- .../scanner2/FileCodeReaderFactory.java | 5 + .../core/pdom/PDOMCodeReaderFactory.java | 85 +++++ .../cdt/internal/core/pdom/PDOMDatabase.java | 238 +++++++++++++ .../cdt/internal/core/pdom/PDOMManager.java | 101 ++++++ .../cdt/internal/core/pdom/PDOMUpdator.java | 239 +++++++++++++ .../cdt/internal/core/pdom/PDOMUtils.java | 74 ++++ .../cdt/internal/core/pdom/db/BTree.java | 326 ++++++++++++++++++ .../cdt/internal/core/pdom/db/Chunk.java | 109 ++++++ .../cdt/internal/core/pdom/db/Database.java | 240 +++++++++++++ .../core/pdom/db/IBTreeComparator.java | 31 ++ .../internal/core/pdom/db/IBTreeVisitor.java | 45 +++ .../core/pdom/db/StringComparator.java | 58 ++++ .../internal/core/pdom/db/StringVisitor.java | 59 ++++ .../cdt/internal/pdom/dom/PDOMBinding.java | 191 ++++++++++ .../cdt/internal/pdom/dom/PDOMFile.java | 123 +++++++ .../cdt/internal/pdom/dom/PDOMName.java | 243 +++++++++++++ .../pdom/dom/PDOMNotImplementedError.java | 21 ++ .../pdom/dom/PDOMTranslationUnit.java | 164 +++++++++ .../eclipse/cdt/pdom/core/PDOMCorePlugin.java | 50 +++ core/org.eclipse.cdt.core/plugin.properties | 4 +- core/org.eclipse.cdt.core/plugin.xml | 16 + .../org.eclipse.cdt.core/schema/language.exsd | 134 +++++++ .../src/org/eclipse/cdt/core/CCorePlugin.java | 1 + .../src/org/eclipse/cdt/core/dom/PDOM.java | 45 ++- .../core/CCorePluginResources.properties | 2 + .../core/dom/InternalASTServiceProvider.java | 4 +- .../PartialWorkingCopyCodeReaderFactory.java | 5 + .../core/dom/SavedCodeReaderFactory.java | 5 + .../internal/ui/CPluginResources.properties | 1 + .../eclipse/cdt/ui/dialogs/IndexerBlock.java | 49 ++- 48 files changed, 3198 insertions(+), 44 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndex.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexReader.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexWriter.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ILanguage.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/c/GCCLanguage.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMCodeReaderFactory.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMDatabase.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUpdator.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUtils.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeComparator.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeVisitor.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringComparator.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringVisitor.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMBinding.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMFile.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMName.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMNotImplementedError.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMTranslationUnit.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/pdom/core/PDOMCorePlugin.java create mode 100644 core/org.eclipse.cdt.core/schema/language.exsd diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java new file mode 100644 index 00000000000..be8467ee061 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java @@ -0,0 +1,145 @@ +package org.eclipse.cdt.internal.pdom.tests; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.db.StringComparator; +import org.eclipse.cdt.internal.core.pdom.db.StringVisitor; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.runtime.IPath; + +public class DBTest extends TestCase { + + protected IPath getTestDir() { + IPath path = PDOMCorePlugin.getDefault().getStateLocation().append("tests/"); + File file = path.toFile(); + if (!file.exists()) + file.mkdir(); + return path; + } + + public void test1() throws Exception { + // Tests block size and simple first block + File f = getTestDir().append("test1.dat").toFile(); + f.delete(); + Database db = new Database(f.getCanonicalPath(), 0); + + final int realsize = 42; + final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE; + + int mem = db.malloc(realsize); + assertEquals(-blocksize, db.getInt(mem - Database.INT_SIZE)); + db.free(mem); + assertEquals(blocksize, db.getInt(mem - Database.INT_SIZE)); + assertEquals(mem - Database.INT_SIZE, db.getInt((blocksize / Database.MIN_SIZE) * Database.INT_SIZE)); + assertEquals(mem - Database.INT_SIZE + blocksize, db.getInt(((Database.CHUNK_SIZE - blocksize) / Database.MIN_SIZE) * Database.INT_SIZE)); + } + + public void test2() throws Exception { + // Tests free block linking + File f = getTestDir().append("test2.dat").toFile(); + f.delete(); + Database db = new Database(f.getCanonicalPath(), 0); + + final int realsize = 42; + final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE; + + int mem1 = db.malloc(realsize); + int mem2 = db.malloc(realsize); + db.free(mem1); + db.free(mem2); + assertEquals(mem2 - Database.INT_SIZE, db.getInt((blocksize / Database.MIN_SIZE) * Database.INT_SIZE)); + assertEquals(0, db.getInt(mem2)); + assertEquals(mem1 - Database.INT_SIZE, db.getInt(mem2 + Database.INT_SIZE)); + assertEquals(mem2 - Database.INT_SIZE, db.getInt(mem1)); + assertEquals(0, db.getInt(mem1 + Database.INT_SIZE)); + } + + public void test3() throws Exception { + // + File f = getTestDir().append("test2.dat").toFile(); + f.delete(); + Database db = new Database(f.getCanonicalPath(), 0); + + int mem1 = db.malloc(42); + db.free(mem1); + int mem2 = db.malloc(42); + assertEquals(mem2, mem1); + } + + private static class FindVisitor extends StringVisitor { + + private int record; + + public FindVisitor(Database db, String key) { + super(db, Database.INT_SIZE, key); + } + + public boolean visit(int record) throws IOException { + this.record = record; + return false; + } + + public int findIn(BTree btree) throws IOException { + btree.visit(this); + return record; + } + + } + + public void testStrings() throws Exception { + // Tests inserting and retrieving strings + File f = getTestDir().append("testStrings.dat").toFile(); + f.delete(); + Database db = new Database(f.getCanonicalPath(), 0); + + String[] names = { + "ARLENE", + "BRET", + "CINDY", + "DENNIS", + "EMILY", + "FRANKLIN", + "GERT", + "HARVEY", + "IRENE", + "JOSE", + "KATRINA", + "LEE", + "MARIA", + "NATE", + "OPHELIA", + "PHILIPPE", + "RITA", + "STAN", + "TAMMY", + "VINCE", + "WILMA", + "ALPHA", + "BETA" + }; + + BTree btree = new BTree(db, Database.DATA_AREA); + for (int i = 0; i < names.length; ++i) { + String name = names[i]; + int record = db.malloc((name.length() + 1) * Database.CHAR_SIZE + Database.INT_SIZE); + db.putInt(record, i); + db.putString(record + Database.INT_SIZE, name); + btree.insert(record, new StringComparator(db, Database.INT_SIZE)); + } + + for (int i = 0; i < names.length; ++i) { + String name = names[i]; + int record = new FindVisitor(db, name).findIn(btree); + assertTrue(record != 0); + assertEquals(i, db.getInt(record)); + String rname = db.getString(record + Database.INT_SIZE); + assertEquals(name, rname); + } + } + +} diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index c06c432525f..b4290abd383 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -55,6 +55,8 @@ Export-Package: ., org.eclipse.cdt.internal.core.parser.scanner2, org.eclipse.cdt.internal.core.parser.token, org.eclipse.cdt.internal.core.parser.util, + org.eclipse.cdt.internal.core.pdom, + org.eclipse.cdt.internal.core.pdom.db;x-friends:="org.eclipse.cdt.pdom.ui", org.eclipse.cdt.internal.core.search, org.eclipse.cdt.internal.core.search.indexing, org.eclipse.cdt.internal.core.search.matching, @@ -63,6 +65,8 @@ Export-Package: ., org.eclipse.cdt.internal.core.util, org.eclipse.cdt.internal.errorparsers, org.eclipse.cdt.internal.formatter, + org.eclipse.cdt.internal.pdom.dom, + org.eclipse.cdt.pdom.core, org.eclipse.cdt.utils, org.eclipse.cdt.utils.coff, org.eclipse.cdt.utils.coff.parser, diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java index 6672b929710..b56477a92a4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java @@ -13,6 +13,8 @@ package org.eclipse.cdt.core.model; import java.util.Map; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.IPDOM; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; @@ -249,4 +251,5 @@ public interface ICProject extends IParent, IOpenable, ICElement { */ Object[] getNonCResources() throws CModelException; + IPDOM getIndex(); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java index 1b4b4e1f703..b32c8f97efd 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java @@ -12,8 +12,10 @@ package org.eclipse.cdt.core.model; import java.util.Map; +import org.eclipse.cdt.core.dom.ILanguage; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.internal.core.model.IBufferFactory; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; /** * Represents an entire C translation unit (.c source file). @@ -363,13 +365,15 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource /** * parse() * returns a map of all new elements and their element info + * @deprecated this is currently only used by the core tests. It should + * be removed from the interface. */ Map parse(); /** - * Returns the root object of a DOM Abstract syntax tree. + * Return the language for this translation unit. * - * @return + * @return */ - IASTTranslationUnit getASTTranslationUnit(); + ILanguage getLanguage() throws CoreException; } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java index 2f81831cc6b..29510e377cf 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; +import org.eclipse.cdt.core.dom.IPDOM; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModelUtil; @@ -42,6 +43,7 @@ import org.eclipse.cdt.core.model.IOutputEntry; import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.model.ISourceEntry; import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.internal.core.pdom.PDOMManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; @@ -695,4 +697,8 @@ public class CProject extends Openable implements ICProject { } } + public IPDOM getIndex() { + return PDOMManager.getInstance().getPDOM(getProject()); + } + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index edf8d6ffab1..31e59f2bc30 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ILanguage; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.IBuffer; @@ -31,9 +32,17 @@ import org.eclipse.cdt.core.model.IUsing; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; /** * @see ITranslationUnit @@ -41,7 +50,8 @@ import org.eclipse.core.runtime.content.IContentType; public class TranslationUnit extends Openable implements ITranslationUnit { IPath location = null; - String fContentTypeID; + String contentTypeId; + ILanguage language; /** * If set, this is the problem requestor which will be used to notify problems @@ -594,8 +604,8 @@ public class TranslationUnit extends Openable implements ITranslationUnit { */ public boolean isHeaderUnit() { return ( - CCorePlugin.CONTENT_TYPE_CHEADER.equals(fContentTypeID) - || CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(fContentTypeID) + CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentTypeId) + || CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentTypeId) ); } @@ -604,9 +614,9 @@ public class TranslationUnit extends Openable implements ITranslationUnit { */ public boolean isSourceUnit() { return ( - CCorePlugin.CONTENT_TYPE_CSOURCE.equals(fContentTypeID) - || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(fContentTypeID) - || CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(fContentTypeID) + CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentTypeId) + || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentTypeId) + || CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(contentTypeId) ); } @@ -615,8 +625,8 @@ public class TranslationUnit extends Openable implements ITranslationUnit { */ public boolean isCLanguage() { return ( - CCorePlugin.CONTENT_TYPE_CSOURCE.equals(fContentTypeID) - || CCorePlugin.CONTENT_TYPE_CHEADER.equals(fContentTypeID) + CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentTypeId) + || CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentTypeId) ); } @@ -625,8 +635,8 @@ public class TranslationUnit extends Openable implements ITranslationUnit { */ public boolean isCXXLanguage() { return ( - CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(fContentTypeID) - || CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(fContentTypeID) + CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentTypeId) + || CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentTypeId) ); } @@ -634,7 +644,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit { * @see org.eclipse.cdt.core.model.ITranslationUnit#isASMLanguage() */ public boolean isASMLanguage() { - return CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(fContentTypeID); + return CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(contentTypeId); } @@ -647,24 +657,43 @@ public class TranslationUnit extends Openable implements ITranslationUnit { return res.exists(); return super.exists(); } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.model.ITranslationUnit#getASTTranslationUnit() - */ - public IASTTranslationUnit getASTTranslationUnit() { - // TODO Auto-generated method stub - return null; - } + public ILanguage getLanguage() throws CoreException { + if (language == null) { + // Look for the language extension registered against the + // content type string + IContentTypeManager manager = Platform.getContentTypeManager(); + IContentType contentType = manager.getContentType(contentTypeId); + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, ILanguage.KEY); + IExtension[] extensions = point.getExtensions(); + for (int i = 0; i < extensions.length; ++i) { + IConfigurationElement[] languages = extensions[i].getConfigurationElements(); + for (int j = 0; j < languages.length; ++j) { + IConfigurationElement language = languages[j]; + IConfigurationElement[] contentTypes = language.getChildren("contentType"); //$NON-NLS-1$ + for (int k = 0; k < contentTypes.length; ++k) { + IContentType langContType = manager.getContentType(contentTypes[k].getAttribute("id")); //$NON-NLS-1$ + if (contentType.equals(langContType)) { + this.language = (ILanguage)language.createExecutableExtension("class"); //$NON-NLS-1$ + return this.language; + } + } + } + } + } + + return language; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.model.ITranslationUnit#getContentTypeId() */ public String getContentTypeId() { - return fContentTypeID; + return contentTypeId; } protected void setContentTypeID(String id) { - fContentTypeID = id; + contentTypeId = id; } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ICodeReaderFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ICodeReaderFactory.java index 71eb306c22b..e1c36f7dfac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ICodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ICodeReaderFactory.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.ICodeReaderCache; @@ -36,6 +37,8 @@ public interface ICodeReaderFactory { */ public CodeReader createCodeReaderForTranslationUnit(String path); + public CodeReader createCodeReaderForTranslationUnit(ITranslationUnit tu); + /** * Create CodeReader for inclusion. * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndex.java new file mode 100644 index 00000000000..7cd3bb88979 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndex.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2005 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.core.dom; + +/** + * @author Doug Schaefer + * + */ +public interface IIndex { + + /** + * Get the index reader. This is used by clients to get at the + * contents of the index. + * + * @return index reader + */ + public IIndexReader getReader(); + + /** + * Get the index writer. This is used by indexers to populate + * the index. + * + * @return index writer + */ + public IIndexWriter getWriter(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexReader.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexReader.java new file mode 100644 index 00000000000..be345fe2592 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexReader.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2005 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.core.dom; + +/** + * @author Doug Schaefer + * + */ +public interface IIndexReader { + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexWriter.java new file mode 100644 index 00000000000..0c8345a9e35 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IIndexWriter.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2005 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.core.dom; + +/** + * @author Doug Schaefer + * + */ +public interface IIndexWriter { + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ILanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ILanguage.java new file mode 100644 index 00000000000..0e66d039394 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ILanguage.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2005 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.core.dom; + +import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; + +/** + * @author Doug Schaefer + * + */ +public interface ILanguage { + + //public static final QualifiedName KEY = new QualifiedName(CCorePlugin.PLUGIN_ID, "language"); //$NON-NLS-1$ + public static final String KEY = "language"; //$NON-NLS-1$ + + /** + * Style for getTranslationUnit. Use the index for resolving bindings that aren't + * found in the AST. + */ + public static final int AST_USE_INDEX = 1; + + /** + * Style for getTranslationUnit. Don't parse header files. It's a good idea to + * turn on AST_USE_INDEX when you do this. + */ + public static final int AST_SKIP_ALL_HEADERS = 2; + + /** + * Style for getTranslationUnit. Used by the indexer to skip over headers it + * already has indexed. + */ + public static final int AST_SKIP_INDEXED_HEADERS = 4; + + public IASTTranslationUnit getTranslationUnit(ITranslationUnit file, int style); + + public ASTCompletionNode getCompletionNode(IWorkingCopy workingCopy, int offset); + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java index c46c430a73d..a43dea25690 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java @@ -190,17 +190,17 @@ public interface IASTTranslationUnit extends IASTNode { public ParserLanguage getParserLanguage(); /** - * Return the PDOM associated with this translation unit. + * Return the Index associated with this translation unit. * - * @return the PDOM for this translation unit + * @return the Index for this translation unit */ - public IPDOM getPDOM(); + public IPDOM getIndex(); /** - * Set the PDOM to be used for this translation unit. + * Set the Index to be used for this translation unit. * - * @param pdom + * @param index */ - public void setPDOM(IPDOM pdom); + public void setIndex(IPDOM index); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/c/GCCLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/c/GCCLanguage.java new file mode 100644 index 00000000000..bc79653505d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/c/GCCLanguage.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2005 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.core.dom.ast.gnu.c; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.dom.ILanguage; +import org.eclipse.cdt.core.dom.PDOM; +import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ParserUtil; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory; +import org.eclipse.cdt.internal.core.dom.parser.ISourceCodeParser; +import org.eclipse.cdt.internal.core.dom.parser.c.GCCParserExtensionConfiguration; +import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser; +import org.eclipse.cdt.internal.core.parser.scanner2.DOMScanner; +import org.eclipse.cdt.internal.core.parser.scanner2.GCCScannerExtensionConfiguration; +import org.eclipse.cdt.internal.core.parser.scanner2.IScannerExtensionConfiguration; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; + +/** + * @author Doug Schaefer + * + */ +public class GCCLanguage implements ILanguage { + + protected static final GCCScannerExtensionConfiguration C_GNU_SCANNER_EXTENSION = new GCCScannerExtensionConfiguration(); + + public IASTTranslationUnit getTranslationUnit(ITranslationUnit tu, int style) { + IFile file = (IFile)tu.getResource(); + IProject project = file.getProject(); + IScannerInfo scanInfo = null; + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null){ + IScannerInfo buildScanInfo = provider.getScannerInformation(file); + if (buildScanInfo != null) + scanInfo = buildScanInfo; + else + scanInfo = new ScannerInfo(); + } + + // TODO - use different factories if we are working copy, or style + // is skip headers. + ICodeReaderFactory fileCreator = SavedCodeReaderFactory.getInstance(); + CodeReader reader = fileCreator.createCodeReaderForTranslationUnit(tu.getElementName()); + if( reader == null ) + return null; + + IScannerExtensionConfiguration scannerExtensionConfiguration = + scannerExtensionConfiguration = C_GNU_SCANNER_EXTENSION; + + IScanner scanner = new DOMScanner(reader, scanInfo, ParserMode.COMPLETE_PARSE, + ParserLanguage.C, ParserFactory.createDefaultLogService(), scannerExtensionConfiguration, fileCreator ); + //assume GCC + ISourceCodeParser parser = new GNUCSourceParser( scanner, ParserMode.COMPLETE_PARSE, ParserUtil.getParserLogService(), + new GCCParserExtensionConfiguration() ); + + // Parse + IASTTranslationUnit ast = parser.parse(); + + if ((style & AST_USE_INDEX) != 0) + ast.setIndex(tu.getCProject().getIndex()); + + return ast; + } + + public ASTCompletionNode getCompletionNode(IWorkingCopy workingCopy, int offset) { + return null; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java new file mode 100644 index 00000000000..ac8687ad4d0 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2005 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.core.dom.ast.gnu.cpp; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.dom.ILanguage; +import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ParserUtil; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory; +import org.eclipse.cdt.internal.core.dom.parser.ISourceCodeParser; +import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; +import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPParserExtensionConfiguration; +import org.eclipse.cdt.internal.core.parser.scanner2.DOMScanner; +import org.eclipse.cdt.internal.core.parser.scanner2.GPPScannerExtensionConfiguration; +import org.eclipse.cdt.internal.core.parser.scanner2.IScannerExtensionConfiguration; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; + +/** + * @author Doug Schaefer + * + */ +public class GPPLanguage implements ILanguage { + + protected static final GPPScannerExtensionConfiguration CPP_GNU_SCANNER_EXTENSION = new GPPScannerExtensionConfiguration(); + + public IASTTranslationUnit getTranslationUnit(ITranslationUnit tu, int style) { + IFile file = (IFile)tu.getResource(); + IProject project = file.getProject(); + IScannerInfo scanInfo = null; + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null){ + IScannerInfo buildScanInfo = provider.getScannerInformation(file); + if (buildScanInfo != null) + scanInfo = buildScanInfo; + else + scanInfo = new ScannerInfo(); + } + + // TODO - use different factories if we are working copy, or style + // is skip headers. + ICodeReaderFactory fileCreator = SavedCodeReaderFactory.getInstance(); + CodeReader reader = fileCreator.createCodeReaderForTranslationUnit(tu); + if( reader == null ) + return null; + + IScannerExtensionConfiguration scannerExtensionConfiguration = CPP_GNU_SCANNER_EXTENSION; + + IScanner scanner = new DOMScanner(reader, scanInfo, ParserMode.COMPLETE_PARSE, + ParserLanguage.CPP, ParserFactory.createDefaultLogService(), scannerExtensionConfiguration, fileCreator ); + ISourceCodeParser parser = new GNUCPPSourceParser( scanner, ParserMode.COMPLETE_PARSE, ParserUtil.getParserLogService(), + new GPPParserExtensionConfiguration() ); + + // Parse + IASTTranslationUnit ast = parser.parse(); + + if ((style & AST_USE_INDEX) != 0) + ast.setIndex(tu.getCProject().getIndex()); + + return ast; + } + + public ASTCompletionNode getCompletionNode(IWorkingCopy workingCopy, + int offset) { + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java index 35772bb18e9..ab2474f92ca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java @@ -521,11 +521,11 @@ public class CASTTranslationUnit extends CASTNode implements return ParserLanguage.C; } - public IPDOM getPDOM() { + public IPDOM getIndex() { return pdom; } - public void setPDOM(IPDOM pdom) { + public void setIndex(IPDOM pdom) { this.pdom = pdom; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index 691b4897143..e7bccf53498 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -1300,7 +1300,7 @@ public class CVisitor { if( blockItem != null) { // We're at the end of our rope, check the PDOM if we can IASTTranslationUnit tu = (IASTTranslationUnit)blockItem; - IPDOM pdom = tu.getPDOM(); + IPDOM pdom = tu.getIndex(); binding = null; if (pdom != null) binding = pdom.resolveBinding(name); @@ -1908,7 +1908,7 @@ public class CVisitor { IASTTranslationUnit tu = name.getTranslationUnit(); if (tu != null) { - IPDOM pdom = tu.getPDOM(); + IPDOM pdom = tu.getIndex(); if (pdom != null) result = (IBinding[])ArrayUtil.addAll(IBinding.class, result, pdom.resolvePrefix(name)); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index 5a0247ef127..ee44469ea26 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -573,11 +573,11 @@ public class CPPASTTranslationUnit extends CPPASTNode implements return ParserLanguage.CPP; } - public IPDOM getPDOM() { + public IPDOM getIndex() { return pdom; } - public void setPDOM(IPDOM pdom) { + public void setIndex(IPDOM pdom) { this.pdom = pdom; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index b6679617de3..6267671fd76 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -746,7 +746,7 @@ public class CPPSemantics { } if( binding == null ){ // Let's try the pdom - IPDOM pdom = name.getTranslationUnit().getPDOM(); + IPDOM pdom = name.getTranslationUnit().getIndex(); if (pdom != null) binding = pdom.resolveBinding(name); @@ -3274,7 +3274,7 @@ public class CPPSemantics { IASTTranslationUnit tu = name.getTranslationUnit(); if (tu != null) { - IPDOM pdom = tu.getPDOM(); + IPDOM pdom = tu.getIndex(); if (pdom != null) result = (IBinding[])ArrayUtil.addAll(IBinding.class, result, pdom.resolvePrefix(name)); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/FileCodeReaderFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/FileCodeReaderFactory.java index 847b7a6b4ca..d46e145500e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/FileCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/FileCodeReaderFactory.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.internal.core.parser.scanner2; import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.ICodeReaderCache; import org.eclipse.cdt.internal.core.dom.parser.EmptyCodeReaderCache; @@ -42,6 +43,10 @@ public class FileCodeReaderFactory implements ICodeReaderFactory { return cache.get(path); } + public CodeReader createCodeReaderForTranslationUnit(ITranslationUnit tu) { + return new CodeReader(tu.getPath().toOSString(), tu.getContents()); + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ICodeReaderFactory#createCodeReaderForInclusion(java.lang.String) */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMCodeReaderFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMCodeReaderFactory.java new file mode 100644 index 00000000000..c1f21c4be73 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMCodeReaderFactory.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2005 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; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.ICodeReaderCache; +import org.eclipse.cdt.core.parser.ParserUtil; +import org.eclipse.cdt.internal.pdom.dom.PDOMFile; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @author Doug Schaefer + * + */ +public class PDOMCodeReaderFactory implements ICodeReaderFactory { + + private final PDOMDatabase pdom; + private List workingCopies; + + public PDOMCodeReaderFactory(PDOMDatabase pdom) { + this.pdom = pdom; + } + + public PDOMCodeReaderFactory(PDOMDatabase pdom, IWorkingCopy workingCopy) { + this(pdom); + workingCopies = new ArrayList(1); + workingCopies.add(workingCopy); + } + + public int getUniqueIdentifier() { + return 0; + } + + public CodeReader createCodeReaderForTranslationUnit(String path) { + return ParserUtil.createReader(path, + workingCopies != null ? workingCopies.iterator() : null); + } + + public CodeReader createCodeReaderForTranslationUnit(ITranslationUnit tu) { + return new CodeReader(tu.getPath().toOSString(), tu.getContents()); + } + + public CodeReader createCodeReaderForInclusion(String path) { + // Don't parse inclusion if it is already captured + try { + try { + path = new File(path).getCanonicalPath(); + } catch (IOException e) { + // ignore and use the path we were passed in + } + if (PDOMFile.find(pdom, path) != null) + return null; + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "PDOM Exception", e))); + } + + return ParserUtil.createReader(path, null); + } + + public ICodeReaderCache getCodeReaderCache() { + // No need for cache here + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMDatabase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMDatabase.java new file mode 100644 index 00000000000..dc4a92449c9 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMDatabase.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright (c) 2005 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; + +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.dom.IPDOM; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.c.CASTVisitor; +import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.pdom.dom.PDOMBinding; +import org.eclipse.cdt.internal.pdom.dom.PDOMName; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Status; + + +/** + * The PDOM Database. + * + * @author Doug Schaefer + */ +public class PDOMDatabase implements IPDOM { + + private final IPath dbPath; + private final Database db; + + private static final int VERSION = 0; + + public static final int STRING_INDEX = Database.DATA_AREA + 0 * Database.INT_SIZE; + private BTree stringIndex; + + public static final int FILE_INDEX = Database.DATA_AREA + 1 * Database.INT_SIZE; + private BTree fileIndex; + + public static final int BINDING_INDEX = Database.DATA_AREA + 2 * Database.INT_SIZE; + private BTree bindingIndex; + + private static final QualifiedName dbNameProperty + = new QualifiedName(PDOMCorePlugin.ID, "dbName"); //$NON-NLS-1$ + + public PDOMDatabase(IProject project, PDOMManager manager) throws CoreException { + String dbName = project.getPersistentProperty(dbNameProperty); + if (dbName == null) { + dbName = project.getName() + "_" + + System.currentTimeMillis() + ".pdom"; + project.setPersistentProperty(dbNameProperty, dbName); + } + + dbPath = PDOMCorePlugin.getDefault().getStateLocation().append(dbName); + + try { + db = new Database(dbPath.toOSString(), VERSION); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "Failed to create database", e)); + } + } + + public Database getDB() { + return db; + } + + public BTree getStringIndex() { + if (stringIndex == null) + stringIndex = new BTree(db, STRING_INDEX); + return stringIndex; + } + + public BTree getFileIndex() { + if (fileIndex == null) + fileIndex = new BTree(db, FILE_INDEX); + return fileIndex; + } + + public BTree getBindingIndex() { + if (bindingIndex == null) + bindingIndex = new BTree(db, BINDING_INDEX); + return bindingIndex; + } + + public void addSymbols(IASTTranslationUnit ast) { + ParserLanguage language = ast.getParserLanguage(); + ASTVisitor visitor; + if (language == ParserLanguage.C) + visitor = new CASTVisitor() { + { + shouldVisitNames = true; + shouldVisitDeclarations = true; + } + + public int visit(IASTName name) { + if (name.toCharArray().length > 0) + addSymbol(name); + return PROCESS_CONTINUE; + }; + }; + else if (language == ParserLanguage.CPP) + visitor = new CPPASTVisitor() { + { + shouldVisitNames = true; + shouldVisitDeclarations = true; + } + + public int visit(IASTName name) { + if (name.toCharArray().length > 0) + addSymbol(name); + return PROCESS_CONTINUE; + }; + }; + else + return; + + ast.accept(visitor); + } + + public void addSymbol(IASTName name) { + try { + IBinding binding = name.resolveBinding(); + if (binding == null) + return; + + IScope scope = binding.getScope(); + if (scope == null) + return; + + IASTName scopeName = scope.getScopeName(); + + if (scopeName == null) { + PDOMBinding pdomBinding = new PDOMBinding(this, name, binding); + new PDOMName(this, name, pdomBinding); + } else { + IBinding scopeBinding = scopeName.resolveBinding(); + if (scopeBinding instanceof IType) { + PDOMBinding pdomBinding = new PDOMBinding(this, name, binding); + new PDOMName(this, name, pdomBinding); + } + } + } catch (CoreException e) { + PDOMCorePlugin.log(e); + } catch (DOMException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "DOMException", e))); + } + } + + public void removeSymbols(ITranslationUnit ast) { + + } + + public void delete() throws CoreException { + // TODO Auto-generated method stub + } + + public ICodeReaderFactory getCodeReaderFactory() { + return new PDOMCodeReaderFactory(this); + } + + public ICodeReaderFactory getCodeReaderFactory(IWorkingCopy root) { + return new PDOMCodeReaderFactory(this, root); + } + + public IASTName[] getDeclarations(IBinding binding) { + try { + if (binding instanceof PDOMBinding) { + PDOMName name = ((PDOMBinding)binding).getFirstDeclaration(); + if (name == null) + return new IASTName[0]; + return new IASTName[] { name }; + } + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "getDeclarations", e))); + } + return new IASTName[0]; + } + + public IBinding resolveBinding(IASTName name) { + try { + return new PDOMBinding(this, name, null); + } catch (CoreException e) { + PDOMCorePlugin.log(e); + return null; + } + } + + public IBinding[] resolvePrefix(IASTName name) { +// try { + final String prefix = new String(name.toCharArray()); + final ArrayList bindings = new ArrayList(); + +// getStringIndex().visit(new PDOMString.Visitor(db, prefix) { +// public boolean visit(int record) throws IOException { +// String value = new String(new PDOMString(PDOMDatabase.this, record).getString()); +// if (value.startsWith(prefix)) { +// PDOMBinding pdomBinding = PDOMBinding.find(PDOMDatabase.this, record); +// if (pdomBinding != null) +// bindings.add(pdomBinding); +// return true; +// } else +// return false; +// } +// }); + + return (IBinding[])bindings.toArray(new IBinding[bindings.size()]); +// } catch (IOException e) { +// PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, +// PDOMCorePlugin.ID, 0, "resolvePrefix", e))); +// return null; +// } + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java new file mode 100644 index 00000000000..2e3b478447a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2005 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; + +import org.eclipse.cdt.core.dom.IPDOM; +import org.eclipse.cdt.core.dom.IPDOMProvider; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; + +/** + * The PDOM Provider. This is likely temporary since I hope + * to integrate the PDOM directly into the core once it has + * stabilized. + * + * @author Doug Schaefer + */ +public class PDOMManager implements IPDOMProvider, IElementChangedListener, IJobChangeListener { + + private static PDOMManager instance; + private PDOMUpdator currJob; + + private static final QualifiedName pdomProperty + = new QualifiedName(PDOMCorePlugin.ID, "pdom"); //$NON-NLS-1$ + + public static PDOMManager getInstance() { + if (instance == null) + instance = new PDOMManager(); + return instance; + } + + public IPDOM getPDOM(IProject project) { + try { + IPDOM pdom = (IPDOM)project.getSessionProperty(pdomProperty); + + if (pdom == null) { + pdom = new PDOMDatabase(project, this); + project.setSessionProperty(pdomProperty, pdom); + } + + return pdom; + } catch (CoreException e) { + PDOMCorePlugin.log(e); + return null; + } + } + + public synchronized void elementChanged(ElementChangedEvent event) { + // Only respond to post change events + if (event.getType() != ElementChangedEvent.POST_CHANGE) + return; + + currJob = new PDOMUpdator(event.getDelta(), currJob); + currJob.addJobChangeListener(this); + currJob.schedule(); + } + + public void aboutToRun(IJobChangeEvent event) { + } + + public void awake(IJobChangeEvent event) { + } + + public synchronized void done(IJobChangeEvent event) { + if (currJob == event.getJob()) + currJob = null; + } + + public void running(IJobChangeEvent event) { + } + + public void scheduled(IJobChangeEvent event) { + } + + public void sleeping(IJobChangeEvent event) { + } + + public void deletePDOM(IProject project) throws CoreException { + IPDOM pdom = (IPDOM)project.getSessionProperty(pdomProperty); + project.setSessionProperty(pdomProperty, null); + pdom.delete(); + } + + public IElementChangedListener getElementChangedListener() { + return this; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUpdator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUpdator.java new file mode 100644 index 00000000000..9478b3b8305 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUpdator.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright (c) 2005 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; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ILanguage; +import org.eclipse.cdt.core.dom.IPDOM; +import org.eclipse.cdt.core.dom.PDOM; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceProxy; +import org.eclipse.core.resources.IResourceProxyVisitor; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.jobs.Job; + +/** + * @author Doug Schaefer + * + */ +public class PDOMUpdator extends Job { + + private PDOMUpdator prevJob; + private ICElementDelta delta; + private ICProject project; + private List addedTUs; + private List changedTUs; + private List removedTUs; + private int count; + + public PDOMUpdator(ICElementDelta delta, PDOMUpdator prevJob) { + super("PDOM Updator"); + this.prevJob = prevJob; + this.delta = delta; + } + + public PDOMUpdator(ICProject project, PDOMUpdator prevJob) { + super("PDOM Project Updator"); + this.prevJob = prevJob; + this.project = project; + } + + protected IStatus run(IProgressMonitor monitor) { + if (prevJob != null) + try { + prevJob.join(); + } catch (InterruptedException e) { + } + + try { + long start = System.currentTimeMillis(); + + if (delta != null) + processDelta(delta); + if (project != null) + processNewProject(project); + + if (addedTUs != null) + for (Iterator i = addedTUs.iterator(); i.hasNext();) { + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + monitor.subTask("Files remaining: " + (count--)); + ITranslationUnit tu = (ITranslationUnit)i.next(); + processAddedTU(tu); + } + + if (changedTUs != null) + for (Iterator i = changedTUs.iterator(); i.hasNext();) { + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + monitor.subTask("Files remaining: " + (count--)); + ITranslationUnit tu = (ITranslationUnit)i.next(); + processChangedTU(tu); + } + + if (removedTUs != null) + for (Iterator i = removedTUs.iterator(); i.hasNext();) { + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + monitor.subTask("Files remaining: " + (count--)); + ITranslationUnit tu = (ITranslationUnit)i.next(); + processRemovedTU(tu); + } + + System.out.println("Updator Time: " + (System.currentTimeMillis() - start)); + return Status.OK_STATUS; + } catch (CoreException e) { + CCorePlugin.log(e); + return e.getStatus(); + } + } + + private void processDelta(ICElementDelta delta) { + // process the children first + ICElementDelta[] children = delta.getAffectedChildren(); + for (int i = 0; i < children.length; ++i) + processDelta(children[i]); + + // what have we got + ICElement element = delta.getElement(); + if (element.getElementType() == ICElement.C_PROJECT) { + switch (delta.getKind()) { + case ICElementDelta.ADDED: + processNewProject((ICProject)element); + break; + } + } else if (element.getElementType() == ICElement.C_UNIT) { + ITranslationUnit tu = (ITranslationUnit)element; + if (tu.isWorkingCopy()) + // Don't care about working copies either + return; + + switch (delta.getKind()) { + case ICElementDelta.ADDED: + if (addedTUs == null) + addedTUs = new LinkedList(); + addedTUs.add(element); + ++count; + break; + case ICElementDelta.CHANGED: + if (changedTUs == null) + changedTUs = new LinkedList(); + changedTUs.add(element); + ++count; + break; + case ICElementDelta.REMOVED: + if (removedTUs == null) + removedTUs = new LinkedList(); + removedTUs.add(element); + ++count; + break; + } + } + } + + private void processNewProject(final ICProject project) { + try { + project.getProject().accept(new IResourceProxyVisitor() { + public boolean visit(IResourceProxy proxy) throws CoreException { + if (proxy.getType() == IResource.FILE) { + String fileName = proxy.getName(); + IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(fileName); + if (contentType == null) + return true; + String contentTypeId = contentType.getId(); + + if (CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentTypeId) + || CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentTypeId)) { + if (addedTUs == null) + addedTUs = new LinkedList(); + addedTUs.add(CoreModel.getDefault().create((IFile)proxy.requestResource())); + ++count; + } + // TODO handle header files + return false; + } else { + return true; + } + } + }, 0); + } catch (CoreException e) { + PDOMCorePlugin.log(e); + } + } + + private void processAddedTU(ITranslationUnit tu) throws CoreException { + ILanguage language = tu.getLanguage(); + if (language == null) + return; + + IASTTranslationUnit ast = language.getTranslationUnit(tu, + ILanguage.AST_USE_INDEX | + ILanguage.AST_SKIP_INDEXED_HEADERS); + + IPDOM pdom = ast.getIndex(); + if (pdom == null || !(pdom instanceof PDOMDatabase)) + return; + + PDOMDatabase mypdom = (PDOMDatabase)pdom; + mypdom.addSymbols(ast); + } + + private void processRemovedTU(ITranslationUnit tu) { + IProject project = tu.getCProject().getProject(); + IPDOM pdom = PDOM.getPDOM(project); + if (pdom == null || !(pdom instanceof PDOMDatabase)) + return; + + PDOMDatabase mypdom = (PDOMDatabase)pdom; + mypdom.removeSymbols(tu); + } + + private void processChangedTU(ITranslationUnit tu) throws CoreException { + IPDOM pdom = PDOM.getPDOM(tu.getCProject().getProject()); + if (pdom == null || !(pdom instanceof PDOMDatabase)) + return; + PDOMDatabase mypdom = (PDOMDatabase)pdom; + + ILanguage language = tu.getLanguage(); + if (language == null) + return; + + IASTTranslationUnit ast = language.getTranslationUnit(tu, + ILanguage.AST_SKIP_ALL_HEADERS | + ILanguage.AST_USE_INDEX); + + if (pdom != ast.getIndex()) + // weird + return; + + mypdom.removeSymbols(tu); + mypdom.addSymbols(ast); + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUtils.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUtils.java new file mode 100644 index 00000000000..00ca46a4755 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMUtils.java @@ -0,0 +1,74 @@ +/** + * + */ +package org.eclipse.cdt.internal.core.pdom; + +import java.io.IOException; + +import org.eclipse.cdt.internal.core.pdom.db.Chunk; +import org.eclipse.cdt.internal.core.pdom.db.Database; + +/** + * @author dschaefer + * + */ +public class PDOMUtils { + + public static int stringCompare(Database db, int record1, int record2) throws IOException { + Chunk chunk1 = db.getChunk(record1); + Chunk chunk2 = db.getChunk(record2); + + int i1 = record1; + int i2 = record2; + char c1 = chunk1.getChar(i1); + char c2 = chunk2.getChar(i2); + + while (c1 != 0 && c2 != 0) { + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + + i1 += 2; + i2 += 2; + c1 = chunk1.getChar(i1); + c2 = chunk2.getChar(i2); + } + + if (c1 == c2) + return 0; + else if (c1 == 0) + return -1; + else + return 1; + } + + public static int stringCompare(Database db, int record1, char[] record2) throws IOException { + Chunk chunk1 = db.getChunk(record1); + + int i1 = record1; + int i2 = 0; + char c1 = chunk1.getChar(i1); + char c2 = i2 < record2.length ? record2[i2] : 0; + + while (c1 != 0 && c2 != 0) { + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + + i1 += 2; + ++i2; + c1 = chunk1.getChar(i1); + c2 = i2 < record2.length ? record2[i2] : 0; + } + + if (c1 == c2) + return 0; + else if (c1 == 0) + return -1; + else + return 1; + + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java new file mode 100644 index 00000000000..e5e03da1c46 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java @@ -0,0 +1,326 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; + +/** + * @author Doug Schaefer + * + */ +public class BTree { + + protected Database db; + protected int rootPointer; + + protected static final int NUM_RECORDS = 15; + protected static final int MEDIAN_RECORD = NUM_RECORDS / 2; + protected static final int NUM_CHILDREN = NUM_RECORDS + 1; + protected static final int OFFSET_CHILDREN = NUM_RECORDS * Database.INT_SIZE; + + /** + * Contructor. + * + * @param db the database containing the btree + * @param root offset into database of the pointer to the root node + */ + public BTree(Database db, int rootPointer) { + this.db = db; + this.rootPointer = rootPointer; + } + + protected int getRoot() throws IOException { + return db.getInt(rootPointer); + } + + protected final void putRecord(Chunk chunk, int node, int index, int record) { + chunk.putInt(node + index * Database.INT_SIZE, record); + } + + protected final int getRecord(Chunk chunk, int node, int index) { + return chunk.getInt(node + index * Database.INT_SIZE); + } + + protected final void putChild(Chunk chunk, int node, int index, int child) { + chunk.putInt(node + OFFSET_CHILDREN + index * Database.INT_SIZE, child); + } + + protected final int getChild(Chunk chunk, int node, int index) { + return chunk.getInt(node + OFFSET_CHILDREN + index * Database.INT_SIZE); + } + + /** + * Inserts the record into the b-tree. We don't insert if the + * key was already there, in which case we return the record + * that matched. In other cases, we just return the record back. + * + * @param offset of the record + * @return + */ + public int insert(int record, IBTreeComparator comparator) throws IOException { + int root = getRoot(); + + // is this our first time in + if (root == 0) { + firstInsert(record); + return record; + } + + return insert(null, 0, 0, root, record, comparator); + } + + private int insert(Chunk pChunk, int parent, int iParent, int node, int record, IBTreeComparator comparator) throws IOException { + Chunk chunk = db.getChunk(node); + + // if this node is full (last record isn't null), split it + if (getRecord(chunk, node, NUM_RECORDS - 1) != 0) { + int median = getRecord(chunk, node, MEDIAN_RECORD); + if (median == record) + // found it, never mind + return median; + else { + // split it + // create the new node and move the larger records over + int newnode = allocateNode(); + Chunk newchunk = db.getChunk(newnode); + for (int i = 0; i < MEDIAN_RECORD; ++i) { + putRecord(newchunk, newnode, i, getRecord(chunk, node, MEDIAN_RECORD + 1 + i)); + putRecord(chunk, node, MEDIAN_RECORD + 1 + i, 0); + putChild(newchunk, newnode, i, getChild(chunk, node, MEDIAN_RECORD + 1 + i)); + putChild(chunk, node, MEDIAN_RECORD + 1 + i, 0); + } + putChild(newchunk, newnode, MEDIAN_RECORD, getChild(chunk, node, NUM_RECORDS)); + putChild(chunk, node, NUM_RECORDS, 0); + + if (parent == 0) { + // create a new root + parent = allocateNode(); + pChunk = db.getChunk(parent); + db.putInt(rootPointer, parent); + putChild(pChunk, parent, 0, node); + } else { + // insert the median into the parent + for (int i = NUM_RECORDS - 2; i >= iParent; --i) { + int r = getRecord(pChunk, parent, i); + if (r != 0) { + putRecord(pChunk, parent, i + 1, r); + putChild(pChunk, parent, i + 2, getChild(pChunk, parent, i + 1)); + } + } + } + putRecord(pChunk, parent, iParent, median); + putChild(pChunk, parent, iParent + 1, newnode); + + putRecord(chunk, node, MEDIAN_RECORD, 0); + + // set the node to the correct one to follow + if (comparator.compare(record, median) > 0) { + node = newnode; + chunk = newchunk; + } + } + } + + // search to find the insert point + int i; + for (i = 0; i < NUM_RECORDS; ++i) { + int record1 = getRecord(chunk, node, i); + if (record1 == 0) { + // past the end + break; + } else { + int compare = comparator.compare(record1, record); + if (compare == 0) + // found it, no insert, just return the record + return record; + else if (compare > 0) + // past it + break; + } + } + + int child = getChild(chunk, node, i); + if (child != 0) { + // visit the children + return insert(chunk, node, i, child, record, comparator); + } else { + // were at the leaf, add us in. + // first copy everything after over one + for (int j = NUM_RECORDS - 2; j >= i; --j) { + int r = getRecord(chunk, node, j); + if (r != 0) + putRecord(chunk, node, j + 1, r); + } + putRecord(chunk, node, i, record); + return record; + } + } + + private void firstInsert(int record) throws IOException { + // create the node and save it as root + int root = allocateNode(); + db.putInt(rootPointer, root); + // put the record in the first slot of the node + putRecord(db.getChunk(root), root, 0, record); + } + + private int allocateNode() throws IOException { + return db.malloc((2 * NUM_RECORDS - 1) * Database.INT_SIZE); + } + + /** + * Deletes the record from the b-tree. + * + * @param offset of the record + */ + public void delete(int record) { + // TODO some day + } + + /** + * Visit all nodes beginning when the visitor comparator + * returns >= 0 until the visitor visit returns falls. + * + * @param visitor + */ + public void visit(IBTreeVisitor visitor) throws IOException { + visit(db.getInt(rootPointer), visitor, false); + } + + private boolean visit(int node, IBTreeVisitor visitor, boolean found) throws IOException { + // if found is false, we are still in search mode + // once found is true visit everything + // return false when ready to quit + if (node == 0) + return visitor.visit(0); + + Chunk chunk = db.getChunk(node); + + if (found) { + int child = getChild(chunk, node, 0); + if (child != 0) + if (!visit(child, visitor, true)) + return false; + } + + int i; + for (i = 0; i < NUM_RECORDS; ++i) { + int record = getRecord(chunk, node, i); + if (record == 0) + break; + + if (found) { + if (!visitor.visit(record)) + return false; + if (!visit(getChild(chunk, node, i + 1), visitor, true)) + return false; + } else { + int compare = visitor.compare(record); + if (compare > 0) { + // start point is to the left + if (!visit(getChild(chunk, node, i), visitor, false)) + return false; + if (!visitor.visit(record)) + return false; + if (!visit(getChild(chunk, node, i + 1), visitor, true)) + return false; + found = true; + } else if (compare == 0) { + if (!visitor.visit(record)) + return false; + if (!visit(getChild(chunk, node, i + 1), visitor, true)) + return false; + found = true; + } + } + } + + return visit(getChild(chunk, node, i), visitor, found); + } + + public int getHeight() throws IOException { + int root = getRoot(); + + if (root == 0) + return 0; + + return getHeight(root); + } + + private int getHeight(int node) throws IOException { + int height = 0; + Chunk chunk = db.getChunk(node); + + for (int i = 0; i < NUM_CHILDREN; ++i) { + int child = getChild(chunk, node, i); + if (child == 0) + break; + int n = getHeight(child); + if (n == -1) + return -1; + if (height != 0 && height != n) + return -1; + height = n; + } + + return height + 1; + } + + public int getRecordCount() throws IOException { + int root = getRoot(); + + if (root == 0) + return 0; + + return getRecordCount(root); + } + + private int getRecordCount(int node) throws IOException { + Chunk chunk = db.getChunk(node); + + int count; + for (count = 0; count < NUM_RECORDS; ++count) + if (getRecord(chunk, node, count) == 0) + break; + + for (int i = 0; i < NUM_CHILDREN; ++i) { + int child = getChild(chunk, node, i); + if (child != 0) + count += getRecordCount(child); + } + + return count; + } + + public int getNodeCount() throws IOException { + int root = getRoot(); + + if (root == 0) + return 0; + + return getNodeCount(root); + } + + private int getNodeCount(int node) throws IOException { + Chunk chunk = db.getChunk(node); + + int count = 1; + + for (int i = 0; i < NUM_CHILDREN; ++i) { + int child = getChild(chunk, node, i); + if (child != 0) + count += getNodeCount(child); + } + + return count; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java new file mode 100644 index 00000000000..4fb13bc082d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel.MapMode; + +/** + * @author Doug Schaefer + * + */ +public class Chunk { + + private MappedByteBuffer buffer; + + // Cache info + private Database db; + int index; + private Chunk prevChunk; + private Chunk nextChunk; + + Chunk(RandomAccessFile file, int offset) throws IOException { + index = offset / Database.CHUNK_SIZE; + buffer = file.getChannel().map(MapMode.READ_WRITE, offset, Database.CHUNK_SIZE); + } + + public void putInt(int offset, int value) { + buffer.putInt(offset % Database.CHUNK_SIZE, value); + } + + public int getInt(int offset) { + return buffer.getInt(offset % Database.CHUNK_SIZE); + } + + public void putChar(int offset, char value) { + buffer.putChar(offset % Database.CHUNK_SIZE, value); + } + + public char getChar(int offset) { + return buffer.getChar(offset % Database.CHUNK_SIZE); + } + + public void putChars(int offset, char[] value) { + buffer.position(offset % Database.CHUNK_SIZE); + for (int i = 0; i < value.length; ++i) + buffer.putChar(value[i]); + buffer.putChar((char)0); + } + + public char[] getChars(int offset) { + buffer.position(offset % Database.CHUNK_SIZE); + int n = 0; + for (char c = buffer.getChar(); c != 0; c = buffer.getChar()) + ++n; + + buffer.position(offset % Database.CHUNK_SIZE); + char[] chars = new char[n]; + int i = 0; + for (char c = buffer.getChar(); c != 0; c = buffer.getChar()) + chars[i++] = c; + return chars; + } + + public void putString(int offset, String value) { + buffer.position(offset % Database.CHUNK_SIZE); + int n = value.length(); + for (int i = 0; i < n; ++i) + buffer.putChar(value.charAt(i)); + buffer.putChar((char)0); + } + + public String getString(int offset) { + return new String(getChars(offset)); + } + + Chunk getNextChunk() { + return nextChunk; + } + + void setNextChunk(Chunk nextChunk) { + this.nextChunk = nextChunk; + } + + Chunk getPrevChunk() { + return prevChunk; + } + + void setPrevChunk(Chunk prevChunk) { + this.prevChunk = prevChunk; + } + + void free() { + // nextChunk should be null + db.toc[index] = null; + db.lruChunk = prevChunk; + prevChunk.nextChunk = null; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java new file mode 100644 index 00000000000..3b09c2e925f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Doug Schaefer + * + */ +public class Database { + + private final RandomAccessFile file; + Chunk[] toc; + Chunk mruChunk; + Chunk lruChunk; + + private int loadedChunks; + + // public for tests only, you shouldn't need these + public static final int VERSION_OFFSET = 0; + public static final int CHUNK_SIZE = 4096; + public static final int CACHE_SIZE = 10000; // Should be configable + public static final int MIN_SIZE = 16; + public static final int INT_SIZE = 4; + public static final int CHAR_SIZE = 2; + public static final int PREV_OFFSET = INT_SIZE; + public static final int NEXT_OFFSET = INT_SIZE * 2; + public static final int DATA_AREA = CHUNK_SIZE / MIN_SIZE * INT_SIZE + INT_SIZE; + + public Database(String filename, int version) throws IOException { + file = new RandomAccessFile(filename, "rw"); //$NON-NLS-1$ + + // Allocate chunk table, make sure we have at least one + long nChunks = file.length() / CHUNK_SIZE; + if (nChunks == 0) { + create(); + ++nChunks; + } + + toc = new Chunk[(int)nChunks]; + + // Load in the magic chunk zero + toc[0] = new Chunk(file, 0); + int oldversion = toc[0].getInt(0); + if (oldversion != version) { + // Conversion? + toc[0].putInt(0, version); + } + } + + /** + * Create the database, including chunk zero and the b-trees. + */ + private void create() throws IOException { + file.seek(0); + file.write(new byte[CHUNK_SIZE]); // the header chunk + } + + /** + * Return the Chunk that contains the given offset. + * + * @param offset + * @return + */ + public Chunk getChunk(int offset) throws IOException { + int index = offset / CHUNK_SIZE; + Chunk chunk = toc[index]; + if (chunk == null) { + if (loadedChunks == CACHE_SIZE) + // cache is full, free lruChunk + lruChunk.free(); + + chunk = toc[index] = new Chunk(file, index * CHUNK_SIZE); + } + + // insert into cache + // TODO We can move this into the chunks + Chunk prevChunk = chunk.getPrevChunk(); + Chunk nextChunk = chunk.getNextChunk(); + if (prevChunk != null) + prevChunk.setNextChunk(nextChunk); + if (nextChunk != null) + nextChunk.setPrevChunk(prevChunk); + if (mruChunk != null) { + chunk.setNextChunk(mruChunk); + mruChunk.setPrevChunk(chunk); + } + mruChunk = chunk; + chunk.setPrevChunk(null); + + return chunk; + } + + /** + * Allocate a block out of the database. + * + * @param size + * @return + */ + public int malloc(int size) throws IOException { + // Which block size + int freeblock = 0; + int blocksize; + int matchsize = 0; + for (blocksize = MIN_SIZE; blocksize <= CHUNK_SIZE; blocksize += MIN_SIZE) { + if (blocksize - INT_SIZE >= size) { + if (matchsize == 0) // our real size + matchsize = blocksize; + freeblock = getFirstBlock(blocksize); + if (freeblock != 0) + break; + } + } + + // get the block + Chunk chunk; + if (freeblock == 0) { + // Out of memory, allocate a new chunk + int i = createChunk(); + chunk = toc[i]; + freeblock = i * CHUNK_SIZE; + blocksize = CHUNK_SIZE; + } else { + chunk = getChunk(freeblock); + removeBlock(chunk, blocksize, freeblock); + } + + if (blocksize != matchsize) { + // Add in the unused part of our block + addBlock(chunk, blocksize - matchsize, freeblock + matchsize); + } + + // Make our size negative to show in use + chunk.putInt(freeblock, - matchsize); + + return freeblock + INT_SIZE; + } + + private int createChunk() throws IOException { + int offset = (int)file.length(); + file.seek(offset); + file.write(new byte[CHUNK_SIZE]); + Chunk[] oldtoc = toc; + int i = oldtoc.length; + toc = new Chunk[i + 1]; + System.arraycopy(oldtoc, 0, toc, 0, i); + toc[i] = new Chunk(file, offset); + return i; + } + + private int getFirstBlock(int blocksize) { + return toc[0].getInt((blocksize / MIN_SIZE) * INT_SIZE); + } + + private void setFirstBlock(int blocksize, int block) { + toc[0].putInt((blocksize / MIN_SIZE) * INT_SIZE, block); + } + + private void removeBlock(Chunk chunk, int blocksize, int block) throws IOException { + int prevblock = chunk.getInt(block + PREV_OFFSET); + int nextblock = chunk.getInt(block + NEXT_OFFSET); + if (prevblock != 0) + putInt(prevblock + NEXT_OFFSET, nextblock); + else // we were the head + setFirstBlock(blocksize, nextblock); + + if (nextblock != 0) + putInt(nextblock + PREV_OFFSET, prevblock); + } + + private void addBlock(Chunk chunk, int blocksize, int block) throws IOException { + // Mark our size + chunk.putInt(block, blocksize); + + // Add us to the head of the list + int prevfirst = getFirstBlock(blocksize); + chunk.putInt(block + PREV_OFFSET, 0); + chunk.putInt(block + NEXT_OFFSET, prevfirst); + if (prevfirst != 0) + putInt(prevfirst + PREV_OFFSET, block); + setFirstBlock(blocksize, block); + } + + /** + * Free an allocate block. + * + * @param offset + */ + public void free(int offset) throws IOException { + // TODO - look for opportunities to merge blocks + int block = offset - INT_SIZE; + Chunk chunk = getChunk(block); + int blocksize = - chunk.getInt(block); + addBlock(chunk, blocksize, block); + } + + public void putInt(int offset, int value) throws IOException { + Chunk chunk = getChunk(offset); + chunk.putInt(offset, value); + } + + public int getInt(int offset) throws IOException { + Chunk chunk = getChunk(offset); + return chunk.getInt(offset); + } + + public void putChars(int offset, char[] value) throws IOException { + Chunk chunk = getChunk(offset); + chunk.putChars(offset, value); + } + + public char[] getChars(int offset) throws IOException { + Chunk chunk = getChunk(offset); + return chunk.getChars(offset); + } + + public void putString(int offset, String value) throws IOException { + Chunk chunk = getChunk(offset); + chunk.putString(offset, value); + } + + public String getString(int offset) throws IOException { + Chunk chunk = getChunk(offset); + return chunk.getString(offset); + } + + public int getNumChunks() { + return toc.length; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeComparator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeComparator.java new file mode 100644 index 00000000000..e418cb22e42 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeComparator.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; + +/** + * @author Doug Schaefer + * + */ +public interface IBTreeComparator { + + /** + * Compare two records. Used for insert. + * + * @param record1 + * @param record2 + * @return + * @throws IOException + */ + public abstract int compare(int record1, int record2) throws IOException; + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeVisitor.java new file mode 100644 index 00000000000..ccbd6a29ede --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IBTreeVisitor.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; + +/** + * @author Doug Schaefer + * + * The visitor walks through the tree until the compare returns + * >= 0, i.e. we reach the first record that meets the criteria. + * + * It then continues until the visit returns false. + * + */ +public interface IBTreeVisitor { + + /** + * Compare the record against an internally held key. + * Used for visiting. + * + * @param record + * @return -1 if record < key, 0 if record == key, 1 if record > key + * @throws IOException + */ + public abstract int compare(int record) throws IOException; + + /** + * Visit a given record and return whether to continue or not. + * + * @param record + * @return + * @throws IOException + */ + public abstract boolean visit(int record) throws IOException; + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringComparator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringComparator.java new file mode 100644 index 00000000000..9446a149687 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringComparator.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; + +/** + * @author Doug Schaefer + * + */ +public class StringComparator implements IBTreeComparator { + + protected Database db; + protected int offset; + + public StringComparator(Database db, int offset) { + this.db = db; + this.offset = offset; + } + + public int compare(int record1, int record2) throws IOException { + Chunk chunk1 = db.getChunk(record1); + Chunk chunk2 = db.getChunk(record2); + + int i1 = record1 + offset; + int i2 = record2 + offset; + char c1 = chunk1.getChar(i1); + char c2 = chunk2.getChar(i2); + + while (c1 != 0 && c2 != 0) { + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + + i1 += 2; + i2 += 2; + c1 = chunk1.getChar(i1); + c2 = chunk2.getChar(i2); + } + + if (c1 == c2) + return 0; + else if (c1 == 0) + return -1; + else + return 1; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringVisitor.java new file mode 100644 index 00000000000..c5f990ab854 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/StringVisitor.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2005 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.db; + +import java.io.IOException; + +/** + * @author Doug Schaefer + * + */ +public abstract class StringVisitor implements IBTreeVisitor { + + public final Database db; + private final int offset; + private final String key; + + public StringVisitor(Database db, int offset, String key) { + this.db = db; + this.offset = offset; + this.key = key; + } + + public int compare(int record) throws IOException { + Chunk chunk = db.getChunk(record); + int i1 = record + offset; + int i2 = 0; + int n2 = key.length(); + char c1 = chunk.getChar(i1); + char c2 = i2 < n2 ? key.charAt(i2) : 0; + + while (c1 != 0 && c2 != 0) { + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + + i1 += 2; + i2 += 1; + c1 = chunk.getChar(i1); + c2 = i2 < n2 ? key.charAt(i2) : 0; + } + + if (c1 == c2) + return 0; + else if (c1 == 0) + return -1; + else + return 1; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMBinding.java new file mode 100644 index 00000000000..245474718b3 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMBinding.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2005 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.dom; + +import java.io.IOException; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.internal.core.pdom.PDOMDatabase; +import org.eclipse.cdt.internal.core.pdom.PDOMUtils; +import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; +import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @author Doug Schaefer + * + */ +public class PDOMBinding implements IBinding { + + protected final PDOMDatabase pdom; + protected int record; + + private static final int STRING_REC_OFFSET = 0; // size 4 + private static final int FIRST_DECL_OFFSET = 4; // size 4 + private static final int FIRST_DEF_OFFSET = 8; // size 4 + private static final int FIRST_REF_OFFSET = 12; // size 4 + private static final int LANGUAGE_OFFSET = 16; // size 2 + private static final int TYPE_OFFSET = 18; // size 2 + + protected int getRecordSize() { + return 20; + } + + public static class Comparator implements IBTreeComparator { + + private Database db; + + public Comparator(Database db) { + this.db = db; + } + + public int compare(int record1, int record2) throws IOException { + int string1 = db.getInt(record1 + STRING_REC_OFFSET); + int string2 = db.getInt(record2 + STRING_REC_OFFSET); + + return PDOMUtils.stringCompare(db, string1, string2); + } + + } + + public abstract static class Visitor implements IBTreeVisitor { + + private Database db; + private char[] key; + + public Visitor(Database db, char[] key) { + this.db = db; + this.key = key; + } + + public int compare(int record1) throws IOException { + int string1 = db.getInt(record1 + STRING_REC_OFFSET); + + return PDOMUtils.stringCompare(db, string1, key); + } + + } + + public static class FindVisitor extends Visitor { + + private int record; + + public FindVisitor(Database db, char[] stringKey) { + super(db, stringKey); + } + + public boolean visit(int record) throws IOException { + this.record = record; + return false; + } + + public int findIn(BTree btree) throws IOException { + btree.visit(this); + return record; + } + + } + + public PDOMBinding(PDOMDatabase pdom, IASTName name, IBinding binding) throws CoreException { + try { + this.pdom = pdom; + + char[] namechars = name.toCharArray(); + + BTree index = pdom.getBindingIndex(); + record = new FindVisitor(pdom.getDB(), namechars).findIn(index); + + if (record == 0) { + Database db = pdom.getDB(); + record = db.malloc(getRecordSize()); + + int stringRecord = db.malloc((namechars.length + 1) * Database.CHAR_SIZE); + db.putChars(stringRecord, namechars); + + db.putInt(record + STRING_REC_OFFSET, stringRecord); + pdom.getBindingIndex().insert(record, new Comparator(db)); + } + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "Failed to allocate binding", e)); + } + } + + public PDOMBinding(PDOMDatabase pdom, int bindingRecord) { + this.pdom = pdom; + this.record = bindingRecord; + } + + public int getRecord() { + return record; + } + + public void addDeclaration(PDOMName name) throws IOException { + PDOMName firstDeclaration = getFirstDeclaration(); + if (firstDeclaration != null) { + firstDeclaration.setPrevInBinding(name); + name.setNextInBinding(firstDeclaration); + } + pdom.getDB().putInt(record + FIRST_DECL_OFFSET, name.getRecord()); + } + + public PDOMName getFirstDeclaration() throws IOException { + int firstDeclRec = pdom.getDB().getInt(record + FIRST_DECL_OFFSET); + return firstDeclRec != 0 ? new PDOMName(pdom, firstDeclRec) : null; + } + + public String getName() { + try { + Database db = pdom.getDB(); + int stringRecord = db.getInt(record + STRING_REC_OFFSET); + return db.getString(stringRecord); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "PDOMString", e))); + return ""; + } + } + + public char[] getNameCharArray() { + try { + Database db = pdom.getDB(); + int stringRecord = db.getInt(record + STRING_REC_OFFSET); + return db.getChars(stringRecord); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "PDOMString", e))); + return new char[0]; + } + } + + public IScope getScope() throws DOMException { + // TODO implement this + return null; + } + + public static PDOMBinding find(PDOMDatabase pdom, char[] name) throws IOException { + BTree index = pdom.getBindingIndex(); + int bindingRecord = new FindVisitor(pdom.getDB(), name).findIn(index); + if (bindingRecord != 0) + return new PDOMBinding(pdom, bindingRecord); + else + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMFile.java new file mode 100644 index 00000000000..f1217abf95a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMFile.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2005 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.dom; + +import java.io.IOException; + +import org.eclipse.cdt.internal.core.pdom.PDOMDatabase; +import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.db.StringComparator; +import org.eclipse.cdt.internal.core.pdom.db.StringVisitor; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Represents a file containing names. + * + * @author Doug Schaefer + * + */ +public class PDOMFile { + + private PDOMDatabase pdom; + private int record; + + private static final int FIRST_NAME_OFFSET = 0; + private static final int FILE_NAME_OFFSET = Database.INT_SIZE; + + public static class Comparator extends StringComparator { + + public Comparator(Database db) { + super(db, FILE_NAME_OFFSET); + } + } + + public abstract static class Visitor extends StringVisitor { + + public Visitor(Database db, String key) { + super(db, FILE_NAME_OFFSET, key); + } + } + + public static class FindVisitor extends Visitor { + + private int record; + + public FindVisitor(Database db, String key) { + super(db, key); + } + + public boolean visit(int record) throws IOException { + this.record = record; + return false; + } + + public int findIn(BTree btree) throws IOException { + btree.visit(this); + return record; + } + + } + + public static PDOMFile insert(PDOMDatabase pdom, String filename) throws IOException { + BTree index = pdom.getFileIndex(); + PDOMFile pdomFile = find(pdom, filename); + if (pdomFile == null) { + Database db = pdom.getDB(); + int record = db.malloc(FILE_NAME_OFFSET + (filename.length() + 1) * Database.CHAR_SIZE); + db.putInt(record + FIRST_NAME_OFFSET, 0); + db.putString(record + FILE_NAME_OFFSET, filename); + index.insert(record, new Comparator(db)); + pdomFile = new PDOMFile(pdom, record); + } + return pdomFile; + } + + public static PDOMFile find(PDOMDatabase pdom, String filename) throws IOException { + BTree index = pdom.getFileIndex(); + int record = new FindVisitor(pdom.getDB(), filename).findIn(index); + return (record != 0) ? new PDOMFile(pdom, record) : null; + } + + public PDOMFile(PDOMDatabase pdom, int record) { + this.pdom = pdom; + this.record = record; + } + + public int getRecord() { + return record; + } + + public String getFileName() throws IOException { + return pdom.getDB().getString(record + FILE_NAME_OFFSET); + } + + public int getFirstName() throws IOException { + return pdom.getDB().getInt(record + FIRST_NAME_OFFSET); + } + + public void setFirstName(int firstName) throws IOException { + pdom.getDB().putInt(record + FIRST_NAME_OFFSET, firstName); + } + + public void free() throws CoreException { + try { + pdom.getDB().free(record); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "Failed to free string", e)); + } + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMName.java new file mode 100644 index 00000000000..7c62d49f80c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMName.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright (c) 2005 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.dom; + +import java.io.IOException; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope2; +import org.eclipse.cdt.internal.core.pdom.PDOMDatabase; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.pdom.core.PDOMCorePlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @author Doug Schaefer + * + */ +public class PDOMName implements IASTName, IASTFileLocation { + + private final PDOMDatabase pdom; + private final int record; + + private static final int FILE_REC_OFFSET = 0 * Database.INT_SIZE; + private static final int FILE_PREV_OFFSET = 1 * Database.INT_SIZE; + private static final int FILE_NEXT_OFFSET = 2 * Database.INT_SIZE; + private static final int BINDING_REC_OFFET = 3 * Database.INT_SIZE; + private static final int BINDING_PREV_OFFSET = 4 * Database.INT_SIZE; + private static final int BINDING_NEXT_OFFSET = 5 * Database.INT_SIZE; + private static final int NODE_OFFSET_OFFSET = 6 * Database.INT_SIZE; + private static final int NODE_LENGTH_OFFSET = 7 * Database.INT_SIZE; + + private static final int RECORD_SIZE = 8 * Database.INT_SIZE; + + public PDOMName(PDOMDatabase pdom, IASTName name, PDOMBinding binding) throws CoreException { + try { + this.pdom = pdom; + Database db = pdom.getDB(); + record = db.malloc(RECORD_SIZE); + + // Hook us up to the binding + if (binding != null) { + db.putInt(record + BINDING_REC_OFFET, binding.getRecord()); + if (name.isDeclaration()) + binding.addDeclaration(this); + } + + // Hook us up the the liked name list from file + IASTFileLocation fileloc = name.getFileLocation(); + String filename = fileloc.getFileName(); + PDOMFile pdomFile = PDOMFile.insert(pdom, filename); + db.putInt(record + FILE_REC_OFFSET, pdomFile.getRecord()); + int firstName = pdomFile.getFirstName(); + if (firstName != 0) { + db.putInt(record + FILE_NEXT_OFFSET, firstName); + db.putInt(firstName + FILE_PREV_OFFSET, record); + } + pdomFile.setFirstName(record); + + db.putInt(record + NODE_OFFSET_OFFSET, fileloc.getNodeOffset()); + db.putInt(record + NODE_LENGTH_OFFSET, fileloc.getNodeLength()); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "Failed to allocate name", e)); + } + } + + public PDOMName(PDOMDatabase pdom, int nameRecord) throws IOException { + this.pdom = pdom; + this.record = nameRecord; + } + + public int getRecord() { + return record; + } + + public void setBinding(PDOMBinding binding) throws IOException { + pdom.getDB().putInt(record + BINDING_REC_OFFET, binding.getRecord()); + } + + public void setPrevInBinding(PDOMName prevName) throws IOException { + pdom.getDB().putInt(record + BINDING_PREV_OFFSET, prevName.getRecord()); + } + + public void setNextInBinding(PDOMName nextName) throws IOException { + pdom.getDB().putInt(record + BINDING_NEXT_OFFSET, nextName.getRecord()); + } + + public IBinding resolveBinding() { + try { + int bindingRecord = pdom.getDB().getInt(record + BINDING_REC_OFFET); + return new PDOMBinding(pdom, bindingRecord); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "Failed to allocate name", e))); + return null; + } + } + + public IBinding getBinding() { + throw new PDOMNotImplementedError(); + } + + public void setBinding(IBinding binding) { + throw new PDOMNotImplementedError(); + } + + public IBinding[] resolvePrefix() { + throw new PDOMNotImplementedError(); + } + + public char[] toCharArray() { + try { + Database db = pdom.getDB(); + int bindingRec = db.getInt(record + BINDING_REC_OFFET); + if (bindingRec == 0) + return null; + + return new PDOMBinding(pdom, bindingRec).getNameCharArray(); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "Failed to allocate name", e))); + return null; + } + } + + public boolean isDeclaration() { + throw new PDOMNotImplementedError(); + } + + public boolean isReference() { + throw new PDOMNotImplementedError(); + } + + public boolean isDefinition() { + throw new PDOMNotImplementedError(); + } + + public IASTTranslationUnit getTranslationUnit() { + // TODO Bug 115367 this is dumb - only need for validation checks + return new PDOMTranslationUnit(); + } + + public IASTNodeLocation[] getNodeLocations() { + throw new PDOMNotImplementedError(); + } + + public IASTFileLocation getFileLocation() { + return this; + } + + public String getContainingFilename() { + throw new PDOMNotImplementedError(); + } + + public IASTNode getParent() { + throw new PDOMNotImplementedError(); + } + + public void setParent(IASTNode node) { + throw new PDOMNotImplementedError(); + } + + public ASTNodeProperty getPropertyInParent() { + throw new PDOMNotImplementedError(); + } + + public void setPropertyInParent(ASTNodeProperty property) { + throw new PDOMNotImplementedError(); + } + + public boolean accept(ASTVisitor visitor) { + throw new PDOMNotImplementedError(); + } + + public String getRawSignature() { + throw new PDOMNotImplementedError(); + } + + public int getEndingLineNumber() { + throw new PDOMNotImplementedError(); + } + + public String getFileName() { + try { + return new PDOMFile(pdom, pdom.getDB().getInt(record + FILE_REC_OFFSET)).getFileName(); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "PDOM Exception", e))); + return null; + } + } + + public int getStartingLineNumber() { + throw new PDOMNotImplementedError(); + } + + public IASTFileLocation asFileLocation() { + throw new PDOMNotImplementedError(); + } + + public int getNodeLength() { + try { + return pdom.getDB().getInt(record + NODE_LENGTH_OFFSET); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "PDOM Exception", e))); + return 0; + } + } + + public int getNodeOffset() { + try { + return pdom.getDB().getInt(record + NODE_OFFSET_OFFSET); + } catch (IOException e) { + PDOMCorePlugin.log(new CoreException(new Status(IStatus.ERROR, + PDOMCorePlugin.ID, 0, "PDOM Exception", e))); + return 0; + } + } + + public IScope2 getScope(IASTNode child, ASTNodeProperty childProperty) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMNotImplementedError.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMNotImplementedError.java new file mode 100644 index 00000000000..68c6370a6e5 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMNotImplementedError.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2005 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.dom; + +/** + * @author Doug Schaefer + * + */ +public class PDOMNotImplementedError extends Error { + + public static final long serialVersionUID = 0; + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMTranslationUnit.java new file mode 100644 index 00000000000..c2da38458e8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/pdom/dom/PDOMTranslationUnit.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2005 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.dom; + +import org.eclipse.cdt.core.dom.IPDOM; +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.IScope2; +import org.eclipse.cdt.core.parser.ParserLanguage; + +/** + * @author Doug Schaefer + * + * This is really a dummy translation unit that is necessary for names + * to be valid. + */ +public class PDOMTranslationUnit implements IASTTranslationUnit { + + public IASTDeclaration[] getDeclarations() { + throw new PDOMNotImplementedError(); + } + + public void addDeclaration(IASTDeclaration declaration) { + throw new PDOMNotImplementedError(); + } + + public IScope getScope() { + throw new PDOMNotImplementedError(); + } + + public IASTName[] getDeclarations(IBinding binding) { + throw new PDOMNotImplementedError(); + } + + public IASTName[] getDefinitions(IBinding binding) { + throw new PDOMNotImplementedError(); + } + + public IASTName[] getReferences(IBinding binding) { + throw new PDOMNotImplementedError(); + } + + public IASTNodeLocation[] getLocationInfo(int offset, int length) { + throw new PDOMNotImplementedError(); + } + + public IASTNode selectNodeForLocation(String path, int offset, int length) { + throw new PDOMNotImplementedError(); + } + + public IASTPreprocessorMacroDefinition[] getMacroDefinitions() { + throw new PDOMNotImplementedError(); + } + + public IASTPreprocessorIncludeStatement[] getIncludeDirectives() { + throw new PDOMNotImplementedError(); + } + + public IASTPreprocessorStatement[] getAllPreprocessorStatements() { + throw new PDOMNotImplementedError(); + } + + public IASTProblem[] getPreprocessorProblems() { + throw new PDOMNotImplementedError(); + } + + public String getUnpreprocessedSignature(IASTNodeLocation[] locations) { + throw new PDOMNotImplementedError(); + } + + public String getFilePath() { + throw new PDOMNotImplementedError(); + } + + public IASTFileLocation flattenLocationsToFile( + IASTNodeLocation[] nodeLocations) { + throw new PDOMNotImplementedError(); + } + + public IDependencyTree getDependencyTree() { + throw new PDOMNotImplementedError(); + } + + public String getContainingFilename(int offset) { + throw new PDOMNotImplementedError(); + } + + public ParserLanguage getParserLanguage() { + throw new PDOMNotImplementedError(); + } + + public IPDOM getIndex() { + throw new PDOMNotImplementedError(); + } + + public void setIndex(IPDOM pdom) { + throw new PDOMNotImplementedError(); + } + + public IASTTranslationUnit getTranslationUnit() { + throw new PDOMNotImplementedError(); + } + + public IASTNodeLocation[] getNodeLocations() { + throw new PDOMNotImplementedError(); + } + + public IASTFileLocation getFileLocation() { + throw new PDOMNotImplementedError(); + } + + public String getContainingFilename() { + throw new PDOMNotImplementedError(); + } + + public IASTNode getParent() { + throw new PDOMNotImplementedError(); + } + + public void setParent(IASTNode node) { + throw new PDOMNotImplementedError(); + } + + public ASTNodeProperty getPropertyInParent() { + throw new PDOMNotImplementedError(); + } + + public void setPropertyInParent(ASTNodeProperty property) { + throw new PDOMNotImplementedError(); + } + + public boolean accept(ASTVisitor visitor) { + throw new PDOMNotImplementedError(); + } + + public String getRawSignature() { + throw new PDOMNotImplementedError(); + } + + public IScope2 getScope(IASTNode child, ASTNodeProperty childProperty) { + throw new PDOMNotImplementedError(); + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/pdom/core/PDOMCorePlugin.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/pdom/core/PDOMCorePlugin.java new file mode 100644 index 00000000000..7b73e59b65b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/pdom/core/PDOMCorePlugin.java @@ -0,0 +1,50 @@ +package org.eclipse.cdt.pdom.core; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Plugin; +import org.osgi.framework.BundleContext; + +/** + * The main plugin class to be used in the desktop. + */ +public class PDOMCorePlugin extends Plugin { + + public static final String ID = "org.eclipse.cdt.pdom.core"; //$NON-NLS-1$ + + //The shared instance. + private static PDOMCorePlugin plugin; + + /** + * The constructor. + */ + public PDOMCorePlugin() { + plugin = this; + } + + /** + * This method is called upon plug-in activation + */ + public void start(BundleContext context) throws Exception { + super.start(context); + } + + /** + * This method is called when the plug-in is stopped + */ + public void stop(BundleContext context) throws Exception { + super.stop(context); + plugin = null; + } + + /** + * Returns the shared instance. + */ + public static PDOMCorePlugin getDefault() { + return plugin; + } + + public static void log(CoreException e) { + plugin.getLog().log(e.getStatus()); + } + +} diff --git a/core/org.eclipse.cdt.core/plugin.properties b/core/org.eclipse.cdt.core/plugin.properties index af47d7cd99c..954026614a8 100644 --- a/core/org.eclipse.cdt.core/plugin.properties +++ b/core/org.eclipse.cdt.core/plugin.properties @@ -70,4 +70,6 @@ asmSourceName=Assembly Source File cdt_pathentry_var.description=CDT PathEntry Variable -PDOMProviderName=PDOM Provider \ No newline at end of file +PDOMProviderName=PDOM Provider + +language.name=Language \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index 4d2f7f5bbc3..294bd2483a8 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -44,6 +44,7 @@ + @@ -575,6 +576,21 @@ class="org.eclipse.cdt.internal.core.SystemBuildConsole" id="org.eclipse.cdt.core.systemConsole"/> + + + + + + + + diff --git a/core/org.eclipse.cdt.core/schema/language.exsd b/core/org.eclipse.cdt.core/schema/language.exsd new file mode 100644 index 00000000000..6f2c891eabb --- /dev/null +++ b/core/org.eclipse.cdt.core/schema/language.exsd @@ -0,0 +1,134 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index 51edecd6a91..856dca21f79 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -87,6 +87,7 @@ public class CCorePlugin extends Plugin { public static final String INDEXER_SIMPLE_ID = "CIndexer"; //$NON-NLS-1$ public static final String INDEXER_UNIQ_ID = PLUGIN_ID + "." + INDEXER_SIMPLE_ID; //$NON-NLS-1$ public final static String PREF_INDEXER = "indexer"; //$NON-NLS-1$ + public final static String USE_PDOM_PREF = "usePDOM"; //$NON-NLS-1$ public final static String DEFAULT_INDEXER_SIMPLE_ID = "domsourceindexer"; //$NON-NLS-1$ public final static String NULL_INDEXER_SIMPLE_ID = "nullindexer"; //$NON-NLS-1$ public final static String NULL_INDEXER_UNIQUE_ID = PLUGIN_ID + "." + NULL_INDEXER_SIMPLE_ID ; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/dom/PDOM.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/dom/PDOM.java index 061fc828d09..9980b39fdca 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/dom/PDOM.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/dom/PDOM.java @@ -10,15 +10,21 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IElementChangedListener; import org.eclipse.cdt.internal.core.dom.NullPDOMProvider; +import org.eclipse.cdt.internal.core.pdom.PDOMManager; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.osgi.service.prefs.BackingStoreException; /** * @author Doug Schaefer @@ -56,6 +62,37 @@ public class PDOM { return pdomProvider; } + private static final String PDOM_NODE = CCorePlugin.PLUGIN_ID + ".pdom"; //$NON-NLS-1$ + private static final String ENABLED_KEY = "enabled"; //$NON-NLS-1$ + + private static IEclipsePreferences getPreferences(IProject project) { + IScopeContext projectScope = new ProjectScope(project); + if (projectScope == null) + return null; + else + return projectScope.getNode(PDOM_NODE); + } + + public static boolean isEnabled(IProject project) { + IEclipsePreferences prefs = getPreferences(project); + if (prefs == null) + return false; + else + return prefs.getBoolean(ENABLED_KEY, false); + } + + public static void setEnabled(IProject project, boolean enabled) { + IEclipsePreferences prefs = getPreferences(project); + if (prefs == null) + return; + + prefs.putBoolean(ENABLED_KEY, enabled); + try { + prefs.flush(); + } catch (BackingStoreException e) { + } + } + /** * Get the PDOM for the given project. * @@ -63,11 +100,15 @@ public class PDOM { * @return the PDOM for the project */ public static IPDOM getPDOM(IProject project) { - return getPDOMProvider().getPDOM(project); + if (isEnabled(project)) + return PDOMManager.getInstance().getPDOM(project); + else + return null; } public static void deletePDOM(IProject project) throws CoreException { - getPDOMProvider().getPDOM(project).delete(); + if (isEnabled(project)) + getPDOMProvider().getPDOM(project).delete(); } /** diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties index d2378c085a9..3938be3b6a3 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties @@ -68,3 +68,5 @@ PathEntryVariableResolver.0=CDT PathEntry variable not specified CTagsIndexMarker.fileMissing=CTags output file missing CTagsIndexMarker.CTagsMissing=CTags not installed or not in path DOMIndexerMarker.EmptyScannerInfo=File not indexed because it was not built + +dom.languageError=Language not found diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/InternalASTServiceProvider.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/InternalASTServiceProvider.java index 0545dd321a6..1b575bbb7dc 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/InternalASTServiceProvider.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/InternalASTServiceProvider.java @@ -171,7 +171,7 @@ public class InternalASTServiceProvider implements IASTServiceProvider { // Parse IASTTranslationUnit tu = parser.parse(); // Set the PDOM if we can find one - tu.setPDOM(PDOM.getPDOM(project)); + tu.setIndex(PDOM.getPDOM(project)); return tu; } @@ -229,7 +229,7 @@ public class InternalASTServiceProvider implements IASTServiceProvider { parser.parse(); ASTCompletionNode node = parser.getCompletionNode(); if (node != null) { - node.getTranslationUnit().setPDOM(PDOM.getPDOM(project)); + node.getTranslationUnit().setIndex(PDOM.getPDOM(project)); node.count = scanner.getCount(); } return node; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/PartialWorkingCopyCodeReaderFactory.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/PartialWorkingCopyCodeReaderFactory.java index 1feb13ee4cb..7ca0c6ddb81 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/PartialWorkingCopyCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/PartialWorkingCopyCodeReaderFactory.java @@ -15,6 +15,7 @@ import java.util.Iterator; import org.eclipse.cdt.core.browser.IWorkingCopyProvider; import org.eclipse.cdt.core.dom.CDOM; import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.ICodeReaderCache; import org.eclipse.cdt.core.parser.ParserUtil; @@ -51,6 +52,10 @@ public class PartialWorkingCopyCodeReaderFactory return checkWorkingCopyThenCache(path); } + public CodeReader createCodeReaderForTranslationUnit(ITranslationUnit tu) { + return new CodeReader(tu.getPath().toOSString(), tu.getContents()); + } + /** * @param path * @return diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/SavedCodeReaderFactory.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/SavedCodeReaderFactory.java index 7633f3d43b0..bebb9643865 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/SavedCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/dom/SavedCodeReaderFactory.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.CDOM; import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.CodeReaderCache; import org.eclipse.cdt.core.parser.ICodeReaderCache; @@ -77,6 +78,10 @@ public class SavedCodeReaderFactory implements ICodeReaderFactory { return cache.get(path); } + public CodeReader createCodeReaderForTranslationUnit(ITranslationUnit tu) { + return new CodeReader(tu.getPath().toOSString(), tu.getContents()); + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ICodeReaderFactory#createCodeReaderForInclusion(java.lang.String) */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties index f3b5673b782..3b7457891d2 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties @@ -45,6 +45,7 @@ ErrorParserBlock.desc=Set the error parsers for this project BinaryParserBlock.label=Binary Parser BinaryParserBlock.desc=Set required binary parser for this project +BaseIndexerBlock.usePDOM=Use PDOM BaseIndexerBlock.label=C/C++ Indexer BaseIndexerBlock.desc=C/C++ Indexer setting for this project. BaseIndexerBlock.comboLabel=Available indexers diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/IndexerBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/IndexerBlock.java index 1ef45b6db17..43c1106f39a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/IndexerBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/IndexerBlock.java @@ -18,7 +18,9 @@ import java.util.List; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ICDescriptor; import org.eclipse.cdt.core.ICDescriptorOperation; +import org.eclipse.cdt.core.dom.PDOM; import org.eclipse.cdt.internal.core.index.domsourceindexer.DOMSourceIndexer; +import org.eclipse.cdt.internal.core.index.nullindexer.NullIndexer; import org.eclipse.cdt.internal.ui.CUIMessages; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.index.AbstractIndexerPage; @@ -34,11 +36,14 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; @@ -65,8 +70,9 @@ public class IndexerBlock extends AbstractCOptionPage { private static final String INDEXER_LABEL = CUIPlugin.getResourceString("BaseIndexerBlock.label" ); //$NON-NLS-1$ private static final String INDEXER_DESCRIPTION = CUIPlugin.getResourceString("BaseIndexerBlock.desc"); //$NON-NLS-1$ private static final String INDEXER_COMBO_LABEL = CUIPlugin.getResourceString("BaseIndexerBlock.comboLabel"); //$NON-NLS-1$ + private static final String INDEXER_USE_PDOM = CUIPlugin.getResourceString("BaseIndexerBlock.usePDOM"); //$NON-NLS-1$ - + private Button indexerUsePDOM; private Combo indexersComboBox; private HashMap indexerPageMap; private List indexerPageList; @@ -74,6 +80,8 @@ public class IndexerBlock extends AbstractCOptionPage { private Composite parentComposite; private ICOptionPage currentPage; + int nullIndexerIndex; + String initialSelected; private IPreferenceStore prefStore=CUIPlugin.getDefault().getPreferenceStore(); @@ -200,6 +208,23 @@ public class IndexerBlock extends AbstractCOptionPage { * @return */ private boolean createIndexerControls(Composite parent) { + // PDOM selection + indexerUsePDOM = new Button(parent, SWT.CHECK); + indexerUsePDOM.setText(INDEXER_USE_PDOM); + indexerUsePDOM.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + if (indexerUsePDOM.getSelection()) { + indexersComboBox.select(nullIndexerIndex); + setPage(); + indexersComboBox.setEnabled(false); + } else + indexersComboBox.setEnabled(true); + } + }); + indexerUsePDOM.setSelection(prefStore.getBoolean(CCorePlugin.USE_PDOM_PREF)); + //TODO: Put in some logic to deal with old CDT project: upgrade old projects //to use the Classic CDT Indexer @@ -260,6 +285,8 @@ public class IndexerBlock extends AbstractCOptionPage { for (int i = 0; i < infos.length; i++) { if (infos[i].getName().equals("indexerUI")) { //$NON-NLS-1$ String id = infos[i].getAttribute("indexerID"); //$NON-NLS-1$ + if (NullIndexer.ID.equals(id)) + nullIndexerIndex = i; indexerPageMap.put(id, new IndexerPageConfiguration(infos[i])); indexerPageList.add(id); } @@ -362,6 +389,7 @@ public class IndexerBlock extends AbstractCOptionPage { } if ( project != null) { + PDOM.setEnabled(project, indexerUsePDOM.isEnabled()); ICDescriptorOperation op = new ICDescriptorOperation() { public void execute(ICDescriptor descriptor, IProgressMonitor monitor) throws CoreException { @@ -388,6 +416,7 @@ public class IndexerBlock extends AbstractCOptionPage { if (initialSelected == null || !selected.equals(initialSelected)) { if (prefStore != null) { + prefStore.setValue(CCorePlugin.USE_PDOM_PREF, indexerUsePDOM.getEnabled()); //First clean out the old indexer settings String indexerId=prefStore.getString(CCorePlugin.PREF_INDEXER); ICOptionPage tempPage = getIndexerPage(indexerId); @@ -450,6 +479,7 @@ public class IndexerBlock extends AbstractCOptionPage { * @param project */ public void setIndexerID(String indexerID, IProject project) { + indexerUsePDOM.setSelection(PDOM.isEnabled(project)); //Get the corresponding text for the given indexer id selectedIndexerId = getIndexerPageName(indexerID); //Store the currently selected indexer id @@ -483,4 +513,21 @@ public class IndexerBlock extends AbstractCOptionPage { return indexerID; } + public IProject getProject() { + ICOptionContainer container = getContainer(); + if (container != null){ + return container.getProject(); + } else { + return ((AbstractIndexerPage)currentPage).getCurrentProject(); + } + + } + + public boolean getUsePDOM() { + IProject project = getProject(); + if (project == null) + return false; + + return PDOM.isEnabled(project); + } }