org.eclipse.recommenders.codesearch.rcp.index.extdoc.LabelProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.recommenders.codesearch.rcp.index.extdoc.LabelProvider.java

Source

/**
 * Copyright (c) 2012 Tobias Boehm.
 * 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:
 *    Marcel Bruch - initial API and implementation.
 */

package org.eclipse.recommenders.codesearch.rcp.index.extdoc;

import static org.apache.commons.lang3.StringUtils.isEmpty;

import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.text.IColorManager;
import org.eclipse.jdt.ui.text.IJavaColorConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.recommenders.codesearch.rcp.index.searcher.SearchResult;
import org.eclipse.recommenders.utils.IOUtils;
import org.eclipse.recommenders.utils.rcp.JavaElementResolver;
import org.eclipse.recommenders.utils.rcp.ast.ASTNodeUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;

import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;

public class LabelProvider extends StyledCellLabelProvider {

    private final JavaElementLabelProvider jdtLabelProvider = new JavaElementLabelProvider();
    private MethodDeclaration astMethod;
    private List<ASTNode> statements;
    private final List<String> searchterms;

    public LabelProvider(final JavaElementResolver jdtCache, final List<String> searchterms,
            final SearchResult searchResults) {
        this.searchterms = searchterms;
    }

    /**
     * Finds all relevant statements and creates a *very* simple summary
     */
    @Override
    public void update(final ViewerCell cell) {
        cell.setFont(JFaceResources.getTextFont());
        final Selection s = (Selection) cell.getElement();
        astMethod = s.method;
        final String varname = s.varname;
        if (s.isError()) {
            cell.setText(s.exception.getMessage());
            return;
        }

        if (astMethod == ContentProvider.EMPTY) {
            cell.setText("// failed to resolve method.");
            setCellToCommentStyle(cell);
            return;
        }

        if (!findStatements(varname)) {
            cell.setText(
                    "// No interesting statements found.\n// Either index is outdated or method is not actually using this variable?");
            setCellToCommentStyle(cell);
            super.update(cell);
            return;
        }
        setCellText(cell);
    }

    private void setCellToCommentStyle(final ViewerCell cell) {
        final IColorManager colorManager = JavaUI.getColorManager();
        final Color color = colorManager.getColor(IJavaColorConstants.JAVA_MULTI_LINE_COMMENT);
        final StyleRange[] ranges = { new StyleRange(0, cell.getText().length(), color, null) };
        cell.setStyleRanges(ranges);
    }

    private boolean findStatements(final String varname) {
        statements = Lists.newArrayList();

        if (isEmpty(varname)) {
            return false;
        }

        astMethod.accept(new ASTVisitor() {
            @Override
            public boolean visit(final SimpleName node) {
                if (node.getIdentifier().equals(varname)) {
                    collectStatement(node);
                }
                return false;
            }

            private void collectStatement(final SimpleName node) {

                for (ASTNode curr = node.getParent(); curr != null; curr = curr.getParent()) {
                    if (curr instanceof ExpressionStatement) {
                        statements.add(curr);
                        return;
                    } else if (curr instanceof ReturnStatement) {
                        statements.add(curr);
                        return;
                    }
                }

                final ASTNode sup = node.getParent();
                switch (sup.getNodeType()) {
                case ASTNode.CLASS_INSTANCE_CREATION:
                    final ASTNode supSup = sup.getParent();
                    switch (supSup.getNodeType()) {
                    case ASTNode.CLASS_INSTANCE_CREATION:
                    case ASTNode.ASSIGNMENT:
                        statements.add(supSup);
                        break;
                    case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
                        final ASTNode supSupSup = supSup.getParent();
                        if (supSupSup instanceof VariableDeclarationStatement) {
                            statements.add(supSupSup);
                        } else {
                            statements.add(supSup);
                        }
                    }

                    break;
                case ASTNode.RETURN_STATEMENT:
                    if (((ReturnStatement) sup).getExpression() instanceof SimpleName) {
                        break;
                    }
                    //$FALL-THROUGH$
                case ASTNode.METHOD_INVOCATION:
                case ASTNode.SUPER_METHOD_INVOCATION:
                case ASTNode.FIELD_ACCESS:
                case ASTNode.SUPER_FIELD_ACCESS:
                case ASTNode.CONSTRUCTOR_INVOCATION:
                case ASTNode.SUPER_CONSTRUCTOR_INVOCATION:
                case ASTNode.CAST_EXPRESSION:
                case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
                    statements.add(sup);
                    break;
                default:
                    break;
                }
            };
        });

        return !statements.isEmpty();
    }

