org.jboss.tools.common.ui.marker.AddSuppressWarningsMarkerResolution.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.common.ui.marker.AddSuppressWarningsMarkerResolution.java

Source

/*******************************************************************************
 * Copyright (c) 2011 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:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.common.ui.marker;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMemberValuePair;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jpt.common.core.internal.utility.jdt.ASTTools;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.ui.IMarkerResolution2;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.jboss.tools.common.EclipseUtil;
import org.jboss.tools.common.preferences.SeverityPreferences;
import org.jboss.tools.common.refactoring.MarkerResolutionUtils;
import org.jboss.tools.common.ui.CommonUIMessages;
import org.jboss.tools.common.ui.CommonUIPlugin;
import org.jboss.tools.common.validation.WarningNameManager;
import org.osgi.service.prefs.BackingStoreException;

/**
 * @author Daniel Azarov
 */
public class AddSuppressWarningsMarkerResolution implements IMarkerResolution2, IJavaCompletionProposal {
    public static final String SUPPRESS_WARNINGS_ANNOTATION = "SuppressWarnings";
    public static final String SPACE = " "; //$NON-NLS-1$
    public static final String DOT = "."; //$NON-NLS-1$
    public static final String AT = "@"; //$NON-NLS-1$
    private static final String PROBLEM_ID = JavaCore.COMPILER_PB_UNHANDLED_WARNING_TOKEN;
    private SP preferences = new SP();

    private IFile file;
    private IAnnotatable element;
    private String preferenceKey;
    private String label;
    private String description;
    private ICompilationUnit cu;

    public AddSuppressWarningsMarkerResolution(IFile file, IJavaElement element, String preferenceKey) {
        this.file = file;
        this.element = getAnnatatableElement(element);
        String[] names = WarningNameManager.getInstance().getWarningNames(preferenceKey);
        if (names != null && names.length > 0) {
            this.preferenceKey = names[0];
        } else {
            this.preferenceKey = null;
        }

        label = NLS.bind(CommonUIMessages.ADD_SUPPRESS_WARNINGS_TITLE, this.preferenceKey,
                element.getElementName());
        if (element instanceof IMethod) {
            label += "()";
        }

        description = getPreview();
    }

    public AddSuppressWarningsMarkerResolution(IFile file, IJavaElement element, String preferenceKey,
            ICompilationUnit compilationUnit) {
        this(file, element, preferenceKey);
        this.cu = compilationUnit;

        description = getPreview();
    }

    private String getPreview() {
        TextChange previewChange = getPreviewChange();

        try {
            return MarkerResolutionUtils.getPreview(previewChange);
        } catch (CoreException e) {
            CommonUIPlugin.getDefault().logError(e);
        }
        return label;
    }

    private IAnnotatable getAnnatatableElement(IJavaElement element) {
        IJavaElement elem = element;
        while (elem != null) {
            if (element instanceof IAnnotatable) {
                return (IAnnotatable) element;
            }
            elem = elem.getParent();
        }
        return null;
    }

    @Override
    public String getLabel() {
        return label;
    }

    private TextChange getPreviewChange() {
        if (element != null && preferenceKey != null) {
            try {
                ICompilationUnit original = (cu != null) ? cu : EclipseUtil.getCompilationUnit(file);
                if (original == null) {
                    return null;
                }
                ICompilationUnit compilationUnit = original.getWorkingCopy(new NullProgressMonitor());

                TextChange change = getChange(compilationUnit);

                compilationUnit.discardWorkingCopy();
                return change;
            } catch (JavaModelException e) {
                CommonUIPlugin.getDefault().logError(e);
            }
        }
        return null;
    }

    private CompilationUnitChange getChange(ICompilationUnit compilationUnit) throws JavaModelException {
        CompilationUnit cuNode = ASTTools.buildASTRoot(compilationUnit);

        IJavaElement workingCopyElement = findWorkingCopy(compilationUnit, (IJavaElement) element);
        ASTNode elementNode = null;
        if (workingCopyElement instanceof JavaElement) {
            elementNode = ((JavaElement) workingCopyElement).findNode(cuNode);
        }

        IAnnotation annotation = findAnnotation(workingCopyElement);
        CompilationUnitChange change = null;
        if (annotation != null) {
            change = updateAnnotation(SUPPRESS_WARNINGS_ANNOTATION, preferenceKey, compilationUnit, annotation);
        } else {
            change = addAnnotation(SUPPRESS_WARNINGS_ANNOTATION + "(\"" + preferenceKey + "\")", compilationUnit,
                    workingCopyElement, elementNode);
        }
        return change;
    }

    @Override
    public void run(IMarker marker) {
        ICompilationUnit original = EclipseUtil.getCompilationUnit(file);
        if (original != null) {
            do_run(original, false);
        }
    }

