1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 351271 - Unused header will be removed from index when saved.

This commit is contained in:
sprigogin 2011-07-14 12:36:43 -07:00
parent 89e15ab2d8
commit c14dcb907d
8 changed files with 266 additions and 58 deletions

View file

@ -90,11 +90,21 @@ public interface IIndexManager extends IPDOMManager {
public final static int UPDATE_CHECK_CONTENTS_HASH= 0x10;
/**
* Include files that are otherwise would be excluded from the index.
* Include files that are otherwise would be excluded from the index. This flag is sticky
* for the duration of the Eclipse session. If the files are later updated without this flag,
* they remain in the index.
* @since 5.3
*/
public final static int FORCE_INDEX_INCLUSION= 0x20;
/**
* Causes files previously included in the index due to FORCE_INDEX_INCLUSION to loose
* their index inclusion privilege. The files included only due to FORCE_INDEX_INCLUSION,
* will be removed from the index.
* @since 5.4
*/
public final static int RESET_INDEX_INCLUSION= 0x40;
/**
* Returns the index for the given project.
* @param project the project to get the index for

View file

@ -74,6 +74,16 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
return false;
}
@Override
public boolean isIndexedUnconditionally(Object tu) {
return false;
}
@Override
public boolean isIndexedUnconditionally(IIndexFileLocation ifl) {
return false;
}
@Override
public boolean isSource(String filename) {
return isValidSourceUnitName(filename);

View file

@ -83,10 +83,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
fUri= uri;
fLinkageID= linkageID;
}
@Override
public int hashCode() {
return fUri.hashCode() * 31 + fLinkageID;
}
@Override
public boolean equals(Object obj) {
FileKey other = (FileKey) obj;
@ -465,7 +467,6 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
final boolean checkTimestamps= (fUpdateFlags & IIndexManager.UPDATE_CHECK_TIMESTAMPS) != 0;
final boolean checkFileContentsHash = (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONTENTS_HASH) != 0;
final boolean checkConfig= (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONFIGURATION) != 0;
final boolean forceInclusion= (fUpdateFlags & IIndexManager.FORCE_INDEX_INCLUSION) != 0;
int count= 0;
int forceFirst= fForceNumberFiles;
@ -484,7 +485,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
final boolean isExcludedSource= isSourceUnit && !fIndexFilesWithoutConfiguration && !fResolver.isFileBuildConfigured(tu);
if ((isSourceUnit && !isExcludedSource) || fIndexHeadersWithoutContext != UnusedHeaderStrategy.skip ||
forceInclusion) {
fResolver.isIndexedUnconditionally(tu)) {
// Headers or sources required with a specific linkage
AbstractLanguage[] langs= fResolver.getLanguages(tu, fIndexHeadersWithoutContext == UnusedHeaderStrategy.useBoth);
for (AbstractLanguage lang : langs) {
@ -515,7 +516,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
for (IIndexFragmentFile ifile : indexFiles) {
if (ifile != null) {
IIndexInclude ctx= ifile.getParsedInContext();
if (ctx == null) {
if (ctx == null && !fResolver.isIndexedUnconditionally(ifile.getLocation())) {
iFilesToRemove.add(ifile);
count++;
} else {

View file

@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2011 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import java.util.HashMap;
/**
* Thread-safe reference counted set of objects.
*
* @param <T> Type of the objects contained in the set.
*/
public class AtomicMultiSet<T> {
private final HashMap<T, Integer> map = new HashMap<T, Integer>();
/**
* Adds object to the set if it was not present, or increments its reference count
* otherwise.
* @param object The object to add to the set.
* @return Reference count of the object after the operation.
*/
public synchronized int add(T object) {
Integer count = map.get(object);
if (count == null) {
count = Integer.valueOf(1);
} else {
count = Integer.valueOf(count.intValue() + 1);
}
map.put(object, count);
return count.intValue();
}
/**
* Decrements reference count of the object in the set and removes the object if its
* reference count reaches zero.
* @param object The object to remove from the set.
* @return Reference count of the object after the operation, or -1 if the object was not
* present in the set.
*/
public synchronized int remove(T object) {
Integer count = map.remove(object);
if (count == null) {
return -1;
}
int n = count.intValue() - 1;
if (n <= 0) {
return n;
}
map.put(object, Integer.valueOf(n));
return n;
}
public synchronized void clear() {
map.clear();
}
public synchronized boolean contains(T object) {
return map.containsKey(object);
}
public synchronized int getCount(T object) {
Integer count = map.get(object);
return count != null ? count.intValue() : 0;
}
public synchronized boolean isEmpty() {
return map.isEmpty();
}
public synchronized int size() {
return map.size();
}
@Override
public synchronized String toString() {
return map.toString();
}
}

View file

@ -50,11 +50,25 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver {
public abstract boolean isFileBuildConfigured(Object tu);
/**
* Returns whether the given translation-unit is not indexed unless it gets included.
* Returns whether the given translation unit is not indexed unless it gets included.
* This applies to files that are outside of a source root.
*/
public abstract boolean isIndexedOnlyIfIncluded(Object tu);
/**
* Checks whether the given translation unit should be indexed unconditionally.
* @param tu An ITranslationUnit or a file location in String form.
* @return {@code true} if the translation unit should be indexed unconditionally.
*/
public abstract boolean isIndexedUnconditionally(Object tu);
/**
* Checks whether the given file should be indexed unconditionally.
* @param ifl The Location of the file.
* @return {@code true} if the file should be indexed unconditionally.
*/
public abstract boolean isIndexedUnconditionally(IIndexFileLocation ifl);
/**
* Tests whether the file in the index is allowed to be part of an SDK. If not
* it will be indexed.

View file

@ -147,6 +147,8 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private final LinkedList<Runnable> fChangeEvents= new LinkedList<Runnable>();
private final Job fNotificationJob;
private final AtomicMultiSet<IIndexFileLocation> fFilesIndexedUnconditionlly= new AtomicMultiSet<IIndexFileLocation>();
/**
* Stores mapping from pdom to project, used to serialize creation of new pdoms.
*/
@ -635,7 +637,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
IConfigurationElement element = elements[i];
if ("run".equals(element.getName())) { //$NON-NLS-1$
try {
indexer = (IPDOMIndexer)element.createExecutableExtension("class"); //$NON-NLS-1$
indexer = (IPDOMIndexer) element.createExecutableExtension("class"); //$NON-NLS-1$
indexer.setProperties(props);
} catch (CoreException e) {
CCorePlugin.log(e);
@ -1366,6 +1368,24 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private void update(ICProject project, List<ICElement> filesAndFolders, int options) throws CoreException {
assert !Thread.holdsLock(fProjectToPDOM);
synchronized (fUpdatePolicies) {
if ((options & IIndexManager.FORCE_INDEX_INCLUSION) != 0) {
for (ICElement element : filesAndFolders) {
if (element instanceof ITranslationUnit) {
ITranslationUnit tu = (ITranslationUnit) element;
IIndexFileLocation ifl = IndexLocationFactory.getIFL(tu);
fFilesIndexedUnconditionlly.add(ifl);
}
}
}
if ((options & IIndexManager.RESET_INDEX_INCLUSION) != 0) {
for (ICElement element : filesAndFolders) {
if (element instanceof ITranslationUnit) {
ITranslationUnit tu = (ITranslationUnit) element;
IIndexFileLocation ifl = IndexLocationFactory.getIFL(tu);
fFilesIndexedUnconditionlly.remove(ifl);
}
}
}
IPDOMIndexer indexer= getIndexer(project);
PDOMUpdateTask task= new PDOMUpdateTask(indexer, options);
task.setTranslationUnitSelection(filesAndFolders);
@ -1541,4 +1561,8 @@ public class PDOMManager implements IWritableIndexManager, IListener {
return true;
}
public boolean isFileIndexedUnconditionally(IIndexFileLocation ifl) {
return fFilesIndexedUnconditionlly.contains(ifl);
}
}

View file

@ -28,6 +28,7 @@ import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.parser.InternalParserUtil;
import org.eclipse.cdt.internal.core.pdom.IndexerInputAdapter;
import org.eclipse.cdt.internal.core.resources.PathCanonicalizationStrategy;
@ -241,6 +242,17 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
return tu instanceof PotentialTranslationUnit;
}
@Override
public boolean isIndexedUnconditionally(Object tuo) {
ITranslationUnit tu= (ITranslationUnit) tuo;
return isIndexedUnconditionally(IndexLocationFactory.getIFL(tu));
}
@Override
public boolean isIndexedUnconditionally(IIndexFileLocation ifl) {
return CCoreInternals.getPDOMManager().isFileIndexedUnconditionally(ifl);
}
@Override
public boolean isSourceUnit(Object tuo) {
ITranslationUnit tu= (ITranslationUnit) tuo;

View file

@ -39,6 +39,8 @@ import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.help.IContext;
import org.eclipse.help.IContextProvider;
@ -176,13 +178,8 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.CModelException;
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.ILanguage;
@ -208,20 +205,20 @@ import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
import org.eclipse.cdt.internal.ui.actions.AddBlockCommentAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectHistoryAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectEnclosingAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectNextAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectPreviousAction;
import org.eclipse.cdt.internal.ui.actions.FindWordAction;
import org.eclipse.cdt.internal.ui.actions.FoldingActionGroup;
import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.GotoNextBookmarkAction;
import org.eclipse.cdt.internal.ui.actions.IndentAction;
import org.eclipse.cdt.internal.ui.actions.RemoveBlockCommentAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectEnclosingAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectHistoryAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectNextAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectPreviousAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectionAction;
import org.eclipse.cdt.internal.ui.actions.SurroundWithActionGroup;
import org.eclipse.cdt.internal.ui.search.IOccurrencesFinder.OccurrenceLocation;
import org.eclipse.cdt.internal.ui.search.IOccurrencesFinder;
import org.eclipse.cdt.internal.ui.search.IOccurrencesFinder.OccurrenceLocation;
import org.eclipse.cdt.internal.ui.search.OccurrencesFinder;
import org.eclipse.cdt.internal.ui.search.actions.SelectionSearchGroup;
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
@ -1225,6 +1222,70 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
}
}
private class IndexerPreferenceListener implements IPreferenceChangeListener {
private IProject fProject;
public void preferenceChange(PreferenceChangeEvent event) {
if (IndexerPreferences.KEY_INDEX_ON_OPEN.equals(event.getKey())) {
ICElement element= getInputCElement();
ITranslationUnit tu = element != null ? (ITranslationUnit) element : null;
updateIndexInclusion(tu, false);
}
}
void registerFor(IProject project) {
if (fProject == project || fProject != null && fProject.equals(project)) {
return;
}
unregister();
fProject = project;
if (fProject != null) {
IndexerPreferences.addChangeListener(fProject, this);
}
}
void unregister() {
if (fProject != null) {
IndexerPreferences.removeChangeListener(fProject, this);
fProject = null;
}
}
}
private static class IndexUpdateRequestorJob extends Job {
private final ITranslationUnit tuToAdd;
private final ITranslationUnit tuToReset;
/**
* @param tu The translation unit to add or to remove from the index.
* @param add {@code true} to add, {@code false} to reset index inclusion.
*/
IndexUpdateRequestorJob(ITranslationUnit tuToAdd, ITranslationUnit tuToReset) {
super(CEditorMessages.CEditor_index_expander_job_name);
this.tuToAdd = tuToAdd;
this.tuToReset = tuToReset;
setSystem(true);
setPriority(Job.DECORATE);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
IIndexManager indexManager = CCorePlugin.getIndexManager();
if (tuToReset != null) {
indexManager.update(new ICElement[] { tuToReset },
IIndexManager.RESET_INDEX_INCLUSION | IIndexManager.UPDATE_CHECK_TIMESTAMPS);
}
if (tuToAdd != null) {
indexManager.update(new ICElement[] { tuToAdd },
IIndexManager.FORCE_INDEX_INCLUSION | IIndexManager.UPDATE_CHECK_TIMESTAMPS);
}
} catch (CoreException e) {
}
return Status.OK_STATUS;
}
}
/**
* The editor selection changed listener.
*
@ -1334,6 +1395,11 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
private SelectionHistory fSelectionHistory;
/** The translation unit that was added by the editor to index, or <code>null</code>. */
private ITranslationUnit fTuAddedToIndex;
private IndexerPreferenceListener fIndexerPreferenceListener;
private static final Set<String> angularIntroducers = new HashSet<String>();
static {
angularIntroducers.add("template"); //$NON-NLS-1$
@ -1369,6 +1435,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
setOutlinerContextMenuId("#CEditorOutlinerContext"); //$NON-NLS-1$
fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this);
fIndexerPreferenceListener = new IndexerPreferenceListener();
}
/**
@ -1421,6 +1488,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
if (cSourceViewer != null && isFoldingEnabled() && (store == null || !store.getBoolean(PreferenceConstants.EDITOR_SHOW_SEGMENTS)))
cSourceViewer.prepareDelayedProjection();
fIndexerPreferenceListener.unregister();
super.doSetInput(input);
setOutlinePageInput(fOutlinePage, input);
@ -1432,57 +1501,39 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
fCEditorErrorTickUpdater.updateEditorImage(getInputCElement());
}
ICElement element= getInputCElement();
if (element != null) {
IProject project = element.getCProject().getProject();
fIndexerPreferenceListener.registerFor(project);
}
if (element instanceof ITranslationUnit) {
ITranslationUnit tu = (ITranslationUnit) element;
addToIndexIfNecessary(tu);
updateIndexInclusion(tu, false);
fBracketMatcher.configure(tu.getLanguage());
} else {
updateIndexInclusion(null, false);
fBracketMatcher.configure(null);
}
}
private void addToIndexIfNecessary(ITranslationUnit tu) {
private void updateIndexInclusion(ITranslationUnit tu, boolean synchronous) {
if (tu!= null) {
IProject project = tu.getCProject().getProject();
if (String.valueOf(true).equals(IndexerPreferences.get(project, IndexerPreferences.KEY_INDEX_ON_OPEN, null))) {
IndexUpdateRequestorJob job = new IndexUpdateRequestorJob(tu);
if (!String.valueOf(true).equals(IndexerPreferences.get(project, IndexerPreferences.KEY_INDEX_ON_OPEN, null))) {
tu = null;
}
}
if (tu != null || fTuAddedToIndex != null) {
IndexUpdateRequestorJob job = new IndexUpdateRequestorJob(tu, fTuAddedToIndex);
fTuAddedToIndex = tu;
job.schedule();
}
}
private static class IndexUpdateRequestorJob extends Job {
private final ITranslationUnit tu;
IndexUpdateRequestorJob(ITranslationUnit tu) {
super(CEditorMessages.CEditor_index_expander_job_name);
this.tu = tu;
setSystem(true);
setPriority(Job.DECORATE);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
ICProject[] projects;
if (synchronous) {
try {
projects = CoreModel.getDefault().getCModel().getCProjects();
IIndexManager indexManager = CCorePlugin.getIndexManager();
IIndex index = indexManager.getIndex(projects);
index.acquireReadLock();
try {
IIndexFileLocation ifl = IndexLocationFactory.getIFL(tu);
IIndexFile file = index.getFile(tu.getLanguage().getLinkageID(), ifl);
if (file != null) {
return Status.OK_STATUS; // Already indexed.
}
indexManager.update(new ICElement[] { tu },
IIndexManager.FORCE_INDEX_INCLUSION | IIndexManager.UPDATE_CHECK_TIMESTAMPS);
} finally {
index.releaseReadLock();
}
} catch (CModelException e) {
} catch (CoreException e) {
job.join();
} catch (InterruptedException e) {
// Ignore.
}
}
return Status.OK_STATUS;
}
}
@ -2147,6 +2198,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
*/
@Override
public void dispose() {
updateIndexInclusion(null, true);
ISourceViewer sourceViewer = getSourceViewer();
if (sourceViewer instanceof ITextViewerExtension)