blob: 1fa086156645e6d0d9a44e7ba931fcdc33897e5b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Pivotal Inc - Adapted for use in quicksearch
*******************************************************************************/
package org.eclipse.text.quicksearch.internal.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.quicksearch.internal.ui.QuickSearchActivator;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* Useful utilities (private methods) copied from org.eclipse.search.internal.core.text.TextSearchVisitor
* and rearanged / massaged to be a more reusable utility class.
* <p>
* These utilities allow us to access the contents of dirty editors so we can search/read in them as though they
* are already saved but without actually requiring the user to save them.
*
* @author Kris De Volder
*/
public class DocumentFetcher {
private Map<IFile, IDocument> dirtyEditors;
//Simple cache remembers the last fetched file and document.
private IFile lastFile = null;
private IDocument lastDocument = null;
IDocumentProvider provider = new TextFileDocumentProvider();
public DocumentFetcher() {
if (PlatformUI.isWorkbenchRunning()) {
dirtyEditors = evalNonFileBufferDocuments();
} else {
dirtyEditors = Collections.emptyMap();
}
}
/**
* Obtains a {@link IDocument} containing the contents of a
* {@link IFile}. Two different scenarios are supported depending
* on whether or not the file is currently opened in a editor.
* <p>
* If the IFile is opened in an editor, then the document reflects
* the editor contents (including any not-yet saved edits).
* <p>
* If the file is not open, then the document just reflects the
* contents of the file.
*
* @param file
* @return Document containing the contents of the file or editor buffer,
* or null if the content can not be found (it exists neither as a editor
* buffer nor corresponds to an existing file in the workspace.
*/
public IDocument getDocument(IFile file) {
if (file==lastFile) {
return lastDocument;
}
lastFile = file;
lastDocument = dirtyEditors.get(file);
if (lastDocument==null) {
lastDocument = getOpenDocument(file);
if (lastDocument==null) {
lastDocument = getClosedDocument(file);
}
}
return lastDocument;
}
private IDocument getOpenDocument(IFile file) {
ITextFileBufferManager bufferManager= FileBuffers.getTextFileBufferManager();
ITextFileBuffer textFileBuffer= bufferManager.getTextFileBuffer(file.getFullPath(), LocationKind.IFILE);
if (textFileBuffer != null) {
return textFileBuffer.getDocument();
}
return null;
}
private IDocument getClosedDocument(IFile file) {
//No in the manager yet. Try to create a temporary buffer then remove it again.
ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
IPath location = file.getFullPath(); //Must use workspace location, not fs location for API below.
ITextFileBuffer buffer = null;
try {
bufferManager.connect(location, LocationKind.IFILE, new NullProgressMonitor());
buffer = bufferManager.getTextFileBuffer(location, LocationKind.IFILE);
if (buffer!=null) {
return buffer.getDocument();
}
} catch (Throwable e) {
QuickSearchActivator.log(e);
} finally {
try {
bufferManager.disconnect(location, LocationKind.IFILE, new NullProgressMonitor());
} catch (CoreException e) {
}
}
return null;
}
/**
* @return returns a map from IFile to IDocument for all open, dirty editors.
*/
private Map<IFile, IDocument> evalNonFileBufferDocuments() {
Map<IFile, IDocument> result= new HashMap<IFile, IDocument>();
IWorkbench workbench= PlatformUI.getWorkbench();
IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
for (int i= 0; i < windows.length; i++) {
IWorkbenchPage[] pages= windows[i].getPages();
for (int x= 0; x < pages.length; x++) {
IEditorReference[] editorRefs= pages[x].getEditorReferences();
for (int z= 0; z < editorRefs.length; z++) {
IEditorPart ep= editorRefs[z].getEditor(false);
if (ep instanceof ITextEditor && ep.isDirty()) { // only dirty editors
evaluateTextEditor(result, ep);
}
}
}
}
return result;
}
private void evaluateTextEditor(Map<IFile, IDocument> result, IEditorPart ep) {
IEditorInput input= ep.getEditorInput();
if (input instanceof IFileEditorInput) {
IFile file= ((IFileEditorInput) input).getFile();
if (!result.containsKey(file)) { // take the first editor found
ITextFileBufferManager bufferManager= FileBuffers.getTextFileBufferManager();
ITextFileBuffer textFileBuffer= bufferManager.getTextFileBuffer(file.getFullPath(), LocationKind.IFILE);
if (textFileBuffer != null) {
// file buffer has precedence
result.put(file, textFileBuffer.getDocument());
} else {
// use document provider
IDocument document= ((ITextEditor) ep).getDocumentProvider().getDocument(input);
if (document != null) {
result.put(file, document);
}
}
}
}
}
}