-
Notifications
You must be signed in to change notification settings - Fork 82
/
CUCorrectionProposal.java
386 lines (344 loc) · 12.8 KB
/
CUCorrectionProposal.java
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/*******************************************************************************
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.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
* Red Hat Inc. - add support to use CUCorrectionProposalCore methods
*******************************************************************************/
package org.eclipse.jdt.ui.text.java.correction;
import org.eclipse.swt.graphics.Image;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.manipulation.CUCorrectionProposalCore;
import org.eclipse.jdt.core.manipulation.ICUCorrectionProposal;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.internal.corext.util.Resources;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
/**
* A proposal for quick fixes and quick assists that work on a single compilation unit. Either a
* {@link TextChange text change} is directly passed in the constructor or method
* {@link #addEdits(IDocument, TextEdit)} is overridden to provide the text edits that are applied
* to the document when the proposal is evaluated.
* <p>
* The proposal takes care of the preview of the changes as proposal information.
* </p>
*
* @since 3.8
*/
public class CUCorrectionProposal extends ChangeCorrectionProposal implements ICUCorrectionProposal {
private boolean fSwitchedEditor;
private CUCorrectionProposalCore fProposalCore;
private ICompilationUnit cu;
/**
* Constructs a correction proposal working on a compilation unit with a given text change.
*
* @param name the name that is displayed in the proposal selection dialog
* @param cu the compilation unit to which the change can be applied
* @param change the change that is executed when the proposal is applied or <code>null</code>
* if implementors override {@link #addEdits(IDocument, TextEdit)} to provide the
* text edits or {@link #createTextChange()} to provide a text change
* @param relevance the relevance of this proposal
* @param image the image that is displayed for this proposal or <code>null</code> if no image
* is desired
*/
public CUCorrectionProposal(String name, ICompilationUnit cu, TextChange change, int relevance, Image image) {
this(name, cu, change, relevance, image, null);
}
/**
* Constructs a correction proposal working on a compilation unit with a given text change. Uses
* the default image for this proposal.
*
* @param name the name that is displayed in the proposal selection dialog
* @param cu the compilation unit to which the change can be applied
* @param change the change that is executed when the proposal is applied or <code>null</code>
* if implementors override {@link #addEdits(IDocument, TextEdit)} to provide the
* text edits or {@link #createTextChange()} to provide a text change.
* @param relevance the relevance of this proposal
*/
public CUCorrectionProposal(String name, ICompilationUnit cu, TextChange change, int relevance) {
this(name, cu, change, relevance, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE));
}
/**
* Constructs a correction proposal working on a compilation unit.
* <p>
* Users have to override {@link #addEdits(IDocument, TextEdit)} to provide the text edits or
* {@link #createTextChange()} to provide a text change.
* </p>
*
* @param name the name that is displayed in the proposal selection dialog
* @param cu the compilation unit on that the change works
* @param relevance the relevance of this proposal
* @param image the image that is displayed for this proposal or <code>null</code> if no image
* is desired
*/
protected CUCorrectionProposal(String name, ICompilationUnit cu, int relevance, Image image) {
this(name, cu, null, relevance, image);
}
/**
* Constructs a correction proposal working on a compilation unit.
* <p>
* Users have to override {@link #addEdits(IDocument, TextEdit)} to provide the text edits or
* {@link #createTextChange()} to provide a text change.
* </p>
*
* @param name the name that is displayed in the proposal selection dialog
* @param cu the compilation unit on that the change works
* @param relevance the relevance of this proposal
* @param image the image that is displayed for this proposal or <code>null</code> if no image
* is desired
* @param delegate The delegate instance
* @since 3.31
*/
public CUCorrectionProposal(String name, ICompilationUnit cu, int relevance, Image image, CUCorrectionProposalCore delegate) {
this(name, cu, null, relevance, image, delegate);
}
/**
* Constructs a correction proposal working on a compilation unit.
* <p>
* Users have to override {@link #addEdits(IDocument, TextEdit)} to provide the text edits or
* {@link #createTextChange()} to provide a text change.
* </p>
*
* @param name the name that is displayed in the proposal selection dialog
* @param cu the compilation unit on that the change works
* @param change The text change to be applied
* @param relevance the relevance of this proposal
* @param image the image that is displayed for this proposal or <code>null</code> if no image
* is desired
* @param delegate The delegate proposal underlying this proposal
* @since 3.31
*/
public CUCorrectionProposal(String name, ICompilationUnit cu, TextChange change, int relevance, Image image, CUCorrectionProposalCore delegate) {
super(name, change, relevance, image);
this.cu = cu;
if (cu == null) {
throw new IllegalArgumentException("Compilation unit must not be null"); //$NON-NLS-1$
}
this.fProposalCore = delegate != null ? delegate : new CUCorrectionProposalCore(this, name, cu, change, relevance);
}
/**
* @since 3.32
* @return the delegate
*/
protected CUCorrectionProposalCore getDelegate() {
return fProposalCore;
}
/**
* Called when the {@link CompilationUnitChange} is initialized. Subclasses can override to add
* text edits to the root edit of the change. Implementors must not access the proposal, e.g.
* not call {@link #getChange()}.
* <p>
* The default implementation does not add any edits
* </p>
*
* @param document content of the underlying compilation unit. To be accessed read only.
* @param editRoot The root edit to add all edits to
* @throws CoreException can be thrown if adding the edits is failing.
*/
protected void addEdits(IDocument document, TextEdit editRoot) throws CoreException {
getDelegate().addEdits(document, editRoot);
}
@Override
public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
return getDelegate().getAdditionalProposalInfo(monitor);
}
/**
* @since 3.31
* @return the compilation unit
*/
protected ICompilationUnit getInitialCompilationUnit() {
return this.cu;
}
@Override
public void apply(IDocument document) {
try {
ICompilationUnit unit= getCompilationUnit();
IEditorPart part= null;
if (unit.getResource().exists()) {
boolean canEdit= performValidateEdit(unit);
if (!canEdit) {
return;
}
part= EditorUtility.isOpenInEditor(unit);
if (part == null) {
part= JavaUI.openInEditor(unit);
if (part != null) {
fSwitchedEditor= true;
document= JavaUI.getDocumentProvider().getDocument(part.getEditorInput());
}
}
IWorkbenchPage page= JavaPlugin.getActivePage();
if (page != null && part != null) {
page.bringToTop(part);
}
if (part != null) {
part.setFocus();
}
}
performChange(part, document);
} catch (CoreException e) {
ExceptionHandler.handle(e, CorrectionMessages.CUCorrectionProposal_error_title, CorrectionMessages.CUCorrectionProposal_error_message);
}
}
private boolean performValidateEdit(ICompilationUnit unit) {
IStatus status= Resources.makeCommittable(unit.getResource(), JavaPlugin.getActiveWorkbenchShell());
if (!status.isOK()) {
String label= CorrectionMessages.CUCorrectionProposal_error_title;
String message= CorrectionMessages.CUCorrectionProposal_error_message;
ErrorDialog.openError(JavaPlugin.getActiveWorkbenchShell(), label, message, status);
return false;
}
return true;
}
/**
* Creates the text change for this proposal.
* This method is only called once and only when no text change has been passed in
* {@link #CUCorrectionProposal(String, ICompilationUnit, TextChange, int, Image)}.
*
* @return the created text change
* @throws CoreException if the creation of the text change failed
*/
protected synchronized TextChange createTextChange() throws CoreException {
if( useDelegateToCreateTextChange() ) {
return createTextChangeViaDelegate();
} else {
return createTextChangeLocal();
}
}
/**
* @since 3.31
*/
protected boolean useDelegateToCreateTextChange() {
return true;
}
/**
* @since 3.31
* @return the text change
*/
protected TextChange createTextChangeLocal() throws CoreException {
TextChange change = fProposalCore.getNewChange();
// initialize text change
IDocument document= change.getCurrentDocument(new NullProgressMonitor());
addEdits(document, change.getEdit());
return change;
}
/**
* @since 3.31
* @return a text change created via the delegate
*/
protected TextChange createTextChangeViaDelegate() throws CoreException {
if ((getDelegate()).getCurrentChange() instanceof TextChange change) {
return change;
}
return (getDelegate()).createTextChange();
}
/**
* Clients should not override this method
*/
@Override
protected final Change createChange() throws CoreException {
return createTextChange(); // make sure that only text changes are allowed here
}
/**
* Returns the text change that is invoked when the change is applied.
*
* @return the text change that is invoked when the change is applied
* @throws CoreException if accessing the change failed
*/
@Override
public final TextChange getTextChange() throws CoreException {
return (TextChange)getChange();
}
/**
* The compilation unit on which the change works.
*
* @return the compilation unit on which the change works
*/
public final ICompilationUnit getCompilationUnit() {
return getDelegate().getCompilationUnit();
}
/**
* Creates a preview of the content of the compilation unit after applying the change.
*
* @return the preview of the changed compilation unit
* @throws CoreException if the creation of the change failed
*
* @noreference This method is not intended to be referenced by clients.
*/
public final String getPreviewContent() throws CoreException {
return getDelegate().getTextChange().getPreviewContent(new NullProgressMonitor());
}
@Override
public String getName() {
if( super.getName() == null || super.getName().isEmpty()) {
return getDelegate().getName();
}
return super.getName();
}
@Override
public String getCommandId() {
if( super.getCommandId() == null || super.getCommandId().isEmpty()) {
return getDelegate().getCommandId();
}
return super.getCommandId();
}
@Override
public String toString() {
try {
return getPreviewContent();
} catch (CoreException e) {
// didn't work out
}
return super.toString();
}
/**
* Returns whether the changed compilation unit was not previously open in an editor.
*
* @return <code>true</code> if the changed compilation unit was not previously open in an
* editor, <code>false</code> if the changed compilation unit was already open in an
* editor
*
* @noreference This method is not intended to be referenced by clients.
*/
protected boolean didOpenEditor() {
return fSwitchedEditor;
}
/**
* @since 3.32
*/
@SuppressWarnings("unchecked")
@Override
public <T> T getAdapter(Class<T> adapter) {
if (getDelegate() != null) {
if( adapter.isInstance(getDelegate())) {
return (T) getDelegate();
}
}
if (adapter.isInstance(this)) {
return (T) this;
}
return null;
}
}