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.ASTTypeUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
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.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
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.IIndexName;
|
||||||
import org.eclipse.cdt.core.index.IndexFilter;
|
import org.eclipse.cdt.core.index.IndexFilter;
|
||||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
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.ICElement;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
@ -1323,4 +1325,29 @@ public class IndexBugsTests extends BaseTestCase {
|
||||||
fIndex.releaseReadLock();
|
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) {
|
if (index != null && (style & AST_SKIP_INDEXED_HEADERS) != 0) {
|
||||||
IndexBasedCodeReaderFactory ibcf= new IndexBasedCodeReaderFactory(index, new ProjectIndexerInputAdapter(getCProject()), linkageID, codeReaderFactory);
|
IndexBasedCodeReaderFactory ibcf= new IndexBasedCodeReaderFactory(index, new ProjectIndexerInputAdapter(getCProject()), linkageID, codeReaderFactory);
|
||||||
|
if ((style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
|
||||||
|
ibcf.setSupportFillGapFromContextToHeader(true);
|
||||||
|
}
|
||||||
codeReaderFactory= ibcf;
|
codeReaderFactory= ibcf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -47,6 +48,7 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
*/
|
*/
|
||||||
public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderFactory {
|
public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderFactory {
|
||||||
private static final class NeedToParseException extends Exception {}
|
private static final class NeedToParseException extends Exception {}
|
||||||
|
private static final String GAP = "__gap__"; //$NON-NLS-1$
|
||||||
|
|
||||||
private final IIndex fIndex;
|
private final IIndex fIndex;
|
||||||
private int fLinkage;
|
private int fLinkage;
|
||||||
|
@ -55,6 +57,7 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
private final ICodeReaderFactory fFallBackFactory;
|
private final ICodeReaderFactory fFallBackFactory;
|
||||||
private final ASTFilePathResolver fPathResolver;
|
private final ASTFilePathResolver fPathResolver;
|
||||||
private final AbstractIndexerTask fRelatedIndexerTask;
|
private final AbstractIndexerTask fRelatedIndexerTask;
|
||||||
|
private boolean fSupportFillGapFromContextToHeader= false;
|
||||||
|
|
||||||
public IndexBasedCodeReaderFactory(IIndex index, ASTFilePathResolver pathResolver, int linkage,
|
public IndexBasedCodeReaderFactory(IIndex index, ASTFilePathResolver pathResolver, int linkage,
|
||||||
ICodeReaderFactory fallbackFactory) {
|
ICodeReaderFactory fallbackFactory) {
|
||||||
|
@ -70,9 +73,25 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
fLinkage= linkage;
|
fLinkage= linkage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSupportFillGapFromContextToHeader(boolean val) {
|
||||||
|
fSupportFillGapFromContextToHeader= val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLinkage(int linkageID) {
|
||||||
|
fLinkage= linkageID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanupAfterTranslationUnit() {
|
||||||
|
fIncludedFiles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public int getUniqueIdentifier() {
|
public int getUniqueIdentifier() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ICodeReaderCache getCodeReaderCache() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public CodeReader createCodeReaderForTranslationUnit(String path) {
|
public CodeReader createCodeReaderForTranslationUnit(String path) {
|
||||||
if (fFallBackFactory != null) {
|
if (fFallBackFactory != null) {
|
||||||
|
@ -91,7 +110,12 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
public boolean getInclusionExists(String path) {
|
public boolean getInclusionExists(String path) {
|
||||||
return fPathResolver.doesIncludeFileExist(path);
|
return fPathResolver.doesIncludeFileExist(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasFileBeenIncludedInCurrentTranslationUnit(String path) {
|
||||||
|
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
|
||||||
|
return fIncludedFiles.contains(ifl);
|
||||||
|
}
|
||||||
|
|
||||||
public IncludeFileContent getContentForInclusion(String path) {
|
public IncludeFileContent getContentForInclusion(String path) {
|
||||||
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
|
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
|
||||||
if (ifl == null) {
|
if (ifl == null) {
|
||||||
|
@ -136,11 +160,7 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
return null;
|
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 {
|
private void collectFileContent(IIndexFile file, Map<IIndexFileLocation, FileContent> macroMap, List<IIndexFile> files, boolean checkIncluded) throws CoreException, NeedToParseException {
|
||||||
IIndexFileLocation ifl= file.getLocation();
|
IIndexFileLocation ifl= file.getLocation();
|
||||||
if (macroMap.containsKey(ifl) || (checkIncluded && fIncludedFiles.contains(ifl))) {
|
if (macroMap.containsKey(ifl) || (checkIncluded && fIncludedFiles.contains(ifl))) {
|
||||||
|
@ -163,8 +183,7 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
|
|
||||||
// follow the includes
|
// follow the includes
|
||||||
IIndexInclude[] includeDirectives= file.getIncludes();
|
IIndexInclude[] includeDirectives= file.getIncludes();
|
||||||
for (int i = 0; i < includeDirectives.length; i++) {
|
for (final IIndexInclude indexInclude : includeDirectives) {
|
||||||
final IIndexInclude indexInclude = includeDirectives[i];
|
|
||||||
IIndexFile includedFile= fIndex.resolveInclude(indexInclude);
|
IIndexFile includedFile= fIndex.resolveInclude(indexInclude);
|
||||||
if (includedFile != null) {
|
if (includedFile != null) {
|
||||||
collectFileContent(includedFile, macroMap, files, true);
|
collectFileContent(includedFile, macroMap, files, true);
|
||||||
|
@ -172,15 +191,108 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanupAfterTranslationUnit() {
|
public IncludeFileContent getContentForContextToHeaderGap(String path) {
|
||||||
fIncludedFiles.clear();
|
if (!fSupportFillGapFromContextToHeader) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
public ICodeReaderCache getCodeReaderCache() {
|
// 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLinkage(int linkageID) {
|
private IIndexFile findContext(IIndexFile file) throws CoreException {
|
||||||
fLinkage= linkageID;
|
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.CharArrayMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
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.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.Lexer.LexerOptions;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
import org.eclipse.core.runtime.IAdaptable;
|
||||||
|
@ -135,11 +136,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
private final ScannerContext fRootContext;
|
private final ScannerContext fRootContext;
|
||||||
private ScannerContext fCurrentContext;
|
private ScannerContext fCurrentContext;
|
||||||
|
|
||||||
private boolean isCancelled = false;
|
private boolean isCancelled= false;
|
||||||
|
private boolean fIsFirstFetchToken= true;
|
||||||
|
|
||||||
private Token fPrefetchedTokens;
|
private Token fPrefetchedTokens;
|
||||||
private Token fLastToken;
|
private Token fLastToken;
|
||||||
|
|
||||||
|
|
||||||
public CPreprocessor(CodeReader reader, IScannerInfo info, ParserLanguage language, IParserLogService log,
|
public CPreprocessor(CodeReader reader, IScannerInfo info, ParserLanguage language, IParserLogService log,
|
||||||
IScannerExtensionConfiguration configuration, ICodeReaderFactory readerFactory) {
|
IScannerExtensionConfiguration configuration, ICodeReaderFactory readerFactory) {
|
||||||
fLog = log;
|
fLog = log;
|
||||||
|
@ -201,6 +204,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
public boolean getInclusionExists(String path) {
|
public boolean getInclusionExists(String path) {
|
||||||
return readerFactory.createCodeReaderForInclusion(path) != null;
|
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() {
|
private void handlePreIncludedFiles() {
|
||||||
final String[] imacro= fPreIncludedFiles[0];
|
final String[] imacro= fPreIncludedFiles[0];
|
||||||
if (imacro != null && imacro.length > 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.
|
* Returns the next token from the preprocessor without concatenating string literals.
|
||||||
*/
|
*/
|
||||||
private Token fetchToken() throws OffsetLimitReachedException {
|
private Token fetchToken() throws OffsetLimitReachedException {
|
||||||
if (fPreIncludedFiles != null) {
|
if (fIsFirstFetchToken) {
|
||||||
handlePreIncludedFiles();
|
beforeFirstFetchToken();
|
||||||
|
fIsFirstFetchToken= false;
|
||||||
}
|
}
|
||||||
Token t= fPrefetchedTokens;
|
Token t= fPrefetchedTokens;
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
package org.eclipse.cdt.internal.core.parser.scanner;
|
package org.eclipse.cdt.internal.core.parser.scanner;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ICodeReaderFactory;
|
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.
|
* 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
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
boolean getInclusionExists(String finalPath);
|
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