* Copyright (C) 2010 Robert Futrell
* robert_futrell at users.sourceforge.net
* http://fifesoft.com/rsyntaxtextarea
* This library is distributed under a modified BSD license. See the included
* RSTALanguageSupport.License.txt file for details.
package org.fife.rsta.ac.java;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.text.JTextComponent;
import org.fife.rsta.ac.java.classreader.MethodInfo;
import org.fife.rsta.ac.java.rjc.ast.FormalParameter;
import org.fife.rsta.ac.java.rjc.ast.Method;
import org.fife.rsta.ac.java.rjc.lang.Type;
import org.fife.ui.autocomplete.Completion;
import org.fife.ui.autocomplete.CompletionProvider;
import org.fife.ui.autocomplete.FunctionCompletion;
import org.fife.ui.autocomplete.ParameterizedCompletion;
* A completion for a Java method. This completion gets its information from
* <li>A {@link MethodInfo} instance, which is loaded by parsing a class
* file. This is used when this completion represents a method found
* in a compiled library.</li>
* <li>A {@link Method} instance, which is created when parsing a Java
* source file. This is used when the completion represents a method
* found in uncompiled source, such as the source in an
* <tt>RSyntaxTextArea</tt>, or in a loose file on disk.</li>
class MethodCompletion extends FunctionCompletion implements MemberCompletion {
* The data source for our completion attributes.
* Used to compare this method completion with another.
private String compareString;
* The relevance of methods. This allows methods to be "higher" in
* the completion list than other types.
private static final int NON_CONSTRUCTOR_RELEVANCE = 2;
* Creates a completion for a method discovered when parsing a Java
* @param m Meta data about the method.
public MethodCompletion(CompletionProvider provider, Method m) {
// NOTE: "void" might not be right - I think this might be constructors
super(provider, m.getName(), m.getType()==null ? "void" : m.getType().toString());
setDefinedIn(m.getParentTypeDeclaration().getName());
this.data = new MethodData(m);
setRelevanceAppropriately();
int count = m.getParameterCount();
List params = new ArrayList(count);
for (int i=0; i<count; i++) {
FormalParameter param = m.getParameter(i);
Type type = param.getType();
String name = param.getName();
params.add(new ParameterizedCompletion.Parameter(type, name));
* Creates a completion for a method discovered when parsing a compiled
* @param info Meta data about the method.
public MethodCompletion(CompletionProvider provider, MethodInfo info) {
super(provider, info.getName(), info.getReturnTypeString(false));
setDefinedIn(info.getClassFile().getClassName(false));
this.data = new MethodInfoData(info, (SourceCompletionProvider)provider);
setRelevanceAppropriately();
String[] paramTypes = info.getParameterTypes();
List params = new ArrayList(paramTypes.length);
for (int i=0; i<paramTypes.length; i++) {
String name = ((MethodInfoData)data).getParameterName(i);
String type = paramTypes[i].substring(paramTypes[i].lastIndexOf('.')+1);
params.add(new ParameterizedCompletion.Parameter(type, name));
* Overridden to compare methods by their comparison strings.
* @param o A <code>Completion</code> to compare to.
* @return The sort order.
public int compareTo(Completion o) {
else if (o instanceof MethodCompletion) {
rc = getCompareString().compareTo(
((MethodCompletion)o).getCompareString());
else if (o instanceof Completion) {
Completion c2 = (Completion)o;
rc = toString().compareToIgnoreCase(c2.toString());
if (rc==0) { // Same text value
String clazz1 = getClass().getName();
clazz1 = clazz1.substring(clazz1.lastIndexOf('.'));
String clazz2 = c2.getClass().getName();
clazz2 = clazz2.substring(clazz2.lastIndexOf('.'));
rc = clazz1.compareTo(clazz2);
public boolean equals(Object obj) {
return (obj instanceof MethodCompletion) &&
//((MethodCompletion)obj).getSignature().equals(getSignature());
((MethodCompletion)obj).getCompareString().equals(getCompareString());
public String getAlreadyEntered(JTextComponent comp) {
String temp = getProvider().getAlreadyEnteredText(comp);
int lastDot = temp.lastIndexOf('.');
temp = temp.substring(lastDot+1);
* Returns a string used to compare this method completion to another.
* @return The comparison string.
private String getCompareString() {
* This string compares the following parts of methods in this order,
* to optimize sort order in completion lists.
* 2. Next, by number of parameters.
* 3. Finally, by parameter type.
if (compareString==null) {
StringBuffer sb = new StringBuffer(getName());
// NOTE: This will fail if a method has > 99 parameters (!)
int paramCount = getParamCount();
for (int i=0; i<paramCount; i++) {
String type = getParam(i).getType();
compareString = sb.toString();
public String getEnclosingClassName(boolean fullyQualified) {
return data.getEnclosingClassName(fullyQualified);
return IconFactory.get().getIcon(data);
public String getSignature() {
return data.getSignature();
public String getSummary() {
String summary = data.getSummary(); // Could be just the method name
// If it's the Javadoc for the method...
if (summary!=null && summary.startsWith("/**")) {
summary = org.fife.rsta.ac.java.Util.docCommentToHtml(summary);
return getCompareString().hashCode();
public boolean isDeprecated() {
return data.isDeprecated();
public void rendererText(Graphics g, int x, int y, boolean selected) {
rendererText(this, g, x, y, selected);
* Sets the relevance of this constructor based on its properties.
private void setRelevanceAppropriately() {
// Only change relevance from the default if this isn't a constructor.
if (!data.isConstructor()) {
setRelevance(NON_CONSTRUCTOR_RELEVANCE);
* Renders a member completion.
public static void rendererText(MemberCompletion mc, Graphics g, int x,
int y, boolean selected) {
String shortType = mc.getType();
int dot = shortType.lastIndexOf('.');
shortType = shortType.substring(dot+1);
// Draw the method signature
String sig = mc.getSignature();
FontMetrics fm = g.getFontMetrics();
int newX = x + fm.stringWidth(sig);
int midY = y + fm.getDescent() - fm.getHeight()/2;
g.drawLine(x, midY, newX, midY);
// Append the return type
StringBuffer sb = new StringBuffer(" : ").append(shortType);
String s = sb.toString();
// Append the type of the containing class of this member.
Color origColor = g.getColor();
g.drawString(mc.getEnclosingClassName(false), x, y);
public String toString() {