mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Improved setup of macro dictionary for headers opened in editor, bug 228012
This commit is contained in:
parent
b89383e939
commit
d844f5e24a
5 changed files with 186 additions and 18 deletions
|
@ -27,6 +27,7 @@ import org.eclipse.cdt.core.dom.IPDOMManager;
|
|||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
@ -49,6 +50,7 @@ import org.eclipse.cdt.core.index.IIndexManager;
|
|||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.index.IndexFilter;
|
||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
|
@ -1323,4 +1325,29 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
fIndex.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
// #define BUG ok
|
||||
|
||||
// int BUG;
|
||||
|
||||
// #include "common.h"
|
||||
// #include "header.h"
|
||||
public void testCommonHeader_Bug228012() throws Exception {
|
||||
String[] contents= getContentsForTest(3);
|
||||
final IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
TestSourceReader.createFile(fCProject.getProject(), "common.h", contents[0]);
|
||||
IFile hfile= TestSourceReader.createFile(fCProject.getProject(), "header.h", contents[1]);
|
||||
TestSourceReader.createFile(fCProject.getProject(), "source.cpp", contents[2]);
|
||||
indexManager.reindex(fCProject);
|
||||
waitForIndexer();
|
||||
ITranslationUnit tu= (ITranslationUnit) CoreModel.getDefault().create(hfile);
|
||||
fIndex.acquireReadLock();
|
||||
try {
|
||||
IASTTranslationUnit ast= tu.getAST(fIndex, ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT | ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
|
||||
IASTSimpleDeclaration decl= (IASTSimpleDeclaration) ast.getDeclarations()[0];
|
||||
assertEquals("ok", decl.getDeclarators()[0].getName().toString());
|
||||
} finally {
|
||||
fIndex.releaseReadLock();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -843,6 +843,9 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
|||
|
||||
if (index != null && (style & AST_SKIP_INDEXED_HEADERS) != 0) {
|
||||
IndexBasedCodeReaderFactory ibcf= new IndexBasedCodeReaderFactory(index, new ProjectIndexerInputAdapter(getCProject()), linkageID, codeReaderFactory);
|
||||
if ((style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
|
||||
ibcf.setSupportFillGapFromContextToHeader(true);
|
||||
}
|
||||
codeReaderFactory= ibcf;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ package org.eclipse.cdt.internal.core.index;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -47,6 +48,7 @@ import org.eclipse.core.runtime.CoreException;
|
|||
*/
|
||||
public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderFactory {
|
||||
private static final class NeedToParseException extends Exception {}
|
||||
private static final String GAP = "__gap__"; //$NON-NLS-1$
|
||||
|
||||
private final IIndex fIndex;
|
||||
private int fLinkage;
|
||||
|
@ -55,6 +57,7 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
|||
private final ICodeReaderFactory fFallBackFactory;
|
||||
private final ASTFilePathResolver fPathResolver;
|
||||
private final AbstractIndexerTask fRelatedIndexerTask;
|
||||
private boolean fSupportFillGapFromContextToHeader= false;
|
||||
|
||||
public IndexBasedCodeReaderFactory(IIndex index, ASTFilePathResolver pathResolver, int linkage,
|
||||
ICodeReaderFactory fallbackFactory) {
|
||||
|
@ -70,10 +73,26 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
|||
fLinkage= linkage;
|
||||
}
|
||||
|
||||
public void setSupportFillGapFromContextToHeader(boolean val) {
|
||||
fSupportFillGapFromContextToHeader= val;
|
||||
}
|
||||
|
||||
public void setLinkage(int linkageID) {
|
||||
fLinkage= linkageID;
|
||||
}
|
||||
|
||||
public void cleanupAfterTranslationUnit() {
|
||||
fIncludedFiles.clear();
|
||||
}
|
||||
|
||||
public int getUniqueIdentifier() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ICodeReaderCache getCodeReaderCache() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public CodeReader createCodeReaderForTranslationUnit(String path) {
|
||||
if (fFallBackFactory != null) {
|
||||
return fFallBackFactory.createCodeReaderForTranslationUnit(path);
|
||||
|
@ -92,6 +111,11 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
|||
return fPathResolver.doesIncludeFileExist(path);
|
||||
}
|
||||
|
||||
public boolean hasFileBeenIncludedInCurrentTranslationUnit(String path) {
|
||||
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
|
||||
return fIncludedFiles.contains(ifl);
|
||||
}
|
||||
|
||||
public IncludeFileContent getContentForInclusion(String path) {
|
||||
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
|
||||
if (ifl == null) {
|
||||
|
@ -136,10 +160,6 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean hasFileBeenIncludedInCurrentTranslationUnit(String path) {
|
||||
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
|
||||
return fIncludedFiles.contains(ifl);
|
||||
}
|
||||
|
||||
private void collectFileContent(IIndexFile file, Map<IIndexFileLocation, FileContent> macroMap, List<IIndexFile> files, boolean checkIncluded) throws CoreException, NeedToParseException {
|
||||
IIndexFileLocation ifl= file.getLocation();
|
||||
|
@ -163,8 +183,7 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
|||
|
||||
// follow the includes
|
||||
IIndexInclude[] includeDirectives= file.getIncludes();
|
||||
for (int i = 0; i < includeDirectives.length; i++) {
|
||||
final IIndexInclude indexInclude = includeDirectives[i];
|
||||
for (final IIndexInclude indexInclude : includeDirectives) {
|
||||
IIndexFile includedFile= fIndex.resolveInclude(indexInclude);
|
||||
if (includedFile != null) {
|
||||
collectFileContent(includedFile, macroMap, files, true);
|
||||
|
@ -172,15 +191,108 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
|||
}
|
||||
}
|
||||
|
||||
public void cleanupAfterTranslationUnit() {
|
||||
fIncludedFiles.clear();
|
||||
}
|
||||
public IncludeFileContent getContentForContextToHeaderGap(String path) {
|
||||
if (!fSupportFillGapFromContextToHeader) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICodeReaderCache getCodeReaderCache() {
|
||||
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
|
||||
if (ifl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
IIndexFile targetFile= fIndex.getFile(fLinkage, ifl);
|
||||
if (targetFile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IIndexFile contextFile= findContext(targetFile);
|
||||
if (contextFile == targetFile || contextFile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HashSet<IIndexFile> filesIncluded= new HashSet<IIndexFile>();
|
||||
ArrayList<IIndexMacro> macros= new ArrayList<IIndexMacro>();
|
||||
ArrayList<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
|
||||
if (!collectFileContentForGap(contextFile, ifl, filesIncluded, macros, directives)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// mark the files in the gap as included
|
||||
for (IIndexFile file : filesIncluded) {
|
||||
fIncludedFiles.add(file.getLocation());
|
||||
}
|
||||
Collections.reverse(macros);
|
||||
return new IncludeFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded));
|
||||
}
|
||||
catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setLinkage(int linkageID) {
|
||||
fLinkage= linkageID;
|
||||
private IIndexFile findContext(IIndexFile file) throws CoreException {
|
||||
final HashSet<IIndexFile> ifiles= new HashSet<IIndexFile>();
|
||||
ifiles.add(file);
|
||||
IIndexInclude include= file.getParsedInContext();
|
||||
while (include != null) {
|
||||
final IIndexFile context= include.getIncludedBy();
|
||||
if (!ifiles.add(context)) {
|
||||
return file;
|
||||
}
|
||||
file= context;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private boolean collectFileContentForGap(IIndexFile from, IIndexFileLocation to,
|
||||
Set<IIndexFile> filesIncluded, List<IIndexMacro> macros,
|
||||
List<ICPPUsingDirective> directives) throws CoreException {
|
||||
|
||||
final IIndexFileLocation ifl= from.getLocation();
|
||||
if (ifl.equals(to)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fIncludedFiles.contains(ifl) || !filesIncluded.add(from)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final IIndexInclude[] includeDirectives= from.getIncludes();
|
||||
IIndexInclude success= null;
|
||||
for (IIndexInclude indexInclude : includeDirectives) {
|
||||
IIndexFile includedFile= fIndex.resolveInclude(indexInclude);
|
||||
if (includedFile != null) {
|
||||
if (collectFileContentForGap(includedFile, to, filesIncluded, macros, directives)) {
|
||||
success= indexInclude;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IIndexMacro[] mymacros= from.getMacros();
|
||||
ICPPUsingDirective[] mydirectives= from.getUsingDirectives();
|
||||
int startm, startd;
|
||||
if (success == null) {
|
||||
startm= mymacros.length-1;
|
||||
startd= mydirectives.length-1;
|
||||
}
|
||||
else {
|
||||
startm= startd= -1;
|
||||
final int offset= success.getNameOffset();
|
||||
for (IIndexMacro macro : from.getMacros()) {
|
||||
if (macro.getFileLocation().getNodeOffset() < offset) {
|
||||
startm++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i= startm; i >= 0; i--) {
|
||||
macros.add(mymacros[i]);
|
||||
}
|
||||
for (int i= startd; i >= 0; i--) {
|
||||
directives.add(mydirectives[i]);
|
||||
}
|
||||
return success != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
|
|||
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
|
@ -135,11 +136,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
private final ScannerContext fRootContext;
|
||||
private ScannerContext fCurrentContext;
|
||||
|
||||
private boolean isCancelled = false;
|
||||
private boolean isCancelled= false;
|
||||
private boolean fIsFirstFetchToken= true;
|
||||
|
||||
private Token fPrefetchedTokens;
|
||||
private Token fLastToken;
|
||||
|
||||
|
||||
public CPreprocessor(CodeReader reader, IScannerInfo info, ParserLanguage language, IParserLogService log,
|
||||
IScannerExtensionConfiguration configuration, ICodeReaderFactory readerFactory) {
|
||||
fLog = log;
|
||||
|
@ -201,6 +204,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
public boolean getInclusionExists(String path) {
|
||||
return readerFactory.createCodeReaderForInclusion(path) != null;
|
||||
}
|
||||
public IncludeFileContent getContentForContextToHeaderGap(String fileLocation) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -296,6 +302,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
}
|
||||
|
||||
private void beforeFirstFetchToken() {
|
||||
if (fPreIncludedFiles != null) {
|
||||
handlePreIncludedFiles();
|
||||
}
|
||||
final String location = fLocationMap.getTranslationUnitPath();
|
||||
IncludeFileContent content= fCodeReaderFactory.getContentForContextToHeaderGap(location);
|
||||
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
|
||||
processInclusionFromIndex(0, location, content);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePreIncludedFiles() {
|
||||
final String[] imacro= fPreIncludedFiles[0];
|
||||
if (imacro != null && imacro.length > 0) {
|
||||
|
@ -377,8 +394,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
* Returns the next token from the preprocessor without concatenating string literals.
|
||||
*/
|
||||
private Token fetchToken() throws OffsetLimitReachedException {
|
||||
if (fPreIncludedFiles != null) {
|
||||
handlePreIncludedFiles();
|
||||
if (fIsFirstFetchToken) {
|
||||
beforeFirstFetchToken();
|
||||
fIsFirstFetchToken= false;
|
||||
}
|
||||
Token t= fPrefetchedTokens;
|
||||
if (t != null) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.cdt.internal.core.parser.scanner;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ICodeReaderFactory;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind;
|
||||
|
||||
/**
|
||||
* The index based code-reader factory fakes the inclusion of files that are already indexed.
|
||||
|
@ -36,4 +37,11 @@ public interface IIndexBasedCodeReaderFactory extends ICodeReaderFactory {
|
|||
* @since 5.0
|
||||
*/
|
||||
boolean getInclusionExists(String finalPath);
|
||||
|
||||
/**
|
||||
* Returns a file-content object of kind {@link InclusionKind#FOUND_IN_INDEX}, representing
|
||||
* the content from the context of the given file up to where the file actually gets included.
|
||||
* @since 5.0
|
||||
*/
|
||||
IncludeFileContent getContentForContextToHeaderGap(String fileLocation);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue