From e0cbc54b21b906995f47ead10764d95eeb2438ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kroi=C3=9F=2C=20Florian?= Date: Mon, 13 Apr 2026 22:38:58 +0200 Subject: [PATCH] build: Support a wider range of Eclipse versions --- .github/workflows/build.yml | 12 ++- .github/workflows/codeql.yml | 2 +- .github/workflows/licensecheck.yml | 2 +- CONTRIBUTING.md | 2 +- org.eclipse.lsp4e.test/META-INF/MANIFEST.MF | 6 +- org.eclipse.lsp4e.test/pom.xml | 7 +- .../test/codeactions/CodeActionTests.java | 9 +- .../DocumentLinkReconcilingTest.java | 4 + .../test/utils/AbstractTestWithProject.java | 12 +++ .../eclipse/lsp4e/outline/CNFOutlinePage.java | 82 +++++++------------ pom.xml | 3 +- ...t-platform-latest.target => latest.target} | 4 +- target-platforms/oldest.target | 42 ++++++++++ target-platforms/staging.target | 42 ++++++++++ .../target-platform-latest/.project | 11 --- 15 files changed, 156 insertions(+), 84 deletions(-) rename target-platforms/{target-platform-latest/target-platform-latest.target => latest.target} (97%) create mode 100644 target-platforms/oldest.target create mode 100644 target-platforms/staging.target delete mode 100644 target-platforms/target-platform-latest/.project diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a9c25dfa0..875c32241 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,6 +71,12 @@ jobs: - windows-latest # https://github.com/actions/partner-runner-images - ubuntu-24.04-arm + target-platform: + - oldest + - latest + include: + - os: ubuntu-latest + target-platform: staging runs-on: ${{ matrix.os }} timeout-minutes: 20 @@ -160,10 +166,11 @@ jobs: ~/.m2/repository/.cache/tycho ~/.m2/repository/.meta/p2-artifacts.properties ~/.m2/repository/p2 - key: ${{ runner.os }}-${{ runner.arch }}-repo-tycho-${{ hashFiles('target-platforms/target-platform-latest/target-platform-latest.target') }} + key: ${{ runner.os }}-${{ runner.arch }}-repo-tycho-${{ hashFiles(format('target-platforms/{0}.target', matrix.target-platform)) }} - name: "Build with Maven 🔨" + continue-on-error: ${{ matrix.target-platform == 'staging' }} uses: nick-fields/retry@v4 with: max_attempts: 3 @@ -195,6 +202,7 @@ jobs: --errors \ --update-snapshots \ --batch-mode \ + -Dlsp4e.targetPlatform=${{ matrix.target-platform }} \ --show-version \ -Declipse.p2.mirrors=false \ -Dsurefire.rerunFailingTestsCount=3 \ @@ -215,7 +223,7 @@ jobs: - name: "Upload: Repository Zip" uses: actions/upload-artifact@v7 - if: runner.os == 'Linux' + if: runner.os == 'Linux' && matrix.target-platform == 'oldest' with: name: org.eclipse.lsp4e.repository-${{matrix.target-platform}}-${{matrix.os}} path: repository/target/org.eclipse.lsp4e.repository-*.zip diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e7b963d0a..4d2bb745f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -122,7 +122,7 @@ jobs: ~/.m2/repository/.cache/tycho ~/.m2/repository/.meta/p2-artifacts.properties ~/.m2/repository/p2 - key: ${{ runner.os }}-${{ runner.arch }}-repo-tycho-${{ hashFiles('target-platforms/target-platform-latest/target-platform-latest.target') }} + key: ${{ runner.os }}-${{ runner.arch }}-repo-tycho-${{ hashFiles('target-platforms/oldest.target') }} # https://docs.github.com/en/code-security/code-scanning diff --git a/.github/workflows/licensecheck.yml b/.github/workflows/licensecheck.yml index 16f6b502f..c9b5b4c3d 100644 --- a/.github/workflows/licensecheck.yml +++ b/.github/workflows/licensecheck.yml @@ -91,7 +91,7 @@ jobs: ~/.m2/repository/.cache/tycho ~/.m2/repository/.meta/p2-artifacts.properties ~/.m2/repository/p2 - key: ${{ runner.os }}-${{ runner.arch }}-repo-tycho-${{ hashFiles('target-platforms/target-platform-latest/target-platform-latest.target') }} + key: ${{ runner.os }}-${{ runner.arch }}-repo-tycho-${{ hashFiles('target-platforms/oldest.target') }} - name: Dash License check # see https://github.com/eclipse/dash-licenses diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef963567d..a1118113a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,7 +52,7 @@ Latest snapshot builds, for testing, can usually be found at `https://download.e 1. _File > Open Projects from Filesystem..._ , select the path to the LSP4E Git repo and the relevant children projects you want to import 1. Depending on the task you're planning to work on, multiple workflows are available to configure the [target-platform](https://help.eclipse.org/latest/topic/org.eclipse.pde.doc.user/concepts/target.htm?cp=4_1_5) * In many cases, this simplest workflow will be sufficient: Install latest LSP4E snapshot in your target-platform (can be your current IDE), or - * If you don't want to mix versions of LSP4E, open [target-platforms/target-platform-latest/target-platform-latest.target](target-platforms/target-platform-latest/target-platform-latest.target) from within Eclipse and click **Set as Active Target-Platform** in the top right corner. + * If you don't want to mix versions of LSP4E, open [target-platforms/latest.target](target-platforms/latest.target) from within Eclipse and click **Set as Active Target-Platform** in the top right corner. 1. Open the project modules you want to work on (right-click > Open project) and their dependencies 1. Happy coding! 🤗 diff --git a/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF b/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF index 09733f8d6..2686ac59e 100644 --- a/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF +++ b/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for language server bundle (Incubation) Bundle-SymbolicName: org.eclipse.lsp4e.test;singleton:=true -Bundle-Version: 0.16.9.qualifier +Bundle-Version: 0.16.10.qualifier Fragment-Host: org.eclipse.lsp4e Bundle-Vendor: Eclipse LSP4E Bundle-RequiredExecutionEnvironment: JavaSE-21 @@ -30,8 +30,8 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.e4.ui.workbench, org.eclipse.tm4e.ui, org.eclipse.core.filesystem, - junit-jupiter-api;bundle-version="[6.0.1,7.0.0)", - junit-jupiter-params;bundle-version="[6.0.1,7.0.0)", + junit-jupiter-api;bundle-version="[5.12.2,6.0.0)", + junit-jupiter-params;bundle-version="[5.12.2,6.0.0)", org.hamcrest, org.opentest4j Automatic-Module-Name: org.eclipse.lsp4e.test diff --git a/org.eclipse.lsp4e.test/pom.xml b/org.eclipse.lsp4e.test/pom.xml index a098539ea..a9eaaea13 100644 --- a/org.eclipse.lsp4e.test/pom.xml +++ b/org.eclipse.lsp4e.test/pom.xml @@ -8,7 +8,7 @@ org.eclipse.lsp4e.test eclipse-test-plugin - 0.16.9-SNAPSHOT + 0.16.10-SNAPSHOT @@ -38,12 +38,15 @@ ${tycho-version} + + + ${lsp4e.targetPlatform} + false true true 1200 -Dfile.encoding=${project.build.sourceEncoding} -Xms1g -Xmx1g -Djava.util.logging.config.file=${project.basedir}/src/jul.properties ${ui.test.vmargs} ${os-jvm-flags} - junit6 diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java index ba901586f..9dfa84da6 100644 --- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java @@ -188,12 +188,9 @@ public void testCodeActionLiteralWorkspaceEdit() throws CoreException { @Test public void testNoCodeActionOnReadOnlySource() throws CoreException { IFile f = TestUtils.createUniqueTestFile(project, "error"); - f.setResourceAttributes(new ResourceAttributes() { - @Override - public boolean isReadOnly() { - return true; - } - }); + ResourceAttributes attrs = f.getResourceAttributes(); + attrs.setReadOnly(true); + f.setResourceAttributes(attrs); final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed"); final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit))); diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/documentLink/DocumentLinkReconcilingTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/documentLink/DocumentLinkReconcilingTest.java index afbd0f257..90ff3bcfa 100644 --- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/documentLink/DocumentLinkReconcilingTest.java +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/documentLink/DocumentLinkReconcilingTest.java @@ -37,6 +37,7 @@ import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.graphics.Color; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIfSystemProperty; public class DocumentLinkReconcilingTest extends AbstractTestWithProject { @@ -188,6 +189,9 @@ public void testMidLineClippedDocumentLinkReconciling() throws Exception { } @Test + @DisabledIfSystemProperty(named = "lsp4e.targetPlatform", matches = "oldest", disabledReason = """ + Fails on oldest target platform. + Note: this will only work when called from Maven or when setting the propery explicitly.""") public void testClippedDocumentLinkReconciling() throws Exception { MockLanguageServer.INSTANCE.setDocumentLinks(CONTENT_LINKS); diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java index 316e8271d..381dd03a4 100644 --- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java @@ -15,6 +15,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.runtime.CoreException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -53,6 +54,17 @@ private static void deleteProjectWithRetries(IProject project, int maxAttempts, if (!project.exists()) { break; } + project.open(null); + project.accept(r -> { + ResourceAttributes attrs = r.getResourceAttributes(); + // At least one test creates a read-only resource. + // This leads to errors when trying to delete the project, so we make all files writable again. + if (attrs != null && attrs.isReadOnly()) { + attrs.setReadOnly(false); + r.setResourceAttributes(attrs); + } + return true; + }); project.close(null); project.delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, null); break; 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 fd267ad48..9b32c07c9 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/outline/CNFOutlinePage.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/outline/CNFOutlinePage.java @@ -16,6 +16,7 @@ import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNullable; import static org.eclipse.lsp4e.internal.NullSafetyHelper.lateNonNull; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import org.eclipse.core.runtime.Adapters; @@ -54,7 +55,6 @@ import org.eclipse.swt.widgets.Control; 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; @@ -77,8 +77,8 @@ public class CNFOutlinePage implements IContentOutlinePage, ILabelProviderListen private final LanguageServerWrapper wrapper; - @Nullable - private static Boolean canUseCommonViewerComparator; + private static @Nullable Class comparatorClass = null; + private static boolean checkedForComparatorClass = false; public CNFOutlinePage(LanguageServerWrapper wrapper, @Nullable ITextEditor textEditor) { preferences = InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID); @@ -95,7 +95,7 @@ public void createControl(final Composite parent) { if (document != null) { outlineViewer.setInput(new OutlineViewerInput(document, wrapper, textEditor)); } - outlineViewer.setComparator(createComparator()); + configureSorterOrComparator(outlineViewer); outlineViewer.getLabelProvider().addListener(this); final var textEditor = this.textEditor; if (textEditor != null) { @@ -130,60 +130,34 @@ 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 + * Workaround for a Bug in Eclipse 4.39: + * Before 4.39, the CommonViewerSorter can be used. + * Starting with 4.39, using the CommonViewerSorter breaks sorting, + * so the newer CommonViewerComparator must be used. + * Once our oldest Target Platform contains CommonViewerComparator, we can drop this workaround. + * @param viewer The viewer to configure */ - private static final class Eclipse439PlusComparator { - static ViewerComparator create() { - return new CommonViewerComparator(); + private void configureSorterOrComparator(CommonViewer viewer) { + if (!checkedForComparatorClass) { + checkedForComparatorClass = true; + try { + comparatorClass = Class.forName("org.eclipse.ui.navigator.CommonViewerComparator"); //$NON-NLS-1$ + } catch (ClassNotFoundException e) { + // Will trigger on < 4.39. + } } - } - /** - * 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(); + if (comparatorClass != null) { + try { + ViewerComparator comparator = (ViewerComparator) comparatorClass.getDeclaredConstructor().newInstance(); + viewer.setComparator(comparator); + return; + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + // Fall-through + } } + viewer.setSorter(new CommonViewerSorter()); } /** diff --git a/pom.xml b/pom.xml index 28dd40043..d2907a2ed 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ scm:git:https://github.com/eclipse-lsp4e/lsp4e.git error + oldest @@ -75,7 +76,7 @@ ${tycho-version} - ${maven.multiModuleProjectDirectory}/target-platforms/target-platform-latest/target-platform-latest.target + ${maven.multiModuleProjectDirectory}/target-platforms/${lsp4e.targetPlatform}.target diff --git a/target-platforms/target-platform-latest/target-platform-latest.target b/target-platforms/latest.target similarity index 97% rename from target-platforms/target-platform-latest/target-platform-latest.target rename to target-platforms/latest.target index 3e98e4153..8a171f834 100644 --- a/target-platforms/target-platform-latest/target-platform-latest.target +++ b/target-platforms/latest.target @@ -13,10 +13,10 @@ - + - + diff --git a/target-platforms/oldest.target b/target-platforms/oldest.target new file mode 100644 index 000000000..f09ec27d7 --- /dev/null +++ b/target-platforms/oldest.target @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.vegardit.no-npe + no-npe-eea-all + 1.3.9 + jar + + + + + + \ No newline at end of file diff --git a/target-platforms/staging.target b/target-platforms/staging.target new file mode 100644 index 000000000..a288cea40 --- /dev/null +++ b/target-platforms/staging.target @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.vegardit.no-npe + no-npe-eea-all + 1.3.9 + jar + + + + + + \ No newline at end of file diff --git a/target-platforms/target-platform-latest/.project b/target-platforms/target-platform-latest/.project deleted file mode 100644 index c857e3918..000000000 --- a/target-platforms/target-platform-latest/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - target-platform-latest - - - - - - - -