diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java index 8ce32b281e7..cb7f52904ee 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java @@ -284,6 +284,16 @@ public class DBTest extends BaseTestCase { assertSignEquals(expected, -biss.compare(aisc, caseSensitive)); assertSignEquals(expected, -biss.compare(a, caseSensitive)); assertSignEquals(expected, -biss.comparePrefix(acs, caseSensitive)); + + if (!caseSensitive && expected != 0) { + assertSignEquals(expected, aiss.compareCompatibleWithIgnoreCase(bcs)); + assertSignEquals(expected, aiss.compareCompatibleWithIgnoreCase(biss)); + assertSignEquals(expected, aiss.compareCompatibleWithIgnoreCase(bisc)); + + assertSignEquals(expected, -biss.compareCompatibleWithIgnoreCase(acs)); + assertSignEquals(expected, -biss.compareCompatibleWithIgnoreCase(aiss)); + assertSignEquals(expected, -biss.compareCompatibleWithIgnoreCase(aisc)); + } } private void assertSignEquals(int a, int b) { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java index 3295b3e92c9..87974999174 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -103,6 +104,7 @@ public class GeneratePDOMApplicationTest extends PDOMTestBase { }); assertTrue(target.exists()); WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); + assertEquals(36, wpdom.getDB().getVersion()); // faked version, remove for CDT 4.1 verifyProject1Content(wpdom); String fid; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java index ad8507202c6..382a7a0821b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.index.provider; @@ -74,7 +75,7 @@ class PDOMCache { result.acquireReadLock(); try { - if(result.versionMismatch()) { + if(!result.isSupportedVersion()) { versionMismatch.add(file); String msg= MessageFormat.format(Messages.PDOMCache_VersionTooOld, new Object[] {file}); CCorePlugin.log(msg); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 4507ff123bb..47fe62dd09c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -6,11 +6,11 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) - * IBM Corporation - * Andrew Ferguson (Symbian) - * Anton Leherbauer (Wind River Systems) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) + * IBM Corporation + * Andrew Ferguson (Symbian) + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -73,7 +73,9 @@ import org.eclipse.core.runtime.Status; public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { protected Database db; - public static final int VERSION = 36; + public static final int CURRENT_VERSION = 37; + public static final int MIN_SUPPORTED_VERSION= 36; + public static final int MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX= 37; // to be removed in 4.1 // 0 - the beginning of it all // 1 - first change to kick off upgrades // 2 - added file inclusions @@ -111,17 +113,24 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { // 34 - fix for base classes represented by qualified names (183843) // 35 - add scanner configuration hash-code (62366) // 36 - changed chunk size back to 4K (184892) + // 37 - added index for nested bindings (189811), compatible with version 36. public static final int LINKAGES = Database.DATA_AREA; public static final int FILE_INDEX = Database.DATA_AREA + 4; public static final int PROPERTIES = Database.DATA_AREA + 8; - + public static final int HAS_NESTED_BINDING_BTREES= Database.DATA_AREA + 12; + public static final int END= Database.DATA_AREA + 13; + static { + assert END <= Database.CHUNK_SIZE; + } + // Local caches private BTree fileIndex; private Map fLinkageIDCache = new HashMap(); private File fPath; private IIndexLocationConverter locationConverter; private Map fPDOMLinkageFactoryCache; + private boolean fHasBTreeForNestedBindings; public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map linkageFactoryMappings) throws CoreException { this(dbPath, locationConverter, ChunkCache.getSharedInstance(), linkageFactoryMappings); @@ -144,13 +153,22 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { fPath= dbPath; final boolean lockDB= db == null || lockCount != 0; - db = new Database(fPath, cache, VERSION, isPermanentlyReadOnly()); + db = new Database(fPath, cache, CURRENT_VERSION, isPermanentlyReadOnly()); fileIndex= null; // holds on to the database, so clear it. db.setLocked(lockDB); int version= db.getVersion(); - if (version == VERSION) { + if (version >= MIN_SUPPORTED_VERSION) { readLinkages(); + fHasBTreeForNestedBindings= db.getByte(HAS_NESTED_BINDING_BTREES) == 1; + + // new PDOM with version ready to write nested bindings index + if (version >= MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX) { + if (!fHasBTreeForNestedBindings && !isPermanentlyReadOnly()) { + fHasBTreeForNestedBindings= true; + db.putByte(HAS_NESTED_BINDING_BTREES, (byte) 1); + } + } } db.setLocked(lockCount != 0); } @@ -159,11 +177,12 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { return locationConverter; } - public boolean versionMismatch() throws CoreException { - if (db.getVersion() != VERSION) { - return true; - } else - return false; + public boolean isCurrentVersion() throws CoreException { + return db.getVersion() == CURRENT_VERSION; + } + + public boolean isSupportedVersion() throws CoreException { + return db.getVersion() >= MIN_SUPPORTED_VERSION; } public void accept(IPDOMVisitor visitor) throws CoreException { @@ -247,7 +266,9 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { assert lockCount < 0; // needs write-lock. // Clear out the database, everything is set to zero. - getDB().clear(VERSION); + db.clear(CURRENT_VERSION); + db.putByte(HAS_NESTED_BINDING_BTREES, (byte) 1); + fHasBTreeForNestedBindings= true; clearCaches(); } @@ -713,26 +734,22 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { PDOMLinkage linkage= (PDOMLinkage) iter.next(); if (filter.acceptLinkage(linkage)) { IBinding[] bindings; - if(filescope) { - BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, false); - visitor.setMonitor(monitor); - try { - linkage.accept(visitor); + BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, false); + visitor.setMonitor(monitor); + try { + linkage.accept(visitor); + if (!filescope) { + if (fHasBTreeForNestedBindings) { + linkage.getNestedBindingsIndex().accept(visitor); + } + else { + linkage.accept(new ApplyVisitor(linkage, visitor)); + } } - catch (OperationCanceledException e) { - } - bindings= visitor.getBindings(); - } else { - BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, false); - visitor.setMonitor(monitor); - try { - linkage.accept(visitor); - linkage.accept(new ApplyVisitor(linkage, visitor)); - } - catch (OperationCanceledException e) { - } - bindings= visitor.getBindings(); } + catch (OperationCanceledException e) { + } + bindings= visitor.getBindings(); for (int j = 0; j < bindings.length; j++) { result.add(bindings[j]); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java index 086d08329d6..00d4e5bfb6d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java @@ -46,6 +46,7 @@ public class PDOMIndexerJob extends Job { } protected IStatus run(IProgressMonitor monitor) { + final long start= System.currentTimeMillis(); fMonitor = monitor; String taskName = CCorePlugin.getResourceString("pdom.indexer.task"); //$NON-NLS-1$ monitor.beginTask(taskName, TOTAL_MONITOR_WORK); @@ -97,6 +98,16 @@ public class PDOMIndexerJob extends Job { } } while (currentTask != null); + + // work-around for https://bugs.eclipse.org/bugs/show_bug.cgi?id=197258 + long rest= 100-(System.currentTimeMillis()-start); + if (rest > 0) { + try { + Thread.sleep(rest); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } return Status.OK_STATUS; } catch (RuntimeException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 9613e9381b3..f89ce2babe5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -327,7 +327,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } WritablePDOM pdom= new WritablePDOM(dbFile, new PDOMProjectIndexLocationConverter(rproject), LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); - if (pdom.versionMismatch() || fromScratch) { + if (!pdom.isSupportedVersion() || fromScratch) { try { pdom.acquireWriteLock(); } catch (InterruptedException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java index fa03036f143..75a7614a9ae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java @@ -203,7 +203,7 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable { WritablePDOM pdom= (WritablePDOM) obj; pdom.acquireReadLock(); try { - if (pdom.versionMismatch()) { + if (!pdom.isSupportedVersion()) { throw new CoreException(CCorePlugin.createStatus( NLS.bind(Messages.PDOMImportTask_errorInvalidPDOMVersion, fProject.getElementName()))); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java index cb35bb7f6af..6cdb683423d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java @@ -1,14 +1,14 @@ /******************************************************************************* - * Copyright (c) 2005, 2006 QNX Software Systems and others. + * Copyright (c) 2005, 2007 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 - * Andrew Ferguson (Symbian) - Provide B-tree deletion routine - * Markus Schorn (Wind River Systems) + * QNX - Initial API and implementation + * Andrew Ferguson (Symbian) - Provide B-tree deletion routine + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -47,7 +47,7 @@ public class BTree { } /** - * Contructor. + * Constructor. * * @param db the database containing the btree * @param root offset into database of the pointer to the root node @@ -160,24 +160,34 @@ public class BTree { } } - // search to find the insert point - int i; - for (i = 0; i < MAX_RECORDS; ++i) { - int record1 = getRecord(chunk, node, i); - if (record1 == 0) { - // past the end - break; - } else { - int compare = cmp.compare(record1, record); - if (compare == 0) - // found it, no insert, just return the record - return record; - else if (compare > 0) - // past it - break; - } + // binary search to find the insert point + int lower= 0; + int upper= MAX_RECORDS-1; + while (lower < upper && getRecord(chunk, node, upper-1) == 0) { + upper--; } + while (lower < upper) { + int middle= (lower+upper)/2; + int checkRec= getRecord(chunk, node, middle); + if (checkRec == 0) { + upper= middle; + } + else { + int compare= cmp.compare(checkRec, record); + if (compare > 0) { + upper= middle; + } + else if (compare < 0) { + lower= middle+1; + } + else { + // found it, no insert, just return the record + return record; + } + } + } + final int i= lower; int child = getChild(chunk, node, i); if (child != 0) { // visit the children @@ -472,7 +482,7 @@ public class BTree { * @param src the node to read from * @param srcPos the initial index to read from (inclusive) * @param dst the node to write to - * @param dstPos the intial index to write to (inclusive) + * @param dstPos the initial index to write to (inclusive) * @param length the number of (key,(predecessor)child) nodes to write */ private void nodeContentCopy(BTNode src, int srcPos, BTNode dst, int dstPos, int length) { @@ -538,14 +548,38 @@ public class BTree { try { Chunk chunk = db.getChunk(node); - - int i= 0; + + // binary search to find first record greater or equal + int lower= 0; + int upper= MAX_RECORDS-1; + while (lower < upper && getRecord(chunk, node, upper-1) == 0) { + upper--; + } + while (lower < upper) { + int middle= (lower+upper)/2; + int checkRec= getRecord(chunk, node, middle); + if (checkRec == 0) { + upper= middle; + } + else { + int compare= visitor.compare(checkRec); + if (compare >= 0) { + upper= middle; + } + else { + lower= middle+1; + } + } + } + + // start with first record greater or equal, reuse comparison results. + int i= lower; for (; i < MAX_RECORDS; ++i) { int record = getRecord(chunk, node, i); if (record == 0) break; - int compare = visitor.compare(record); + int compare= visitor.compare(record); if (compare > 0) { // start point is to the left return accept(getChild(chunk, node, i), visitor); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java index 6135b4e1bc1..687b10c7235 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java @@ -6,10 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Symbian - Add some non-javadoc implementation notes - * Markus Schorn (Wind River Systems) - * IBM Corporation + * QNX - Initial API and implementation + * Symbian - Add some non-javadoc implementation notes + * Markus Schorn (Wind River Systems) + * IBM Corporation *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -111,7 +111,7 @@ public class Database { } else { fHeaderChunk.read(); - fVersion= fHeaderChunk.getInt(0); + fVersion= fHeaderChunk.getInt(VERSION_OFFSET); fChunks = new Chunk[nChunksOnDisk]; // chunk[0] is unused. } } catch (IOException e) { @@ -139,7 +139,7 @@ public class Database { public void setVersion(int version) throws CoreException { assert fExclusiveLock; - fHeaderChunk.putInt(0, version); + fHeaderChunk.putInt(VERSION_OFFSET, version); fVersion= version; } @@ -574,7 +574,7 @@ public class Database { if (isComplete) { if (fHeaderChunk.fDirty || fIsMarkedIncomplete) { - fHeaderChunk.putInt(0, fVersion); + fHeaderChunk.putInt(VERSION_OFFSET, fVersion); fHeaderChunk.flush(); fIsMarkedIncomplete= false; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java index c7e485616f8..c4b5b070b5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java @@ -6,8 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Andrew Ferguson (Symbian) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -30,7 +31,7 @@ public interface IString { // strcmp equivalents /** * Compare this IString record and the specified IString record - * @param chars + * @param string * @param caseSensitive whether to compare in a case-sensitive way * @return <ul><li> -1 if this < string * <li> 0 if this == string @@ -42,7 +43,7 @@ public interface IString { /** * Compare this IString record and the specified String object - * @param chars + * @param string * @param caseSensitive whether to compare in a case-sensitive way * @return <ul><li> -1 if this < string * <li> 0 if this == string @@ -64,6 +65,29 @@ public interface IString { */ public int compare(char[] chars, boolean caseSensitive) throws CoreException; + /** + * Compare this IString record and the specified IString record in a case sensitive manner + * such that it is compatible with case insensitive comparison. + * @param string + * @return <ul><li> -1 if this < string + * <li> 0 if this == string + * <li> 1 if this > string + * </ul> + * @throws CoreException + */ + public int compareCompatibleWithIgnoreCase(IString string) throws CoreException; + + /** + * Compare this IString record and the specified char array in a case sensitive manner + * such that it is compatible with case insensitive comparison. + * @param chars + * @return <ul><li> -1 if this < string + * <li> 0 if this == string + * <li> 1 if this > string + * </ul> + * @throws CoreException + */ + public int compareCompatibleWithIgnoreCase(char[] chars) throws CoreException; /** * Compare this IString record and the specified character array diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/LongString.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/LongString.java index e4afd6941a0..54de8293e1d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/LongString.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/LongString.java @@ -6,8 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Andrew Ferguson (Symbian) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -329,4 +330,13 @@ public class LongString implements IString { return buffer.toString(); } + public int compareCompatibleWithIgnoreCase(IString string) throws CoreException { + int cmp= compare(string, false); + return cmp==0 ? compare(string, true) : cmp; + } + + public int compareCompatibleWithIgnoreCase(char[] chars) throws CoreException { + int cmp= compare(chars, false); + return cmp==0 ? compare(chars, true) : cmp; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ShortString.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ShortString.java index 3fb4e1efa02..f632da91e3f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ShortString.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ShortString.java @@ -6,8 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Andrew Ferguson (Symbian) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -241,6 +242,94 @@ public class ShortString implements IString { return 0; } + + public int compareCompatibleWithIgnoreCase(IString string) throws CoreException { + if (string instanceof ShortString) + return compareCompatibleWithIgnoreCase((ShortString)string); + else if (string instanceof LongString) + return - ((LongString)string).compareCompatibleWithIgnoreCase(this); + else + throw new IllegalArgumentException(); + } + + + public int compareCompatibleWithIgnoreCase(ShortString other) throws CoreException { + Chunk chunk1 = db.getChunk(record); + Chunk chunk2 = other.db.getChunk(other.record); + + int i1 = record + CHARS; + int i2 = other.record + CHARS; + int n1 = i1 + chunk1.getInt(record + LENGTH) * 2; + int n2 = i2 + chunk2.getInt(other.record + LENGTH) * 2; + int sensitiveCmp= 0; + while (i1 < n1 && i2 < n2) { + final char c1= chunk1.getChar(i1); + final char c2= chunk2.getChar(i2); + if (c1 != c2) { + int cmp= compareChars(c1, c2, false); // insensitive + if(cmp!=0) + return cmp; + + if (sensitiveCmp == 0) { + if (c1 < c2) { + sensitiveCmp= -1; + } + else { + sensitiveCmp= 1; + } + } + } + + i1 += 2; + i2 += 2; + } + + if (i1 == n1 && i2 != n2) + return -1; + else if (i2 == n2 && i1 != n1) + return 1; + + return sensitiveCmp; + } + + public int compareCompatibleWithIgnoreCase(char[] chars) throws CoreException { + Chunk chunk1 = db.getChunk(record); + + int i1 = record + CHARS; + int i2 = 0; + int n1 = i1 + chunk1.getInt(record + LENGTH) * 2; + int n2 = chars.length; + int sensitiveCmp= 0; + while (i1 < n1 && i2 < n2) { + final char c1= chunk1.getChar(i1); + final char c2= chars[i2]; + if (c1 != c2) { + int cmp= compareChars(c1, c2, false); // insensitive + if(cmp!=0) + return cmp; + + if (sensitiveCmp == 0) { + if (c1 < c2) { + sensitiveCmp= -1; + } + else { + sensitiveCmp= 1; + } + } + } + + i1 += 2; + i2++; + } + + if (i1 == n1 && i2 != n2) + return -1; + else if (i2 == n2 && i1 != n1) + return 1; + + return sensitiveCmp; + } + public int comparePrefix(char[] other, boolean caseSensitive) throws CoreException { Chunk chunk = db.getChunk(record); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java index a9251d538d6..6abf7ebd893 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial API and implementation + * Andrew Ferguson (Symbian) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -34,27 +35,46 @@ public class FindBinding { public int compare(int record1, int record2) throws CoreException { IString nm1 = PDOMNamedNode.getDBName(pdom, record1); IString nm2 = PDOMNamedNode.getDBName(pdom, record2); - int cmp= nm1.compare(nm2, false); - cmp= cmp==0 ? nm1.compare(nm2, true) : cmp; + int cmp= nm1.compareCompatibleWithIgnoreCase(nm2); if(cmp == 0) { - int t1 = PDOMNamedNode.getNodeType(pdom, record1); - int t2 = PDOMNamedNode.getNodeType(pdom, record2); + int t1 = PDOMNode.getNodeType(pdom, record1); + int t2 = PDOMNode.getNodeType(pdom, record2); return t1 < t2 ? -1 : (t1 > t2 ? 1 : 0); } return cmp; } } + public static class NestedBindingsBTreeComparator extends DefaultBindingBTreeComparator implements IBTreeComparator { + protected PDOMLinkage linkage; + + public NestedBindingsBTreeComparator(PDOMLinkage linkage) { + super(linkage.pdom); + this.linkage= linkage; + } + public int compare(int record1, int record2) throws CoreException { + int cmp= super.compare(record1, record2); // compare names + if (cmp==0) { // any order will do. + if (record1 < record2) { + return -1; + } + else if (record1 > record2) { + return 1; + } + } + return cmp; + } + } + public static PDOMBinding findBinding(BTree btree, final PDOM pdom, final char[]name, final int[] constants) throws CoreException { final PDOMBinding[] result = new PDOMBinding[1]; btree.accept(new IBTreeVisitor() { public int compare(int record) throws CoreException { IString nm1 = PDOMNamedNode.getDBName(pdom, record); - int cmp= nm1.compare(name, false); - return cmp==0 ? nm1.compare(name, true) : cmp; + return nm1.compareCompatibleWithIgnoreCase(name); } public boolean visit(int record) throws CoreException { - PDOMNamedNode nnode = (PDOMNamedNode) PDOMLinkage.getLinkage(pdom, record).getNode(record); + PDOMNamedNode nnode = (PDOMNamedNode) PDOMNode.getLinkage(pdom, record).getNode(record); if(nnode.hasName(name)) { int constant = nnode.getNodeType(); for(int i=0; i<constants.length; i++) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/NamedNodeCollector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/NamedNodeCollector.java index 284ee0fdc9c..654e1153e9f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/NamedNodeCollector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/NamedNodeCollector.java @@ -62,6 +62,8 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor { } final public int compare(int record) throws CoreException { + if (monitor != null) + checkCancelled(); IString name= PDOMNamedNode.getDBName(linkage.getPDOM(), record); return compare(name); } @@ -75,9 +77,11 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor { } return cmp; } else { - cmp= rhsName.compare(name, false); if(caseSensitive) { - cmp= cmp==0 ? rhsName.compare(name, true) : cmp; + cmp= rhsName.compareCompatibleWithIgnoreCase(name); + } + else { + cmp= rhsName.compare(name, false); } } return cmp; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index a583db9ca53..1f7be7e8e17 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -6,10 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) - * IBM Corporation - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) + * IBM Corporation + * Andrew Ferguson (Symbian) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -64,8 +64,9 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage private static final int ID_OFFSET = PDOMNamedNode.RECORD_SIZE + 0; private static final int NEXT_OFFSET = PDOMNamedNode.RECORD_SIZE + 4; private static final int INDEX_OFFSET = PDOMNamedNode.RECORD_SIZE + 8; + private static final int NESTED_BINDINGS_INDEX = PDOMNamedNode.RECORD_SIZE + 12; - protected static final int RECORD_SIZE = PDOMNamedNode.RECORD_SIZE + 12; + protected static final int RECORD_SIZE = PDOMNamedNode.RECORD_SIZE + 16; // node types protected static final int LINKAGE= 0; // special one for myself @@ -110,6 +111,15 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage return new BTree(pdom.getDB(), record + INDEX_OFFSET, getIndexComparator()); } + /** + * Returns the BTree for the nested bindings. + * @return + * @throws CoreException + */ + public BTree getNestedBindingsIndex() throws CoreException { + return new BTree(getPDOM().getDB(), record + NESTED_BINDINGS_INDEX, getNestedBindingsComparator()); + } + public void accept(final IPDOMVisitor visitor) throws CoreException { if (visitor instanceof IBTreeVisitor) { getIndex().accept((IBTreeVisitor) visitor); @@ -166,6 +176,10 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage } public abstract IBTreeComparator getIndexComparator(); + + public IBTreeComparator getNestedBindingsComparator() { + return new FindBinding.NestedBindingsBTreeComparator(this); + } public abstract PDOMBinding addBinding(IASTName name) throws CoreException; @@ -326,6 +340,34 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage public void onDeleteName(PDOMName nextName) throws CoreException { } + /** + * Callback informing the linkage that a binding has been added. Used to index nested bindings. + * @param pdomBinding + * @throws CoreException + * @since 4.0.1 + */ + public void afterAddBinding(PDOMBinding pdomBinding) throws CoreException { + if (pdomBinding.getParentNodeRec() != record) { + if (pdom.getDB().getVersion() >= PDOM.MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX) { + getNestedBindingsIndex().insert(pdomBinding.getRecord()); + } + } + } + + /** + * Callback informing the linkage that a binding is about to be removed. Used to index nested bindings. + * @param pdomBinding + * @throws CoreException + * @since 4.0.1 + */ + public void beforeRemoveBinding(PDOMBinding pdomBinding) throws CoreException { + if (pdomBinding.getParentNodeRec() != record) { + if (pdom.getDB().getVersion() >= PDOM.MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX) { + getNestedBindingsIndex().delete(pdomBinding.getRecord()); + } + } + } + /** * Searches for the a file local scope object. If none is found depending * on the value of the parameter 'create' such an object is created. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNode.java index efb5edad9c4..36a909e00eb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNode.java @@ -6,9 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Andrew Ferguson (Symbian) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -90,8 +90,12 @@ public abstract class PDOMNode implements IPDOMNode { return pdom.getDB().getInt(record + TYPE); } + public int getParentNodeRec() throws CoreException { + return pdom.getDB().getInt(record + PARENT); + } + public PDOMNode getParentNode() throws CoreException { - int parentrec = pdom.getDB().getInt(record + PARENT); + int parentrec = getParentNodeRec(); return parentrec != 0 ? getLinkageImpl().getNode(parentrec) : null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java index fe6c38d616e..5f7fed65c59 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java @@ -6,10 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) - * IBM Corporation - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) + * IBM Corporation + * Andrew Ferguson (Symbian) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.c; @@ -100,8 +100,9 @@ class PDOMCLinkage extends PDOMLinkage implements IIndexCBindingConstants { } else if (binding instanceof ITypedef) pdomBinding = new PDOMCTypedef(pdom, parent, (ITypedef)binding); - if(pdomBinding!=null) { + if (pdomBinding!=null) { parent.addChild(pdomBinding); + afterAddBinding(pdomBinding); } } return pdomBinding; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java index 62b4ea3c8aa..82210482b75 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial API and implementation + * Andrew Ferguson (Symbian) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; @@ -43,9 +44,7 @@ public class CPPFindBinding extends FindBinding { public int compare(int record) throws CoreException { IString nm1 = PDOMNamedNode.getDBName(pdom, record); - int cmp = nm1.compare(name, false); - cmp = cmp == 0 ? nm1.compare(name, true) : cmp; - + int cmp = nm1.compareCompatibleWithIgnoreCase(name); if (cmp == 0) { int c1 = PDOMNode.getNodeType(pdom, record); cmp = c1 < c2 ? -1 : (c1 > c2 ? 1 : 0); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 14be62d369b..b350529b388 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -364,6 +364,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if(pdomBinding!=null) { parent.addChild(pdomBinding); + afterAddBinding(pdomBinding); } pushPostProcesses(pdomBinding, binding); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java index db225dd9ae7..a6c8981ba70 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.export; @@ -21,6 +22,7 @@ import org.eclipse.cdt.core.index.export.IExportProjectProvider; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.internal.core.CCoreInternals; +import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.WritablePDOM; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.core.runtime.CoreException; @@ -78,6 +80,10 @@ public class GeneratePDOM implements ISafeRunnable { exportedPDOM.setProperty((String) entry.getKey(), (String) entry.getValue()); } } + // fake version of pdom, such that it works with CDT 4.0.0, also. + if (PDOM.CURRENT_VERSION == PDOM.MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX) { + exportedPDOM.getDB().setVersion(PDOM.CURRENT_VERSION-1); + } exportedPDOM.close(); } finally { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java index cbf911c4983..e5f435fe78e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java @@ -209,6 +209,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } // sources first + sources= sortByContentType(sources); for (Iterator iter = sources.iterator(); iter.hasNext();) { if (monitor.isCanceled()) return; @@ -220,6 +221,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } // headers with context + headers= sortByContentType(headers); for (Iterator iter = headers.iterator(); iter.hasNext();) { if (monitor.isCanceled()) return; @@ -253,6 +255,38 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } } + private Collection sortByContentType(Collection sources) { + HashMap ctToLists= new HashMap(); + for (Iterator iterator = sources.iterator(); iterator.hasNext();) { + final ITranslationUnit tu = (ITranslationUnit) iterator.next(); + final String ct= tu.getContentTypeId(); + List list= (List) ctToLists.get(ct); + if (list == null) { + list= new ArrayList(); + ctToLists.put(ct, list); + } + list.add(tu); + } + if (ctToLists.size() <= 1) { + return sources; + } + Collection result= new ArrayList(sources.size()); + // do C++ first + List list= (List) ctToLists.remove(CCorePlugin.CONTENT_TYPE_CXXSOURCE); + if (list != null) { + result.addAll(list); + } + list= (List) ctToLists.remove(CCorePlugin.CONTENT_TYPE_CXXHEADER); + if (list != null) { + result.addAll(list); + } + for (Iterator iterator = ctToLists.values().iterator(); iterator.hasNext();) { + list = (List) iterator.next(); + result.addAll(list); + } + return result; + } + /** * Convenience method to check whether a translation unit in the index is outdated * with respect to its timestamp.