Skip to content

Commit ef2a4e7

Browse files
sebthommickaelistria
authored andcommitted
Fix Windows UNC Path issues
1 parent 1ea3d0d commit ef2a4e7

File tree

6 files changed

+97
-42
lines changed

6 files changed

+97
-42
lines changed

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/debug/AbstractDebugAdapterLaunchShortcut.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* which is available at https://www.eclipse.org/legal/epl-2.0/
77
*
88
* SPDX-License-Identifier: EPL-2.0
9-
*
9+
*
1010
* Contributors:
1111
* Pierre-Yves B. - Issue #309 Launch called from the wrong thread
1212
*******************************************************************************/
@@ -43,6 +43,7 @@
4343
import org.eclipse.ui.IEditorInput;
4444
import org.eclipse.ui.IEditorPart;
4545
import org.eclipse.ui.part.FileEditorInput;
46+
import org.eclipse.wildwebdeveloper.util.FileUtils;
4647

4748
public abstract class AbstractDebugAdapterLaunchShortcut implements ILaunchShortcut2 {
4849

@@ -156,7 +157,7 @@ private void launch(String mode, ILaunchConfiguration[] configurations, File lau
156157
DebugUITools.launch(configuration, mode);
157158
} else {
158159
if (DebugUIPlugin.openLaunchConfigurationEditDialog(Display.getCurrent().getActiveShell(), configuration, DebugUITools.getLaunchGroup(configuration, mode).getIdentifier(), null, true) == IDialogConstants.OK_ID) {
159-
DebugUITools.launch(configuration, mode);
160+
DebugUITools.launch(configuration, mode);
160161
}
161162
}
162163
});
@@ -202,15 +203,15 @@ private ILaunchConfigurationWorkingCopy createNewLaunchConfiguration(File file)
202203
String configName = launchManager.generateLaunchConfigurationName(file.getAbsolutePath());
203204
ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, configName);
204205
wc.setAttribute(DebugPlugin.ATTR_WORKING_DIRECTORY, file.getParentFile().getAbsolutePath());
205-
wc.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.toURI()));
206+
wc.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(FileUtils.toUri(file)));
206207
configureLaunchConfiguration(file, wc);
207208
return wc;
208209
}
209210

210211
/**
211212
* Takes a working copy of a launch configuration and sets the default
212213
* attributes according to provided file
213-
*
214+
*
214215
* @param file
215216
* @param wc
216217
*/

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/debug/AbstractRunHTMLDebugTab.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@
5656
import org.eclipse.wildwebdeveloper.Activator;
5757
import org.eclipse.wildwebdeveloper.debug.chrome.ChromeRunDAPDebugDelegate;
5858
import org.eclipse.wildwebdeveloper.debug.chrome.ChromeRunDebugLaunchShortcut;
59+
import org.eclipse.wildwebdeveloper.util.FileUtils;
5960

