Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
* Copyright (c) 2000, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -198,6 +198,78 @@ private int getMemberCategory(int kind) {
return offset + MEMBERSOFFSET;
}

static class NumericalStringComparator {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Why it is a class at all? It can be just a static function.
  2. The comparator function needs tests. Without tests it is a no go.
  3. The code change affects any Java related UI, not only Package Explorer as advertised in the PR. Either fix PR description or the code.
  4. If it is supposed to be used by any UI related to Java, why does it apply only to types and not to methods / fields? They also could contain numbers.
  5. The comparator function creates lot of substrings, but that is expensive. Ideally the code should be rewritten to avoid using substrings and use indexes.

Beside this, if Eclipse views should provide natural sort order, ideally there should be an implementation of that algorithm provided somewhere in platform which could be used by all interested parties (Project Explorer, Outline view etc).
Therefore I believe JDT UI is a wrong place to introduce it.


public int compare(String s1, String s2) {
int s1CompLength = s1.length();
int s2CompLength = s2.length();
//chop off file extensions to restrict comparison to filenames
if(s1.contains(".")) { //$NON-NLS-1$
s1CompLength = s1.indexOf('.');
}
if(s2.contains(".")) { //$NON-NLS-1$
s2CompLength = s2.indexOf('.');
}

//sort numerically only if portion after first '.' is equal
String s1Post = s1.substring(s1CompLength);
String s2Post = s2.substring(s2CompLength);

//only perform numerical sort if suffixes are equal, otherwise default to alphabetical
if(!s1Post.equals(s2Post))
{
return s1.compareTo(s2);
}

//isolate numerical portions
String s1Prefix = s1.substring(0, s1CompLength);
String s2Prefix = s2.substring(0, s2CompLength);

String ints = "0123456789"; //$NON-NLS-1$
StringBuilder sb = new StringBuilder();
int index = s1CompLength - 1;
while(ints.contains(String.valueOf(s1.charAt(index))))
{
sb.append(s1.charAt(index));
index--;
}
String s1NumStr = sb.reverse().toString();
sb.setLength(0);
index = s2CompLength - 1;
while(ints.contains(String.valueOf(s2.charAt(index))))
{
sb.append(s2.charAt(index));
index--;
}
String s2NumStr = sb.reverse().toString();

s1Prefix = s1Prefix.substring(0, s1Prefix.length() - s1NumStr.length());
s2Prefix = s2Prefix.substring(0, s2Prefix.length() - s2NumStr.length());

//if non-numeric portion is sortable, return comparison now
if(s1Prefix.compareTo(s2Prefix) != 0)
return s1Prefix.compareTo(s2Prefix);

//if non-numeric portion is equal, and suffix after first '.' is equal, compare numerical portions
//if either is empty, return that as first item
if(s1NumStr.length() == 0)
return -1;

if(s2NumStr.length() == 0)
return 1;

int s1Int = Integer.parseInt(s1NumStr);
int s2Int = Integer.parseInt(s2NumStr);

if(s1Int > s2Int)
return 1;
else if(s2Int > s1Int)
return -1;
else
return 0;
}
}

@Override
public int compare(Viewer viewer, Object e1, Object e2) {
int cat1= category(e1);
Expand Down Expand Up @@ -259,6 +331,7 @@ public int compare(Viewer viewer, Object e1, Object e2) {
if (name1.length() == 0) {
if (name2.length() == 0) {
try {

return getComparator().compare(((IType) e1).getSuperclassName(), ((IType) e2).getSuperclassName());
} catch (JavaModelException e) {
return 0;
Expand All @@ -271,7 +344,9 @@ public int compare(Viewer viewer, Object e1, Object e2) {
}
}

int cmp= getComparator().compare(name1, name2);
// allow for sorting by numerical portions when strings are otherwise equal (ignoring file extensions)
NumericalStringComparator comp = new NumericalStringComparator();
int cmp= comp.compare(name1, name2);
if (cmp != 0) {
return cmp;
}
Expand Down
Loading