package com.redhat.ceylon.eclipse.code.complete;
import static com.redhat.ceylon.eclipse.util.Types.getResultType;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.isNameMatching;
import static java.lang.Character.isUpperCase;
import java.util.Comparator;
import com.redhat.ceylon.eclipse.util.Types;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.DeclarationWithProximity;
import com.redhat.ceylon.model.typechecker.model.Type;
final class ProposalComparator
implements Comparator<DeclarationWithProximity> {
private final String prefix;
private final Types.Required required;
ProposalComparator(String prefix, Types.Required type) {
this.prefix = prefix;
this.required = type;
}
public int compare(
DeclarationWithProximity x,
DeclarationWithProximity y) {
try {
/*boolean xbt = x.getDeclaration() instanceof NothingType;
boolean ybt = y.getDeclaration() instanceof NothingType;
if (xbt&&ybt) {
return 0;
}
if (xbt&&!ybt) {
return 1;
}
if (ybt&&!xbt) {
return -1;
}*/
String xName = x.getName();
String yName = y.getName();
boolean yUpperCase =
isUpperCase(yName.codePointAt(0));
boolean xUpperCase =
isUpperCase(xName.codePointAt(0));
if (!prefix.isEmpty()) {
//proposals which match the case of the
//typed prefix first
boolean upperCasePrefix =
isUpperCase(prefix.codePointAt(0));
if (!xUpperCase && yUpperCase) {
return upperCasePrefix ? 1 : -1;
}
else if (xUpperCase && !yUpperCase) {
return upperCasePrefix ? -1 : 1;
}
}
Declaration xd = x.getDeclaration();
Declaration yd = y.getDeclaration();
Type requiredType = required.getType();
if (requiredType!=null) {
Type xtype = getResultType(xd);
Type ytype = getResultType(yd);
boolean xassigns =
xtype!=null &&
xtype.isSubtypeOf(requiredType);
boolean yassigns =
ytype!=null &&
ytype.isSubtypeOf(requiredType);
if (xassigns && !yassigns) {
return -1;
}
if (yassigns && !xassigns) {
return 1;
}
if (xassigns && yassigns) {
//both are assignable - prefer the
//one which isn't assignable to
//*everything*
boolean xbottom =
xtype!=null &&
xtype.isNothing();
boolean ybottom =
ytype!=null &&
ytype.isNothing();
if (xbottom && !ybottom) {
return 1;
}
if (ybottom && !xbottom) {
return -1;
}
/*boolean xtd =
xd instanceof TypedDeclaration;
boolean ytd =
yd instanceof TypedDeclaration;
if (xtd && !ytd) {
return -1;
}
if (ytd && !xtd) {
return 1;
}*/
}
}
boolean xdepr = xd.isDeprecated();
boolean ydepr = yd.isDeprecated();
if (xdepr && !ydepr) {
return 1;
}
if (!xdepr && ydepr) {
return -1;
}
int pc = Integer.compare(x.getProximity(),
y.getProximity());
if (pc!=0) {
return pc;
}
String requiredName =
required.getParameterName();
if (requiredName!=null) {
boolean xnr =
isNameMatching(xName, requiredName);
boolean ynr =
isNameMatching(yName, requiredName);
if (xnr && !ynr) {
return -1;
}
if (!xnr && ynr) {
return 1;
}
}
//lowercase proposals first if no prefix
if (!xUpperCase && yUpperCase) {
return -1;
}
else if (xUpperCase && !yUpperCase) {
return 1;
}
int nc = xName.compareTo(yName);
if (nc!=0) {
return nc;
}
String xqn = xd.getQualifiedNameString();
String yqn = yd.getQualifiedNameString();
return xqn.compareTo(yqn);
}
catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}