From d844f5e24a519efc74b17e48f6a8daa5290023d6 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 25 Apr 2008 12:45:14 +0000 Subject: [PATCH] Improved setup of macro dictionary for headers opened in editor, bug 228012 --- .../internal/index/tests/IndexBugsTests.java | 27 ++++ .../internal/core/model/TranslationUnit.java | 3 + .../index/IndexBasedCodeReaderFactory.java | 142 ++++++++++++++++-- .../core/parser/scanner/CPreprocessor.java | 24 ++- .../scanner/IIndexBasedCodeReaderFactory.java | 8 + 5 files changed, 186 insertions(+), 18 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 9e1bd7e621b..ba26dd09cde 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -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(); + } + } } \ No newline at end of file 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 e6e464fbb53..f83093e4bc4 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 @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java index a4888fcf362..6c0b7ad20ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java @@ -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,9 +73,25 @@ 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) { @@ -91,7 +110,12 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF public boolean getInclusionExists(String path) { 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,11 +160,7 @@ 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 macroMap, List files, boolean checkIncluded) throws CoreException, NeedToParseException { IIndexFileLocation ifl= file.getLocation(); if (macroMap.containsKey(ifl) || (checkIncluded && fIncludedFiles.contains(ifl))) { @@ -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; + } + + 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 filesIncluded= new HashSet(); + ArrayList macros= new ArrayList(); + ArrayList directives= new ArrayList(); + 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(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 ifiles= new HashSet(); + 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 filesIncluded, List macros, + List 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; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 5d65ad0e563..03536c9e8de 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IIndexBasedCodeReaderFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IIndexBasedCodeReaderFactory.java index 217cfea2bfd..0f58e303555 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IIndexBasedCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IIndexBasedCodeReaderFactory.java @@ -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); }