From b3993d8615bf38d18db545a8c127b978a64a68da Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 9 Dec 2022 10:30:36 -0500 Subject: [PATCH] Use template to determine jakarta namespace in snippets - Use `${jakarta}` to point to either `javax` or `jakarta`, depending on which is available, and prefering `jakarta` - Rename `jaxrc` to `rest_class` and `jaxrm` to `rest_get` Closes #320, closes #229 Signed-off-by: David Thompson --- .../ls/java/JavaFileTextDocumentService.java | 3 +- .../java/JavaTextDocumentSnippetRegistry.java | 19 ++++- ...MicroProfileJavaSnippetRegistryLoader.java | 2 +- .../eclipse/lsp4mp/snippets/jakarta-rest.json | 47 ++++++++++++ .../org/eclipse/lsp4mp/snippets/jax-rs.json | 41 ---------- .../eclipse/lsp4mp/snippets/mp-health.json | 4 +- .../lsp4mp/snippets/mp-restclient.json | 8 +- .../JavaTextDocumentSnippetRegistryTest.java | 75 +++++++++++++++---- 8 files changed, 133 insertions(+), 66 deletions(-) create mode 100644 microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jakarta-rest.json delete mode 100644 microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jax-rs.json diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaFileTextDocumentService.java b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaFileTextDocumentService.java index 985a9b96d..15b883f3d 100644 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaFileTextDocumentService.java +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaFileTextDocumentService.java @@ -162,7 +162,8 @@ public CompletableFuture, CompletionList>> completio return ((SnippetContextForJava) context).isMatch(projectInfo); } return true; - }).forEach(item -> { + }, projectInfo) // + .forEach(item -> { list1.getItems().add(item); }); diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistry.java b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistry.java index 9d7dc156c..d77c5f13b 100644 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistry.java +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistry.java @@ -20,6 +20,7 @@ import java.util.function.BiPredicate; import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4mp.commons.ProjectLabelInfoEntry; import org.eclipse.lsp4mp.commons.utils.StringUtils; import org.eclipse.lsp4mp.ls.commons.BadLocationException; import org.eclipse.lsp4mp.ls.commons.snippets.ISnippetContext; @@ -41,6 +42,15 @@ public class JavaTextDocumentSnippetRegistry extends TextDocumentSnippetRegistry { private static final String PACKAGENAME_KEY = "packagename"; + private static final String EE_NAMESPACE_KEY = "ee-namespace"; + private static final String JAVAX_VALUE = "javax"; + private static final String JAKARTA_VALUE = "jakarta"; + + /** + * The type whose presence indicates that the jakarta namespace should be used. + */ + private static final String JAKARTA_FLAG_TYPE = "jakarta.ws.rs.GET"; + private List types; public JavaTextDocumentSnippetRegistry() { @@ -69,6 +79,7 @@ private synchronized List collectTypes() { return types; } List types = new ArrayList<>(); + types.add(JAKARTA_FLAG_TYPE); for (Snippet snippet : getSnippets()) { if (snippet.getContext() != null && snippet.getContext() instanceof SnippetContextForJava) { List snippetTypes = ((SnippetContextForJava) snippet.getContext()).getTypes(); @@ -92,7 +103,7 @@ public void registerSnippet(Snippet snippet) { /** * Preprocess Snippet body for managing package name. - * + * * @param snippet */ private void preprocessSnippetBody(Snippet snippet) { @@ -128,7 +139,7 @@ private void preprocessSnippetBody(Snippet snippet) { public List getCompletionItems(JavaTextDocument document, int completionOffset, boolean canSupportMarkdown, boolean snippetsSupported, - BiPredicate, Map> contextFilter) { + BiPredicate, Map> contextFilter, ProjectLabelInfoEntry projectInfo) { Map model = new HashMap<>(); String packageStatement = ""; String packageName = document.getPackageName(); @@ -154,7 +165,11 @@ public List getCompletionItems(JavaTextDocument document, int co } } model.put(PACKAGENAME_KEY, packageStatement); + model.put(EE_NAMESPACE_KEY, projectInfo.getLabels().contains(JavaTextDocumentSnippetRegistry.JAKARTA_FLAG_TYPE) + ? JavaTextDocumentSnippetRegistry.JAKARTA_VALUE + : JavaTextDocumentSnippetRegistry.JAVAX_VALUE); return super.getCompletionItems(document, completionOffset, canSupportMarkdown, snippetsSupported, contextFilter, model); } + } diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/snippets/MicroProfileJavaSnippetRegistryLoader.java b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/snippets/MicroProfileJavaSnippetRegistryLoader.java index 8a6b9e69c..cdd493805 100644 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/snippets/MicroProfileJavaSnippetRegistryLoader.java +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/snippets/MicroProfileJavaSnippetRegistryLoader.java @@ -38,7 +38,7 @@ public void load(SnippetRegistry registry) throws IOException { SnippetContextForJava.TYPE_ADAPTER); registry.registerSnippets(MicroProfileJavaSnippetRegistryLoader.class.getResourceAsStream("mp-health.json"), SnippetContextForJava.TYPE_ADAPTER); - registry.registerSnippets(MicroProfileJavaSnippetRegistryLoader.class.getResourceAsStream("jax-rs.json"), + registry.registerSnippets(MicroProfileJavaSnippetRegistryLoader.class.getResourceAsStream("jakarta-rest.json"), SnippetContextForJava.TYPE_ADAPTER); } diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jakarta-rest.json b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jakarta-rest.json new file mode 100644 index 000000000..05c9d688b --- /dev/null +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jakarta-rest.json @@ -0,0 +1,47 @@ +{ + "New REST resource class": { + "prefix": "rest_class", + "body": [ + "package ${1:packagename};", + "", + "import ${ee-namespace}.ws.rs.GET;", + "import ${ee-namespace}.ws.rs.Path;", + "import ${ee-namespace}.ws.rs.Produces;", + "import ${ee-namespace}.ws.rs.core.MediaType;", + "", + "@Path(\"${2:/path}\")", + "public class ${TM_FILENAME_BASE} {", + "", + "\t@GET", + "\t@Produces(MediaType.TEXT_PLAIN)", + "\tpublic String ${3:methodname}() {", + "\t\treturn \"hello\";", + "\t}", + "}" + ], + "description": "REST resource class", + "context": { + "type": [ + "javax.ws.rs.GET", + "jakarta.ws.rs.GET" + ] + } + }, + "New REST resource GET method": { + "prefix": "rest_get", + "body": [ + "@GET", + "@Produces(MediaType.TEXT_PLAIN)", + "public String ${1:methodname}() {", + "\treturn \"hello\";", + "}" + ], + "description": "REST resource GET method", + "context": { + "type": [ + "javax.ws.rs.GET", + "jakarta.ws.rs.GET" + ] + } + } +} diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jax-rs.json b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jax-rs.json deleted file mode 100644 index 452c0338d..000000000 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/jax-rs.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "JAX-RS - new resource class": { - "prefix": "jaxrc", - "body": [ - "package ${1:packagename};", - "", - "import javax.ws.rs.GET;", - "import javax.ws.rs.Path;", - "import javax.ws.rs.Produces;", - "import javax.ws.rs.core.MediaType;", - "", - "@Path(\"${2:/path}\")", - "public class ${TM_FILENAME_BASE} {", - "", - "\t@GET", - "\t@Produces(MediaType.TEXT_PLAIN)", - "\tpublic String ${3:methodname}() {", - "\t\treturn \"hello\";", - "\t}", - "}" - ], - "description": "JAX-RS REST resource class", - "context": { - "type": "javax.ws.rs.GET" - } - }, - "JAX-RS - new resource method": { - "prefix": "jaxrm", - "body": [ - "@GET", - "@Produces(MediaType.TEXT_PLAIN)", - "public String ${1:methodname}() {", - "\treturn \"hello\";", - "}" - ], - "description": "JAX-RS REST resource method", - "context": { - "type": "javax.ws.rs.GET" - } - } -} diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-health.json b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-health.json index b468ceabf..6386ce006 100644 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-health.json +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-health.json @@ -8,7 +8,7 @@ "import org.eclipse.microprofile.health.HealthCheckResponse;", "import org.eclipse.microprofile.health.Readiness;", "", - "import javax.enterprise.context.ApplicationScoped;", + "import ${ee-namespace}.enterprise.context.ApplicationScoped;", "", "@Readiness", "@ApplicationScoped", @@ -34,7 +34,7 @@ "import org.eclipse.microprofile.health.HealthCheckResponse;", "import org.eclipse.microprofile.health.Liveness;", "", - "import javax.enterprise.context.ApplicationScoped;", + "import ${ee-namespace}.enterprise.context.ApplicationScoped;", "", "@Liveness", "@ApplicationScoped", diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-restclient.json b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-restclient.json index 6ea02ea03..0a68dcd4b 100644 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-restclient.json +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/resources/org/eclipse/lsp4mp/snippets/mp-restclient.json @@ -6,10 +6,10 @@ "", "import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;", "", - "import javax.enterprise.context.ApplicationScoped;", - "import javax.ws.rs.GET;", - "import javax.ws.rs.Path;", - "import javax.ws.rs.PathParam;", + "import ${ee-namespace}.enterprise.context.ApplicationScoped;", + "import ${ee-namespace}.ws.rs.GET;", + "import ${ee-namespace}.ws.rs.Path;", + "import ${ee-namespace}.ws.rs.PathParam;", "", "@RegisterRestClient", "@ApplicationScoped", diff --git a/microprofile.ls/org.eclipse.lsp4mp.ls/src/test/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistryTest.java b/microprofile.ls/org.eclipse.lsp4mp.ls/src/test/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistryTest.java index 3e8ddac74..67f161b73 100644 --- a/microprofile.ls/org.eclipse.lsp4mp.ls/src/test/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistryTest.java +++ b/microprofile.ls/org.eclipse.lsp4mp.ls/src/test/java/org/eclipse/lsp4mp/ls/java/JavaTextDocumentSnippetRegistryTest.java @@ -5,7 +5,7 @@ * http://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 -* +* * Contributors: * Red Hat Inc. - initial API and implementation *******************************************************************************/ @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -33,7 +34,7 @@ /** * Test for Java snippet registry. - * + * * @author Angelo ZERR * */ @@ -41,27 +42,41 @@ public class JavaTextDocumentSnippetRegistryTest { private static JavaTextDocumentSnippetRegistry registry = new JavaTextDocumentSnippetRegistry(); + private static final ProjectLabelInfoEntry JAVAX_PROJECT_INFO = new ProjectLabelInfoEntry("", "", Collections.emptyList()); + private static final ProjectLabelInfoEntry JAKARTA_PROJECT_INFO = new ProjectLabelInfoEntry("", "", Collections.singletonList("jakarta.ws.rs.GET")); + @Test public void haveJavaSnippets() { assertFalse("Tests has MicroProfile Java snippets", registry.getSnippets().isEmpty()); } @Test - public void jaxrsSnippets() { - Optional jaxrsSnippet = findByPrefix("jaxrc", registry); - assertTrue("Tests has jaxrc Java snippets", jaxrsSnippet.isPresent()); + public void restSnippets() { + Optional restClassSnippet = findByPrefix("rest_class", registry); + assertTrue("Tests has rest_class Java snippet", restClassSnippet.isPresent()); + + Optional restGetSnippet = findByPrefix("rest_get", registry); + assertTrue("Tests has rest_get Java snippet", restGetSnippet.isPresent()); - ISnippetContext context = jaxrsSnippet.get().getContext(); - assertNotNull("jaxrc snippet has context", context); - assertTrue("jaxrc snippet context is Java context", context instanceof SnippetContextForJava); + ISnippetContext context = restClassSnippet.get().getContext(); + assertNotNull("rest_class snippet has context", context); + assertTrue("rest_class snippet context is Java context", context instanceof SnippetContextForJava); ProjectLabelInfoEntry projectInfo = new ProjectLabelInfoEntry("", "", new ArrayList<>()); boolean match = ((SnippetContextForJava) context).isMatch(projectInfo); - assertFalse("Project has no javax.ws.rs.GET type", match); + assertFalse("Project has no javax.ws.rs.GET or jakarta.ws.rs.GET type", match); ProjectLabelInfoEntry projectInfo2 = new ProjectLabelInfoEntry("", "", Arrays.asList("javax.ws.rs.GET")); boolean match2 = ((SnippetContextForJava) context).isMatch(projectInfo2); assertTrue("Project has javax.ws.rs.GET type", match2); + + ProjectLabelInfoEntry projectInfo3 = new ProjectLabelInfoEntry("", "", Arrays.asList("jakarta.ws.rs.GET")); + boolean match3 = ((SnippetContextForJava) context).isMatch(projectInfo3); + assertTrue("Project has jakarta.ws.rs.GET type", match3); + + ProjectLabelInfoEntry projectInfo4 = new ProjectLabelInfoEntry("", "", Arrays.asList("javax.ws.rs.GET", "jakarta.ws.rs.GET")); + boolean match4= ((SnippetContextForJava) context).isMatch(projectInfo4); + assertTrue("Project has javax.ws.rs.GET and jakarta.ws.rs.GET types", match4); } @Test @@ -172,13 +187,13 @@ public void mpRestClientSnippets() { } @Test - public void completionWithPackagename() { + public void completionWithPackagenameJavax() { // Create the snippet Snippet snippet = new Snippet(); snippet.setPrefixes(Arrays.asList("test")); snippet.setBody(new ArrayList<>(Arrays.asList("package ${packagename};", // - "import javax.ws.rs.GET;", // - "import javax.ws.rs.Path;"))); + "import ${ee-namespace}.ws.rs.GET;", // + "import ${ee-namespace}.ws.rs.Path;"))); JavaTextDocumentSnippetRegistry registry = new JavaTextDocumentSnippetRegistry(false); registry.registerSnippet(snippet); @@ -187,7 +202,7 @@ public void completionWithPackagename() { .createDocument(new TextDocumentItem("test.java", "java", 0, "abcd")); document.setPackageName("com.foo"); - List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true); + List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true, JAVAX_PROJECT_INFO); assertEquals("Completion size", 1, items.size()); CompletionItem item = items.get(0); assertNotNull("Completion text edit", item.getTextEdit()); @@ -200,6 +215,35 @@ public void completionWithPackagename() { , item.getTextEdit().getLeft().getNewText()); } + @Test + public void completionWithPackagenameJakarta() { + // Create the snippet + Snippet snippet = new Snippet(); + snippet.setPrefixes(Arrays.asList("test")); + snippet.setBody(new ArrayList<>(Arrays.asList("package ${packagename};", // + "import ${ee-namespace}.ws.rs.GET;", // + "import ${ee-namespace}.ws.rs.Path;"))); + JavaTextDocumentSnippetRegistry registry = new JavaTextDocumentSnippetRegistry(false); + registry.registerSnippet(snippet); + + // Create a Java text document with com.foo package. + JavaTextDocument document = new JavaTextDocuments(null, null) + .createDocument(new TextDocumentItem("test.java", "java", 0, "abcd")); + document.setPackageName("com.foo"); + + List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true, JAKARTA_PROJECT_INFO); + assertEquals("Completion size", 1, items.size()); + CompletionItem item = items.get(0); + assertNotNull("Completion text edit", item.getTextEdit()); + assertEquals("package com.foo;" + // + System.lineSeparator() + // + System.lineSeparator() + // + "import jakarta.ws.rs.GET;" + // + System.lineSeparator() + // + "import jakarta.ws.rs.Path;" // + , item.getTextEdit().getLeft().getNewText()); + } + @Test public void completionWithoutPackagename() { // Create the snippet @@ -216,7 +260,7 @@ public void completionWithoutPackagename() { .createDocument(new TextDocumentItem("test.java", "java", 0, "abcd")); document.setPackageName(null); - List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true); + List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true, JAVAX_PROJECT_INFO); assertEquals("Completion size", 1, items.size()); CompletionItem item = items.get(0); assertNotNull("Completion text edit", item.getTextEdit()); @@ -245,7 +289,7 @@ public void completionWithEmptyPackagename() { .createDocument(new TextDocumentItem("test.java", "java", 0, "abcd")); document.setPackageName(""); - List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true); + List items = registry.getCompletionItems(document, 0, true, true, (context, model) -> true, JAVAX_PROJECT_INFO); assertEquals("Completion size", 1, items.size()); CompletionItem item = items.get(0); assertNotNull("Completion text edit", item.getTextEdit()); @@ -258,4 +302,5 @@ public void completionWithEmptyPackagename() { private static Optional findByPrefix(String prefix, SnippetRegistry registry) { return registry.getSnippets().stream().filter(snippet -> snippet.getPrefixes().contains(prefix)).findFirst(); } + }