6061
public abstract class AbstractRunHTMLDebugTab extends AbstractLaunchConfigurationTab {
61-
62+
6263
private Text programPathText;
6364
private Text argumentsText;
6465
private Text workingDirectoryText;
@@ -82,8 +83,8 @@ public AbstractRunHTMLDebugTab() {
8283
public void createControl(Composite parent) {
8384
resComposite = new Composite(parent, SWT.NONE);
8485
resComposite.setLayout(new GridLayout(4, false));
85-
86-
fileRadio = createRadioButton(resComposite, Messages.FirefoxDebugTab_File);
86+
87+
fileRadio = createRadioButton(resComposite, Messages.FirefoxDebugTab_File);
8788
fileRadio.setToolTipText(Messages.AbstractRunHTMLDebugTab_fileRadioToolTip);
8889
fileRadio.setLayoutData(new GridData(SWT.DEFAULT, SWT.DEFAULT, false, false));
8990
fileRadio.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
@@ -96,7 +97,7 @@ public void createControl(Composite parent) {
9697
validateProgramPathAndURL();
9798
updateLaunchConfigurationDialog();
9899
}));
99-
100+
100101
this.programPathText = new Text(resComposite, SWT.BORDER);
101102
this.programPathText.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
102103
fileDecoration = new ControlDecoration(programPathText, SWT.TOP | SWT.LEFT);
@@ -118,7 +119,7 @@ public void createControl(Composite parent) {
118119
programPathText.setText(path);
119120
}
120121
}));
121-
122+
122123
urlRadio = createRadioButton(resComposite, "URL: ");
123124
urlRadio.setToolTipText(Messages.RunFirefoxDebugTab_URL_Note);
124125
urlRadio.setLayoutData(new GridData(SWT.DEFAULT, SWT.DEFAULT, false, false));
@@ -142,7 +143,7 @@ public void createControl(Composite parent) {
142143
validateProgramPathAndURL();
143144
updateLaunchConfigurationDialog();
144145
});
145-
146+
146147
new Label(resComposite, SWT.NONE).setText(Messages.AbstractRunHTMLDebugTab_webRoot_folder);
147148
webRootText = new Text(resComposite, SWT.BORDER);
148149
webRootText.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
@@ -232,7 +233,7 @@ public void createControl(Composite parent) {
232233

233234
private void validateProgramPathAndURL() {
234235
setDirty(true);
235-
236+
236237
setErrorMessage(null);
237238
fileDecoration.hide();
238239
urlDecoration.hide();
@@ -252,23 +253,23 @@ private void validateProgramPathAndURL() {
252253
} catch (CoreException ex) {
253254
errorMessage = ex.getMessage();
254255
}
255-
256+
256257
if (errorMessage != null) {
257258
setErrorMessage(errorMessage);
258259
fileDecoration.setDescriptionText(errorMessage);
259260
fileDecoration.show();
260261
}
261-
262+
262263
} else if (urlRadio.getSelection()) {
263264
try {
264265
new URL(urlText.getText());
265266
} catch (MalformedURLException ex) {
266267
errorMessage = MessageFormat.format(
267-
Messages.RunProgramTab_error_malformedUR,
268+
Messages.RunProgramTab_error_malformedUR,
268269
ex.getMessage());
269270
urlDecoration.setDescriptionText(errorMessage);
270271
urlDecoration.show();
271-
}
272+
}
272273
boolean showWebRootDecoration = false;
273274
if(webRootText.getText().isBlank()) {
274275
errorMessage = Messages.AbstractRunHTMLDebugTab_cannot_debug_without_webroot;
@@ -338,9 +339,9 @@ public void initializeFrom(ILaunchConfiguration configuration) {
338339
webRootProjectSelectButton.setEnabled(true);
339340
webRootFilesystemSelectButton.setEnabled(true);
340341
}
341-
342+
342343
validateProgramPathAndURL();
343-
344+
344345
} catch (CoreException e) {
345346
ILog.get().log(e.getStatus());
346347
}
@@ -357,7 +358,7 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
357358
configuration.setAttribute(AbstractHTMLDebugDelegate.ARGUMENTS, this.argumentsText.getText());
358359
String workingDirectory = this.workingDirectoryText.getText();
359360
configuration.setAttribute(DebugPlugin.ATTR_WORKING_DIRECTORY, workingDirectory);
360-
configuration.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(new File(programPath).toURI()));
361+
configuration.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(FileUtils.toUri(programPath)));
361362
}
362363

363364
@Override

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/debug/node/RunProgramTab.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.eclipse.swt.widgets.Text;
3838
import org.eclipse.wildwebdeveloper.debug.LaunchConstants;
3939
import org.eclipse.wildwebdeveloper.debug.Messages;
40+
import org.eclipse.wildwebdeveloper.util.FileUtils;
4041

4142
public class RunProgramTab extends AbstractLaunchConfigurationTab {
4243

@@ -127,7 +128,7 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
127128
configuration.setAttribute(LaunchConstants.PROGRAM, programPath);
128129
configuration.setAttribute(NodeRunDAPDebugDelegate.ARGUMENTS, this.argumentsText.getText());
129130
configuration.setAttribute(DebugPlugin.ATTR_WORKING_DIRECTORY, this.workingDirectoryText.getText());
130-
configuration.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(new File(programPath).toURI()));
131+
configuration.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(FileUtils.toUri(programPath)));
131132
}
132133

133134
@Override

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/debug/npm/NpmLaunchTab.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.eclipse.wildwebdeveloper.debug.AbstractDebugAdapterLaunchShortcut;
4040
import org.eclipse.wildwebdeveloper.debug.AbstractHTMLDebugDelegate;
4141
import org.eclipse.wildwebdeveloper.debug.LaunchConstants;
42+
import org.eclipse.wildwebdeveloper.util.FileUtils;
4243

