From f73314ecbef7f1ab458138ef7641d6bad162149c Mon Sep 17 00:00:00 2001 From: Andrew Ferguson Date: Mon, 3 Sep 2007 14:06:18 +0000 Subject: [PATCH] 196338: apply fix --- .../index/tests/EmptyIndexFragment.java | 112 ++++++ .../index/tests/IndexProviderManagerTest.java | 201 ++++++++-- .../internal/core/index/IIndexFragment.java | 31 +- .../index/provider/IndexProviderManager.java | 180 ++++++++- .../core/index/provider/Messages.java | 1 + .../core/index/provider/PDOMCache.java | 55 +-- .../core/index/provider/messages.properties | 1 + .../eclipse/cdt/internal/core/pdom/PDOM.java | 95 +++-- .../cdt/internal/core/pdom/WritablePDOM.java | 10 +- .../guide/dom/index/prebuiltVersioning.html | 350 ++++++++++++++++++ .../prebuiltVersioning_files/image001.jpg | Bin 0 -> 37182 bytes doc/org.eclipse.cdt.doc.isv/topics_Guide.xml | 1 + 12 files changed, 915 insertions(+), 122 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java create mode 100644 doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning.html create mode 100644 doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning_files/image001.jpg diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java new file mode 100644 index 00000000000..a2e41c70274 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2007 Symbian Software Ltd. 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: + * Andrew Ferguson (Symbian) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.index.tests; + +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.index.IIndexLinkage; +import org.eclipse.cdt.core.index.IndexFilter; +import org.eclipse.cdt.internal.core.index.IIndexFragment; +import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; +import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; +import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude; +import org.eclipse.cdt.internal.core.index.IIndexFragmentName; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * An empty index fragment implementation + * @since 4.0.1 + */ +public class EmptyIndexFragment implements IIndexFragment { + public void acquireReadLock() throws InterruptedException {} + + public IIndexFragmentBinding adaptBinding(IBinding binding) + throws CoreException { + return null; + } + + public IIndexFragmentBinding adaptBinding(IIndexFragmentBinding proxy) + throws CoreException { + return null; + } + + public IIndexFragmentBinding findBinding(IASTName astName) throws CoreException { + return null; + } + + public IIndexFragmentBinding[] findBindings(Pattern[] patterns, + boolean isFullyQualified, IndexFilter filter, + IProgressMonitor monitor) throws CoreException { + return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + + public IIndexFragmentBinding[] findBindings(char[][] names, + IndexFilter filter, IProgressMonitor monitor) throws CoreException { + return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + + public IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, + boolean filescope, IndexFilter filter, IProgressMonitor monitor) + throws CoreException { + return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + + public IIndexFragmentInclude[] findIncludedBy(IIndexFragmentFile file) + throws CoreException { + return IIndexFragmentInclude.EMPTY_FRAGMENT_INCLUDES_ARRAY; + } + + public IIndexFragmentName[] findNames(IIndexFragmentBinding binding, + int flags) throws CoreException { + return IIndexFragmentName.EMPTY_NAME_ARRAY; + } + + public long getCacheHits() { + return 0; + } + + public long getCacheMisses() { + return 0; + } + + public IIndexFragmentFile getFile(IIndexFileLocation location) + throws CoreException { + return null; + } + + public long getLastWriteAccess() { + return 0; + } + + public IIndexLinkage[] getLinkages() { + return IIndexLinkage.EMPTY_INDEX_LINKAGE_ARRAY; + } + + public String getProperty(String key) throws CoreException { + if(IIndexFragment.PROPERTY_FRAGMENT_ID.equals(key)) { + return "org.eclipse.cdt.internal.core.index.EmptyIndexFragment"; //$NON-NLS-1$ + } + if(IIndexFragment.PROPERTY_FRAGMENT_FORMAT_ID.equals(key)) { + return "org.eclipse.cdt.internal.core.index.EmptyIndexFragmentFormat"; //$NON-NLS-1$ + } + if(IIndexFragment.PROPERTY_FRAGMENT_FORMAT_VERSION.equals(key)) { + return "0"; //$NON-NLS-1$ + } + return null; + } + + public void releaseReadLock() {} + public void resetCacheCounters() {} +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexProviderManagerTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexProviderManagerTest.java index 0859add59cf..8d2df68f928 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexProviderManagerTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexProviderManagerTest.java @@ -11,10 +11,6 @@ package org.eclipse.cdt.internal.index.tests; import java.io.File; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -55,6 +51,7 @@ import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.provider.IIndexFragmentProvider; import org.eclipse.cdt.internal.core.index.provider.IndexProviderManager; +import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOMManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; @@ -63,6 +60,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.osgi.service.resolver.VersionRange; /** * Example usage and test for IIndexProvider @@ -76,6 +74,14 @@ public class IndexProviderManagerTest extends IndexTestBase { final static Class DP5= Providers.Dummy5.class; final static Class[] DPS= new Class[] {DP4, DP2, DP1, DP3, DP5}; + /* + * Fictional compatibility ranges for testing + */ + final static VersionRange VERSION_400= new VersionRange("36"); + final static VersionRange VERSION_401= new VersionRange("[36,37]"); + final static VersionRange VERSION_405= new VersionRange("[37,39]"); + final static VersionRange VERSION_502= new VersionRange("[89,91]"); + final CCorePlugin core= CCorePlugin.getDefault(); public IndexProviderManagerTest() { @@ -86,6 +92,11 @@ public class IndexProviderManagerTest extends IndexTestBase { return suite(IndexProviderManagerTest.class); } + protected void tearDown() throws Exception { + IndexProviderManager ipm= ((PDOMManager)CCorePlugin.getIndexManager()).getIndexProviderManager(); + ipm.reset(); ipm.startup(); + } + public void testProvider_SimpleLifeCycle_200958() throws Exception { for(int i=0; inull, if no such file exists. - * This method may only return files that are actually managed by this fragement. + * This method may only return files that are actually managed by this fragment. * @param location the IIndexFileLocation representing the location of the file - * @return the file for the location + * @return the file for the location, or null if the file is not present in the index * @throws CoreException */ IIndexFragmentFile getFile(IIndexFileLocation location) throws CoreException; @@ -167,11 +184,17 @@ public interface IIndexFragment { /** * Read the named property in this fragment. All fragments are expected to return a non-null value for - *
PROPERTY_FRAGMENT_ID
+ * * @param key a case-sensitive identifier for a property, or null * @return the value associated with the key, or null if either no such property is set, or the specified key was null * @throws CoreException * @see IIndexFragment#PROPERTY_FRAGMENT_ID + * @see IIndexFragment#PROPERTY_FRAGMENT_FORMAT_ID + * @see IIndexFragment#PROPERTY_FRAGMENT_FORMAT_VERSION */ public String getProperty(String propertyName) throws CoreException; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/IndexProviderManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/IndexProviderManager.java index aadc4ed83eb..0a134b6dc9e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/IndexProviderManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/IndexProviderManager.java @@ -13,11 +13,12 @@ package org.eclipse.cdt.internal.core.index.provider; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.index.provider.IIndexProvider; @@ -28,31 +29,70 @@ 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.IElementChangedListener; +import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.internal.core.index.IIndexFragment; +import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.core.resources.IProject; 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.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; - +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.osgi.framework.Version; /** * The IndexProviderManager is responsible for maintaining the set of index * fragments contributed via the CIndex extension point. *

* It is an internal class, and is public only for testing purposes. + * @since 4.0 + */ +/* + * For bug 196338, the role of this class was extended. It now has responsibility to + * look at the pool of fragments available depending on their IDs, and select the most appropriate. + * The following rules are applied + * (i) If its not compatible, don't use it + * (ii) If multiple are compatible, pick the latest + * + * A warning is logged if a fragment is contributed which is incompatible, and for which there is + * no compatible equivalent. */ public final class IndexProviderManager implements IElementChangedListener { - public static final String READ_ONLY_PDOM_PROVIDER= "ReadOnlyPDOMProvider"; //$NON-NLS-1$ - private IIndexFragmentProvider[] allProviders= {}; - private Map provisionMap= new HashMap(); + private static final String ELEMENT_RO_PDOMPROVIDER= "ReadOnlyPDOMProvider"; //$NON-NLS-1$ + private static final String ATTRIBUTE_CLASS = "class"; //$NON-NLS-1$ + + private IIndexFragmentProvider[] allProviders; + private Map/**/ provisionMap; + private Set/**/ compatibleFragmentUnavailable; + private VersionRange pdomVersionRange; public IndexProviderManager() { + reset(); + } + + /** + * Note: This method should not be called by clients for purposes other than testing + */ + public void reset() { + reset(new VersionRange("["+PDOM.MIN_SUPPORTED_VERSION+','+PDOM.CURRENT_VERSION+']')); //$NON-NLS-1$ } + /** + * Note: This method should not be called by clients for purposes other than testing + * @param pdomVersionRange + */ + public void reset(VersionRange pdomVersionRange) { + this.allProviders= new IIndexFragmentProvider[0]; + this.provisionMap= new HashMap(); + this.pdomVersionRange= pdomVersionRange; + this.compatibleFragmentUnavailable= new HashSet(); + } + public void startup() { List providers = new ArrayList(); IExtensionRegistry registry = Platform.getExtensionRegistry(); @@ -63,8 +103,9 @@ public final class IndexProviderManager implements IElementChangedListener { try { IConfigurationElement[] ce = extension.getConfigurationElements(); for(int j=0; j custom IIndexFragment implementation) + * changes are coped with. + */ + } + } else { + id2fragment.put(cid, candidate); + } + } else { + if(existing==null) { + id2fragment.put(cid, null); // signifies candidate is unusable + } + } } /** - * This is only public for test purposes + * Note: This method should not be called for purposes other than testing * @param provider */ public void addIndexProvider(IIndexProvider provider) { @@ -131,6 +269,20 @@ public final class IndexProviderManager implements IElementChangedListener { allProviders = newAllProviders; } + /** + * Removes the specified provider by object identity + * Note: This method should not be called for purposes other than testing + * @param provider + */ + public void removeIndexProvider(IIndexProvider provider) { + ArrayUtil.remove(allProviders, provider); + if(allProviders[allProviders.length-1]==null) { + IIndexFragmentProvider[] newAllProviders = new IIndexFragmentProvider[allProviders.length-1]; + System.arraycopy(allProviders, 0, newAllProviders, 0, allProviders.length-1); + allProviders= newAllProviders; + } + } + private boolean providesForProject(IIndexProvider provider, IProject project) { List key = new ArrayList(); key.add(provider); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/Messages.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/Messages.java index fe1cf9091f3..f448a387f74 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/Messages.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/Messages.java @@ -15,6 +15,7 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.core.index.provider.messages"; //$NON-NLS-1$ public static String IndexProviderManager_0; + public static String IndexProviderManager_NoCompatibleFragmentsAvailable; public static String OfflinePDOMProviderBridge_UnsupportedUsage; public static String PDOMCache_VersionTooOld; static { 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 382a7a0821b..7b56eef267c 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 @@ -12,11 +12,8 @@ package org.eclipse.cdt.internal.core.index.provider; import java.io.File; -import java.text.MessageFormat; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.index.IIndexLocationConverter; @@ -29,17 +26,15 @@ import org.eclipse.core.runtime.IPath; * Internal singleton map maintained for non-project PDOM objects */ class PDOMCache { - private Map/**/ path2pdom; // gives the pdom for a particular path - private Set/**/ versionMismatch; - + private Map/**/ path2pdom; // gives the PDOM for a particular path + private static PDOMCache singleton; private static Object singletonMutex = new Object(); private PDOMCache() { this.path2pdom = new HashMap(); - this.versionMismatch = new HashSet(); } - + /** * Returns the instance of the cache * @return @@ -54,48 +49,30 @@ class PDOMCache { } /** - * Returns the mapped pdom for the path specified, if such a pdom is not already known about + * Returns the mapped PDOM for the path specified, if such a pdom is not already known about * then one is created using the location converter specified. * @param path * @param converter - * @return a pdom instance or null if the pdom version was too old + * @return a PDOM instance or null if the PDOM version was too old */ public PDOM getPDOM(IPath path, IIndexLocationConverter converter) { PDOM result= null; File file = path.toFile(); - if(!versionMismatch.contains(file)) { - synchronized(path2pdom) { - if(path2pdom.containsKey(file)) { - result = (PDOM) path2pdom.get(file); + synchronized(path2pdom) { + if(path2pdom.containsKey(file)) { + result = (PDOM) path2pdom.get(file); + } + if(result==null) { + try { + result = new PDOM(file, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); + path2pdom.put(file, result); + } catch(CoreException ce) { + CCorePlugin.log(ce); } - if(result==null) { - try { - result = new PDOM(file, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); - - result.acquireReadLock(); - try { - if(!result.isSupportedVersion()) { - versionMismatch.add(file); - String msg= MessageFormat.format(Messages.PDOMCache_VersionTooOld, new Object[] {file}); - CCorePlugin.log(msg); - return null; - } else { - path2pdom.put(file, result); - } - } finally { - result.releaseReadLock(); - } - } catch(CoreException ce) { - CCorePlugin.log(ce); - } catch(InterruptedException ie) { - CCorePlugin.log(ie); - } - } - } } return result; } -} +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/messages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/messages.properties index a0e7f83d6c8..87063621795 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/messages.properties +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/messages.properties @@ -11,3 +11,4 @@ IndexProviderManager_0=Ignoring unrecognized implementation of IIndexProvider contributed by {0} OfflinePDOMProviderBridge_UnsupportedUsage=Unsupported usage of IOfflinePDOMProvider PDOMCache_VersionTooOld=External index (PDOM) version is not supported: {0} +IndexProviderManager_NoCompatibleFragmentsAvailable=No compatible index fragment found for fragment id: {0} 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 47fe62dd09c..65df7b909e0 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 @@ -73,47 +73,60 @@ import org.eclipse.core.runtime.Status; public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { protected Database db; + /** + * Identifier for PDOM format + * @see IIndexFragment#PROPERTY_FRAGMENT_FORMAT_ID + */ + public static final String FRAGMENT_PROPERTY_VALUE_FORMAT_ID= "org.eclipse.cdt.internal.core.pdom.PDOM"; //$NON-NLS-1$ + 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 - // 3 - added macros and change string implementation - // 4 - added parameters in C++ - // 5 - added types and restructured nodes a bit - // 6 - function style macros. - // 7 - class key - // 8 - enumerators - // 9 - base classes - // 10 - typedefs, types on C++ variables - // 11 - changed how members work - // 12 - one more change for members (is-a list -> has-a list) - // 13 - CV-qualifiers, storage class specifiers, function/method annotations - // 14 - added timestamps for files (bug 149571) - // 15 - fixed offsets for pointer types and qualifier types and PDOMCPPVariable (bug 160540). - // 16 - have PDOMCPPField store type information, and PDOMCPPNamespaceAlias store what it is aliasing - // 17 - use single linked list for names in file, adds a link to enclosing definition name. - // 18 - distinction between c-unions and c-structs. - // 19 - alter representation of paths in the pdom (162172) - // 20 - add pointer to member types, array types, return types for functions - // 21 - change representation of paths in the pdom (167549) - // 22 - fix inheritance relations (167396) - // 23 - types on c-variables, return types on c-functions - // 24 - file local scopes (161216) - // 25 - change ordering of bindings (175275) - // 26 - add properties storage - // 27 - templates: classes, functions, limited nesting support, only template type parameters - // 28 - templates: class instance/specialization base classes - // 29 - includes: fixed modeling of unresolved includes (180159) - // 30 - templates: method/constructor templates, typedef specializations - // 31 - macros: added file locations - // 32 - support stand-alone function types (181936) - // 33 - templates: constructor instances - // 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. + + /* + * PDOM internal format history + * + * #x# = the version was used in an official release + * + * 0 - the beginning of it all + * 1 - first change to kick off upgrades + * 2 - added file inclusions + * 3 - added macros and change string implementation + * 4 - added parameters in C++ + * 5 - added types and restructured nodes a bit + * 6 - function style macros + * # 7#- class key - <> + * 8 - enumerators + * 9 - base classes + * 10 - typedefs, types on C++ variables + * #11#- changed how members work - <>, <> + * 12 - one more change for members (is-a list -> has-a list) + * 13 - CV-qualifiers, storage class specifiers, function/method annotations + * 14 - added timestamps for files (bug 149571) + * 15 - fixed offsets for pointer types and qualifier types and PDOMCPPVariable (bug 160540). + * 16 - have PDOMCPPField store type information, and PDOMCPPNamespaceAlias store what it is aliasing + * 17 - use single linked list for names in file, adds a link to enclosing definition name. + * 18 - distinction between c-unions and c-structs. + * 19 - alter representation of paths in the pdom (162172) + * 20 - add pointer to member types, array types, return types for functions + * 21 - change representation of paths in the pdom (167549) + * 22 - fix inheritance relations (167396) + * 23 - types on c-variables, return types on c-functions + * 24 - file local scopes (161216) + * 25 - change ordering of bindings (175275) + * 26 - add properties storage + * 27 - templates: classes, functions, limited nesting support, only template type parameters + * 28 - templates: class instance/specialization base classes + * 29 - includes: fixed modeling of unresolved includes (180159) + * 30 - templates: method/constructor templates, typedef specializations + * 31 - macros: added file locations + * 32 - support stand-alone function types (181936) + * 33 - templates: constructor instances + * 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; @@ -760,6 +773,12 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { } public String getProperty(String propertyName) throws CoreException { + if(IIndexFragment.PROPERTY_FRAGMENT_FORMAT_ID.equals(propertyName)) { + return FRAGMENT_PROPERTY_VALUE_FORMAT_ID; + } + if(IIndexFragment.PROPERTY_FRAGMENT_FORMAT_VERSION.equals(propertyName)) { + return ""+db.getVersion(); //$NON-NLS-1$ + } return new DBProperties(db, PROPERTIES).getProperty(propertyName); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java index 158c70591d2..508bde45d3b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexLocationConverter; +import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; @@ -88,11 +89,18 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { return result; } + /* + * (non-Javadoc) + * @see org.eclipse.cdt.internal.core.index.IWritableIndexFragment#setProperty(java.lang.String, java.lang.String) + */ public void setProperty(String propertyName, String value) throws CoreException { + if(IIndexFragment.PROPERTY_FRAGMENT_FORMAT_ID.equals(propertyName) + || IIndexFragment.PROPERTY_FRAGMENT_FORMAT_VERSION.equals(propertyName)) { + throw new IllegalArgumentException("Property "+value+" may not be written to"); //$NON-NLS-1$ //$NON-NLS-2$ + } new DBProperties(db, PROPERTIES).setProperty(propertyName, value); } - /** * Use the specified location converter to update each internal representation of a file location. * The file index is rebuilt with the new representations. Individual PDOMFile records are unmoved so diff --git a/doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning.html b/doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning.html new file mode 100644 index 00000000000..dc319b7243c --- /dev/null +++ b/doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning.html @@ -0,0 +1,350 @@ + + + + + + + + + + +Versioning pre-built indexes + + + + + + + +

+ +

Versioning of pre-built indexes

+ +

 

+ +

In CDT 4.0.1 support for +versioning of pre-built indexes was added. This means that if you release +pre-built indexes for the same content (for example, the same SDK version), but +they were built with different versions of CDT, then a suitable version will +now be used automatically. The previous behaviour assumed only one format +version of any particular content would be provided via the CIndex +extension point.

+ +

 

+ +

It is important to distinguish +between two versions: the content version and the index format version. A +content version refers to the version of the source code being indexed +independent of how it is represented in the index e.g. SDK v1.0 and SDK v1.2. +The index format version is the version of the internal representation of the +index. This document is about coping with the latter.

+ +

 

+ +

Our versioning policy for index +formats is that they should be compatible within major (yearly) release +versions. That is if you build an index using CDT 4.0.X it should work with CDT +4.0.Y. This policy should mean that ISVs do not need to worry about index +format versioning, but this page describes how to handle it should it be +necessary (for example bugzilla 189811).Each +pre-built index carries a string ID which identifies it uniquely within a +logical index - i.e. it identifies the content (e.g MySDK v1.2). When multiple pre-built indexes are provided +with the same ID, the particular one for use is disambiguated automatically by +CDT which chooses the most recent compatible version.

+ +

Compatibility +Table

+ +

 

+ +

This table shows the +compatibility of pre-built indexes built with one version of CDT and used with +another. “Built With” is the vertical axis.

+ +

 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Built With \ Use With

+
+

CDT 4.0

+
+

CDT 4.0.1

+
+

CDT Next**

+
+

 

+
+

CDT 4.0

+
+

Yes*

+
+

Yes*

+
+

No

+
+

 

+
+

CDT 4.0.1

+
+

Yes*

+
+

Yes

+
+

No

+
+

 

+
+

CDT Next**

+
+

No

+
+

No

+
+

Yes

+
+

 

+
+

 

+
+

 

+
+

 

+
+

 

+
+

 

+
+ +

 

+ +

Note that even though in the PDOM +format has its own internal versioning scheme, consumers of official CDT +releases need only be aware of compatibility constraints between these +releases.

+ +

 

+ +

* with +performance issues in very large projects. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=189811

+ +

** represents +the next major release of CDT. It +is assumed significant changes to the PDOM database will occur.

+ +

 

+ +

Example scenario

+ +

 

+ +
+
+ +

 

+ +

+ +

 

+ +

The figure above shows an example +scenario where pre-built indexes are contributed by multiple plug-ins. +The same content is contributed in multiple index format versions. The versions +selected for use by each version of CDT are highlighted in gray.

+ +

 

+ +

 

+ +

 

+ +

Versioning Bugzilla: https://bugs.eclipse.org/bugs/show_bug.cgi?id=196338

+ +

 

+ +
+ + + + diff --git a/doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning_files/image001.jpg b/doc/org.eclipse.cdt.doc.isv/guide/dom/index/prebuiltVersioning_files/image001.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0acc405f98173d1ce149953bf665fad4fe1e7719 GIT binary patch literal 37182 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
P-lBi#c=?(mP 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 +