    private void do_run(ICompilationUnit original, boolean leaveDirty) {
        if (element != null && preferenceKey != null && original != null) {
            disablePreference();
            try {
                ICompilationUnit compilationUnit = original.getWorkingCopy(new NullProgressMonitor());

                CompilationUnitChange change = getChange(compilationUnit);

                if (change != null) {
                    if (leaveDirty) {
                        change.setSaveMode(TextFileChange.LEAVE_DIRTY);
                    }
                    change.perform(new NullProgressMonitor());
                    original.reconcile(ICompilationUnit.NO_AST, false, null, new NullProgressMonitor());
                }
                compilationUnit.discardWorkingCopy();
            } catch (JavaModelException e) {
                CommonUIPlugin.getDefault().logError(e);
            } catch (CoreException e) {
                CommonUIPlugin.getDefault().logError(e);
            }
        }
    }

    private IAnnotation findAnnotation(IJavaElement workingCopyElement) throws JavaModelException {
        IAnnotation annotation = ((IAnnotatable) workingCopyElement).getAnnotation(SUPPRESS_WARNINGS_ANNOTATION);
        if (annotation != null && annotation.exists()) {
            return annotation;
        }

        return null;
    }

    public static String getShortName(String qualifiedName) {
        int lastDot = qualifiedName.lastIndexOf(DOT);
        String name;
        if (lastDot < 0)
            name = qualifiedName;
        else
            name = qualifiedName.substring(lastDot + 1);
        return name;
    }

    private void disablePreference() {
        String value = preferences.getProjectPreference(file.getProject(), PROBLEM_ID);
        if (!SeverityPreferences.IGNORE.equals(value)) {

            IEclipsePreferences projectPreferences = preferences.getProjectPreferences(file.getProject());
            String projectValue = null;
            if (projectPreferences != null) {
                projectValue = projectPreferences.get(PROBLEM_ID, null);
            }

            if (projectValue != null) {
                MessageDialog dialog = new MessageDialog(getShell(), label, null,
                        CommonUIMessages.ADD_SUPPRESS_WARNINGS_MESSAGE
                                + CommonUIMessages.ADD_SUPPRESS_WARNINGS_QUESTION1,
                        MessageDialog.QUESTION_WITH_CANCEL,
                        new String[] { CommonUIMessages.ADD_SUPPRESS_WARNINGS_CANCEL,
                                CommonUIMessages.ADD_SUPPRESS_WARNINGS_DISABLE },
                        0);
                int result = dialog.open();
                if (result == 1) {
                    IEclipsePreferences ePrefs = preferences.getProjectPreferences(file.getProject());
                    ePrefs.put(PROBLEM_ID, SeverityPreferences.IGNORE);
                    try {
                        ePrefs.flush();
                    } catch (BackingStoreException e) {
                        CommonUIPlugin.getDefault().logError(e);
                    }
                }
            } else {
                MessageDialog dialog = new MessageDialog(getShell(), label, null,
                        CommonUIMessages.ADD_SUPPRESS_WARNINGS_MESSAGE + NLS.bind(
                                CommonUIMessages.ADD_SUPPRESS_WARNINGS_QUESTION2, file.getProject().getName()),
                        MessageDialog.QUESTION_WITH_CANCEL,
                        new String[] { CommonUIMessages.ADD_SUPPRESS_WARNINGS_CANCEL,
                                CommonUIMessages.ADD_SUPPRESS_WARNINGS_WORKSPACE,
                                CommonUIMessages.ADD_SUPPRESS_WARNINGS_PROJECT },
                        0);
                int result = dialog.open();
                if (result == 1) {
                    IEclipsePreferences ePrefs = preferences.getInstancePreferences();
                    ePrefs.put(PROBLEM_ID, SeverityPreferences.IGNORE);
                    try {
                        ePrefs.flush();
                    } catch (BackingStoreException e) {
                        CommonUIPlugin.getDefault().logError(e);
                    }
                } else if (result == 2) {
                    IEclipsePreferences ePrefs = preferences.getProjectPreferences(file.getProject());
                    ePrefs.put(PROBLEM_ID, SeverityPreferences.IGNORE);
                    try {
                        ePrefs.flush();
                    } catch (BackingStoreException e) {
                        CommonUIPlugin.getDefault().logError(e);
                    }
                }
            }
        }
    }

