1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-20 15:35:24 +02:00

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>
This commit is contained in:
Nathan Ridge 2013-07-09 01:27:28 -04:00 committed by Sergey Prigogin
parent 6df967d0d4
commit 8f78f34f19
4 changed files with 87 additions and 33 deletions

View file

@ -915,7 +915,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
for (IIndexFile indexFile : index.getFiles(linkageID, ifl)) { for (IIndexFile indexFile : index.getFiles(linkageID, ifl)) {
int score= indexFile.getMacros().length * 2; int score= indexFile.getMacros().length * 2;
IIndexFile context= getParsedInContext(indexFile); IIndexFile context= getParsedInContext(indexFile);
if (isSourceFile(context)) if (isSourceFile(context, getCProject().getProject()))
score++; score++;
if (score > bestScore) { if (score > bestScore) {
bestScore= score; bestScore= score;
@ -936,7 +936,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return null; return null;
} }
private IIndexFile getParsedInContext(IIndexFile indexFile) throws CoreException { public static IIndexFile getParsedInContext(IIndexFile indexFile) throws CoreException {
HashSet<IIndexFile> visited= new HashSet<IIndexFile>(); HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
// Bug 199412, may recurse. // Bug 199412, may recurse.
while (visited.add(indexFile)) { 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 * @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(); String path = indexFile.getLocation().getURI().getPath();
IContentType cType = CCorePlugin.getContentType(getCProject().getProject(), path); IContentType cType = CCorePlugin.getContentType(project, path);
if (cType == null) if (cType == null)
return false; return false;

View file

@ -132,9 +132,6 @@ public interface IIndexFragment {
* for different sets of macro definitions. * for different sets of macro definitions.
* This method may only return files that are actually managed by this fragment. * This method may only return files that are actually managed by this fragment.
* This method returns files without content, also. * 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 linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file * @param location the IIndexFileLocation representing the location of the file

View 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.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; 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.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLocationConverter; 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.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.FileContentKey; import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; 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.ChunkCache;
import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.DBProperties;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
@ -256,6 +259,41 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
return false; 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 { public PDOMFile getFileForASTNode(int linkageID, IASTNode node) throws CoreException {
if (fPathResolver != null && node != null) { if (fPathResolver != null && node != null) {
IASTFileLocation loc= node.getFileLocation(); IASTFileLocation loc= node.getFileLocation();
@ -265,7 +303,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
IIndexFileLocation location = fPathResolver.resolveASTPath(loc.getFileName()); IIndexFileLocation location = fPathResolver.resolveASTPath(loc.getFileName());
if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros))) if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros)))
return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile; return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile;
return getFile(linkageID, location, sigMacros); return getBestFile(linkageID, location, node.getTranslationUnit().getOriginatingTranslationUnit());
} }
} }
} }

View file

@ -1308,8 +1308,27 @@ public class CompletionTests extends AbstractContentAssistTest {
// void foo() { // void foo() {
// __LINE__; // __LINE__;
// } // }
public void testLineMacro_Bug412463() throws Exception { public void testPreprocessorProvidedMacro_Bug412463() throws Exception {
final String[] expected = { "Cat", "meow(void)" }; final String[] expected = { "Cat", "meow(void)" };
assertContentAssistResults(fCursorOffset, expected, true, COMPARE_ID_STRINGS); 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);
}
} }