From d3f2eb6a8f05ef3bce5859e52500000eb3b8ee5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kroi=C3=9F=2C=20Florian?= Date: Sat, 7 Feb 2026 18:40:08 +0100 Subject: [PATCH] Fix: Error when using paths with non-ASCII characters for file watching on Unix/MacOS --- org.eclipse.lsp4e.test/META-INF/MANIFEST.MF | 2 +- org.eclipse.lsp4e.test/pom.xml | 2 +- .../lsp4e/test/edit/LSPEclipseUtilsTest.java | 9 ++++++++- .../files/FileSystemWatcherManagerTest.java | 13 ++++++++++++- org.eclipse.lsp4e/META-INF/MANIFEST.MF | 2 +- org.eclipse.lsp4e/pom.xml | 2 +- .../src/org/eclipse/lsp4e/LSPEclipseUtils.java | 18 ++---------------- 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF b/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF index 8962a6a6a..7367814e1 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.7.qualifier +Bundle-Version: 0.16.8.qualifier Fragment-Host: org.eclipse.lsp4e Bundle-Vendor: Eclipse LSP4E Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/org.eclipse.lsp4e.test/pom.xml b/org.eclipse.lsp4e.test/pom.xml index d95907fcd..1dbcfaff1 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.7-SNAPSHOT + 0.16.8-SNAPSHOT diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/edit/LSPEclipseUtilsTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/edit/LSPEclipseUtilsTest.java index 40529c7aa..84855f3f4 100644 --- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/edit/LSPEclipseUtilsTest.java +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/edit/LSPEclipseUtilsTest.java @@ -329,7 +329,6 @@ public void testUNCwindowsURI() { public void testToUri_WindowsUNC() { File unc = new File("\\\\localhost\\c$\\Windows"); URI uri = LSPEclipseUtils.toUri(unc); - System.err.println(uri.toString()); assertTrue(uri.toString().startsWith("file://localhost/c$/Windows")); File uncWithSpaces = new File("\\\\server-name\\shared folder\\dir with space"); @@ -339,6 +338,14 @@ public void testToUri_WindowsUNC() { // Ensure there is an authority and no malformed quadruple slashes assertFalse(uriWithSpaces.toString().startsWith("file:////")); } + + @Test + void testFileUriWithNonAsciiPath() throws Exception { + // File name contains a German Eszett and a Japanese Kana + String fileName = "foo ßア"; + IFile targetFile = project.getFile(fileName); + assertEquals(fileName, Paths.get(LSPEclipseUtils.toUri(targetFile)).getFileName().toString()); + } @Test public void testToWorkspaceFolder() { diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/files/FileSystemWatcherManagerTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/files/FileSystemWatcherManagerTest.java index 94c3e086d..42c770215 100644 --- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/files/FileSystemWatcherManagerTest.java +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/files/FileSystemWatcherManagerTest.java @@ -12,13 +12,15 @@ *******************************************************************************/ package org.eclipse.lsp4e.test.files; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import org.eclipse.lsp4e.LSPEclipseUtils; import org.eclipse.lsp4e.internal.files.FileSystemWatcherManager; import org.eclipse.lsp4j.FileSystemWatcher; import org.eclipse.lsp4j.WatchKind; @@ -128,6 +130,15 @@ void watcherKindFiltering() { assertNoMatchFile(deleteUri, WatchKind.Change); assertMatchFile(deleteUri, WatchKind.Delete); } + + @Test + void nonAsciiFile() { + registerWatchers("watcher-kind", List.of( + new FileSystemWatcher(Either.forLeft("*.txt"), null))); + // We use LSPEclipseUtils.toUri because this is also used to create the URI to check + URI createUri = LSPEclipseUtils.toUri(projectDir.resolve("fooß.txt").toFile()); + assertMatchFile(createUri, WatchKind.Create); + } @Test void globMatchingSimple() { diff --git a/org.eclipse.lsp4e/META-INF/MANIFEST.MF b/org.eclipse.lsp4e/META-INF/MANIFEST.MF index ffe2dbf57..494912d00 100644 --- a/org.eclipse.lsp4e/META-INF/MANIFEST.MF +++ b/org.eclipse.lsp4e/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Language Server Protocol client for Eclipse IDE (Incubation) Bundle-SymbolicName: org.eclipse.lsp4e;singleton:=true -Bundle-Version: 0.19.7.qualifier +Bundle-Version: 0.19.8.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-21 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0", org.eclipse.equinox.common;bundle-version="3.8.0", diff --git a/org.eclipse.lsp4e/pom.xml b/org.eclipse.lsp4e/pom.xml index e379bb9ca..8868cfff3 100644 --- a/org.eclipse.lsp4e/pom.xml +++ b/org.eclipse.lsp4e/pom.xml @@ -10,7 +10,7 @@ org.eclipse.lsp4e eclipse-plugin - 0.19.7-SNAPSHOT + 0.19.8-SNAPSHOT diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LSPEclipseUtils.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LSPEclipseUtils.java index bbb13a983..2a14d8874 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LSPEclipseUtils.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LSPEclipseUtils.java @@ -31,7 +31,6 @@ import java.io.OutputStream; import java.lang.reflect.Method; import java.net.URI; -import java.net.URISyntaxException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -1354,21 +1353,8 @@ public static URI toUri(IPath absolutePath) { } public static URI toUri(File file) { - // URI scheme specified by language server protocol and LSP - try { - final var path = file.getAbsoluteFile().toURI().getPath(); - if (path.startsWith("//")) { // UNC path like //localhost/c$/Windows/ //$NON-NLS-1$ - // split: authority = "localhost", absPath = "/c$/Windows/" - final int slash = path.indexOf('/', 2); - final String authority = slash > 2 ? path.substring(2, slash) : path.substring(2); - final String absPath = slash > 2 ? path.substring(slash) : "/"; //$NON-NLS-1$ - return new URI(FILE_SCHEME, authority, absPath, null); - } - return new URI(FILE_SCHEME, "", path, null); //$NON-NLS-1$ - } catch (URISyntaxException e) { - LanguageServerPlugin.logError(e); - return file.getAbsoluteFile().toURI(); - } + // Perform one round-trip to make sure all non-ASCII characters are properly encoded. + return URI.create((file.toPath().toUri()).toASCIIString()); } public static @Nullable IFile getFile(@Nullable IDocument document) {