| /******************************************************************************* |
| * Copyright (c) 2007, 2009 Wind River Systems, 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: |
| * Markus Schorn - initial API and implementation |
| * IBM Corporation |
| *******************************************************************************/ |
| |
| package org.eclipse.cdt.internal.core.indexer; |
| |
| import java.io.File; |
| import java.io.FilenameFilter; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.cdt.core.parser.IParserLogService; |
| import org.eclipse.cdt.core.parser.IScannerInfo; |
| import org.eclipse.cdt.internal.core.index.IWritableIndex; |
| import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; |
| import org.eclipse.cdt.internal.core.pdom.IndexerProgress; |
| import org.eclipse.cdt.internal.core.pdom.PDOMWriter; |
| import org.eclipse.cdt.internal.core.pdom.WritablePDOM; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| |
| /** |
| * The base class for standalone index population tools. |
| * |
| * <p> |
| * <strong>EXPERIMENTAL</strong>. This class or interface has been added as |
| * part of a work in progress. There is no guarantee that this API will work or |
| * that it will remain the same. Please do not use this API without consulting |
| * with the CDT team. |
| * |
| * This class is not thread safe. |
| * </p> |
| * |
| * @since 4.0 |
| */ |
| public abstract class StandaloneIndexer { |
| |
| /** |
| * Parser should not skip any references. |
| */ |
| public static final int SKIP_NO_REFERENCES = PDOMWriter.SKIP_NO_REFERENCES; |
| |
| /** |
| * Parser to skip all references. |
| */ |
| public static final int SKIP_ALL_REFERENCES = PDOMWriter.SKIP_ALL_REFERENCES; |
| |
| /** |
| * Parser to skip type references. |
| */ |
| public static final int SKIP_TYPE_REFERENCES = PDOMWriter.SKIP_TYPE_REFERENCES; |
| |
| /** |
| * Constant for indicating to update all translation units. |
| */ |
| public final static int UPDATE_ALL= 0x1; |
| |
| /** |
| * Constant for indicating to update translation units if their timestamp |
| * has changed. |
| */ |
| public final static int UPDATE_CHECK_TIMESTAMPS= 0x2; |
| |
| /** |
| * Empty list. |
| */ |
| protected static final List<String> NO_TUS = Collections.emptyList(); |
| |
| |
| /** |
| * The IWritableIndex that stores all bindings and names. |
| */ |
| protected IWritableIndex fIndex; |
| |
| /** |
| * A flag that indicates if all files (sources without config, headers not included) |
| * should be parsed. |
| */ |
| protected boolean fIndexAllFiles; |
| |
| /** |
| * Collection of valid file extensions for C/C++ source. |
| */ |
| protected Set<String> fValidSourceUnitNames; |
| |
| /** |
| * The IScannerInfo that provides include paths and defined symbols. |
| * Either a single scanner info or a IStandaloneScannerInfoProvider must |
| * be provided, but not both. If a single IScannerInfo object is provided |
| * it will always be used. Otherwise the provider will be used. |
| */ |
| @Deprecated |
| protected IScannerInfo fScanner; |
| |
| /** |
| * Creates IScannerInfo objects from file paths, allows there |
| * to be separate scanner infos for specific files and folders. |
| */ |
| protected IStandaloneScannerInfoProvider fScannerInfoProvider; |
| |
| /** |
| * The ILanguageMapper that determines the ILanguage for a file. |
| */ |
| protected ILanguageMapper fMapper; |
| |
| /** |
| * The logger during parsing. |
| */ |
| protected IParserLogService fLog; |
| |
| /** |
| * A flag that indicates if all activities during indexing should be shown. |
| */ |
| protected boolean fShowActivity; |
| |
| /** |
| * A flag that indicates if any problems encountered during indexing. |
| * should be shown. |
| */ |
| protected boolean fShowProblems; |
| |
| /** |
| * A flag that indicates if statistics should be gathered during indexing. |
| */ |
| protected boolean fTraceStatistics; |
| |
| /** |
| * The type of references the parser should skip. |
| */ |
| protected int fSkipReferences = SKIP_NO_REFERENCES; |
| |
| /** |
| * The exclusion filter that skips over files that should not be indexed. |
| */ |
| protected FilenameFilter fExclusionFilter; |
| |
| /** |
| * Files to parse up front. |
| */ |
| protected String[] fFilesToParseUpFront = new String[0]; |
| |
| protected int fUpdateOptions = UPDATE_ALL; |
| |
| private IndexerProgress fProgress = null; |
| private volatile StandaloneIndexerTask fDelegate; |
| |
| private static FilenameFilter DEFAULT_FILTER = new FilenameFilter() { |
| public boolean accept(File dir, String name) { |
| return true; |
| } |
| }; |
| |
| protected FileEncodingRegistry fFileEncodingRegistry; |
| |
| /** |
| * @deprecated Its better to provide a scanner info provider instead. |
| */ |
| @Deprecated |
| public StandaloneIndexer(IWritableIndex index, boolean indexAllFiles, |
| ILanguageMapper mapper, IParserLogService log, IScannerInfo scanner, FileEncodingRegistry fileEncodingRegistry) { |
| fIndex = index; |
| fIndexAllFiles = indexAllFiles; |
| fMapper = mapper; |
| fLog = log; |
| fScanner = scanner; |
| fScannerInfoProvider = null; |
| fFileEncodingRegistry = fileEncodingRegistry; |
| setupASTFilePathResolver(); |
| } |
| |
| |
| public StandaloneIndexer(IWritableIndex index, boolean indexAllFiles, |
| ILanguageMapper mapper, IParserLogService log, IStandaloneScannerInfoProvider scannerProvider, FileEncodingRegistry fileEncodingRegistry) { |
| fIndex = index; |
| fIndexAllFiles = indexAllFiles; |
| fMapper = mapper; |
| fLog = log; |
| fScanner = null; |
| fScannerInfoProvider = scannerProvider; |
| fFileEncodingRegistry = fileEncodingRegistry; |
| setupASTFilePathResolver(); |
| } |
| |
| |
| private void setupASTFilePathResolver() { |
| IWritableIndexFragment fragment = getIndex().getWritableFragment(); |
| if(fragment instanceof WritablePDOM) { |
| WritablePDOM pdom = (WritablePDOM)fragment; |
| pdom.setASTFilePathResolver(new StandaloneIndexerInputAdapter(this)); |
| } |
| } |
| |
| public void setScannerInfoProvider(IStandaloneScannerInfoProvider provider) { |
| fScannerInfoProvider = provider; |
| fScanner = null; |
| } |
| |
| /** |
| * Returns the index. |
| * @return the IWritable index the indexer is writing to |
| */ |
| public IWritableIndex getIndex() { |
| return fIndex; |
| } |
| |
| /** |
| * Returns true if all files (sources without config, headers not included) |
| * should be parsed. Otherwise, this method returns false. |
| */ |
| public boolean getIndexAllFiles() { |
| return fIndexAllFiles; |
| } |
| |
| /** |
| * If true then all files will be indexed. |
| */ |
| public void setIndexAllFiles(boolean indexAllFiles) { |
| fIndexAllFiles = indexAllFiles; |
| } |
| |
| /** |
| * Returns the collection of valid file extensions for C/C++ source. |
| */ |
| public Set<String> getValidSourceUnitNames() { |
| return fValidSourceUnitNames; |
| } |
| |
| /** |
| * Sets the collection of valid file extensions for C/C++ source. |
| */ |
| public void setValidSourceUnitNames(Set<String> validSourceUnitNames) { |
| fValidSourceUnitNames = validSourceUnitNames; |
| } |
| |
| /** |
| * Returns the IScannerInfo that provides include paths and defined symbols. |
| * @deprecated Should probably be using a IStandaloneScannerInfoProvider instead and |
| * calling getScannerInfo(String). |
| */ |
| @Deprecated |
| public IScannerInfo getScannerInfo() { |
| return fScanner; |
| } |
| |
| |
| /** |
| * Returns the IScannerInfo for the given path. |
| * If the current instance was created with an IScannerInfo instead of |
| * an IScannerInfoProvider then the path will be ignored and |
| * that IScannerInfo will always be returned. |
| */ |
| public IScannerInfo getScannerInfo(String path) { |
| if(fScanner != null) |
| return fScanner; |
| |
| return fScannerInfoProvider.getScannerInformation(path); |
| } |
| |
| |
| /** |
| * Returns the IStandaloneScannerInfoProvider or null if one was not provided. |
| */ |
| public IStandaloneScannerInfoProvider getScannerInfoProvider() { |
| return fScannerInfoProvider; |
| } |
| |
| /** |
| * Returns the ILanguageMapper that determines the ILanguage for a file. |
| */ |
| public ILanguageMapper getLanguageMapper() { |
| return fMapper; |
| } |
| |
| |
| public void setLanguageMapper(ILanguageMapper mapper) { |
| fMapper = mapper; |
| } |
| |
| /** |
| * Returns the logger. |
| */ |
| public IParserLogService getParserLog() { |
| return fLog; |
| } |
| |
| /** |
| * Sets the logger. |
| */ |
| public void setParserLog(IParserLogService log) { |
| fLog = log; |
| } |
| |
| /** |
| * Returns true if indexing activities should be shown. |
| * Otherwise, this method returns false. |
| */ |
| public boolean getShowActivity() { |
| return fShowActivity; |
| } |
| |
| /** |
| * Tells indexer if indexing activities should be shown. |
| */ |
| public void setShowActivity(boolean showActivity) { |
| fShowActivity = showActivity; |
| } |
| |
| /** |
| * Returns true if problems during indexing should be shown. |
| * Otherwise, this method returns false. |
| */ |
| public boolean getShowProblems() { |
| return fShowProblems; |
| } |
| |
| /** |
| * Tells indexer if problems during indexing should be shown. |
| */ |
| public void setShowProblems(boolean showProblems) { |
| fShowProblems = showProblems; |
| } |
| |
| /** |
| * Returns true if statistics should be gathered during indexing. |
| * Otherwise, this method returns false.. |
| */ |
| public boolean getTraceStatistics() { |
| return fTraceStatistics; |
| } |
| |
| /** |
| * Tells indexer if statistics should be gathered during indexing. |
| */ |
| public void setTraceStatistics(boolean traceStatistics) { |
| fTraceStatistics = traceStatistics; |
| } |
| |
| private IndexerProgress createProgress() { |
| IndexerProgress progress= new IndexerProgress(); |
| progress.fTimeEstimate= 1000; |
| return progress; |
| } |
| |
| private void clearIndex() throws CoreException, InterruptedException { |
| IWritableIndex index= getIndex(); |
| // First clear the pdom |
| index.acquireWriteLock(0); |
| try { |
| index.clear(); |
| } |
| finally { |
| index.releaseWriteLock(0); |
| } |
| } |
| |
| /** |
| * Returns the progress information. |
| */ |
| public synchronized IndexerProgress getProgressInformation() { |
| return fDelegate != null ? fDelegate.getProgressInformation() : fProgress; |
| } |
| |
| /** |
| * Returns the update options specified. |
| */ |
| public int getUpdateOptions() { |
| return fUpdateOptions; |
| } |
| |
| /** |
| * Specifies the update options, whether all translation units should be updated or only the ones |
| * with timestamp changes. |
| * @param options |
| */ |
| public void setUpdateOptions (int options) { |
| fUpdateOptions = options; |
| } |
| |
| /** |
| * Clears the index and rebuild |
| * @param tus - directories/files to be added to index |
| * @param monitor |
| * @throws IOException |
| */ |
| public void rebuild(List<String> tus, IProgressMonitor monitor) throws IOException { |
| fProgress = createProgress(); |
| |
| try { |
| clearIndex(); |
| fDelegate= createTask(getFilesAdded(tus), NO_TUS, NO_TUS); |
| fDelegate.setUpdateFlags(fUpdateOptions); |
| fDelegate.setParseUpFront(); |
| |
| if (fDelegate != null) { |
| fDelegate.run(monitor); |
| } |
| } catch (CoreException e) { |
| e.printStackTrace(); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| /** |
| * Updates the index with changes. |
| * @param added - directories/files to be added to the index |
| * @param changed - files that have been changed |
| * @param removed - files to be removed from the index |
| * @param monitor |
| * @throws IOException |
| */ |
| public void handleDelta(List<String> added, List<String> changed, List<String> removed, IProgressMonitor monitor) throws IOException { |
| fProgress= new IndexerProgress(); |
| |
| fDelegate= createTask(getFilesAdded(added), changed, removed); |
| if (fDelegate != null) { |
| try { |
| fDelegate.setUpdateFlags(fUpdateOptions); |
| fDelegate.run(monitor); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| } |
| |
| /** |
| * Returns files that are being added to the index, skipping over files that |
| * should not be excluded. |
| * @param tus |
| * @return |
| */ |
| private List<String> getFilesAdded(List<String> tus) { |
| List<String> added = new ArrayList<String>(); |
| |
| FilenameFilter filter = getExclusionFilter(); |
| if (filter == null) { |
| filter = DEFAULT_FILTER; |
| } |
| |
| Iterator<String> iter = tus.iterator(); |
| while (iter.hasNext()) { |
| String path = iter.next(); |
| File file = new File(path); |
| if (file.isDirectory()) { |
| String[] files = file.list(filter); |
| for (String file2 : files) { |
| added.add(file2); |
| } |
| } |
| else { |
| if (filter.accept(file.getParentFile(), file.getName())) { |
| added.add(path); |
| } |
| } |
| } |
| return added; |
| } |
| |
| /** |
| * Creates a delegate standalone indexing task |
| */ |
| protected abstract StandaloneIndexerTask createTask(List<String> added, List<String> changed, List<String> removed); |
| |
| /** |
| * Return the type of references the parser should skip. |
| */ |
| public int getSkipReferences() { |
| return fSkipReferences; |
| } |
| |
| /** |
| * Sets the type of references the parser should skip. |
| * @param skipReferences |
| */ |
| public void setSkipReferences(int skipReferences) { |
| fSkipReferences = skipReferences; |
| } |
| |
| /** |
| * Returns an array of files that should be parsed up front. |
| */ |
| public String[] getFilesToParseUpFront() { |
| return fFilesToParseUpFront; |
| } |
| |
| /** |
| * Sets an array of files that should be parsed up front. |
| * @param filesToParseUpFront |
| */ |
| public void setFilesToParseUpFront(String[] filesToParseUpFront) { |
| fFilesToParseUpFront = filesToParseUpFront; |
| } |
| |
| /** |
| * Returns the exclusion filter for this indexer. |
| */ |
| public FilenameFilter getExclusionFilter() { |
| return fExclusionFilter; |
| } |
| |
| /** |
| * Sets the exclusion filter that tells the indexer to skip over |
| * files that should not be indexed. |
| * @param exclusionFilter |
| */ |
| public void setExclusionFilter(FilenameFilter exclusionFilter) { |
| fExclusionFilter = exclusionFilter; |
| } |
| |
| |
| public FileEncodingRegistry getFileEncodingRegistry() { |
| return fFileEncodingRegistry; |
| } |
| |
| |
| public void setFileEncodingRegistry(FileEncodingRegistry fileEncodingRegistry) { |
| fFileEncodingRegistry = fileEncodingRegistry; |
| } |
| |
| |
| |
| |
| } |