package com.redhat.ceylon.eclipse.code.correct;
import static com.redhat.ceylon.eclipse.code.editor.Navigation.openInEditor;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.CEYLON_CONFIG_NOT_IN_SYNC_MARKER;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.CHARSET_PROBLEM_MARKER_ID;
import static com.redhat.ceylon.eclipse.util.EditorUtil.getDocument;
import static com.redhat.ceylon.eclipse.util.EditorUtil.getEditorInput;
import static com.redhat.ceylon.eclipse.java2ceylon.Java2CeylonProxies.*;
import java.util.ArrayList;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolution2;
import org.eclipse.ui.IMarkerResolutionGenerator;
import org.eclipse.ui.IMarkerResolutionGenerator2;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.texteditor.ITextEditor;
import com.redhat.ceylon.eclipse.code.preferences.CeylonBuildPathsPropertiesPage;
import com.redhat.ceylon.eclipse.ui.CeylonEncodingSynchronizer;
import com.redhat.ceylon.eclipse.ui.CeylonResources;
public class MarkerResolutionGenerator
implements IMarkerResolutionGenerator, IMarkerResolutionGenerator2 {
private static class OpenBuildPathsCorrection implements IMarkerResolution {
@Override
public String getLabel() {
return "Resolve the conflict in the 'Ceylon Build Paths' properties page";
}
@Override
public void run(IMarker marker) {
IProject project = (IProject) marker.getResource();
PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(null,
project, CeylonBuildPathsPropertiesPage.ID, new String[0], null);
dialog.open();
}
}
private static final IMarkerResolution[] NO_RESOLUTIONS =
new IMarkerResolution[0];
private static final class CharsetCorrection
implements IMarkerResolution, IMarkerResolution2 {
private final IProject project;
private final String encoding;
private CharsetCorrection(IProject project, String encoding) {
this.project = project;
this.encoding = encoding;
}
@Override
public void run(IMarker marker) {
CeylonEncodingSynchronizer.getInstance()
.updateEncoding(project, encoding);
}
@Override
public String getLabel() {
return "change project character encoding to " +
encoding;
}
@Override
public String getDescription() {
return null;
}
@Override
public Image getImage() {
return CeylonResources.MINOR_CHANGE;
}
}
private static class CorrectionMarkerResolution
implements IMarkerResolution, IMarkerResolution2 {
private int fOffset;
private int fLength;
private ICompletionProposal fProposal;
private final IDocument fDocument;
public CorrectionMarkerResolution(int offset, int length,
ICompletionProposal proposal, IMarker marker,
IDocument document) {
fOffset = offset;
fLength = length;
fProposal = proposal;
fDocument = document;
}
public String getLabel() {
return fProposal.getDisplayString();
}
public void run(IMarker marker) {
try {
IEditorPart part = openInEditor(marker.getResource());
if (part instanceof ITextEditor) {
((ITextEditor) part).selectAndReveal(fOffset, fLength);
}
if (fDocument != null) {
fProposal.apply(fDocument);
}
} catch (CoreException e) {
// JavaPlugin.log(e);
}
}
public String getDescription() {
return fProposal.getAdditionalProposalInfo();
}
public Image getImage() {
return fProposal.getImage();
}
}
public IMarkerResolution[] getResolutions(final IMarker marker) {
if (!hasResolutions(marker)) {
return NO_RESOLUTIONS;
}
try {
if (marker.getType().equals(CHARSET_PROBLEM_MARKER_ID)) {
IProject project = (IProject) marker.getResource();
String encoding = project.getDefaultCharset();
String ceylonEncoding =
modelJ2C().ceylonModel().getProject(project).getDefaultCharset();
return new IMarkerResolution[] {
new CharsetCorrection(project, encoding),
new CharsetCorrection(project, ceylonEncoding),
};
}
if (marker.getType().equals(CEYLON_CONFIG_NOT_IN_SYNC_MARKER)) {
return new IMarkerResolution[] {
new OpenBuildPathsCorrection()
};
}
IQuickAssistInvocationContext quickAssistContext =
new IQuickAssistInvocationContext() {
public ISourceViewer getSourceViewer() { return null; }
public int getOffset() {
return marker.getAttribute(IMarker.CHAR_START, 0);
}
public int getLength() {
return marker.getAttribute(IMarker.CHAR_END, 0)
- getOffset();
}
};
ArrayList<ICompletionProposal> proposals =
new ArrayList<ICompletionProposal>();
IDocument doc =
getDocument(getEditorInput(marker.getResource()));
new CeylonCorrectionProcessor(marker)
.collectCorrections(quickAssistContext,
new ProblemLocation(marker), proposals);
IMarkerResolution[] resolutions =
new IMarkerResolution[proposals.size()];
int i = 0;
for (ICompletionProposal proposal: proposals) {
resolutions[i++] =
new CorrectionMarkerResolution(
quickAssistContext.getOffset(),
quickAssistContext.getLength(),
proposal, marker, doc);
}
return resolutions;
} catch (Exception e) {
e.printStackTrace();
}
return NO_RESOLUTIONS;
}
public boolean hasResolutions(IMarker marker) {
try {
return CeylonCorrectionProcessor.canFix(marker) ||
marker.getType().equals(CHARSET_PROBLEM_MARKER_ID) ||
marker.getType().equals(CEYLON_CONFIG_NOT_IN_SYNC_MARKER);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
}