diff options
author | Nathan Ridge | 2013-07-09 05:27:28 +0000 |
---|---|---|
committer | Sergey Prigogin | 2013-07-10 01:58:36 +0000 |
commit | 8f78f34f192c998c81eb72b8f49e79d24f7f2a95 (patch) | |
tree | 5fa2536fcba6a98e122de7b133b320438c4f92e7 | |
parent | 6df967d0d40701ba0c09ad943286f332fec4ae87 (diff) | |
download | org.eclipse.cdt-8f78f34f192c998c81eb72b8f49e79d24f7f2a95.tar.gz org.eclipse.cdt-8f78f34f192c998c81eb72b8f49e79d24f7f2a95.tar.xz org.eclipse.cdt-8f78f34f192c998c81eb72b8f49e79d24f7f2a95.zip |
Bug 412463 - Code completion stops working in the presence of predefined
macro
Change-Id: Iabeb0742ce5564a150f859185c0f8eb64805955a
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
Reviewed-on: https://git.eclipse.org/r/14399
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
4 files changed, 87 insertions, 33 deletions
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index 7325f61bf5e..d0a2a33118f 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -915,7 +915,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit { for (IIndexFile indexFile : index.getFiles(linkageID, ifl)) { int score= indexFile.getMacros().length * 2; IIndexFile context= getParsedInContext(indexFile); - if (isSourceFile(context)) + if (isSourceFile(context, getCProject().getProject())) score++; if (score > bestScore) { bestScore= score; @@ -936,7 +936,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit { return null; } - private IIndexFile getParsedInContext(IIndexFile indexFile) throws CoreException { + public static IIndexFile getParsedInContext(IIndexFile indexFile) throws CoreException { HashSet<IIndexFile> visited= new HashSet<IIndexFile>(); // Bug 199412, may recurse. while (visited.add(indexFile)) { @@ -949,12 +949,12 @@ public class TranslationUnit extends Openable implements ITranslationUnit { } /** - * Returns <code>true</code> if the given file was parsed in a context of a source file. + * Returns <code>true</code> if the given file is a source file. * @throws CoreException */ - private boolean isSourceFile(IIndexFile indexFile) throws CoreException { + public static boolean isSourceFile(IIndexFile indexFile, IProject project) throws CoreException { String path = indexFile.getLocation().getURI().getPath(); - IContentType cType = CCorePlugin.getContentType(getCProject().getProject(), path); + IContentType cType = CCorePlugin.getContentType(project, path); if (cType == null) return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index 7a2bc0ccf72..9bc0b4b3410 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -97,7 +97,7 @@ public interface IIndexFragment { * <p> * When a header file is stored in the index in multiple variants for different sets of macro * definitions, this method will return an arbitrary one of these variants. - * + * * @param linkageID the id of the linkage in which the file has been parsed. * @param location the IIndexFileLocation representing the location of the file * @return the file for the location, or <code>null</code> if the file is not present in @@ -114,7 +114,7 @@ public interface IIndexFragment { * May return <code>null</code>, if no such file exists. * This method may only return files that are actually managed by this fragment. * This method returns files without content, also. - * + * * @param linkageID the id of the linkage in which the file has been parsed. * @param location the IIndexFileLocation representing the location of the file * @param macroDictionary The names and definitions of the macros used to disambiguate between @@ -132,10 +132,7 @@ public interface IIndexFragment { * for different sets of macro definitions. * This method may only return files that are actually managed by this fragment. * This method returns files without content, also. - * <p> - * When a header file is stored in the index in multiple variants for different sets of macro - * definitions, this method will return an arbitrary one of these variants. - * + * * @param linkageID the id of the linkage in which the file has been parsed. * @param location the IIndexFileLocation representing the location of the file * @return the files for the location and the linkage. @@ -224,7 +221,7 @@ public interface IIndexFragment { * Searches for all names that resolve to the given binding. You can limit the result to * references, declarations or definitions, or a combination of those. * @param binding a binding for which names are searched for - * @param flags a combination of {@link #FIND_DECLARATIONS}, {@link #FIND_DEFINITIONS}, + * @param flags a combination of {@link #FIND_DECLARATIONS}, {@link #FIND_DEFINITIONS}, * {@link #FIND_REFERENCES} and {@link #FIND_NON_LOCAL_ONLY} * @return an array of names * @throws CoreException 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 89b1b26d487..6e75095eadb 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 @@ -9,7 +9,7 @@ * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) * Sergey Prigogin (Google) - *******************************************************************************/ + *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; import java.io.File; @@ -23,14 +23,17 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexLocationConverter; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.ISignificantMacros; import org.eclipse.cdt.internal.core.index.FileContentKey; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; +import org.eclipse.cdt.internal.core.model.TranslationUnit; import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; @@ -43,7 +46,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMMacroReferenceName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.core.runtime.CoreException; -public class WritablePDOM extends PDOM implements IWritableIndexFragment { +public class WritablePDOM extends PDOM implements IWritableIndexFragment { private boolean fClearedBecauseOfVersionMismatch= false; private boolean fCreatedFromScratch= false; private ASTFilePathResolver fPathResolver; @@ -55,12 +58,12 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException { this(dbPath, locationConverter, ChunkCache.getSharedInstance(), linkageFactoryMappings); } - + public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter, ChunkCache cache, Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException { super(dbPath, locationConverter, cache, linkageFactoryMappings); } - + public void setASTFilePathResolver(ASTFilePathResolver resolver) { fPathResolver= resolver; } @@ -69,7 +72,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) throws CoreException { if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros))) return uncommittedFile; - + return super.addFile(linkageID, location, sigMacros); } @@ -138,11 +141,11 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { } @Override - public void addFileContent(IIndexFragmentFile sourceFile, IncludeInformation[] includes, + public void addFileContent(IIndexFragmentFile sourceFile, IncludeInformation[] includes, IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver pathResolver, YieldableIndexLock lock) throws CoreException, InterruptedException { assert sourceFile.getIndexFragment() == this; - + PDOMFile pdomFile = (PDOMFile) sourceFile; pdomFile.addMacros(macros); final ASTFilePathResolver origResolver= fPathResolver; @@ -154,7 +157,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { } // Includes expose the temporary file in the index, we must not yield the lock beyond this point. pdomFile.addIncludesTo(includes); - + final IIndexFileLocation location = pdomFile.getLocation(); if (location != null) { fEvent.fClearedFiles.remove(location); @@ -167,37 +170,37 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { assert file.getIndexFragment() == this; IIndexFileLocation location = file.getLocation(); PDOMFile pdomFile = (PDOMFile) file; - pdomFile.clear(); + pdomFile.clear(); fEvent.fClearedFiles.add(location); } - + @Override public void clear() throws CoreException { super.clear(); } - + @Override public void flush() throws CoreException { super.flush(); } - + @Override public void setProperty(String propertyName, String value) throws CoreException { - if (IIndexFragment.PROPERTY_FRAGMENT_FORMAT_ID.equals(propertyName) + 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); } - + /** * Uses 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 as to maintain referential integrity with other PDOM records. - * + * * <b>A write-lock must be obtained before calling this method</b> - * + * * @param newConverter the converter to use to update internal file representations * @throws CoreException */ @@ -250,12 +253,47 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { void setCreatedFromScratch(boolean createdFromScratch) { fCreatedFromScratch = createdFromScratch; } - + @Override protected final boolean isPermanentlyReadOnly() { return false; } + /** + * Returns the best file for the given location, linkage, and translation unit. + * May return <code>null</code>, if no such file exists. + * + * The "best" file (variant) is the one with the most content, as measured + * by the total number of macros defined in the file. The rationale is that + * often one of the variants will contain most of the code and the others + * just small pieces, and we are usually interested in the one with most of + * the code. As a tiebreaker, a variant that was parsed in the context of a + * source file is preferred, since a header parsed outside of the context of + * a code file may not represent code that a compiler actually sees. + * + * @param linkageID the id of the linkage in which the file has been parsed. + * @param location the IIndexFileLocation representing the location of the file + * @param tu the translation unit from which 'location' originates + * @return the best file for the location, or <code>null</code> if the file is not + * present in the index + * @throws CoreException + */ + private PDOMFile getBestFile(int linkageID, IIndexFileLocation location, ITranslationUnit tu) throws CoreException { + IIndexFile[] files = getFiles(linkageID, location); + IIndexFile best = null; + int bestScore = -1; + for (IIndexFile file : files) { + int score = file.getMacros().length * 2; + if (TranslationUnit.isSourceFile(TranslationUnit.getParsedInContext(file), tu.getCProject().getProject())) + score++; + if (score > bestScore) { + bestScore = score; + best = file; + } + } + return (PDOMFile) best; + } + public PDOMFile getFileForASTNode(int linkageID, IASTNode node) throws CoreException { if (fPathResolver != null && node != null) { IASTFileLocation loc= node.getFileLocation(); @@ -265,7 +303,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { IIndexFileLocation location = fPathResolver.resolveASTPath(loc.getFileName()); if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros))) return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile; - return getFile(linkageID, location, sigMacros); + return getBestFile(linkageID, location, node.getTranslationUnit().getOriginatingTranslationUnit()); } } } @@ -274,13 +312,13 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { private ISignificantMacros getSignificantMacros(IASTNode node, IASTFileLocation loc) throws CoreException { IASTPreprocessorIncludeStatement owner= loc.getContextInclusionStatement(); - if (owner != null) + if (owner != null) return owner.getSignificantMacros(); IASTTranslationUnit tu = node.getTranslationUnit(); if (tu != null) return tu.getSignificantMacros(); - + return null; } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java index 271d87b219a..fb918407e8e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java @@ -1308,8 +1308,27 @@ public class CompletionTests extends AbstractContentAssistTest { // void foo() { // __LINE__; // } - public void testLineMacro_Bug412463() throws Exception { + public void testPreprocessorProvidedMacro_Bug412463() throws Exception { final String[] expected = { "Cat", "meow(void)" }; assertContentAssistResults(fCursorOffset, expected, true, COMPARE_ID_STRINGS); } + + // struct Cat { + // void meow(); + // }; + // + // struct Waldo { + // void bar() { + // c./*cursor*/ + // } + // + // Cat c; + // }; + // + // int x = __CDT_PARSER__; + public void testPredefinedMacro_Bug412463() throws Exception { + final String[] expected = { "Cat", "meow(void)" }; + assertContentAssistResults(fCursorOffset, expected, true, COMPARE_ID_STRINGS); + } + }
\ No newline at end of file |