/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.rubypeople.rdt.internal.ui.text.ruby;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.Assert;
import org.rubypeople.rdt.core.CompletionProposal;
import org.rubypeople.rdt.core.Flags;
import org.rubypeople.rdt.internal.ui.RubyPluginImages;
import org.rubypeople.rdt.internal.ui.viewsupport.RubyElementImageProvider;
import org.rubypeople.rdt.ui.RubyElementImageDescriptor;
import org.rubypeople.rdt.ui.RubyElementLabels;
/**
* Provides labels for ruby content assist proposals. The functionality is
* similar to the one provided by {@link org.rubypeople.rdt.ui.RubyElementLabels},
* but based on signatures and {@link CompletionProposal}s.
*
* @since 0.8.0
*/
public class CompletionProposalLabelProvider {
/**
* Creates and returns a decorated image descriptor for a completion
* proposal.
*
* @param proposal
* the proposal for which to create an image descriptor
* @return the created image descriptor, or <code>null</code> if no image
* is available
*/
public ImageDescriptor createImageDescriptor(CompletionProposal proposal) {
final int flags = proposal.getFlags();
ImageDescriptor descriptor;
switch (proposal.getKind()) {
case CompletionProposal.METHOD_DECLARATION:
case CompletionProposal.METHOD_NAME_REFERENCE:
case CompletionProposal.METHOD_REF:
case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
descriptor = RubyElementImageProvider.getMethodImageDescriptor(flags);
break;
case CompletionProposal.TYPE_REF:
descriptor = RubyElementImageProvider.getTypeImageDescriptor(
false, false, false);
break;
case CompletionProposal.CONSTANT_REF:
descriptor = RubyElementImageProvider.getConstantImageDescriptor();
break;
case CompletionProposal.GLOBAL_REF:
descriptor = RubyElementImageProvider.getGlobalVariableImageDescriptor();
break;
case CompletionProposal.INSTANCE_VARIABLE_REF:
descriptor = RubyElementImageProvider.getInstanceVariableImageDescriptor();
break;
case CompletionProposal.CLASS_VARIABLE_REF:
descriptor = RubyElementImageProvider.getClassVariableImageDescriptor();
break;
case CompletionProposal.LOCAL_VARIABLE_REF:
case CompletionProposal.VARIABLE_DECLARATION:
descriptor = RubyPluginImages.DESC_OBJS_LOCAL_VAR;
break;
case CompletionProposal.KEYWORD:
descriptor = null;
break;
default:
descriptor = null;
Assert.isTrue(false);
}
if (descriptor == null)
return null;
return decorateImageDescriptor(descriptor, proposal);
}
/**
* Returns a version of <code>descriptor</code> decorated according to
* the passed <code>modifier</code> flags.
*
* @param descriptor the image descriptor to decorate
* @param proposal the proposal
* @return an image descriptor for a method proposal
* @see Flags
*/
private ImageDescriptor decorateImageDescriptor(ImageDescriptor descriptor, CompletionProposal proposal) {
int adornments= 0;
int flags= proposal.getFlags();
int kind= proposal.getKind();
if (kind == CompletionProposal.CONSTANT_REF || kind == CompletionProposal.METHOD_DECLARATION || kind == CompletionProposal.METHOD_DECLARATION || kind == CompletionProposal.METHOD_NAME_REFERENCE || kind == CompletionProposal.METHOD_REF)
if (Flags.isStatic(flags))
adornments |= RubyElementImageDescriptor.STATIC;
return new RubyElementImageDescriptor(descriptor, adornments, RubyElementImageProvider.SMALL_SIZE);
}
public String createLabel(CompletionProposal proposal) {
switch (proposal.getKind()) {
case CompletionProposal.METHOD_NAME_REFERENCE:
case CompletionProposal.METHOD_REF:
case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
return createMethodProposalLabel(proposal);
// case CompletionProposal.METHOD_DECLARATION:
// return createOverrideMethodProposalLabel(proposal);
case CompletionProposal.TYPE_REF:
return createTypeProposalLabel(proposal);
case CompletionProposal.CONSTANT_REF:
case CompletionProposal.CLASS_VARIABLE_REF:
case CompletionProposal.INSTANCE_VARIABLE_REF:
case CompletionProposal.GLOBAL_REF:
case CompletionProposal.LOCAL_VARIABLE_REF:
case CompletionProposal.VARIABLE_DECLARATION:
case CompletionProposal.METHOD_DECLARATION:
return createSimpleLabelWithType(proposal);
case CompletionProposal.KEYWORD:
return createSimpleLabel(proposal);
default:
Assert.isTrue(false);
return null;
}
}
/**
* Creates a display label for a given type proposal. The display label
* consists of:
* <ul>
* <li>the simple type name (erased when the context is in javadoc)</li>
* <li>the package name</li>
* </ul>
* <p>
* Examples:
* A proposal for the generic type <code>java.util.List<E></code>, the display label
* is: <code>List<E> - java.util</code>.
* </p>
*
* @param typeProposal the method proposal to display
* @return the display label for the given type proposal
*/
String createTypeProposalLabel(CompletionProposal typeProposal) {
return typeProposal.getType();
}
/**
* Creates a display label for the given method proposal. The display label
* consists of:
* <ul>
* <li>the method name</li>
* <li>the parameter list (see {@link #createParameterList(CompletionProposal)})</li>
* <li>the upper bound of the return type (see {@link SignatureUtil#getUpperBound(String)})</li>
* <li>the raw simple name of the declaring type</li>
* </ul>
* <p>
* Examples:
* For the <code>get(int)</code> method of a variable of type <code>List<? extends Number></code>, the following
* display name is returned: <code>get(int index) Number - List</code>.<br>
* For the <code>add(E)</code> method of a variable of type <code>List<? super Number></code>, the following
* display name is returned: <code>add(Number o) void - List</code>.<br>
* </p>
*
* @param methodProposal the method proposal to display
* @return the display label for the given method proposal
*/
String createMethodProposalLabel(CompletionProposal methodProposal) {
StringBuffer nameBuffer= new StringBuffer();
// method name
nameBuffer.append(methodProposal.getName());
// parameters
appendUnboundedParameterList(nameBuffer, methodProposal);
// declaring type
nameBuffer.append(RubyElementLabels.CONCAT_STRING);
String declaringType= methodProposal.getDeclaringType();
nameBuffer.append(declaringType);
return nameBuffer.toString();
}
private final StringBuffer appendUnboundedParameterList(StringBuffer buffer, CompletionProposal methodProposal) {
String[] names = methodProposal.getParameterNames();
if (names == null) return buffer;
if (names.length > 0) {
buffer.append('(');
}
for (int i = 0; i < names.length; i++) {
if (i > 0) {
buffer.append(',');
buffer.append(' ');
}
buffer.append(names[i]);
}
if (names.length > 0) {
buffer.append(')');
}
return buffer;
}
String createSimpleLabel(CompletionProposal proposal) {
return String.valueOf(proposal.getCompletion());
}
String createSimpleLabelWithType(CompletionProposal proposal) {
StringBuffer buf= new StringBuffer();
buf.append(proposal.getCompletion());
String typeName= proposal.getType();
if (typeName.length() > 0) {
buf.append(" "); //$NON-NLS-1$
buf.append(typeName);
}
return buf.toString();
}
/**
* Creates and returns a parameter list of the given method proposal
* suitable for display. The list does not include parentheses. The lower
* bound of parameter types is returned.
* <p>
* Examples:
* <pre>
* "void method(int i, Strings)" -> "int i, String s"
* "? extends Number method(java.lang.String s, ? super Number n)" -> "String s, Number n"
* </pre>
* </p>
*
* @param methodProposal the method proposal to create the parameter list
* for. Must be of kind {@link CompletionProposal#METHOD_REF}.
* @return the list of comma-separated parameters suitable for display
*/
public String createParameterList(CompletionProposal methodProposal) {
Assert.isTrue(methodProposal.getKind() == CompletionProposal.METHOD_REF);
return appendUnboundedParameterList(new StringBuffer(), methodProposal).toString();
}
}