io.sarl.lang.ui.labeling.SARLDiagnosticLabelDecorator.java Source code

Java tutorial

Introduction

Here is the source code for io.sarl.lang.ui.labeling.SARLDiagnosticLabelDecorator.java

Source

/*
 * $Id$
 *
 * SARL is an general-purpose agent programming language.
 * More details on http://www.sarl.io
 *
 * Copyright (C) 2014-2017 the original authors or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sarl.lang.ui.labeling;

import java.lang.reflect.Method;

import javax.inject.Singleton;

import com.google.inject.Inject;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
import org.eclipse.jdt.ui.JavaElementImageDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.BaseLabelProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.xtend.core.xtend.XtendMember;
import org.eclipse.xtext.diagnostics.AbstractDiagnostic;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.ui.IImageHelper;
import org.eclipse.xtext.ui.IImageHelper.IImageDescriptorHelper;

/**
 * A decorator that add the diagnotic results on Ecore elements.
 *
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 */
@Singleton
public class SARLDiagnosticLabelDecorator extends BaseLabelProvider implements ILabelDecorator {

    private static final Method GET_NODE_METHOD;

    static {
        try {
            GET_NODE_METHOD = AbstractDiagnostic.class.getDeclaredMethod("getNode"); //$NON-NLS-1$
            GET_NODE_METHOD.setAccessible(true);
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    @Inject
    private IImageHelper imageHelper;

    @Inject
    private IImageDescriptorHelper imageDescriptorHelper;

    private static boolean inside(INode node, ICompositeNode parentCandidate) {
        INode current = node;
        while (current != null) {
            if (current.equals(parentCandidate)) {
                return true;
            }
            current = current.getParent();
        }
        return false;
    }

    /** Replies the image that corresponds to the given object.
     *
     * @param imageDescription
     *            a {@link String}, an {@link ImageDescriptor} or an {@link Image}
     * @return the {@link Image} associated with the description or <code>null</code>
     */
    protected Image convertToImage(Object imageDescription) {
        if (imageDescription instanceof Image) {
            return (Image) imageDescription;
        } else if (imageDescription instanceof ImageDescriptor) {
            return this.imageHelper.getImage((ImageDescriptor) imageDescription);
        } else if (imageDescription instanceof String) {
            return this.imageHelper.getImage((String) imageDescription);
        }
        return null;
    }

    private static boolean hasParserIssue(ICompositeNode node, Iterable<Resource.Diagnostic> issues) {
        for (final Resource.Diagnostic resourceDiagnostic : issues) {
            if (resourceDiagnostic instanceof AbstractDiagnostic) {
                final AbstractDiagnostic diag = (AbstractDiagnostic) resourceDiagnostic;
                final INode diagNode;
                try {
                    diagNode = (INode) GET_NODE_METHOD.invoke(diag);
                } catch (Exception e) {
                    throw new Error(e);
                }
                if (inside(diagNode, node)) {
                    return true;
                }
            }
        }
        return false;
    }

    /** Replies the diagnotic adornment for the given element.
     *
     * @param element the model element.
     * @return the adornment.
     */
    @SuppressWarnings("static-method")
    protected int getIssueAdornment(XtendMember element) {
        final ICompositeNode node = NodeModelUtils.getNode(element);
        if (node == null) {
            return 0;
        }
        // Error markers are more important than warning markers.
        // Order of checks:
        // - parser error (from the resource) or semantic error (from Diagnostician)
        // - parser warning or semantic warning
        final Resource resource = element.eResource();
        if (hasParserIssue(node, resource.getErrors())) {
            return JavaElementImageDescriptor.ERROR;
        }
        final Diagnostic diagnostic = Diagnostician.INSTANCE.validate(element);
        switch (diagnostic.getSeverity()) {
        case Diagnostic.ERROR:
            return JavaElementImageDescriptor.ERROR;
        case Diagnostic.WARNING:
            return JavaElementImageDescriptor.WARNING;
        default:
        }
        if (hasParserIssue(node, resource.getWarnings())) {
            return JavaElementImageDescriptor.WARNING;
        }
        return 0;
    }

    /**Replies the size of the images.
     *
     * @return {@link JavaElementImageProvider#SMALL_SIZE} or {@link JavaElementImageProvider#BIG_SIZE}
     */
    @SuppressWarnings("static-method")
    protected Point imagesSize() {
        return JavaElementImageProvider.BIG_SIZE;
    }

    @Override
    public Image decorateImage(Image image, Object element) {
        if (element instanceof XtendMember) {
            final int adornment = getIssueAdornment((XtendMember) element);
            if (adornment != 0) {
                final ImageDescriptor descriptor = this.imageDescriptorHelper.getImageDescriptor(image);
                final ImageDescriptor newDescriptor = new JavaElementImageDescriptor(descriptor, adornment,
                        imagesSize());
                return convertToImage(newDescriptor);
            }
        }
        return image;
    }

    @Override
    public String decorateText(String text, Object element) {
        return text;
    }

}