1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Moved the PDOM into the Core. Started introduction of ILanguage, the mechanism of language extensibility for the CDT.

This commit is contained in:
Doug Schaefer 2005-11-25 22:01:48 +00:00
parent 7d0a99f4e8
commit 41d26bc514
48 changed files with 3198 additions and 44 deletions

View file

@ -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);
}
}
}

View file

@ -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,

View file

@ -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();
}

View file

@ -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 (<code>.c</code> 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;
}

View file

@ -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());
}
}

View file

@ -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)

View file

@ -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.
*

View file

@ -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();
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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)
*/

View file

@ -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;
}
}

View file

@ -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;
// }
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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));
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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());
}
}

View file

@ -70,4 +70,6 @@ asmSourceName=Assembly Source File
cdt_pathentry_var.description=CDT PathEntry Variable
PDOMProviderName=PDOM Provider
PDOMProviderName=PDOM Provider
language.name=Language

View file

@ -44,6 +44,7 @@
<extension-point id="CodeFormatter" name="%CodeFormatter.name" schema="schema/CodeFormatter.exsd"/>
<extension-point id="CIndexer" name="C/C++ Indexer" schema="schema/CIndexer.exsd"/>
<extension-point id="PDOMProvider" name="%PDOMProviderName" schema="schema/PDOMProvider.exsd"/>
<extension-point id="language" name="%language.name" schema="schema/language.exsd"/>
<!-- =================================================================================== -->
<!-- Define the list of the Binary Parser provided by the CDT -->
<!-- =================================================================================== -->
@ -575,6 +576,21 @@
class="org.eclipse.cdt.internal.core.SystemBuildConsole"
id="org.eclipse.cdt.core.systemConsole"/>
</extension>
<extension
point="org.eclipse.cdt.core.language">
<language
class="org.eclipse.cdt.core.dom.ast.gnu.c.GCCLanguage"
id="gcc"
name="GNU C">
<contentType id="org.eclipse.cdt.core.cSource"/>
</language>
<language
class="org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage"
id="g++"
name="GNU C++">
<contentType id="org.eclipse.cdt.core.cxxSource"/>
</language>
</extension>
<!-- =================================================================================== -->
<!-- Dynamic Variables -->

View file

@ -0,0 +1,134 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.core">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="language" name="%language.name"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<complexType>
<sequence>
<element ref="language"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="language">
<complexType>
<sequence>
<element ref="contentType"/>
</sequence>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.core.dom.ILanguage"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="contentType">
<complexType>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiInfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>
</documentation>
</annotation>
</schema>

View file

@ -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$

View file

@ -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();
}
/**

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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)
*/

View file

@ -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

View file

@ -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);
}
}