4344
public class NpmLaunchTab extends AbstractLaunchConfigurationTab {
4445

@@ -168,7 +169,7 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
168169
configuration.setAttribute(LaunchConstants.PROGRAM, programPath);
169170
configuration.setAttribute(AbstractHTMLDebugDelegate.ARGUMENTS, this.argumentsCombo.getText());
170171
configuration.setAttribute(DebugPlugin.ATTR_WORKING_DIRECTORY, workingDirectory);
171-
configuration.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(new File(programPath).toURI()));
172+
configuration.setMappedResources(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(FileUtils.toUri(programPath)));
172173
}
173174

174175
@Override

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/eslint/ESLintClientImpl.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66
* which is available at https://www.eclipse.org/legal/epl-2.0/
77
*
88
* SPDX-License-Identifier: EPL-2.0
9-
*
9+
*
1010
* Contributors:
1111
* Pierre-Yves Bigourdan - Allow configuring directory of ESLint package
1212
*******************************************************************************/
1313
package org.eclipse.wildwebdeveloper.eslint;
1414

1515
import java.io.File;
16-
import java.net.URI;
17-
import java.net.URISyntaxException;
1816
import java.net.URL;
1917
import java.util.Collections;
2018
import java.util.HashMap;
@@ -32,6 +30,7 @@
3230
import org.eclipse.ui.PlatformUI;
3331
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
3432
import org.eclipse.wildwebdeveloper.jsts.ui.preferences.JSTSPreferenceServerConstants;
33+
import org.eclipse.wildwebdeveloper.util.FileUtils;
3534