    private void setCellText(final ViewerCell cell) {
        final StringBuilder sb = new StringBuilder();
        for (final ASTNode n : statements) {
            // term matching in here:... waiting for contribution of
            // Kristjian...
            sb.append(n.toString()).append(IOUtils.LINE_SEPARATOR);
        }
        final String[] split = StringUtils.split(sb.toString(), IOUtils.LINE_SEPARATOR);
        final String summary = StringUtils.join(ArrayUtils.subarray(split, 0, 3), IOUtils.LINE_SEPARATOR);
        cell.setText(summary);
        final List<StyleRange> ranges = Lists.newArrayList();
        final Color color = JavaUI.getColorManager().getColor(IJavaColorConstants.JAVA_KEYWORD);

        for (final String term : searchterms) {

            int index = 0;
            while (true) {
                index = StringUtils.indexOfIgnoreCase(summary, term, index);
                if (index == -1) {
                    break;
                }
                ranges.add(new StyleRange(index, term.length(), color, null));
                index += term.length();
            }
        }
        cell.setFont(JFaceResources.getTextFont());
        cell.setStyleRanges(ranges.toArray(new StyleRange[0]));
    }

    @Override
    protected void measure(final Event event, final Object element) {
        final TableItem item = (TableItem) event.item;
        final GC gc = event.gc;
        gc.setFont(item.getFont());
        final Point size = gc.textExtent("\n\n\n");
        final Table parent = item.getParent();
        final Rectangle clientArea = parent.getClientArea();
        final int clientWidth = clientArea.width;
        event.width = clientWidth - 20;
        event.height = size.y;
        final Rectangle bounds = item.getBounds();
        gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
        gc.drawLine(bounds.x, bounds.y, bounds.x + clientWidth, bounds.y);
        super.measure(event, element);
    }

    @Override
    public String getToolTipText(final Object element) {
        if (element instanceof Selection) {
            final Selection s = (Selection) element;
            if (s.method != null) {
                final Optional<TypeDeclaration> enclosingType = ASTNodeUtils.getClosestParent(s.method,
                        TypeDeclaration.class);

                return (enclosingType.isPresent()
                        ? "class " + enclosingType.get().resolveBinding().getQualifiedName()
                        : "") + "\n" + s.method.toString();
            } else if (s.isError()) {
                return Throwables.getStackTraceAsString(s.exception);
            } else if (s.doc != null) {
                return s.doc.toString();
            }
        }
        return null;
    }

    @Override
    public org.eclipse.swt.graphics.Image getToolTipImage(final Object object) {
        if (object instanceof Selection) {
            final Selection s = (Selection) object;
            return jdtLabelProvider.getImage(s.element());
        }
        return null;

    };

    @Override
    public boolean useNativeToolTip(final Object object) {
        return true;
    }

    @Override
    public Point getToolTipShift(final Object object) {
        return new Point(5, 5);
    }

    @Override
    public int getToolTipDisplayDelayTime(final Object object) {
        return 100;
    }

    @Override
    public int getToolTipTimeDisplayed(final Object object) {
        return 5000;
    }

    @Override
    public void dispose() {
        super.dispose();
    }
}