From c8168d2784861e80d5f2134406bd15cc85b3d5b6 Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Wed, 8 Apr 2026 13:11:45 +0200 Subject: [PATCH] fix: add ViewerComparator compatibility workaround for Outline view CommonViewerComparator was introduced in Eclipse 4.39 and so Outline can't use this class on older Eclipse versions. Let use old CommonViewerSorter for compatibility with older Eclipse releases. See https://github.com/eclipse-platform/eclipse.platform.ui/pull/3621 Fixes https://github.com/eclipse-lsp4e/lsp4e/issues/1515 --- .../eclipse/lsp4e/outline/CNFOutlinePage.java | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/outline/CNFOutlinePage.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/outline/CNFOutlinePage.java index 0c45d944d..fd267ad48 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/outline/CNFOutlinePage.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/outline/CNFOutlinePage.java @@ -40,6 +40,7 @@ import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.lsp4e.LSPEclipseUtils; import org.eclipse.lsp4e.LanguageServerPlugin; import org.eclipse.lsp4e.LanguageServerWrapper; @@ -54,6 +55,7 @@ import org.eclipse.ui.IActionBars; import org.eclipse.ui.navigator.CommonViewer; import org.eclipse.ui.navigator.CommonViewerComparator; +import org.eclipse.ui.navigator.CommonViewerSorter; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; @@ -75,6 +77,9 @@ public class CNFOutlinePage implements IContentOutlinePage, ILabelProviderListen private final LanguageServerWrapper wrapper; + @Nullable + private static Boolean canUseCommonViewerComparator; + public CNFOutlinePage(LanguageServerWrapper wrapper, @Nullable ITextEditor textEditor) { preferences = InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID); preferences.addPreferenceChangeListener(this); @@ -90,7 +95,7 @@ public void createControl(final Composite parent) { if (document != null) { outlineViewer.setInput(new OutlineViewerInput(document, wrapper, textEditor)); } - outlineViewer.setComparator(new CommonViewerComparator()); + outlineViewer.setComparator(createComparator()); outlineViewer.getLabelProvider().addListener(this); final var textEditor = this.textEditor; if (textEditor != null) { @@ -124,6 +129,63 @@ public void createControl(final Composite parent) { } } + /** + * Try to be compatible with older Eclipse versions (before 4.39) where + * CommonViewerComparator is not available. + * + * @return comparator for the outline + */ + private static ViewerComparator createComparator() { + if (checkIfCommonViewerComparatorAvailable()) { + return Eclipse439PlusComparator.create(); + } + return EclipseBefore439Comparator.create(); + } + + private static boolean checkIfCommonViewerComparatorAvailable() { + if(canUseCommonViewerComparator != null) { + return canUseCommonViewerComparator.booleanValue(); + } + try { + Class.forName("org.eclipse.ui.navigator.CommonViewerComparator"); //$NON-NLS-1$ + canUseCommonViewerComparator = Boolean.TRUE; + return true; + } catch (ClassNotFoundException e) { + canUseCommonViewerComparator = Boolean.FALSE; + return false; + } + } + + /** + * Compatible with modern Eclipse versions (4.39 and later) where + * CommonViewerComparator is available. + *

+ * This is extracted to an extra class to avoid classloading issues on older Eclipse versions where + * the CommonViewerComparator class is not available. If we try to load a class referencing + * CommonViewerComparator on an older Eclipse version, it will result in a ClassNotFoundException. + * + * @return comparator for the outline + */ + private static final class Eclipse439PlusComparator { + static ViewerComparator create() { + return new CommonViewerComparator(); + } + } + + /** + * Compatible with older Eclipse versions (before 4.39) where + * CommonViewerComparator is not available. + *

+ * This is extracted to an extra class to avoid classloading issues + * + * @return comparator for the outline + */ + private static final class EclipseBefore439Comparator { + static ViewerComparator create() { + return new CommonViewerSorter(); + } + } + /** * Returns the range of the given selection and null otherwise. *