3635
public class ESLintClientImpl extends LanguageClientImpl implements ESLintLanguageServerExtension {
3736

@@ -43,7 +42,7 @@ public CompletableFuture<Integer> confirmESLintExecution(Object param) {
4342
@Override
4443
public CompletableFuture<List<Object>> configuration(ConfigurationParams configurationParams) {
4544
ConfigurationItem configurationItem = configurationParams.getItems().get(0);
46-
45+
4746
Map<String, Object> config = new HashMap<>(6, 1.f);
4847

4948
// search first for the highest directory that has a package.json file
@@ -52,29 +51,24 @@ public CompletableFuture<List<Object>> configuration(ConfigurationParams configu
5251
// until the workspaceFolder which folder is best suited for its workingDirectoy (where the config files are in)
5352
// also this workspaceFolder is also used to find the node models (eslint module)
5453
// because we set the nodePath below to this same directory.
55-
File highestPackageJsonDir = null;
56-
try {
57-
highestPackageJsonDir = new File(new URI(configurationItem.getScopeUri())).getParentFile();
58-
File parentFile = highestPackageJsonDir;
59-
while (parentFile != null) {
60-
if (new File(parentFile, "package.json").exists()) highestPackageJsonDir = parentFile;
61-
parentFile = parentFile.getParentFile();
62-
}
63-
} catch (URISyntaxException e) {
64-
// shouldn't happen else what to do here?
54+
File highestPackageJsonDir = FileUtils.fromUri(configurationItem.getScopeUri()).getParentFile();
55+
File parentFile = highestPackageJsonDir;
56+
while (parentFile != null) {
57+
if (new File(parentFile, "package.json").exists()) highestPackageJsonDir = parentFile;
58+
parentFile = parentFile.getParentFile();
6559
}
66-
67-
// `pre-release/2.3.0`: Disable using experimental Flat Config system
60+
61+
// `pre-release/2.3.0`: Disable using experimental Flat Config system
6862
config.put("experimental", Collections.emptyMap());
6963

7064
// `pre-release/2.3.0`: Add stub `problems` settings due to:
7165
// ESLint: Cannot read properties of undefined (reading \u0027shortenToSingleLine\u0027). Please see the \u0027ESLint\u0027 output channel for details.
7266
config.put("problems", Collections.emptyMap());
7367

74-
config.put("workspaceFolder", Collections.singletonMap("uri", highestPackageJsonDir.toURI().toString()));
68+
config.put("workspaceFolder", Collections.singletonMap("uri", FileUtils.toUri(highestPackageJsonDir).toString()));
7569

7670
// if you set a workspaceFolder and then the working dir in auto mode eslint will try to get to the right config location.
77-
config.put("workingDirectory", Collections.singletonMap("mode", "auto"));
71+
config.put("workingDirectory", Collections.singletonMap("mode", "auto"));
7872

7973
// this should not point to a nodejs executable but to a parent directory containing the ESLint package
8074
config.put("nodePath",getESLintPackageDir(highestPackageJsonDir));
@@ -83,7 +77,7 @@ public CompletableFuture<List<Object>> configuration(ConfigurationParams configu
8377
config.put("run", "onType");
8478
config.put("rulesCustomizations", Collections.emptyList());
8579

86-
config.put("codeAction", Map.of("disableRuleComment", Map.of("enable", "true", "location", "separateLine"),
80+
config.put("codeAction", Map.of("disableRuleComment", Map.of("enable", "true", "location", "separateLine"),
8781
"showDocumentation", Collections.singletonMap("enable", "true")));
8882
return CompletableFuture.completedFuture(Collections.singletonList(config));
8983
}
@@ -112,7 +106,7 @@ public CompletableFuture<Void> eslintStatus(Object o) {
112106
// ignore for now
113107
return CompletableFuture.completedFuture(null);
114108
}
115-
109+
116110
@Override
117111
public CompletableFuture<Void> openDoc(Map<String,String> data) {
118112
if (data.containsKey("url")) {
@@ -127,7 +121,7 @@ public CompletableFuture<Void> openDoc(Map<String,String> data) {
127121
}
128122
return CompletableFuture.completedFuture(null);
129123
}
130-
124+
131125
@Override
132126
public CompletableFuture<Void> noLibrary(Map<String,Map<String,String>> data) {
133127
MessageParams params = new MessageParams(MessageType.Info, "No ES Library found for file: " + data.get("source").get("uri"));
@@ -137,7 +131,7 @@ public CompletableFuture<Void> noLibrary(Map<String,Map<String,String>> data) {
137131

138132
@Override
139133
public CompletableFuture<Void> noConfig(Map<String, Map<String, String>> data) {
140-
MessageParams params = new MessageParams(MessageType.Info, "No ES Configuration found for file: " + data.get("source").get("uri")
134+
MessageParams params = new MessageParams(MessageType.Info, "No ES Configuration found for file: " + data.get("source").get("uri")
141135
+ ": " + data.get("message"));
142136
logMessage(params);
143137
return CompletableFuture.completedFuture(null);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Vegard IT GmbH and others.
3+
*
4+
* This program and the accompanying materials are made
5+
* available under the terms of the Eclipse Public License 2.0
6+
* which is available at https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Sebastian Thomschke (Vegard IT GmbH) - initial implementation
12+
*******************************************************************************/
13+
package org.eclipse.wildwebdeveloper.util;
14+
15+
import java.io.File;
16+
import java.net.URI;
17+
import java.net.URISyntaxException;
18+
import java.nio.file.Paths;
19+
20+
import org.eclipse.core.runtime.IStatus;
21+
import org.eclipse.core.runtime.Status;
22+
import org.eclipse.wildwebdeveloper.Activator;
23+
24+
public class FileUtils {
25+
private static final String FILE_SCHEME = "file"; //$NON-NLS-1$
26+
27+
public static File fromUri(String uri) {
28+
// not using `new File(new URI(uri))` here which does not support Windows UNC paths
29+
// and instead throws IllegalArgumentException("URI has an authority component")
30+
return Paths.get(URI.create(uri)).toFile();
31+
}
32+
33+
public static URI toUri(String filePath) {
34+
return toUri(new File(filePath));
35+
}
36+
37+
public static URI toUri(File file) {
38+
// copied from org.eclipse.lsp4e.LSPEclipseUtils#toUri(File)
39+
40+
// URI scheme specified by language server protocol and LSP
41+
try {
42+
final var path = file.getAbsoluteFile().toURI().getPath();
43+
if (path.startsWith("//")) { // UNC path like //localhost/c$/Windows/ //$NON-NLS-1$
44+
// split: authority = "localhost", absPath = "/c$/Windows/"
45+
final int slash = path.indexOf('/', 2);
46+
final String authority = slash > 2 ? path.substring(2, slash) : path.substring(2);
47+
final String absPath = slash > 2 ? path.substring(slash) : "/"; //$NON-NLS-1$
48+
return new URI(FILE_SCHEME, authority, absPath, null);
49+
}
50+
return new URI(FILE_SCHEME, "", path, null); //$NON-NLS-1$
51+
} catch (URISyntaxException ex) {
52+
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, ex.getMessage(), ex));
53+
return file.getAbsoluteFile().toURI();
54+
}
55+
}
56+
57+
}

0 commit comments

Comments
 (0)