From 098712b4d916df7a8f00098a45b8571057ca8593 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 5 Oct 2011 16:54:24 +0200 Subject: [PATCH] Manage the removal of an include guard --- .../core/index/IIndexFragmentFile.java | 6 + .../internal/core/index/IWritableIndex.java | 12 ++ .../internal/core/index/WritableCIndex.java | 14 +- .../core/pdom/AbstractIndexerTask.java | 188 ++++++++++++------ .../cdt/internal/core/pdom/PDOMWriter.java | 47 ++++- .../cdt/internal/core/pdom/dom/PDOMFile.java | 24 ++- 6 files changed, 214 insertions(+), 77 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java index 0c6be49c501..210261583b7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java @@ -61,4 +61,10 @@ public interface IIndexFragmentFile extends IIndexFile { * The file 'source' must belong to the same fragment as this file. */ void transferIncluders(IIndexFragmentFile source) throws CoreException; + + /** + * Changes the inclusion from the context of 'source' to point to this file, instead. + * The file 'source' must belong to the same fragment as this file. + */ + void transferContext(IIndexFragmentFile source) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java index a44bfa6bcf4..b0833880aae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java @@ -59,6 +59,12 @@ public interface IWritableIndex extends IIndex { IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location, ISignificantMacros macroDictionary) throws CoreException; + /** + * Returns the writable files for the given location and linkage. This method + * returns file objects without content, also. + */ + IIndexFragmentFile[] getWritableFiles(int linkageID, IIndexFileLocation location) throws CoreException; + /** * Returns the writable files for the given location in any linkage. This method * returns file objects without content, also. @@ -178,4 +184,10 @@ public interface IWritableIndex extends IIndex { * Both files must belong to the writable fragment. */ void transferIncluders(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException; + + /** + * Changes the inclusion from the context of 'source' to point to 'target', instead. + * Both files must belong to the writable fragment. + */ + void transferContext(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java index 6eb50a58e44..0a0526da2c5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java @@ -46,7 +46,11 @@ public class WritableCIndex extends CIndex implements IWritableIndex { ISignificantMacros macroDictionary) throws CoreException { return fWritableFragment.getFile(linkageID, location, macroDictionary); } - + + public IIndexFragmentFile[] getWritableFiles(int linkageID, IIndexFileLocation location) throws CoreException { + return fWritableFragment.getFiles(linkageID, location); + } + public IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException { return fWritableFragment.getFiles(location); } @@ -185,4 +189,12 @@ public class WritableCIndex extends CIndex implements IWritableIndex { return; target.transferIncluders(source); } + + public void transferContext(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException { + if (source == null || target == null || !isWritableFile(source) || !isWritableFile(target)) + throw new IllegalArgumentException(); + if (source.equals(target)) + return; + target.transferContext(source); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java index 1e14e8e0e3c..6f69f48146a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java @@ -20,10 +20,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMIndexerTask; @@ -802,7 +802,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (monitor.isCanceled() || hasUrgentTasks()) return; parseVersionInContext(linkageID, map, ifl, versionTask, locTask.fTu, - new HashSet(), monitor); + new LinkedHashSet(), monitor); } } } @@ -857,19 +857,60 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } private void parseVersionInContext(int linkageID, LinkageTask map, IIndexFileLocation ifl, - final FileVersionTask versionTask, Object tu, Set safeGuard, + final FileVersionTask versionTask, Object tu, LinkedHashSet safeGuard, IProgressMonitor monitor) throws CoreException, InterruptedException { final IIndexFragmentFile headerFile = versionTask.fIndexFile; - IIndexFragmentFile ctx= headerFile; + + final int safeguardSize= safeGuard.size(); for(;;) { - IIndexInclude ctxInclude= ctx.getParsedInContext(); - if (ctxInclude == null) - break; - - final IIndexFragmentFile nextCtx= (IIndexFragmentFile) ctxInclude.getIncludedBy(); - if (!fIndex.isWritableFile(nextCtx) || !safeGuard.add(nextCtx)) - break; + // Look for a context and parse the file + IIndexFragmentFile ctxFile = findContextFile(linkageID, map, versionTask, safeGuard, monitor); + if (ctxFile == null || ctxFile == headerFile) + return; + + Object contextTu= fResolver.getInputFile(ctxFile.getLocation()); + if (contextTu == null) + return; + final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, contextTu); + FileContext ctx= new FileContext(ctxFile, headerFile); + parseFile(tu, linkageID, ifl, scannerInfo, ctx, monitor); + if (!ctx.fLostPragmaOnceSemantics) + return; + + // Try the next context + restoreSet(safeGuard, safeguardSize); + } + } + + private void restoreSet(LinkedHashSet set, int restoreSize) { + for (Iterator it = set.iterator(); it.hasNext();) { + it.next(); + if (restoreSize == 0) { + it.remove(); + } else { + restoreSize--; + } + } + } + + private IIndexFragmentFile findContextFile(int linkageID, LinkageTask map, + final FileVersionTask versionTask, LinkedHashSet safeGuard, IProgressMonitor monitor) + throws CoreException, InterruptedException { + IIndexFragmentFile ctxFile= versionTask.fIndexFile; + for(;;) { + IIndexInclude ctxInclude= ctxFile.getParsedInContext(); + if (ctxInclude == null) + return ctxFile; + + IIndexFragmentFile nextCtx= (IIndexFragmentFile) ctxInclude.getIncludedBy(); + if (!fIndex.isWritableFile(nextCtx)) + return ctxFile; + + // Found a recursion + if (!safeGuard.add(nextCtx)) + return null; + final IIndexFileLocation ctxIfl = nextCtx.getLocation(); LocationTask ctxTask= map.find(ctxIfl); if (ctxTask != null) { @@ -880,30 +921,19 @@ public abstract class AbstractIndexerTask extends PDOMWriter { safeGuard, monitor); if (ctxVersionTask.fOutdated // This is unexpected. || !versionTask.fOutdated) // Our file was parsed. - return; - + return null; + // The file is no longer a context, look for a different one. - ctxInclude= ctx.getParsedInContext(); - continue; + nextCtx= ctxFile; } } - ctx= nextCtx; + ctxFile= nextCtx; } - - // See if we found a context and parse the file - if (ctx != headerFile) { - Object contextTu= fResolver.getInputFile(ctx.getLocation()); - if (contextTu != null) { - final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, contextTu); - IIndexFragmentFile[] ctx2header= {ctx, headerFile}; - parseFile(tu, linkageID, ifl, scannerInfo, ctx2header, monitor); - } - } } private void parseFile(Object tu, int linkageID, IIndexFileLocation ifl, IScannerInfo scanInfo, - IIndexFragmentFile[] ctx2header, IProgressMonitor pm) throws CoreException, InterruptedException { + FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException { IPath path= getLabel(ifl); AbstractLanguage[] langs= fResolver.getLanguages(tu, true); AbstractLanguage lang= null; @@ -926,11 +956,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter { path.lastSegment(), path.removeLastSegments(1).toString())); long start= System.currentTimeMillis(); FileContent codeReader= fResolver.getCodeReader(tu); - IASTTranslationUnit ast= createAST(tu, lang, codeReader, scanInfo, fASTOptions, ctx2header, pm); + IIndexFile[] ctxFiles = ctx == null ? null : new IIndexFile[] {ctx.fContext, ctx.fOldFile}; + + IASTTranslationUnit ast= createAST(tu, lang, codeReader, scanInfo, fASTOptions, ctxFiles, pm); fStatistics.fParsingTime += System.currentTimeMillis() - start; if (ast != null) { - IIndexFragmentFile rewrite= ctx2header == null ? null : ctx2header[1]; - writeToIndex(linkageID, ast, codeReader.getContentsHash(), rewrite, pm); + writeToIndex(linkageID, ast, codeReader.getContentsHash(), ctx, pm); } } catch (CoreException e) { th= e; @@ -1055,7 +1086,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } private void writeToIndex(final int linkageID, IASTTranslationUnit ast, long fileContentsHash, - IIndexFragmentFile replace, IProgressMonitor pm) throws CoreException, InterruptedException { + FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException { HashSet enteredFiles= new HashSet(); ArrayList orderedFileKeys= new ArrayList(); @@ -1068,13 +1099,20 @@ public abstract class AbstractIndexerTask extends PDOMWriter { collectOrderedFileKeys(linkageID, inclusion, enteredFiles, orderedFileKeys); } - if (replace != null || needToStoreInIndex(linkageID, topIfl, ast.getSignificantMacros())) { + IIndexFile newFile= selectIndexFile(linkageID, topIfl, ast.getSignificantMacros()); + if (ctx != null) { + orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash)); + if (newFile != null && fIndex.isWritableFile(newFile)) { + // File can be reused + ctx.fNewFile= (IIndexFragmentFile) newFile; + } + } else if (newFile == null) { orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash)); } - + FileInAST[] fileKeys= orderedFileKeys.toArray(new FileInAST[orderedFileKeys.size()]); try { - addSymbols(ast, fileKeys, fIndex, false, replace, fTodoTaskUpdater, pm); + addSymbols(ast, fileKeys, fIndex, false, ctx, fTodoTaskUpdater, pm); } catch (CoreException e) { // Avoid parsing files again, that caused an exception to be thrown. withdrawRequests(linkageID, fileKeys); @@ -1099,37 +1137,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter { for (IASTInclusionNode element : nested) { collectOrderedFileKeys(linkageID, element, enteredFiles, orderedFileKeys); } - if (isFirstEntry && needToStoreInIndex(linkageID, ifl, include.getSignificantMacros())) { + if (isFirstEntry && selectIndexFile(linkageID, ifl, include.getSignificantMacros()) == null) { orderedFileKeys.add(new FileInAST(include, fileKey, include.getContentsHash())); } } } - private boolean needToStoreInIndex(int linkageID, IIndexFileLocation ifl, ISignificantMacros sigMacros) throws CoreException { - LinkageTask map = findRequestMap(linkageID); - if (map != null) { - LocationTask locTask= map.find(ifl); - if (locTask != null) { - FileVersionTask task = locTask.findVersion(sigMacros); - if (task != null) { - return task.fOutdated; - } - } - } - IIndexFile ifile= null; - if (fResolver.canBePartOfSDK(ifl)) { - // Check for a version in potentially another pdom. - ifile = fIndex.getFile(linkageID, ifl, sigMacros); - } else { - // Search the writable PDOM, only. - IIndexFragmentFile fragFile = fIndex.getWritableFile(linkageID, ifl, sigMacros); - if (fragFile != null && fragFile.hasContent()) { - ifile= fragFile; - } - } - return ifile == null; - } - private void withdrawRequests(int linkageID, FileInAST[] fileKeys) { LinkageTask map = findRequestMap(linkageID); if (map != null) { @@ -1171,6 +1184,26 @@ public abstract class AbstractIndexerTask extends PDOMWriter { return fc; } + IIndexFile selectIndexFile(int linkageID, IIndexFileLocation ifl, ISignificantMacros sigMacros) throws CoreException { + LinkageTask map = findRequestMap(linkageID); + if (map != null) { + LocationTask locTask= map.find(ifl); + if (locTask != null) { + FileVersionTask task = locTask.findVersion(sigMacros); + if (task != null) { + return task.fOutdated ? null : task.fIndexFile; + } + } + } + + IIndexFile[] files = getAvailableIndexFiles(linkageID, ifl); + for (IIndexFile file : files) { + if (sigMacros.equals(file.getSignificantMacros())) + return file; + } + return null; + } + public IIndexFile selectIndexFile(int linkageID, IIndexFileLocation ifl, IMacroDictionary md) throws CoreException { LinkageTask map = findRequestMap(linkageID); if (map != null) { @@ -1187,11 +1220,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } } - IIndexFile[] files= fIndexFilesCache.get(ifl); - if (files == null) { - files= fIndex.getFiles(linkageID, ifl); - fIndexFilesCache.put(ifl, files); - } + IIndexFile[] files = getAvailableIndexFiles(linkageID, ifl); for (IIndexFile indexFile : files) { if (md.satisfies(indexFile.getSignificantMacros())) { return indexFile; @@ -1199,4 +1228,33 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } return null; } + + public IIndexFile[] getAvailableIndexFiles(int linkageID, IIndexFileLocation ifl) + throws CoreException { + IIndexFile[] files= fIndexFilesCache.get(ifl); + if (files == null) { + if (fResolver.canBePartOfSDK(ifl)) { + // Check for a version in potentially another pdom. + files= fIndex.getFiles(linkageID, ifl); + } else { + IIndexFragmentFile[] fragFiles = fIndex.getWritableFiles(linkageID, ifl); + int j= 0; + for (int i = 0; i < fragFiles.length; i++) { + if (fragFiles[i].hasContent()) { + if (j != i) + fragFiles[j]= fragFiles[i]; + j++; + } + } + if (j == fragFiles.length) { + files= fragFiles; + } else { + files= new IIndexFile[j]; + System.arraycopy(fragFiles, 0, files, 0, j); + } + } + fIndexFilesCache.put(ifl, files); + } + return files; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index e17e1505122..7bf753147d3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -87,6 +87,19 @@ abstract public class PDOMWriter { return fFileContentKey.toString(); } } + + public static class FileContext { + final IIndexFragmentFile fContext; + final IIndexFragmentFile fOldFile; + IIndexFragmentFile fNewFile; + public boolean fLostPragmaOnceSemantics; + + public FileContext(IIndexFragmentFile context, IIndexFragmentFile oldFile) { + fContext= context; + fOldFile= oldFile; + fNewFile= null; + } + } public static int SKIP_ALL_REFERENCES= -1; public static int SKIP_TYPE_REFERENCES= 1; @@ -174,7 +187,7 @@ abstract public class PDOMWriter { * the index after your last write operation. */ final protected void addSymbols(IASTTranslationUnit ast, FileInAST[] selectedFiles, - IWritableIndex index, boolean flushIndex, IIndexFragmentFile replaceFile, + IWritableIndex index, boolean flushIndex, FileContext ctx, ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException, CoreException { if (fShowProblems) { @@ -196,7 +209,7 @@ abstract public class PDOMWriter { resolveNames(data, pm); // Index update - storeSymbolsInIndex(data, replaceFile, flushIndex, pm); + storeSymbolsInIndex(data, ctx, flushIndex, pm); // Tasks update if (taskUpdater != null) { @@ -228,8 +241,9 @@ abstract public class PDOMWriter { } } - private void storeSymbolsInIndex(final Data data, IIndexFragmentFile replaceFile, boolean flushIndex, IProgressMonitor pm) + private void storeSymbolsInIndex(final Data data, FileContext ctx, boolean flushIndex, IProgressMonitor pm) throws InterruptedException, CoreException { + final IIndexFragmentFile newFile= ctx == null ? null : ctx.fNewFile; final int linkageID= data.fAST.getLinkage().getLinkageID(); for (int i= 0; i < data.fSelectedFiles.length; i++) { if (pm.isCanceled()) @@ -244,14 +258,27 @@ abstract public class PDOMWriter { YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex); lock.acquire(); try { - IIndexFragmentFile ifile= storeFileInIndex(data, fileInAST, linkageID, lock); - if (fileInAST.fIncludeStatement == null && replaceFile != null && !replaceFile.equals(ifile)) { - data.fIndex.transferIncluders(replaceFile, ifile); + final boolean isReplacement= ctx != null && fileInAST.fIncludeStatement == null; + IIndexFragmentFile ifile= null; + if (!isReplacement || newFile == null) { + ifile= storeFileInIndex(data, fileInAST, linkageID, lock); reportFileWrittenToIndex(fileInAST, ifile); - } else { - reportFileWrittenToIndex(fileInAST, ifile); - } - } catch (RuntimeException e) { + } + + if (isReplacement) { + if (ifile == null) + ifile= newFile; + if (ctx != null && !ctx.fOldFile.equals(ifile) && ifile != null) { + if (ctx.fOldFile.hasPragmaOnceSemantics() && + !ifile.hasPragmaOnceSemantics()) { + data.fIndex.transferContext(ctx.fOldFile, ifile); + ctx.fLostPragmaOnceSemantics= true; + } else { + data.fIndex.transferIncluders(ctx.fOldFile, ifile); + } + } + } + } catch (RuntimeException e) { th= e; } catch (StackOverflowError e) { th= e; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index b35b944e132..2d03e026b0a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -219,9 +219,13 @@ public class PDOMFile implements IIndexFragmentFile { PDOMFile source= (PDOMFile) sourceFile; PDOMInclude include = source.getFirstIncludedBy(); if (include != null) { + // Detach the includes + source.setFirstIncludedBy(null); + // Adjust the includes for (PDOMInclude i=include; i != null; i= i.getNextInIncludedBy()) { i.setIncludes(this); } + // Append the includes PDOMInclude last= getFirstIncludedBy(); if (last == null) { setFirstIncludedBy(include); @@ -233,7 +237,25 @@ public class PDOMFile implements IIndexFragmentFile { include.setPrevInIncludedBy(last); } } - source.setFirstIncludedBy(null); + } + + public void transferContext(IIndexFragmentFile sourceFile) throws CoreException { + PDOMFile source= (PDOMFile) sourceFile; + PDOMInclude include = source.getFirstIncludedBy(); + if (include != null) { + // Detach the include + final PDOMInclude next = include.getNextInIncludedBy(); + include.setNextInIncludedBy(null); + source.setFirstIncludedBy(next); + if (next != null) + next.setPrevInIncludedBy(null); + + // Adjust the include + include.setIncludes(this); + + // Insert the include + addIncludedBy(include, false); + } } /**