1 11 12 package org.eclipse.jdt.internal.ui.text.correction; 13 14 import java.util.ArrayList ; 15 import java.util.Iterator ; 16 17 import org.eclipse.core.runtime.Assert; 18 19 import org.eclipse.swt.graphics.Color; 20 import org.eclipse.swt.graphics.Point; 21 import org.eclipse.swt.graphics.RGB; 22 import org.eclipse.swt.widgets.Shell; 23 24 import org.eclipse.jface.internal.text.html.HTMLTextPresenter; 25 import org.eclipse.jface.preference.IPreferenceStore; 26 import org.eclipse.jface.preference.PreferenceConverter; 27 28 import org.eclipse.jface.text.BadLocationException; 29 import org.eclipse.jface.text.DefaultInformationControl; 30 import org.eclipse.jface.text.IDocument; 31 import org.eclipse.jface.text.IInformationControl; 32 import org.eclipse.jface.text.IInformationControlCreator; 33 import org.eclipse.jface.text.IRegion; 34 import org.eclipse.jface.text.ITextViewer; 35 import org.eclipse.jface.text.Position; 36 import org.eclipse.jface.text.quickassist.IQuickAssistAssistant; 37 import org.eclipse.jface.text.quickassist.QuickAssistAssistant; 38 import org.eclipse.jface.text.source.Annotation; 39 import org.eclipse.jface.text.source.IAnnotationModel; 40 import org.eclipse.jface.text.source.ISourceViewer; 41 42 import org.eclipse.ui.IEditorPart; 43 import org.eclipse.ui.texteditor.IDocumentProvider; 44 import org.eclipse.ui.texteditor.ITextEditor; 45 46 import org.eclipse.jdt.core.ICompilationUnit; 47 import org.eclipse.jdt.core.IJavaElement; 48 49 import org.eclipse.jdt.ui.JavaUI; 50 import org.eclipse.jdt.ui.PreferenceConstants; 51 import org.eclipse.jdt.ui.text.IColorManager; 52 import org.eclipse.jdt.ui.text.JavaTextTools; 53 54 import org.eclipse.jdt.internal.ui.JavaPlugin; 55 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; 56 57 58 public class JavaCorrectionAssistant extends QuickAssistAssistant { 59 60 private ITextViewer fViewer; 61 private ITextEditor fEditor; 62 private Position fPosition; 63 private Annotation[] fCurrentAnnotations; 64 65 private QuickAssistLightBulbUpdater fLightBulbUpdater; 66 67 68 71 public JavaCorrectionAssistant(ITextEditor editor) { 72 super(); 73 Assert.isNotNull(editor); 74 fEditor= editor; 75 76 JavaCorrectionProcessor processor= new JavaCorrectionProcessor(this); 77 78 setQuickAssistProcessor(processor); 79 80 setInformationControlCreator(getInformationControlCreator()); 81 82 JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools(); 83 IColorManager manager= textTools.getColorManager(); 84 85 IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); 86 87 Color c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND, manager); 88 setProposalSelectorForeground(c); 89 90 c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND, manager); 91 setProposalSelectorBackground(c); 92 } 93 94 public IEditorPart getEditor() { 95 return fEditor; 96 } 97 98 99 private IInformationControlCreator getInformationControlCreator() { 100 return new IInformationControlCreator() { 101 public IInformationControl createInformationControl(Shell parent) { 102 return new DefaultInformationControl(parent, new HTMLTextPresenter()); 103 } 104 }; 105 } 106 107 private static Color getColor(IPreferenceStore store, String key, IColorManager manager) { 108 RGB rgb= PreferenceConverter.getColor(store, key); 109 return manager.getColor(rgb); 110 } 111 112 115 public void install(ISourceViewer sourceViewer) { 116 super.install(sourceViewer); 117 fViewer= sourceViewer; 118 119 fLightBulbUpdater= new QuickAssistLightBulbUpdater(fEditor, sourceViewer); 120 fLightBulbUpdater.install(); 121 } 122 123 124 125 128 public void uninstall() { 129 if (fLightBulbUpdater != null) { 130 fLightBulbUpdater.uninstall(); 131 fLightBulbUpdater= null; 132 } 133 super.uninstall(); 134 } 135 136 140 141 150 public String showPossibleQuickAssists() { 151 fPosition= null; 152 fCurrentAnnotations= null; 153 154 if (fViewer == null || fViewer.getDocument() == null) 155 return super.showPossibleQuickAssists(); 157 158 159 ArrayList resultingAnnotations= new ArrayList (20); 160 try { 161 Point selectedRange= fViewer.getSelectedRange(); 162 int currOffset= selectedRange.x; 163 int currLength= selectedRange.y; 164 boolean goToClosest= (currLength == 0); 165 166 int newOffset= collectQuickFixableAnnotations(fEditor, currOffset, goToClosest, resultingAnnotations); 167 if (newOffset != currOffset) { 168 storePosition(currOffset, currLength); 169 fViewer.setSelectedRange(newOffset, 0); 170 fViewer.revealRange(newOffset, 0); 171 } 172 } catch (BadLocationException e) { 173 JavaPlugin.log(e); 174 } 175 fCurrentAnnotations= (Annotation[]) resultingAnnotations.toArray(new Annotation[resultingAnnotations.size()]); 176 177 return super.showPossibleQuickAssists(); 178 } 179 180 181 private static IRegion getRegionOfInterest(ITextEditor editor, int invocationLocation) throws BadLocationException { 182 IDocumentProvider documentProvider= editor.getDocumentProvider(); 183 if (documentProvider == null) { 184 return null; 185 } 186 IDocument document= documentProvider.getDocument(editor.getEditorInput()); 187 if (document == null) { 188 return null; 189 } 190 return document.getLineInformationOfOffset(invocationLocation); 191 } 192 193 public static int collectQuickFixableAnnotations(ITextEditor editor, int invocationLocation, boolean goToClosest, ArrayList resultingAnnotations) throws BadLocationException { 194 IAnnotationModel model= JavaUI.getDocumentProvider().getAnnotationModel(editor.getEditorInput()); 195 if (model == null) { 196 return invocationLocation; 197 } 198 199 ensureUpdatedAnnotations(editor); 200 201 Iterator iter= model.getAnnotationIterator(); 202 if (goToClosest) { 203 IRegion lineInfo= getRegionOfInterest(editor, invocationLocation); 204 if (lineInfo == null) { 205 return invocationLocation; 206 } 207 int rangeStart= lineInfo.getOffset(); 208 int rangeEnd= rangeStart + lineInfo.getLength(); 209 210 ArrayList allAnnotations= new ArrayList (); 211 ArrayList allPositions= new ArrayList (); 212 int bestOffset= Integer.MAX_VALUE; 213 while (iter.hasNext()) { 214 Annotation annot= (Annotation) iter.next(); 215 if (JavaCorrectionProcessor.isQuickFixableType(annot)) { 216 Position pos= model.getPosition(annot); 217 if (pos != null && isInside(pos.offset, rangeStart, rangeEnd)) { allAnnotations.add(annot); 219 allPositions.add(pos); 220 bestOffset= processAnnotation(annot, pos, invocationLocation, bestOffset); 221 } 222 } 223 } 224 if (bestOffset == Integer.MAX_VALUE) { 225 return invocationLocation; 226 } 227 for (int i= 0; i < allPositions.size(); i++) { 228 Position pos= (Position) allPositions.get(i); 229 if (isInside(bestOffset, pos.offset, pos.offset + pos.length)) { 230 resultingAnnotations.add(allAnnotations.get(i)); 231 } 232 } 233 return bestOffset; 234 } else { 235 while (iter.hasNext()) { 236 Annotation annot= (Annotation) iter.next(); 237 if (JavaCorrectionProcessor.isQuickFixableType(annot)) { 238 Position pos= model.getPosition(annot); 239 if (pos != null && isInside(invocationLocation, pos.offset, pos.offset + pos.length)) { 240 resultingAnnotations.add(annot); 241 } 242 } 243 } 244 return invocationLocation; 245 } 246 } 247 248 private static void ensureUpdatedAnnotations(ITextEditor editor) { 249 Object inputElement= editor.getEditorInput().getAdapter(IJavaElement.class); 250 if (inputElement instanceof ICompilationUnit) { 251 JavaPlugin.getDefault().getASTProvider().getAST((ICompilationUnit) inputElement, ASTProvider.WAIT_ACTIVE_ONLY, null); 252 } 253 } 254 255 private static int processAnnotation(Annotation annot, Position pos, int invocationLocation, int bestOffset) { 256 int posBegin= pos.offset; 257 int posEnd= posBegin + pos.length; 258 if (isInside(invocationLocation, posBegin, posEnd)) { return invocationLocation; 260 } else if (bestOffset != invocationLocation) { 261 int newClosestPosition= computeBestOffset(posBegin, invocationLocation, bestOffset); 262 if (newClosestPosition != -1) { 263 if (newClosestPosition != bestOffset) { if (JavaCorrectionProcessor.hasCorrections(annot)) { return newClosestPosition; 266 } 267 } 268 } 269 } 270 return bestOffset; 271 } 272 273 274 private static boolean isInside(int offset, int start, int end) { 275 return offset == start || offset == end || (offset > start && offset < end); } 277 278 288 private static int computeBestOffset(int newOffset, int invocationLocation, int bestOffset) { 289 if (newOffset <= invocationLocation) { 290 if (bestOffset > invocationLocation) { 291 return newOffset; } else if (bestOffset <= newOffset) { 293 return newOffset; } 295 return -1; } 297 298 if (newOffset <= bestOffset) 299 return newOffset; 301 return -1; } 303 304 307 protected void possibleCompletionsClosed() { 308 super.possibleCompletionsClosed(); 309 restorePosition(); 310 } 311 312 private void storePosition(int currOffset, int currLength) { 313 fPosition= new Position(currOffset, currLength); 314 } 315 316 private void restorePosition() { 317 if (fPosition != null && !fPosition.isDeleted() && fViewer.getDocument() != null) { 318 fViewer.setSelectedRange(fPosition.offset, fPosition.length); 319 fViewer.revealRange(fPosition.offset, fPosition.length); 320 } 321 fPosition= null; 322 } 323 324 327 public boolean isUpdatedOffset() { 328 return fPosition != null; 329 } 330 331 334 public Annotation[] getAnnotationsAtOffset() { 335 return fCurrentAnnotations; 336 } 337 } 338 | Popular Tags |