/*******************************************************************************
* Copyright (c) 2011 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.quickfix;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.TextInvocationContext;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.SimpleMarkerAnnotation;
import org.eclipse.wst.sse.ui.StructuredTextInvocationContext;
import org.eclipse.wst.sse.ui.internal.correction.CompoundQuickAssistProcessor;
import org.eclipse.wst.sse.ui.internal.correction.QuickFixRegistry;
import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
import org.jboss.tools.common.CommonPlugin;
public class MarkerAnnotationInfo {
public static final String UNKNOWN_TAG = "Unknown tag"; //$NON-NLS-1$
public static final String MISSING_ATTRIBUTE = "Missing required attribute"; //$NON-NLS-1$
public static final String PREFERENCE_KEY_ATTRIBUTE_NAME = "preference_key"; //$NON-NLS-1$
public static final String MESSAGE_TYPE_ATTRIBUTE_NAME = "jbt.type"; //$NON-NLS-1$
public final List<AnnotationInfo> infos;
public final ISourceViewer viewer;
private CompoundQuickAssistProcessor fCompoundQuickAssistProcessor = new CompoundQuickAssistProcessor();
public MarkerAnnotationInfo(List<AnnotationInfo> infos, ISourceViewer textViewer) {
this.infos = infos;
this.viewer = textViewer;
}
public List<ICompletionProposal> getCompletionProposals(AnnotationInfo info) {
ArrayList<String> proposalNames = new ArrayList<String>();
proposalNames.add(XMLUIMessages.SurroundWithNewElementQuickAssistProposal_1);
ArrayList<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
for(Annotation annotation : info.getAnnotations()){
if(annotation instanceof SimpleMarkerAnnotation){
for (ICompletionProposal proposal : getMarkerProposals((SimpleMarkerAnnotation)annotation, info.getPosition())) {
if(!proposalNames.contains(proposal.getDisplayString())){
proposals.add(proposal);
proposalNames.add(proposal.getDisplayString());
}
}
} else if(annotation instanceof TemporaryAnnotation){
for (ICompletionProposal proposal : getProposals((TemporaryAnnotation)annotation, info.getPosition())) {
if(!proposalNames.contains(proposal.getDisplayString())){
proposals.add(proposal);
proposalNames.add(proposal.getDisplayString());
}
}
}
}
return proposals;
}
private static boolean isJBTAnnotation(Annotation annotation){
boolean isJBTAnnotation = false;
if(annotation instanceof SimpleMarkerAnnotation){
SimpleMarkerAnnotation sa = (SimpleMarkerAnnotation)annotation;
if(sa.getMarker() != null && sa.getMarker().exists()){
try {
isJBTAnnotation = sa.getMarker().getAttribute(PREFERENCE_KEY_ATTRIBUTE_NAME) != null;
} catch (CoreException e) {
CommonPlugin.getDefault().logError(e);
}
}
}else if(annotation instanceof TemporaryAnnotation){
TemporaryAnnotation ta = (TemporaryAnnotation)annotation;
if(ta.getAttributes() != null){
String attribute = (String)ta.getAttributes().get(MESSAGE_TYPE_ATTRIBUTE_NAME);
isJBTAnnotation = attribute != null;
}
}
return isJBTAnnotation;
}
private List<ICompletionProposal> getMarkerProposals(SimpleMarkerAnnotation annotation, Position position) {
ArrayList<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
boolean isJBTAnnotation = isJBTAnnotation(annotation);
IMarker marker = annotation.getMarker();
IMarkerResolution[] resolutions = IDE.getMarkerHelpRegistry().getResolutions(marker);
for (IMarkerResolution resolution : resolutions) {
proposals.add(new QuickFixProposal(resolution, marker));
}
if(!isJBTAnnotation){
TextInvocationContext sseContext = new TextInvocationContext(viewer, position.getOffset(), position.getLength());
ICompletionProposal[] compoundQuickAssistProcessorProposals = fCompoundQuickAssistProcessor.computeQuickAssistProposals(sseContext);
if (compoundQuickAssistProcessorProposals != null) {
for (ICompletionProposal proposal : compoundQuickAssistProcessorProposals) {
proposals.add(proposal);
}
}
}
return proposals;
}
private List<ICompletionProposal> getProposals(TemporaryAnnotation annotation, Position position) {
List<ICompletionProposal> allProposals = new ArrayList<ICompletionProposal>();
List<IQuickAssistProcessor> processors = new ArrayList<IQuickAssistProcessor>();
boolean isJBTAnnotation = isJBTAnnotation(annotation);
// get all relevant quick fixes for this annotation
if(QuickFixManager.getInstance().hasProposals(annotation, position)){
if(annotation.getText().startsWith(UNKNOWN_TAG) || annotation.getText().startsWith(MISSING_ATTRIBUTE)){
annotation.setAdditionalFixInfo(viewer.getDocument());
}
List<IJavaCompletionProposal> proposals = QuickFixManager.getInstance().getProposals(annotation, position);
allProposals.addAll(proposals);
}
if(!isJBTAnnotation){
Object o = annotation.getAdditionalFixInfo();
if (o instanceof IQuickAssistProcessor) {
processors.add((IQuickAssistProcessor)o);
}
QuickFixRegistry registry = QuickFixRegistry.getInstance();
processors.addAll(Arrays.asList(registry.getQuickFixProcessors(annotation)));
// set up context
Map attributes = annotation.getAttributes();
StructuredTextInvocationContext sseContext = new StructuredTextInvocationContext(viewer, position.getOffset(), position.getLength(), attributes);
ICompletionProposal[] compoundQuickAssistProcessorProposals = fCompoundQuickAssistProcessor.computeQuickAssistProposals(sseContext);
if (compoundQuickAssistProcessorProposals != null) {
for (ICompletionProposal proposal : compoundQuickAssistProcessorProposals) {
allProposals.add(proposal);
}
}
// call each processor
for (int i = 0; i < processors.size(); ++i) {
List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
collectProposals((IQuickAssistProcessor) processors.get(i), annotation, sseContext, proposals);
allProposals.addAll(proposals);
}
}
return allProposals;
}
private void collectProposals(IQuickAssistProcessor processor, Annotation annotation, IQuickAssistInvocationContext invocationContext, List<ICompletionProposal> proposalsList) {
ICompletionProposal[] proposals = processor.computeQuickAssistProposals(invocationContext);
if (proposals != null && proposals.length > 0) {
proposalsList.addAll(Arrays.asList(proposals));
}
}
public boolean canFix(Annotation annotation) {
return true;
}
public static class AnnotationInfo {
private ArrayList<Annotation> annotations = new ArrayList<Annotation>();
private Position position;
public AnnotationInfo(Annotation annotation, Position position){
add(annotation);
this.position = position;
}
public void add(Annotation annotation){
annotations.add(annotation);
}
public List<Annotation> getAnnotations(){
return annotations;
}
public Annotation getMainAnnotation(){
for(Annotation annotation : annotations){
if(annotation instanceof SimpleMarkerAnnotation){
return annotation;
}
}
return annotations.get(0);
}
public Position getPosition(){
return position;
}
public boolean isTop(){
return isJBTAnnotation(getMainAnnotation());
}
}
@Override
public String toString() {
return null;
}
}