    private static Shell getShell() {
        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (window == null) {
            IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
            if (windows.length > 0) {
                return windows[0].getShell();
            }
        } else {
            return window.getShell();
        }
        return null;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public Image getImage() {
        String key = "ADD_ANNOTATION";
        ImageRegistry registry = CommonUIPlugin.getDefault().getImageRegistry();
        Image image = registry.get(key);
        if (image == null) {
            try {
                image = ImageDescriptor.createFromURL(
                        new URL(CommonUIPlugin.getDefault().getBundle().getEntry("/"), "icons/add_annotation.png"))
                        .createImage();
                registry.put(key, image);
            } catch (MalformedURLException e) {
                CommonUIPlugin.getDefault().logError(e);
            }
        }
        return image;
    }

    private CompilationUnitChange updateAnnotation(String name, String parameter, ICompilationUnit compilationUnit,
            IAnnotation annotation) throws JavaModelException {
        String str = AT + name;

        str += "({";

        for (IMemberValuePair pair : annotation.getMemberValuePairs()) {
            if (pair.getValueKind() == IMemberValuePair.K_STRING) {
                Object value = pair.getValue();
                if (value instanceof String) {
                    if (value.toString().equals(parameter)) {
                        return null;
                    }
                    str += "\"" + value + "\", ";
                } else if (value instanceof Object[]) {
                    Object[] array = (Object[]) value;
                    for (Object a : array) {
                        if (a instanceof String) {
                            if (a.toString().equals(parameter)) {
                                return null;
                            }
                            str += "\"" + a + "\", ";
                        }
                    }
                }
            } else if (pair.getValueKind() == IMemberValuePair.K_QUALIFIED_NAME
                    || pair.getValueKind() == IMemberValuePair.K_SIMPLE_NAME) {
                Object value = pair.getValue();
                if (value instanceof String) {
                    str += value + ", ";
                } else if (value instanceof Object[]) {
                    Object[] array = (Object[]) value;
                    for (Object a : array) {
                        if (a instanceof String) {
                            str += a + ", ";
                        }
                    }
                }
            }
        }

        str += "\"" + parameter + "\"";

        str += "})";

        CompilationUnitChange change = new CompilationUnitChange("", compilationUnit);

        ReplaceEdit edit = new ReplaceEdit(annotation.getSourceRange().getOffset(),
                annotation.getSourceRange().getLength(), str);
        change.setEdit(edit);

        return change;
    }

    private CompilationUnitChange addAnnotation(String name, ICompilationUnit compilationUnit, IJavaElement element,
            ASTNode node) throws JavaModelException {
        if (!(element instanceof ISourceReference))
            return null;

        ISourceReference workingCopySourceReference = (ISourceReference) element;

        IBuffer buffer = compilationUnit.getBuffer();

        int position = workingCopySourceReference.getSourceRange().getOffset();

        if (node != null) {
            position = node.getStartPosition();
            if (node instanceof BodyDeclaration && ((BodyDeclaration) node).getJavadoc() != null) {
                position += ((BodyDeclaration) node).getJavadoc().getLength();
                char c = buffer.getChar(position);
                while ((c == '\r' || c == '\n') && position < buffer.getLength() - 2) {
                    position++;
                    c = buffer.getChar(position);
                }
            }
            while (position < buffer.getLength() - 1) {
                char c = buffer.getChar(position);
                if (c != '\r' && c != '\n' && c != ' ' && c != '\t') {
                    break;
                }
                position++;
            }
        }

        String str = AT + name;

        if (!(workingCopySourceReference instanceof ILocalVariable)) {

            str += compilationUnit.findRecommendedLineSeparator();

            int index = position;
            while (index >= 0) {
                char c = buffer.getChar(index);
                if (c == '\r' || c == '\n')
                    break;
                index--;
            }
            index++;
            if (index < position) {
                String spaces = buffer.getText(index, position - index);
                str += spaces;
            }

        } else {
            str += SPACE;
        }

        CompilationUnitChange change = new CompilationUnitChange("", compilationUnit);

        InsertEdit edit = new InsertEdit(position, str);

        change.setEdit(edit);

        return change;
    }

    @SuppressWarnings("unchecked")
    private static <T extends IJavaElement> T findWorkingCopy(ICompilationUnit compilationUnit, T element)
            throws JavaModelException {
        if (element instanceof IAnnotation) {
            IJavaElement parent = findWorkingCopy(compilationUnit, element.getParent());
            if (parent instanceof IAnnotatable) {
                for (IAnnotation a : ((IAnnotatable) parent).getAnnotations()) {
                    if (a.getElementName().equals(element.getElementName()))
                        return (T) a;
                }
            }
        } else if (element instanceof ILocalVariable && ((ILocalVariable) element).isParameter()) {
            IJavaElement parent = findWorkingCopy(compilationUnit, element.getParent());
            if (parent instanceof IMethod) {
                for (ILocalVariable parameter : ((IMethod) parent).getParameters()) {
                    if (parameter.getElementName().equals(element.getElementName())
                            && parameter.getTypeSignature().equals(((ILocalVariable) element).getTypeSignature()))
                        return (T) parameter;
                }
            }
        } else {
            IJavaElement[] elements = compilationUnit.findElements(element);
            if (elements != null) {
                for (IJavaElement e : elements) {
                    if (e.getClass().equals(element.getClass()))
                        return (T) e;
                }
            }
        }
        return null;
    }

    static class SP extends SeverityPreferences {

        @Override
        protected Set<String> getSeverityOptionNames() {
            return null;
        }

        @Override
        protected String createSeverityOption(String shortName) {
            return null;
        }

        @Override
        protected String getPluginId() {
            return JavaCore.PLUGIN_ID;
        }

    }

    @Override
    public void apply(IDocument document) {
        do_run(cu, true);
    }

    @Override
    public Point getSelection(IDocument document) {
        return null;
    }

    @Override
    public String getAdditionalProposalInfo() {
        return description;
    }

    @Override
    public String getDisplayString() {
        return label;
    }

    @Override
    public IContextInformation getContextInformation() {
        return null;
    }

    @Override
    public int getRelevance() {
        return 100;
    }

}