/******************************************************************************* * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Kaloyan Raev - Bug 485250 - Quick fixes in the Problems view *******************************************************************************/ package org.eclipse.php.internal.ui.text.correction; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.dltk.compiler.problem.DefaultProblemIdentifier; import org.eclipse.dltk.compiler.problem.IProblemIdentifier; import org.eclipse.dltk.core.*; import org.eclipse.dltk.internal.ui.editor.EditorUtility; import org.eclipse.dltk.ui.DLTKUIPlugin; import org.eclipse.dltk.ui.editor.ScriptMarkerAnnotation; import org.eclipse.dltk.ui.text.completion.IScriptCompletionProposal; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.php.internal.ui.PHPUiPlugin; import org.eclipse.php.internal.ui.editor.contentassist.CompletionProposalComparator; import org.eclipse.php.ui.text.correction.IInvocationContext; import org.eclipse.php.ui.text.correction.IProblemLocation; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.*; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.MarkerUtilities; public class CorrectionMarkerResolutionGenerator implements IMarkerResolutionGenerator2 { public static class CorrectionMarkerResolution implements IMarkerResolution2 { private ISourceModule fSourceModule; private int fOffset; private int fLength; private IScriptCompletionProposal fProposal; /** * Constructor for CorrectionMarkerResolution. * * @param cu * the source module * @param offset * the offset * @param length * the length * @param proposal * the proposal for the given marker * @param marker * the marker to fix */ public CorrectionMarkerResolution(ISourceModule cu, int offset, int length, IScriptCompletionProposal proposal) { fSourceModule = cu; fOffset = offset; fLength = length; fProposal = proposal; } @Override public String getLabel() { return fProposal.getDisplayString(); } @Override public void run(IMarker marker) { try { IEditorPart part = EditorUtility.isOpenInEditor(fSourceModule); if (part == null) { part = DLTKUIPlugin.openInEditor(fSourceModule, true, false); if (part instanceof ITextEditor) { ((ITextEditor) part).selectAndReveal(fOffset, fLength); } } if (part != null) { IEditorInput input = part.getEditorInput(); IDocument doc = DLTKUIPlugin.getDocumentProvider().getDocument(input); fProposal.apply(doc); } } catch (CoreException e) { PHPUiPlugin.log(e); } } @Override public String getDescription() { return fProposal.getAdditionalProposalInfo(); } @Override public Image getImage() { return fProposal.getImage(); } } private static final IMarkerResolution[] NO_RESOLUTIONS = new IMarkerResolution[0]; /** * Constructor for CorrectionMarkerResolutionGenerator. */ public CorrectionMarkerResolutionGenerator() { super(); } @Override public IMarkerResolution[] getResolutions(IMarker marker) { return internalGetResolutions(marker); } @Override public boolean hasResolutions(IMarker marker) { return internalHasResolutions(marker); } private static boolean internalHasResolutions(IMarker marker) { String id = marker.getAttribute(IModelMarker.ID, ""); IProblemIdentifier problemId = DefaultProblemIdentifier.decode(id); ISourceModule cu = getSourceModule(marker); return cu != null && problemId != null && PHPCorrectionProcessor.hasCorrections(cu, problemId, MarkerUtilities.getMarkerType(marker)); } @SuppressWarnings("unchecked") private static IMarkerResolution[] internalGetResolutions(IMarker marker) { if (!internalHasResolutions(marker)) { return NO_RESOLUTIONS; } ISourceModule cu = getSourceModule(marker); if (cu != null) { IEditorInput input = EditorUtility.getEditorInput(cu); if (input != null) { IProblemLocation location = findProblemLocation(input, marker); if (location != null) { IInvocationContext context = new AssistContext(cu, location.getOffset(), location.getLength()); List<IScriptCompletionProposal> proposals = new ArrayList<>(); PHPCorrectionProcessor.collectCorrections(context, new IProblemLocation[] { location }, proposals); Collections.sort(proposals, new CompletionProposalComparator()); int nProposals = proposals.size(); IMarkerResolution[] resolutions = new IMarkerResolution[nProposals]; for (int i = 0; i < nProposals; i++) { resolutions[i] = new CorrectionMarkerResolution(context.getCompilationUnit(), location.getOffset(), location.getLength(), proposals.get(i)); } return resolutions; } } } return NO_RESOLUTIONS; } private static ISourceModule getSourceModule(IMarker marker) { IResource res = marker.getResource(); if (res instanceof IFile && res.isAccessible()) { IModelElement element = DLTKCore.create((IFile) res); if (element instanceof ISourceModule) return (ISourceModule) element; } return null; } private static IProblemLocation findProblemLocation(IEditorInput input, IMarker marker) { IAnnotationModel model = DLTKUIPlugin.getDocumentProvider().getAnnotationModel(input); if (model != null) { // open in editor Iterator<Annotation> iter = model.getAnnotationIterator(); while (iter.hasNext()) { Annotation curr = iter.next(); if (curr instanceof ScriptMarkerAnnotation) { ScriptMarkerAnnotation annot = (ScriptMarkerAnnotation) curr; if (marker.equals(annot.getMarker())) { Position pos = model.getPosition(annot); if (pos != null) { return new ProblemLocation(pos.getOffset(), pos.getLength(), annot); } } } } } else { // not open in editor ISourceModule cu = getSourceModule(marker); return createFromMarker(marker, cu); } return null; } private static IProblemLocation createFromMarker(IMarker marker, ISourceModule cu) { try { String id = marker.getAttribute(IModelMarker.ID, ""); IProblemIdentifier problemId = DefaultProblemIdentifier.decode(id); int start = marker.getAttribute(IMarker.CHAR_START, -1); int end = marker.getAttribute(IMarker.CHAR_END, -1); int severity = marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO); String[] arguments = CorrectionEngine.getProblemArguments(marker); String markerType = marker.getType(); if (cu != null && problemId != null && start != -1 && end != -1) { boolean isError = (severity == IMarker.SEVERITY_ERROR); return new ProblemLocation(start, end - start, problemId, arguments, isError, markerType); } } catch (CoreException e) { PHPUiPlugin.log(e); } return null; } }