diff --git a/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestLanguageServers.java b/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestLanguageServers.java index 4055efb90b..b07d2d1158 100644 --- a/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestLanguageServers.java +++ b/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestLanguageServers.java @@ -46,257 +46,262 @@ @ExtendWith(AllCleanRule.class) public class TestLanguageServers { - private IProject project; + private IProject project; - @BeforeEach - public void setUpProject() throws Exception { - this.project = ResourcesPlugin.getWorkspace().getRoot().getProject(getClass().getName() + System.nanoTime()); - project.create(null); - project.open(null); - IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - for (IViewReference ref : activePage.getViewReferences()) { - activePage.hideView(ref); - } - } + @BeforeEach + public void setUpProject() throws Exception { + this.project = ResourcesPlugin.getWorkspace().getRoot().getProject(getClass().getName() + System.nanoTime()); + project.create(null); + project.open(null); + IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + for (IViewReference ref : activePage.getViewReferences()) { + activePage.hideView(ref); + } + } - @Test - public void testCSSFile() throws Exception { - final IFile file = project.getFile("blah.css"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testCSSFile() throws Exception { + final IFile file = project.getFile("blah.css"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testHTMLFile() throws Exception { - final IFile file = project.getFile("blah.html"); - file.create("FAIL".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("<"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testHTMLFile() throws Exception { + final IFile file = project.getFile("blah.html"); + file.create("FAIL".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("<"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testYAMLFile() throws Exception { - final IFile file = project.getFile("blah.yaml"); - file.create("FAIL".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("hello: '"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testYAMLFile() throws Exception { + final IFile file = project.getFile("blah.yaml"); + file.create("FAIL".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("hello: '"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testJSONFile() throws Exception { - final IFile file = project.getFile("blah.json"); - file.create("FAIL".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("ERROR"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testJSONFile() throws Exception { + final IFile file = project.getFile("blah.json"); + file.create("FAIL".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("ERROR"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testJSFile() throws Exception { - final IFile file = project.getFile("blah.js"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - DisplayHelper.sleep(2000); // Give time for LS to initialize enough before making edit and sending a - // didChange - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("a<"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testJSFile() throws Exception { + final IFile file = project.getFile("blah.js"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + DisplayHelper.sleep(2000); // Give time for LS to initialize enough before making edit and sending a + // didChange + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("a<"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testTSFile() throws Exception { - final IFile file = project.getFile("blah.ts"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 15000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testTSFile() throws Exception { + final IFile file = project.getFile("blah.ts"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 15000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testJSXFile() throws Exception { - final IFile file = project.getFile("blah.jsx"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("a<"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testJSXFile() throws Exception { + final IFile jsconfig = project.getFile("jsconfig.json"); + jsconfig.create("{\"compilerOptions\":{\"jsx\":\"react\"}}".getBytes(), true, false, null); + final IFile file = project.getFile("blah.jsx"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("a<"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testTSXFile() throws Exception { - final IFile file = project.getFile("blah.tsx"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); + @Test + public void testTSXFile() throws Exception { + final IFile jsconfig = project.getFile("jsconfig.json"); + jsconfig.create("{\"compilerOptions\":{\"jsx\":\"react\"}}".getBytes(), true, false, null); + final IFile file = project.getFile("blah.tsx"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 15000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 15000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("const x = <>;export default x;"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 15000, () -> { - try { - IMarker[] markers = file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO); - for (IMarker m : markers) { - if (((String) m.getAttribute(IMarker.MESSAGE)).contains("React")) { - return true; - } - } - return false; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not cleared"); - } + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("const x = <>;export default x;"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 15000, () -> { + try { + IMarker[] markers = file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO); + for (IMarker m : markers) { + if (((String) m.getAttribute(IMarker.MESSAGE)).contains("React")) { + return true; + } + } + return false; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not cleared"); + } - @Test - public void testResourcesPathIsntTooLong() throws Exception { - // NOTE: this test does only work with jar file; when testing - // from IDE, the too long folder isn't excluded so test fail + @Test + public void testResourcesPathIsntTooLong() throws Exception { + // NOTE: this test does only work with jar file; when testing + // from IDE, the too long folder isn't excluded so test fail - final int MAX_ALLOWED_RELATIVE_PATH = 140; // that leaves 120 characters for the path to the bundle -//C:/Users/Jean-Jacques Saint-Romain/developpement/eclipse/plugins/org.eclipse.wildwebdeveloper_1.2.3.20201212_1605/ - String location = Platform.getBundle("org.eclipse.wildwebdeveloper").getLocation(); + final int MAX_ALLOWED_RELATIVE_PATH = 140; // that leaves 120 characters for the path to the bundle + // C:/Users/Jean-Jacques + // Saint-Romain/developpement/eclipse/plugins/org.eclipse.wildwebdeveloper_1.2.3.20201212_1605/ + String location = Platform.getBundle("org.eclipse.wildwebdeveloper").getLocation(); - if (location.startsWith("initial@")) { - location = location.substring("initial@".length()); - } - if (location.startsWith("reference:")) { - location = location.substring("reference:".length()); - } - if (location.startsWith("file:")) { - location = location.substring("file:".length()); - } - System.out.println("Location (" + location.length() + "): " + location); - StringBuilder maxLocation = new StringBuilder(); + if (location.startsWith("initial@")) { + location = location.substring("initial@".length()); + } + if (location.startsWith("reference:")) { + location = location.substring("reference:".length()); + } + if (location.startsWith("file:")) { + location = location.substring("file:".length()); + } + System.out.println("Location (" + location.length() + "): " + location); + StringBuilder maxLocation = new StringBuilder(); - // This reflects the difference between executing the test from IDE and from a - // command line - File file = new File(location).isAbsolute() ? new File(location) - : new File(new File(Platform.getInstallLocation().getURL().toURI()), location); - assertTrue(file.isDirectory()); - Map tooLongPaths = new TreeMap<>(); - Path pluginPath = file.toPath(); - Files.walkFileTree(pluginPath, new SimpleFileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - String relativePathInsideBundle = pluginPath.relativize(dir).toString(); - if (relativePathInsideBundle.startsWith("target")) { - return FileVisitResult.SKIP_SUBTREE; - } - if (maxLocation.length() < relativePathInsideBundle.length()) { - maxLocation.setLength(0); - maxLocation.append(relativePathInsideBundle); - } - if (relativePathInsideBundle.length() > MAX_ALLOWED_RELATIVE_PATH) { - tooLongPaths.put(relativePathInsideBundle, relativePathInsideBundle.length()); - return FileVisitResult.SKIP_SUBTREE; - } - return FileVisitResult.CONTINUE; - } + // This reflects the difference between executing the test from IDE and from a + // command line + File file = new File(location).isAbsolute() ? new File(location) + : new File(new File(Platform.getInstallLocation().getURL().toURI()), location); + assertTrue(file.isDirectory()); + Map tooLongPaths = new TreeMap<>(); + Path pluginPath = file.toPath(); + Files.walkFileTree(pluginPath, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + String relativePathInsideBundle = pluginPath.relativize(dir).toString(); + if (relativePathInsideBundle.startsWith("target")) { + return FileVisitResult.SKIP_SUBTREE; + } + if (maxLocation.length() < relativePathInsideBundle.length()) { + maxLocation.setLength(0); + maxLocation.append(relativePathInsideBundle); + } + if (relativePathInsideBundle.length() > MAX_ALLOWED_RELATIVE_PATH) { + tooLongPaths.put(relativePathInsideBundle, relativePathInsideBundle.length()); + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - String relativePathInsideBundle = pluginPath.relativize(file).toString(); - if (maxLocation.length() < relativePathInsideBundle.length()) { - maxLocation.setLength(0); - maxLocation.append(relativePathInsideBundle); - } - if (relativePathInsideBundle.length() > MAX_ALLOWED_RELATIVE_PATH) { - tooLongPaths.put(relativePathInsideBundle, relativePathInsideBundle.length()); - } - return FileVisitResult.CONTINUE; - } - }); - System.out.println("Max Location found (" + maxLocation.length() + "): " + maxLocation.toString()); - assertEquals(Collections.emptyMap(), tooLongPaths); - } + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String relativePathInsideBundle = pluginPath.relativize(file).toString(); + if (maxLocation.length() < relativePathInsideBundle.length()) { + maxLocation.setLength(0); + maxLocation.append(relativePathInsideBundle); + } + if (relativePathInsideBundle.length() > MAX_ALLOWED_RELATIVE_PATH) { + tooLongPaths.put(relativePathInsideBundle, relativePathInsideBundle.length()); + } + return FileVisitResult.CONTINUE; + } + }); + System.out.println("Max Location found (" + maxLocation.length() + "): " + maxLocation.toString()); + assertEquals(Collections.emptyMap(), tooLongPaths); + } - @Test - public void testSCSSFile() throws Exception { - final IFile file = project.getFile("blah.scss"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testSCSSFile() throws Exception { + final IFile file = project.getFile("blah.scss"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } - @Test - public void testLESSFile() throws Exception { - final IFile file = project.getFile("blah.less"); - file.create("ERROR".getBytes(), true, false, null); - ITextEditor editor = (ITextEditor) IDE - .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); - editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); - assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { - try { - return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; - } catch (CoreException e) { - return false; - } - }), "Diagnostic not published"); - } + @Test + public void testLESSFile() throws Exception { + final IFile file = project.getFile("blah.less"); + file.create("ERROR".getBytes(), true, false, null); + ITextEditor editor = (ITextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("FAIL"); + assertTrue(DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 5000, () -> { + try { + return file.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO).length != 0; + } catch (CoreException e) { + return false; + } + }), "Diagnostic not published"); + } } diff --git a/org.eclipse.wildwebdeveloper/package.json b/org.eclipse.wildwebdeveloper/package.json index 89605ae93f..d247d1f670 100644 --- a/org.eclipse.wildwebdeveloper/package.json +++ b/org.eclipse.wildwebdeveloper/package.json @@ -4,15 +4,15 @@ "astro-vscode" : "2.15.4", "firefox-debugadapter": "2.15.0", "typescript": "5.9.2", - "typescript-language-server": "4.3.4", + "typescript-language-server": "5.0.0", "typescript-lit-html-plugin": "0.9.0", "typescript-plugin-css-modules": "5.2.0", "yaml-language-server": "1.18.0", "vscode-css-languageservice": "6.3.7", "vscode-html-languageservice": "5.5.1", "vscode-json-languageservice": "5.6.1", - "@vue/language-server" : "2.2.10", - "@vue/typescript-plugin" : "2.2.10", + "@vue/language-server" : "3.0.7", + "@vue/typescript-plugin" : "3.0.7", "fsevents" : "2.3.3", "vscode-css-languageserver": "file:target/vscode-css-languageserver-1.0.0.tgz", "vscode-html-languageserver": "file:target/vscode-html-languageserver-1.0.0.tgz", diff --git a/org.eclipse.wildwebdeveloper/plugin.xml b/org.eclipse.wildwebdeveloper/plugin.xml index 7af4efa824..6d4a598354 100644 --- a/org.eclipse.wildwebdeveloper/plugin.xml +++ b/org.eclipse.wildwebdeveloper/plugin.xml @@ -377,6 +377,7 @@ @@ -568,7 +569,6 @@ clientImpl="org.eclipse.wildwebdeveloper.vue.VueClientImpl" serverInterface="org.eclipse.wildwebdeveloper.vue.VueLanguageServerAPI" id="org.eclipse.wildwebdeveloper.vue" - singleton="true" label="VUE Language Server"/> diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServer.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServer.java index 95c372b461..739dfffe3e 100644 --- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServer.java +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServer.java @@ -77,7 +77,7 @@ public Object getInitializationOptions(URI rootUri) { // plugins.add(new TypeScriptPlugin("@angular/language-service")); plugins.add(new TypeScriptPlugin("typescript-plugin-css-modules")); plugins.add(new TypeScriptPlugin("typescript-lit-html-plugin")); - plugins.add(new TypeScriptPlugin("@vue/typescript-plugin", new String[] {"vue"})); + plugins.add(new TypeScriptPlugin("@vue/typescript-plugin", "@vue/language-server", new String[] {"vue"})); options.put("plugins", plugins.stream().map(TypeScriptPlugin::toMap).toArray()); // If the tsserver path is not explicitly specified, tsserver will use the local diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServerAPI.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServerAPI.java new file mode 100644 index 0000000000..19f66a0fe5 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/JSTSLanguageServerAPI.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) Dawid Pakuła and others. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dawid Pakuła - initial implementation + *******************************************************************************/ +package org.eclipse.wildwebdeveloper.jsts; + +import org.eclipse.lsp4j.services.LanguageServer; + +public interface JSTSLanguageServerAPI extends LanguageServer { + + public final static String TS_REQUEST_COMMAND = "typescript.tsserverRequest"; +} diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/TypeScriptPlugin.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/TypeScriptPlugin.java index 0da4f830af..3161b07b81 100644 --- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/TypeScriptPlugin.java +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/TypeScriptPlugin.java @@ -30,8 +30,12 @@ public TypeScriptPlugin(String name) throws IOException { } public TypeScriptPlugin(String name, String[] languages) throws IOException { + this(name, name, null); + } + + public TypeScriptPlugin(String name, String locationName, String[] languages) throws IOException { pluginName = name; - URL fileURL = FileLocator.toFileURL(getClass().getResource("/node_modules/" + name)); + URL fileURL = FileLocator.toFileURL(getClass().getResource("/node_modules/" + locationName)); pluginProbeLocation = new File(fileURL.getPath()).getAbsolutePath(); pluginLanguages = languages; } diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/request/ExecuteInfo.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/request/ExecuteInfo.java new file mode 100644 index 0000000000..6b443828ca --- /dev/null +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/jsts/request/ExecuteInfo.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2025 Dawid Pakuła and others. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dawid Pakuła - initial implementation + *******************************************************************************/ +package org.eclipse.wildwebdeveloper.jsts.request; + +public class ExecuteInfo { + + private int executionTarget = 0; + + private boolean expectsResult = true; + + private boolean isAsync = false; + + private boolean lowPriority = true; + + public int getExecutionTarget() { + return executionTarget; + } + + public void setExecutionTarget(int executionTarget) { + this.executionTarget = executionTarget; + } + + public boolean isExpectsResult() { + return expectsResult; + } + + public void setExpectsResult(boolean expectsResult) { + this.expectsResult = expectsResult; + } + + public boolean isAsync() { + return isAsync; + } + + public void setAsync(boolean isAsync) { + this.isAsync = isAsync; + } + + public boolean isLowPriority() { + return lowPriority; + } + + public void setLowPriority(boolean lowPriority) { + this.lowPriority = lowPriority; + } +} diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueClientImpl.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueClientImpl.java index cb3aaf7910..8c57973182 100644 --- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueClientImpl.java +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueClientImpl.java @@ -12,13 +12,24 @@ *******************************************************************************/ package org.eclipse.wildwebdeveloper.vue; +import static org.eclipse.wildwebdeveloper.css.ui.preferences.CSSPreferenceServerConstants.isMatchCssSection; +import static org.eclipse.wildwebdeveloper.html.ui.preferences.HTMLPreferenceServerConstants.isMatchHtmlSection; + +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; -import org.eclipse.lsp4e.LanguageClientImpl; +import org.eclipse.lsp4e.client.DefaultLanguageClient; +import org.eclipse.lsp4j.ConfigurationItem; +import org.eclipse.lsp4j.ConfigurationParams; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.MessageType; +import org.eclipse.wildwebdeveloper.css.ui.preferences.CSSPreferenceServerConstants; +import org.eclipse.wildwebdeveloper.html.ui.preferences.HTMLPreferenceServerConstants; +import org.eclipse.wildwebdeveloper.ui.preferences.Settings; -public class VueClientImpl extends LanguageClientImpl implements VueLanguageServerExtention { +public class VueClientImpl extends DefaultLanguageClient implements VueLanguageServerExtention { @Override public void projectLoadingFinish(Object object) { @@ -26,15 +37,57 @@ public void projectLoadingFinish(Object object) { // or maybe even after projectLanguageService "enabled" call logMessage(new MessageParams(MessageType.Info, "Vue project loading finished")); } - + @Override public void projectLoadingStart(Object object) { logMessage(new MessageParams(MessageType.Info, "Vue project loading started")); } - + @Override - public void projectLanguageService(Map data) { - logMessage(new MessageParams(MessageType.Info, "Language Service is " + (((Boolean)data.get("languageServiceEnabled")).booleanValue()?"":"not yet ") + "enabled for project " + data.get("projectName"))); + public void projectLanguageService(Map data) { + logMessage(new MessageParams(MessageType.Info, + "Language Service is " + + (((Boolean) data.get("languageServiceEnabled")).booleanValue() ? "" : "not yet ") + + "enabled for project " + data.get("projectName"))); + } + + @Override + public void tsserverRequest(Object[] params) { + logMessage(new MessageParams(MessageType.Info, "Forward TS message " + params[0])); } + @Override + public CompletableFuture> configuration(ConfigurationParams params) { + return CompletableFuture.supplyAsync(() -> { + // The HTML language server asks for a given uri, the settings for 'css', + // 'javascript', 'html' + // See + // https://github.com/microsoft/vscode/blob/7bd27b4287b49e61a1cb49e18f370260144c8685/extensions/html-language-features/server/src/htmlServer.ts#L123 + List settings = new ArrayList<>(); + for (ConfigurationItem item : params.getItems()) { + String section = item.getSection(); + if (isMatchHtmlSection(section)) { + // 'html' section, returns the html settings + Settings htmlSettings = HTMLPreferenceServerConstants.getGlobalSettings(); + settings.add(htmlSettings.findSettings(section.split("[.]"))); + } else if (isMatchCssSection(section)) { + // 'css' section, returns the css settings + Settings cssSettings = CSSPreferenceServerConstants.getGlobalSettings(); + settings.add(cssSettings.findSettings(section.split("[.]"))); + } else if (section.equals("vue.suggest.defineAssignment")) { + settings.add(true); + } else if (section.equals("vue.suggest.propNameCasing")) { + settings.add("preferKebabCase"); + } else if (section.equals("vue.suggest.componentNameCasing")) { + settings.add("preferPascalCase"); + } else { + // TODO match javascript section once those preferences will be + // implemented. + settings.add(null); + } + } + return settings; + }); + } + } diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java index 308bc545fc..b20a09fb39 100644 --- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java @@ -16,34 +16,41 @@ import java.io.IOException; import java.net.URI; import java.net.URL; -import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.ILog; +import org.eclipse.lsp4e.LSPEclipseUtils; +import org.eclipse.lsp4e.LanguageServers; import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider; +import org.eclipse.lsp4j.ExecuteCommandParams; +import org.eclipse.lsp4j.jsonrpc.messages.Message; +import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage; +import org.eclipse.lsp4j.services.LanguageServer; import org.eclipse.wildwebdeveloper.embedder.node.NodeJSManager; +import org.eclipse.wildwebdeveloper.jsts.JSTSLanguageServerAPI; +import org.eclipse.wildwebdeveloper.jsts.request.ExecuteInfo; public class VueLanguageServer extends ProcessStreamConnectionProvider { - private static String tsserverPath = null; private static String vuePath = null; + private static String TS_REQUEST = "tsserver/request"; public VueLanguageServer() { List commands = new ArrayList<>(); commands.add(NodeJSManager.getNodeJsLocation().getAbsolutePath()); try { - if (vuePath == null || tsserverPath == null) { + if (vuePath == null) { resolvePaths(); } commands.add(vuePath); commands.add("--stdio"); setCommands(commands); - setWorkingDirectory(System.getProperty("user.dir")); + //setWorkingDirectory(System.getProperty("user.dir")); } catch (IOException e) { ILog.get().error(e.getMessage(), e); } @@ -53,44 +60,56 @@ private void resolvePaths() throws IOException { URL url = FileLocator .toFileURL(getClass().getResource("/node_modules/@vue/language-server/bin/vue-language-server.js")); vuePath = new File(url.getPath()).getAbsolutePath(); - - url = FileLocator.toFileURL(getClass().getResource("/node_modules/typescript/lib")); - tsserverPath = new File(url.getPath()).getAbsolutePath(); + } + @Override protected ProcessBuilder createProcessBuilder() { ProcessBuilder builder = super.createProcessBuilder(); builder.environment().put("VUE_NONPOLLING_WATCHER", Boolean.toString(true)); + builder.environment().put("NODE_ENV", "production"); return builder; } @Override - public Object getInitializationOptions(URI rootUri) { - Map options = new HashMap<>(); - setWorkingDirectory(Paths.get(rootUri).toString()); - - options.put("typescript", Collections.singletonMap("tsdk", tsserverPath)); - options.put("diagnosticModel", 0); - options.put("additionalExtensions", new String[] {}); - - Map legend = new HashMap<>(); - legend.put("tokenTypes", new String[] {"component"} ); - legend.put("tokenModifiers", new String[] {} ); - options.put("semanticTokensLegend", legend); - - Map vue = new HashMap<>(); - vue.put("hybridMode", false); - - options.put("vue", vue); - - return options; + public String toString() { + return "VUE Language Server: " + super.toString(); } @Override - public String toString() { - return "VUE Language Server: " + super.toString(); + public void handleMessage(Message message, LanguageServer languageServer, URI rootURI) { + if (message instanceof NotificationMessage) { + NotificationMessage msg = (NotificationMessage) message; + if (msg.getMethod().equals(TS_REQUEST)) { + forwardTS((Object[]) msg.getParams(), (VueLanguageServerAPI) languageServer, rootURI); + } + } + super.handleMessage(message, languageServer, rootURI); + } + + @SuppressWarnings("restriction") + private void forwardTS(Object[] params, VueLanguageServerAPI languageServer, URI rootURI) { + Object requestId = params[0]; + String commandId = (String) params[1]; + Object args = params.length > 2 ? params[2] : null; + + LanguageServers.forProject(LSPEclipseUtils.findResourceFor(rootURI).getProject()) + .collectAll((w, ls) -> CompletableFuture.completedFuture(ls)).thenAccept((lss) -> { + lss.stream().filter(JSTSLanguageServerAPI.class::isInstance).map(JSTSLanguageServerAPI.class::cast) + .findAny().ifPresent(jsts -> { + jsts.getWorkspaceService() + .executeCommand(new ExecuteCommandParams(JSTSLanguageServerAPI.TS_REQUEST_COMMAND, + Arrays.asList(new Object[] { commandId, args, new ExecuteInfo() }))) + .whenComplete((result, e) -> { + Object body = null; + if (result instanceof Map) { + body = ((Map)result).get("body"); + } + languageServer.tsserverResponse(new Object[] {requestId, body}); + }); + }); + }); } - } diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerAPI.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerAPI.java index 1a9f3c3324..e972df22fa 100644 --- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerAPI.java +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerAPI.java @@ -15,6 +15,7 @@ import java.util.concurrent.CompletableFuture; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; import org.eclipse.lsp4j.services.LanguageServer; import org.eclipse.wildwebdeveloper.vue.autoinsert.AutoInsertParams; @@ -38,5 +39,9 @@ public interface VueLanguageServerAPI extends LanguageServer { @JsonRequest("volar/client/autoInsert") CompletableFuture> autoInsert(AutoInsertParams params); + @JsonNotification("tsserver/response") + void tsserverResponse(Object any); + + } diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java index 6994da1036..117796a17a 100644 --- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java @@ -26,4 +26,8 @@ public interface VueLanguageServerExtention { @JsonNotification(value = "vue/projectLanguageService") public void projectLanguageService(Map data); + + + @JsonNotification(value = "tsserver/request") + public void tsserverRequest(Object[] params); }