| /* |
| * Copyright (c) 2013, the Dart project authors. |
| * |
| * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.dart.tools.ui.internal.text.correction; |
| |
| import com.google.common.collect.Lists; |
| import com.google.dart.server.generated.types.AnalysisError; |
| import com.google.dart.server.generated.types.Location; |
| import com.google.dart.tools.core.DartCore; |
| import com.google.dart.tools.ui.DartToolsPlugin; |
| import com.google.dart.tools.ui.internal.text.editor.DartEditor; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.DefaultInformationControl; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IInformationControl; |
| import org.eclipse.jface.text.IInformationControlCreator; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITextViewer; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.jface.text.quickassist.IQuickAssistAssistant; |
| import org.eclipse.jface.text.quickassist.QuickAssistAssistant; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.texteditor.IDocumentProvider; |
| import org.eclipse.ui.texteditor.ITextEditor; |
| |
| import java.util.List; |
| |
| /** |
| * @coverage dart.editor.ui.correction |
| */ |
| public class DartCorrectionAssistant_NEW extends QuickAssistAssistant { |
| private static IRegion getRegionOfInterest(ITextEditor editor, int invocationLocation) |
| throws BadLocationException { |
| IDocumentProvider documentProvider = editor.getDocumentProvider(); |
| if (documentProvider == null) { |
| return null; |
| } |
| IDocument document = documentProvider.getDocument(editor.getEditorInput()); |
| if (document == null) { |
| return null; |
| } |
| return document.getLineInformationOfOffset(invocationLocation); |
| } |
| |
| private static boolean isInside(int offset, int start, int end) { |
| // make sure to handle 0-length ranges |
| return offset == start || offset == end || offset > start && offset < end; |
| } |
| |
| private final DartEditor editor; |
| |
| private ITextViewer viewer; |
| /** |
| * The {@link AnalysisError} to propose fixes for. |
| */ |
| private AnalysisError problemToFix; |
| |
| public DartCorrectionAssistant_NEW(ITextEditor editor) { |
| Assert.isNotNull(editor); |
| if (editor instanceof DartEditor) { |
| this.editor = (DartEditor) editor; |
| DartCorrectionProcessor_NEW processor = new DartCorrectionProcessor_NEW(this); |
| setQuickAssistProcessor(processor); |
| } else { |
| this.editor = null; |
| } |
| setInformationControlCreator(getInformationControlCreator()); |
| } |
| |
| /** |
| * @return the underlying {@link DartEditor}. |
| */ |
| public DartEditor getEditor() { |
| return editor; |
| } |
| |
| /** |
| * @return the {@link AnalysisError} to compute fixes for. |
| */ |
| public AnalysisError getProblemToFix() { |
| return problemToFix; |
| } |
| |
| @Override |
| public void install(ISourceViewer sourceViewer) { |
| super.install(sourceViewer); |
| this.viewer = sourceViewer; |
| } |
| |
| /** |
| * Show completions at caret position. If current position does not contain quick fixes look for |
| * next quick fix on same line by moving from left to right and restarting at end of line if the |
| * beginning of the line is reached. |
| * |
| * @see IQuickAssistAssistant#showPossibleQuickAssists() |
| */ |
| @Override |
| public String showPossibleQuickAssists() { |
| prepareProblemsAtCaretLocation(); |
| return super.showPossibleQuickAssists(); |
| } |
| |
| public void showProblemToFix() { |
| if (problemToFix == null) { |
| return; |
| } |
| int offset = problemToFix.getLocation().getOffset(); |
| viewer.setSelectedRange(offset, 0); |
| viewer.revealRange(offset, 0); |
| } |
| |
| /** |
| * @return the {@link IInformationControlCreator} used to display prefix and help user to decide |
| * which correction to choose. |
| */ |
| private IInformationControlCreator getInformationControlCreator() { |
| return new IInformationControlCreator() { |
| @Override |
| public IInformationControl createInformationControl(Shell parent) { |
| return new DefaultInformationControl( |
| parent, |
| DartToolsPlugin.getAdditionalInfoAffordanceString()); |
| } |
| }; |
| } |
| |
| /** |
| * Fills {@link #problemToFix}. |
| */ |
| private void prepareProblemsAtCaretLocation() { |
| problemToFix = null; |
| try { |
| Point selectedRange = viewer.getSelectedRange(); |
| int currOffset = selectedRange.x; |
| // prepare file |
| String file = editor.getInputFilePath(); |
| if (file == null) { |
| return; |
| } |
| // prepare errors |
| AnalysisError[] errors = DartCore.getAnalysisServerData().getErrors(file); |
| // prepare current line range |
| IRegion lineInfo = getRegionOfInterest(editor, currOffset); |
| if (lineInfo == null) { |
| return; |
| } |
| int rangeStart = lineInfo.getOffset(); |
| int rangeEnd = rangeStart + lineInfo.getLength(); |
| // prepare fixable problems on the current line |
| List<AnalysisError> allProblems = Lists.newArrayList(); |
| List<Position> allPositions = Lists.newArrayList(); |
| for (AnalysisError error : errors) { |
| Location location = error.getLocation(); |
| Position pos = new Position(location.getOffset(), location.getLength()); |
| // check that error is on the current line |
| if (!isInside(pos.offset, rangeStart, rangeEnd)) { |
| continue; |
| } |
| // add only if has fix |
| if (QuickFixProcessor_NEW.hasFix(error)) { |
| allProblems.add(error); |
| allPositions.add(pos); |
| } |
| } |
| // problem under caret |
| for (int i = 0; i < allPositions.size(); i++) { |
| Position pos = allPositions.get(i); |
| if (pos.includes(currOffset)) { |
| problemToFix = allProblems.get(i); |
| break; |
| } |
| } |
| // problem after caret |
| if (problemToFix == null) { |
| int bestOffset = Integer.MAX_VALUE; |
| for (int i = 0; i < allPositions.size(); i++) { |
| Position pos = allPositions.get(i); |
| if (pos.offset > currOffset) { |
| int offset = pos.offset - currOffset; |
| if (offset < bestOffset) { |
| bestOffset = offset; |
| problemToFix = allProblems.get(i); |
| } |
| } |
| } |
| } |
| // problem before caret |
| if (problemToFix == null) { |
| int bestOffset = Integer.MAX_VALUE; |
| for (int i = 0; i < allPositions.size(); i++) { |
| Position pos = allPositions.get(i); |
| if (pos.offset < currOffset) { |
| int offset = currOffset - pos.offset; |
| if (offset < bestOffset) { |
| bestOffset = offset; |
| problemToFix = allProblems.get(i); |
| } |
| } |
| } |
| } |
| // not found |
| if (problemToFix == null) { |
| return; |
| } |
| } catch (Throwable e) { |
| DartToolsPlugin.log(e); |
| } |
| } |
| } |