/**
* Copyright (c) 2013-2016 Angelo ZERR.
* 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:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
*/
package tern.eclipse.ide.jsdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension2;
import org.eclipse.ui.IEditorPart;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.wst.jsdt.ui.JavaScriptUI;
import org.eclipse.wst.jsdt.ui.text.java.IInvocationContext;
import org.eclipse.wst.jsdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.wst.jsdt.ui.text.java.IProblemLocation;
import org.eclipse.wst.jsdt.ui.text.java.IQuickFixProcessor;
import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
import tern.eclipse.ide.jsdt.internal.ui.contentassist.JSDTTernCompletionCollector;
import tern.server.protocol.lint.Fix;
import tern.utils.StringUtils;
/**
* {@link IQuickFixProcessor} implementation wich uses tern {@link Fix}.
*
*/
public class TernLintQuickFixProcessor implements IQuickFixProcessor {
@Override
public boolean hasCorrections(IJavaScriptUnit unit, int problemId) {
// never called?
return false;
}
@Override
public IJavaCompletionProposal[] getCorrections(IInvocationContext context, IProblemLocation[] locations)
throws CoreException {
List<IJavaCompletionProposal> proposals = new ArrayList<IJavaCompletionProposal>();
IJavaScriptUnit cu = context.getCompilationUnit();
// tern stores fix (from eslint, etc) inside
// TemporaryAnnotation#getAdditionalFixInfo
// We must retrieve the original annotation to get the fix
// Loop for origin annotations
Iterator e = getOriginAnnotation(cu, locations);
while (e.hasNext()) {
Annotation annotation = (Annotation) e.next();
Fix fix = getFix(annotation);
if (fix != null) {
// Annotation has tern Fix.
proposals.add(new ReplaceTextProposal(cu, fix));
}
}
return proposals.toArray(new IJavaCompletionProposal[proposals.size()]);
}
/**
* Returns the tern {@link Fix} from the given annotation and null
* otherwise.
*
* @param annotation
* @return the tern {@link Fix} from the given annotation and null
* otherwise.
*/
private Fix getFix(Annotation annotation) {
if (annotation instanceof TemporaryAnnotation) {
Object fixInfo = ((TemporaryAnnotation) annotation).getAdditionalFixInfo();
return (fixInfo instanceof Fix) ? (Fix) fixInfo : null;
}
return null;
}
/**
* Returns the original {@link Annotation} from the given
* {@link IJavaScriptUnit} an {@link IProblemLocation} locations.
*
* @param cu
* @param locations
* @return the original {@link Annotation} from the given
* {@link IJavaScriptUnit} an {@link IProblemLocation} locations.
*/
private Iterator getOriginAnnotation(IJavaScriptUnit cu, IProblemLocation[] locations) {
IEditorPart part = EditorUtility.isOpenInEditor(cu);
IAnnotationModel model = JavaScriptUI.getDocumentProvider().getAnnotationModel(part.getEditorInput());
if (model instanceof IAnnotationModelExtension2) {
int start = 0;
int end = 0;
IProblemLocation location;
for (int i = 0; i < locations.length; i++) {
location = locations[i];
if (i == 0) {
start = location.getOffset();
end = location.getOffset() + location.getLength();
} else {
if (start > location.getOffset()) {
start = location.getOffset();
}
if (end < location.getOffset() + location.getLength()) {
end = location.getOffset() + location.getLength();
}
}
}
return ((IAnnotationModelExtension2) model).getAnnotationIterator(start, end - start, true, true);
}
return model.getAnnotationIterator();
}
}