/**
* Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Sep 14, 2004
*
* @author Fabio Zadrozny
*/
package org.python.pydev.editor.codecompletion;
import java.util.Comparator;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalSorter;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.IToken;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.shared_ui.proposals.IPyCompletionProposal;
import org.python.pydev.shared_ui.proposals.IPyCompletionProposal.ICompareContext;
/**
* @author Fabio Zadrozny
*/
public final class ProposalsComparator implements Comparator<ICompletionProposal>, ICompletionProposalSorter {
public static class CompareContext implements ICompareContext {
private IProject project;
public CompareContext(IToken token) {
this(token.getNature());
}
public CompareContext(IPythonNature nature) {
this(nature != null ? nature.getProject() : null);
}
public CompareContext(IProject project) {
this.project = project;
}
public CompareContext(PyEdit edit) {
this(edit == null ? null : edit.getProject());
}
@Override
public int getPriorityRelatedTo(ICompareContext compareContext) {
if (compareContext instanceof CompareContext) {
CompareContext compareContext2 = (CompareContext) compareContext;
if (compareContext2.project != null && project != null) {
if (compareContext2.project.equals(project)) {
return ICompareContext.SAME_PROJECT_PRIORITY;
}
}
}
if (this.project != null) {
return ICompareContext.ANY_PROJECT_PRIORITY;
}
return ICompareContext.DEFAULT_PRIORITY;
}
@Override
public String toString() {
return "CompareContext[" + (project != null ? project.getName() : "null") + "]";
}
}
private String qualifier;
private String qualifierLower;
private ICompareContext compareContext;
private boolean qualifierHasUpper;
public ProposalsComparator(String qualifier, ICompareContext compareContext) {
this.compareContext = compareContext;
this.setQualifier(qualifier);
}
public void setQualifier(String qualifier) {
this.qualifier = qualifier;
this.qualifierLower = qualifier.toLowerCase();
this.qualifierHasUpper = this.qualifierLower.equals(this.qualifier);
}
public void setCompareContext(CompareContext compareContext) {
this.compareContext = compareContext;
}
public int compare(String o1Str, String o2Str, int priority1, int priority2, ICompareContext ctx1,
ICompareContext ctx2) {
final String o1StrOriginal = o1Str;
final String o2StrOriginal = o2Str;
int o1Len = o1Str.length();
int o2Len = o2Str.length();
//START: Get the contents only to the first parens or space for the comparisons.
{
int iSplit1 = o1Str.indexOf('(', 0);
int iSplit2 = o2Str.indexOf('(', 0);
int iSpace1 = o1Str.indexOf(' ', 0);
int iSpace2 = o2Str.indexOf(' ', 0);
if (iSplit1 == -1 || (iSpace1 >= 0 && iSpace1 < iSplit1)) {
iSplit1 = iSpace1;
}
if (iSplit2 == -1 || (iSpace2 >= 0 && iSpace2 < iSplit2)) {
iSplit2 = iSpace2;
}
if (iSplit1 >= 0) {
o1Str = o1Str.substring(0, iSplit1);
o1Len = o1Str.length();
}
if (iSplit2 >= 0) {
o2Str = o2Str.substring(0, iSplit2);
o2Len = o2Str.length();
}
}
//END: Get the contents only to the first parens or space for the comparisons.
int v = onlyStringCompare(o1Str, o2Str);
if (v != 0) {
return v;
}
if (priority1 < priority2) {
return -1;
}
if (priority1 > priority2) {
return 1;
}
int ctx1Priority = ctx1 != null ? ctx1.getPriorityRelatedTo(compareContext)
: ICompareContext.DEFAULT_PRIORITY;
int ctx2Priority = ctx2 != null ? ctx2.getPriorityRelatedTo(compareContext)
: ICompareContext.DEFAULT_PRIORITY;
if (ctx1Priority != ctx2Priority) {
if (ctx1Priority < ctx2Priority) {
return -1;
}
return 1;
}
boolean o1StartsWithUnder = false;
boolean o2StartsWithUnder = false;
try {
o1StartsWithUnder = o1Str.charAt(0) == '_';
} catch (Exception e1) {
//Shouldn't happen (empty completion?), but if it does, just ignore...
}
try {
o2StartsWithUnder = o2Str.charAt(0) == '_';
} catch (Exception e) {
//Shouldn't happen (empty completion?), but if it does, just ignore...
}
if (o1StartsWithUnder != o2StartsWithUnder) {
if (o1StartsWithUnder) {
return 1;
}
return -1;
} else if (o1StartsWithUnder) {//both start with '_' at this point, let's check for '__'
if (o1Len > 1) {
o1StartsWithUnder = o1Str.charAt(1) == '_';
} else {
o1StartsWithUnder = false;
}
if (o2Len > 1) {
o2StartsWithUnder = o2Str.charAt(1) == '_';
} else {
o2StartsWithUnder = false;
}
if (o1StartsWithUnder != o2StartsWithUnder) {
if (o1StartsWithUnder) {
return 1;
}
return -1;
}
//Ok, at this point, both start with '__', so, the final thing is checking for '__' in the end.
boolean o1EndsWithUnder = false;
boolean o2EndsWithUnder = false;
if (o1Len > 2) {
o1EndsWithUnder = o1Str.charAt(o1Len - 1) == '_';
}
if (o2Len > 2) {
o2EndsWithUnder = o2Str.charAt(o2Len - 1) == '_';
}
if (o1EndsWithUnder != o2EndsWithUnder) {
if (o1EndsWithUnder) {
return 1;
}
return -1;
}
}
return o1StrOriginal.compareToIgnoreCase(o2StrOriginal);
}
private int onlyStringCompare(String o1Str, String o2Str) {
if (qualifierHasUpper) {
if (o1Str.equals(qualifier) && !o2Str.equals(qualifier)) {
return -1;
} else {
if (o2Str.equals(qualifier) && !o1Str.equals(qualifier)) {
return 1;
}
}
}
if (o1Str.equalsIgnoreCase(qualifier) && !o2Str.equalsIgnoreCase(qualifier)) {
return -1;
} else {
if (o2Str.equalsIgnoreCase(qualifier) && !o1Str.equalsIgnoreCase(qualifier)) {
return 1;
}
}
if (qualifierHasUpper) {
if (o1Str.startsWith(qualifier) && !o2Str.startsWith(qualifier)) {
return -1;
} else {
if (o2Str.startsWith(qualifier) && !o1Str.startsWith(qualifier)) {
return 1;
}
}
}
if (o1Str.toLowerCase().startsWith(qualifierLower) && !o2Str.toLowerCase().startsWith(qualifierLower)) {
return -1;
} else {
if (o2Str.toLowerCase().startsWith(qualifierLower)
&& !o1Str.toLowerCase().startsWith(qualifierLower)) {
return 1;
}
}
return 0;
}
@Override
public int compare(ICompletionProposal o1, ICompletionProposal o2) {
String o1Str = o1.getDisplayString();
String o2Str = o2.getDisplayString();
int p1;
int p2;
ICompareContext ctx1;
ICompareContext ctx2;
if (o1 instanceof IPyCompletionProposal) {
IPyCompletionProposal iPyCompletionProposal = (IPyCompletionProposal) o1;
p1 = iPyCompletionProposal.getPriority();
ctx1 = iPyCompletionProposal.getCompareContext();
} else {
p1 = IPyCompletionProposal.PRIORITY_DEFAULT;
ctx1 = null;
}
if (o2 instanceof IPyCompletionProposal) {
IPyCompletionProposal iPyCompletionProposal = (IPyCompletionProposal) o2;
p2 = iPyCompletionProposal.getPriority();
ctx2 = iPyCompletionProposal.getCompareContext();
} else {
p2 = IPyCompletionProposal.PRIORITY_DEFAULT;
ctx2 = null;
}
int ret = compare(
o1Str,
o2Str,
p1,
p2,
ctx1,
ctx2);
// System.out.println(
// StringUtils.format("Compare (%s - %s): qual: %s %s and %s p1: %s p2: %s ctx1: %s ctx2: %s", ret,
// this.hashCode(), qualifier,
// o1Str, o2Str, p1,
// p2, ctx1, ctx2));
return ret;
}
}