Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 52544d206b860634c4362bb1614b93dc4a752efa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*******************************************************************************
 * Copyright (c) 2000, 2008, 2013-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.search.internal.ui.SearchPlugin;
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
 */
@SuppressWarnings("restriction")
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= SearchPlugin.getDefault().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);
					}
				}
			}
		}
	}

}

Back to the top