4040import org .eclipse .jface .viewers .TreePath ;
4141import org .eclipse .jface .viewers .TreeSelection ;
4242import org .eclipse .jface .viewers .TreeViewer ;
43+ import org .eclipse .jface .viewers .ViewerComparator ;
4344import org .eclipse .lsp4e .LSPEclipseUtils ;
4445import org .eclipse .lsp4e .LanguageServerPlugin ;
4546import org .eclipse .lsp4e .LanguageServerWrapper ;
5455import org .eclipse .ui .IActionBars ;
5556import org .eclipse .ui .navigator .CommonViewer ;
5657import org .eclipse .ui .navigator .CommonViewerComparator ;
58+ import org .eclipse .ui .navigator .CommonViewerSorter ;
5759import org .eclipse .ui .texteditor .ITextEditor ;
5860import org .eclipse .ui .views .contentoutline .IContentOutlinePage ;
5961
@@ -75,6 +77,9 @@ public class CNFOutlinePage implements IContentOutlinePage, ILabelProviderListen
7577
7678 private final LanguageServerWrapper wrapper ;
7779
80+ @ Nullable
81+ private static Boolean canUseCommonViewerComparator ;
82+
7883 public CNFOutlinePage (LanguageServerWrapper wrapper , @ Nullable ITextEditor textEditor ) {
7984 preferences = InstanceScope .INSTANCE .getNode (LanguageServerPlugin .PLUGIN_ID );
8085 preferences .addPreferenceChangeListener (this );
@@ -90,7 +95,7 @@ public void createControl(final Composite parent) {
9095 if (document != null ) {
9196 outlineViewer .setInput (new OutlineViewerInput (document , wrapper , textEditor ));
9297 }
93- outlineViewer .setComparator (new CommonViewerComparator ());
98+ outlineViewer .setComparator (createComparator ());
9499 outlineViewer .getLabelProvider ().addListener (this );
95100 final var textEditor = this .textEditor ;
96101 if (textEditor != null ) {
@@ -124,6 +129,63 @@ public void createControl(final Composite parent) {
124129 }
125130 }
126131
132+ /**
133+ * Try to be compatible with older Eclipse versions (before 4.39) where
134+ * CommonViewerComparator is not available.
135+ *
136+ * @return comparator for the outline
137+ */
138+ private static ViewerComparator createComparator () {
139+ if (checkIfCommonViewerComparatorAvailable ()) {
140+ return Eclipse439PlusComparator .create ();
141+ }
142+ return EclipseBefore439Comparator .create ();
143+ }
144+
145+ private static boolean checkIfCommonViewerComparatorAvailable () {
146+ if (canUseCommonViewerComparator != null ) {
147+ return canUseCommonViewerComparator .booleanValue ();
148+ }
149+ try {
150+ Class .forName ("org.eclipse.ui.navigator.CommonViewerComparator" ); //$NON-NLS-1$
151+ canUseCommonViewerComparator = Boolean .TRUE ;
152+ return true ;
153+ } catch (ClassNotFoundException e ) {
154+ canUseCommonViewerComparator = Boolean .FALSE ;
155+ return false ;
156+ }
157+ }
158+
159+ /**
160+ * Compatible with modern Eclipse versions (4.39 and later) where
161+ * CommonViewerComparator is available.
162+ * <p>
163+ * This is extracted to an extra class to avoid classloading issues on older Eclipse versions where
164+ * the CommonViewerComparator class is not available. If we try to load a class referencing
165+ * CommonViewerComparator on an older Eclipse version, it will result in a ClassNotFoundException.
166+ *
167+ * @return comparator for the outline
168+ */
169+ private static final class Eclipse439PlusComparator {
170+ static ViewerComparator create () {
171+ return new CommonViewerComparator ();
172+ }
173+ }
174+
175+ /**
176+ * Compatible with older Eclipse versions (before 4.39) where
177+ * CommonViewerComparator is not available.
178+ * <p>
179+ * This is extracted to an extra class to avoid classloading issues
180+ *
181+ * @return comparator for the outline
182+ */
183+ private static final class EclipseBefore439Comparator {
184+ static ViewerComparator create () {
185+ return new CommonViewerSorter ();
186+ }
187+ }
188+
127189 /**
128190 * Returns the range of the given selection and null otherwise.
129191 *
0 commit comments