From d74bf3bc28b7c9b3beec85fa83c973b5b870638d Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 7 Mar 2018 11:52:01 -0800 Subject: [PATCH 01/30] Concourse: Add document symbol support for Groups --- .../ide/vscode/concourse/PipelineYmlSchema.java | 8 ++++++-- .../ide/vscode/concourse/ConcourseEditorTest.java | 11 ++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java index 29aa9e026..3fda51e44 100644 --- a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java +++ b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java @@ -401,8 +401,11 @@ public class PipelineYmlSchema implements YamlSchema { addProp(resourceType, "source", resourceSource); addProp(resourceType, "privileged", t_boolean); + YType t_group_name_def= f.yatomic("Group Name") + .parseWith(ValueParsers.NE_STRING); + AbstractType group = f.ybean("Group"); - addProp(group, "name", t_ne_string).isPrimary(true); + addProp(group, "name", t_group_name_def).isPrimary(true); addProp(group, "resources", f.yseq(t_resource_name)); addProp(group, "jobs", f.yseq(t_job_name)); @@ -414,7 +417,8 @@ public class PipelineYmlSchema implements YamlSchema { definitionTypes = ImmutableList.of( jobNameDef, resourceTypeNameDef, - t_resource_name_def + t_resource_name_def, + t_group_name_def ); initializeDefaultResourceTypes(); diff --git a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java index 0e30f3b89..b27444084 100644 --- a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java +++ b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java @@ -3458,15 +3458,20 @@ public class ConcourseEditorTest { "- name: bar-resource\n" + "jobs:\n" + "- name: do-some-stuff\n" + - "- name: do-more-stuff\n" + "- name: do-more-stuff\n" + + "groups:\n" + + "- name: group-one\n" + + "- name: group-two\n" ); - editor.assertDocumentSymbols( + editor.assertDocumentSymbols( "some-resource-type|ResourceType", "foo-resource|Resource", "bar-resource|Resource", "do-some-stuff|Job", - "do-more-stuff|Job" + "do-more-stuff|Job", + "group-one|Group", + "group-two|Group" ); } From d035c26a28415d3920d2c55b3e5cb4438444ac57 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 7 Mar 2018 11:58:21 -0800 Subject: [PATCH 02/30] Cleanup some debug logging --- .../vscode/commons/languageserver/util/SimpleLanguageServer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index d770b1800..ef68da4a4 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -236,7 +236,6 @@ public class SimpleLanguageServer implements Sts4LanguageServer, LanguageClientA if (ih!=null){ ih.accept(params); } - Log.info("IntializeResult = {}"); return CompletableFuture.completedFuture(result); } From 338d571cdd9af1d69819883b35eb05f521176458 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 7 Mar 2018 15:30:12 -0800 Subject: [PATCH 03/30] Define job to tag atom releases --- concourse/pipeline.yml | 38 ++++++++++++++++++++++++++- concourse/tasks/tag-atom-releases.sh | 19 ++++++++++++++ concourse/tasks/tag-atom-releases.yml | 14 ++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100755 concourse/tasks/tag-atom-releases.sh create mode 100644 concourse/tasks/tag-atom-releases.yml diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index 4ffcc7ddc..dbd35bb23 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -494,6 +494,41 @@ jobs: params: repository: out/repo rebase: true +- name: tag-atom-release + plan: + - aggregate: + - get: sts4 + - get: atom-bosh + passed: + - prepare-bosh-atom-rc + - get: atom-concourse + passed: + - prepare-concourse-atom-rc + - get: atom-spring-boot + passed: + - prepare-spring-boot-atom-rc + - get: atom-cf-manifest-yaml + passed: + - prepare-manifest-yaml-atom-rc + - task: tag-atom-releases + file: sts4/concourse/tasks/tag-atom-releases.yml + - aggregate: + - put: atom-bosh + params: + repository: out/atom-bosh + only_tag: true + - put: atom-concourse + params: + repository: out/atom-concourse + only_tag: true + - put: atom-spring-boot + params: + repository: out/atom-spring-boot + only_tag: true + - put: atom-cf-manifest-yaml + params: + repository: out/atom-cf-manifest-yaml + only_tag: true - name: build-concourse-rc plan: - aggregate: @@ -993,13 +1028,14 @@ groups: - build-bosh-atom-package - build-manifest-yaml-atom-package - build-spring-boot-atom-package -- name: atom-rc +- name: atom-release jobs: - prepare-bosh-atom-rc - prepare-concourse-atom-rc - prepare-manifest-yaml-atom-rc - prepare-spring-boot-atom-rc - promote-fatjars-to-rc + - tag-atom-release - name: setup jobs: - build-mvn-cache diff --git a/concourse/tasks/tag-atom-releases.sh b/concourse/tasks/tag-atom-releases.sh new file mode 100755 index 000000000..72ccc9fe4 --- /dev/null +++ b/concourse/tasks/tag-atom-releases.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e +workdir=$(pwd) +outdir=${workdir}/out + +git config --global user.email "kdevolder@pivotal.io" +git config --global user.name "Kris De Volder" + +for package in atom-* ; do + echo "Processing ${package}..." + + mkdir "${out}/${package}" + cd "${out}" + git clone "${workdir}/${package}/.git" + + cd ${package} + tag=v$(cat package.json | jq -r ".version") + git tag $tag +done \ No newline at end of file diff --git a/concourse/tasks/tag-atom-releases.yml b/concourse/tasks/tag-atom-releases.yml new file mode 100644 index 000000000..5bc3f295e --- /dev/null +++ b/concourse/tasks/tag-atom-releases.yml @@ -0,0 +1,14 @@ +platform: linux +image_resource: + type: docker-image + source: + repository: kdvolder/sts4-build-env +inputs: +- name: atom-bosh +- name: atom-concourse +- name: atom-spring-boot +- name: atom-cf-manifest-yaml +outputs: +- name: out +run: + path: sts4/concourse/tasks/tag-atom-releases.sh From 069323b7f011dd006f882128fcbc28e66cfb7dfe Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 7 Mar 2018 16:55:19 -0800 Subject: [PATCH 04/30] Fix some problems in tag-atom-releases task --- concourse/tasks/tag-atom-releases.sh | 6 ++++-- concourse/tasks/tag-atom-releases.yml | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/concourse/tasks/tag-atom-releases.sh b/concourse/tasks/tag-atom-releases.sh index 72ccc9fe4..cc6ffed87 100755 --- a/concourse/tasks/tag-atom-releases.sh +++ b/concourse/tasks/tag-atom-releases.sh @@ -1,7 +1,8 @@ #!/bin/bash -set -e +set -e +# set -x workdir=$(pwd) -outdir=${workdir}/out +out=${workdir}/out git config --global user.email "kdevolder@pivotal.io" git config --global user.name "Kris De Volder" @@ -15,5 +16,6 @@ for package in atom-* ; do cd ${package} tag=v$(cat package.json | jq -r ".version") + echo "Tag: ${tag}" git tag $tag done \ No newline at end of file diff --git a/concourse/tasks/tag-atom-releases.yml b/concourse/tasks/tag-atom-releases.yml index 5bc3f295e..022ab6e2f 100644 --- a/concourse/tasks/tag-atom-releases.yml +++ b/concourse/tasks/tag-atom-releases.yml @@ -4,6 +4,7 @@ image_resource: source: repository: kdvolder/sts4-build-env inputs: +- name: sts4 - name: atom-bosh - name: atom-concourse - name: atom-spring-boot From 57b83da757b8d1d9341957a96c1ef215644725f7 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Thu, 8 Mar 2018 09:54:10 +0100 Subject: [PATCH 05/30] change the way webflux code lenses for handler methods are displayed --- .../WebfluxHandlerCodeLensProvider.java | 9 +++- .../WebfluxHandlerInformation.java | 38 +++++++++---- .../WebfluxRouterSymbolProvider.java | 9 ++-- .../test/WebFluxCodeLensProviderTest.java | 8 +-- .../WebFluxMappingSymbolProviderTest.java | 53 +++++++++++++------ 5 files changed, 84 insertions(+), 33 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java index 556394572..14593c14f 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java @@ -71,7 +71,14 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider { CodeLens codeLens = new CodeLens(); codeLens.setRange(document.toRange(node.getName().getStartPosition(), node.getName().getLength())); - codeLens.setCommand(new Command(handlerInfo.getSymbol(), null)); + + String codeLensCommand = handlerInfo.getHttpMethod() != null ? handlerInfo.getHttpMethod() + " " : ""; + codeLensCommand += handlerInfo.getPath(); + + codeLensCommand += handlerInfo.getContentType() != null ? " Content-Type: " + handlerInfo.getContentType() : ""; + codeLensCommand += handlerInfo.getAcceptType() != null ? " Accept: " + handlerInfo.getAcceptType() : ""; + + codeLens.setCommand(new Command(codeLensCommand, null)); resultAccumulator.add(codeLens); } catch (BadLocationException e) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java index 4bf3c4ae9..7f7b34142 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java @@ -15,18 +15,22 @@ package org.springframework.ide.vscode.boot.java.requestmapping; */ public class WebfluxHandlerInformation { - private final String symbol; - private String handlerClass; - private String handlerMethod; + private final String handlerClass; + private final String handlerMethod; - public WebfluxHandlerInformation(String symbol, String handlerClass, String handlerMethod) { - this.symbol = symbol; + private final String path; + private final String httpMethod; + private final String contentType; + private final String acceptType; + + public WebfluxHandlerInformation(String handlerClass, String handlerMethod, String path, String httpMethod, String contentType, String acceptType) { this.handlerClass = handlerClass; this.handlerMethod = handlerMethod; - } - - public String getSymbol() { - return symbol; + + this.path = path; + this.httpMethod = httpMethod; + this.contentType = contentType; + this.acceptType = acceptType; } public String getHandlerClass() { @@ -36,5 +40,21 @@ public class WebfluxHandlerInformation { public String getHandlerMethod() { return handlerMethod; } + + public String getPath() { + return path; + } + + public String getHttpMethod() { + return httpMethod; + } + + public String getContentType() { + return contentType; + } + + public String getAcceptType() { + return acceptType; + } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java index 30fdeda6c..e9b494bb5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java @@ -91,6 +91,9 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { String path = extractPath(node, foundPath); String httpMethod = extractMethod(node); + String contentType = null; + String acceptType = null; + int methodNameStart = node.getName().getStartPosition(); int invocationStart = node.getStartPosition(); @@ -99,7 +102,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart))); String label = "@" + (path.startsWith("/") ? path : ("/" + path)) + (httpMethod == null || httpMethod.isEmpty() ? "" : " -- " + httpMethod); - WebfluxHandlerInformation handler = extractHandlerInformation(node, label); + WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethod, contentType, acceptType); result.add(new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), handler)); } catch (BadLocationException e) { @@ -161,7 +164,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { return method; } - private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String symbol) { + private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, String httpMethod, String contentType, String acceptType) { List arguments = node.arguments(); if (arguments != null) { @@ -177,7 +180,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { String handlerMethod = methodBinding.getMethodDeclaration().toString(); if (handlerMethod != null) handlerMethod = handlerMethod.trim(); - return new WebfluxHandlerInformation(symbol, handlerClass, handlerMethod); + return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, httpMethod, contentType, acceptType); } } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java index d374973b4..786a535c7 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java @@ -53,10 +53,10 @@ public class WebFluxCodeLensProviderTest { assertEquals(4, codeLenses.size()); - assertTrue(containsCodeLens(codeLenses, "@/hello -- GET", 25, 29, 25, 34)); - assertTrue(containsCodeLens(codeLenses, "@/echo -- POST", 30, 29, 30, 33)); - assertTrue(containsCodeLens(codeLenses, "@/quotes -- GET", 35, 29, 35, 41)); - assertTrue(containsCodeLens(codeLenses, "@/quotes -- GET", 41, 29, 41, 40)); + assertTrue(containsCodeLens(codeLenses, "GET /hello", 25, 29, 25, 34)); + assertTrue(containsCodeLens(codeLenses, "POST /echo", 30, 29, 30, 33)); + assertTrue(containsCodeLens(codeLenses, "GET /quotes", 35, 29, 35, 41)); + assertTrue(containsCodeLens(codeLenses, "GET /quotes", 41, 29, 41, 40)); } private boolean containsCodeLens(List codeLenses, String commandTitle, int startLine, int startPosition, int endLine, int endPosition) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index 7e41d4173..00d7b7d5c 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -69,23 +69,35 @@ public class WebFluxMappingSymbolProviderTest { List addons = getAdditionalInformation(docUri); assertEquals(4, addons.size()); - WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "@/hello -- GET").get(0); - assertEquals("@/hello -- GET", handlerInfo1.getSymbol()); + WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/hello", "GET").get(0); + assertEquals("/hello", handlerInfo1.getPath()); + assertEquals("GET", handlerInfo1.getHttpMethod()); + assertNull(handlerInfo1.getContentType()); + assertNull(handlerInfo1.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo1.getHandlerClass()); assertEquals("public Mono hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "@/echo -- POST").get(0); - assertEquals("@/echo -- POST", handlerInfo2.getSymbol()); + WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/echo", "POST").get(0); + assertEquals("/echo", handlerInfo2.getPath()); + assertEquals("POST", handlerInfo2.getHttpMethod()); + assertNull(handlerInfo2.getContentType()); + assertNull(handlerInfo2.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo2.getHandlerClass()); assertEquals("public Mono echo(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "@/quotes -- GET").get(0); - assertEquals("@/quotes -- GET", handlerInfo3.getSymbol()); + WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/quotes", "GET").get(0); + assertEquals("/quotes", handlerInfo3.getPath()); + assertEquals("GET", handlerInfo3.getHttpMethod()); + assertNull(handlerInfo3.getContentType()); + assertNull(handlerInfo3.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo3.getHandlerClass()); assertEquals("public Mono streamQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "@/quotes -- GET").get(1); - assertEquals("@/quotes -- GET", handlerInfo4.getSymbol()); + WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "/quotes", "GET").get(1); + assertEquals("/quotes", handlerInfo4.getPath()); + assertEquals("GET", handlerInfo4.getHttpMethod()); + assertNull(handlerInfo4.getContentType()); + assertNull(handlerInfo4.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo4.getHandlerClass()); assertEquals("public Mono fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod()); } @@ -105,18 +117,27 @@ public class WebFluxMappingSymbolProviderTest { List addons = getAdditionalInformation(docUri); assertEquals(3, addons.size()); - WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "@/person/{id} -- GET").get(0); - assertEquals("@/person/{id} -- GET", handlerInfo1.getSymbol()); + WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0); + assertEquals("/person/{id}", handlerInfo1.getPath()); + assertEquals("GET", handlerInfo1.getHttpMethod()); + assertNull(handlerInfo1.getContentType()); + assertNull(handlerInfo1.getAcceptType()); assertEquals("org.test.PersonHandler", handlerInfo1.getHandlerClass()); assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "@/person/ -- POST").get(0); - assertEquals("@/person/ -- POST", handlerInfo2.getSymbol()); + WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/", "POST").get(0); + assertEquals("/person/", handlerInfo2.getPath()); + assertEquals("POST", handlerInfo2.getHttpMethod()); + assertNull(handlerInfo2.getContentType()); + assertNull(handlerInfo2.getAcceptType()); assertEquals("org.test.PersonHandler", handlerInfo2.getHandlerClass()); assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "@/person -- GET").get(0); - assertEquals("@/person -- GET", handlerInfo3.getSymbol()); + WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "GET").get(0); + assertEquals("/person", handlerInfo3.getPath()); + assertEquals("GET", handlerInfo3.getHttpMethod()); + assertNull(handlerInfo3.getContentType()); + assertNull(handlerInfo3.getAcceptType()); assertEquals("org.test.PersonHandler", handlerInfo3.getHandlerClass()); assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); } @@ -146,11 +167,11 @@ public class WebFluxMappingSymbolProviderTest { return harness.getServerWrapper().getComponents().getSpringIndexer().getAdditonalInformation(docUri); } - private List getWebfluxHandler(List addons, String symbol) { + private List getWebfluxHandler(List addons, String path, String httpMethod) { return addons.stream() .filter((obj) -> obj instanceof WebfluxHandlerInformation) .map((obj -> (WebfluxHandlerInformation) obj)) - .filter((addon) -> addon.getSymbol().equals(symbol)) + .filter((addon) -> addon.getPath().equals(path) && addon.getHttpMethod().equals(httpMethod)) .collect(Collectors.toList()); } From 7328932b7ca70fa77af48046455f91eb898cea79 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Thu, 8 Mar 2018 13:28:23 +0100 Subject: [PATCH 06/30] added media types to webflux symbol and code lens logic --- .../java/requestmapping/MediaTypeMapping.java | 33 +++++ .../WebfluxAcceptTypeFinder.java | 50 +++++++ .../WebfluxContentTypeFinder.java | 55 ++++++++ .../WebfluxHandlerCodeLensProvider.java | 18 ++- .../requestmapping/WebfluxMethodFinder.java | 19 +-- .../requestmapping/WebfluxPathFinder.java | 2 +- .../WebfluxRouterSymbolProvider.java | 125 ++++++++++++++---- .../java/requestmapping/WebfluxUtils.java | 37 +++++- .../test/WebFluxCodeLensProviderTest.java | 8 +- .../WebFluxMappingSymbolProviderTest.java | 20 +-- .../test-webflux-project/pom.xml | 44 +----- .../main/java/org/test/RouterExperiments.java | 34 +++++ .../src/main/java/org/test/TradingUser.java | 72 ---------- .../java/org/test/TradingUserRepository.java | 11 -- .../main/java/org/test/UserController.java | 20 +-- 15 files changed, 345 insertions(+), 203 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java delete mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUser.java delete mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUserRepository.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java new file mode 100644 index 000000000..f834f255d --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2018 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.requestmapping; + +/** + * @author Martin Lippert + */ +public enum MediaTypeMapping { + + TEXT_PLAIN("text/plain"), + APPLICATION_JSON("application/json"), + APPLICATION_STREAM_JSON("application/stream+json"); + + + private String mediaType; + + private MediaTypeMapping(String mediaType) { + this.mediaType = mediaType; + } + + public String getMediaType() { + return mediaType; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java new file mode 100644 index 000000000..f711b7281 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2018 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.requestmapping; + +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.MethodInvocation; + +/** + * @author Martin Lippert + */ +public class WebfluxAcceptTypeFinder extends ASTVisitor { + + private String acceptType; + + public WebfluxAcceptTypeFinder() { + } + + public String getAcceptType() { + return acceptType; + } + + @Override + public boolean visit(MethodInvocation node) { + boolean visitChildren = true; + + IMethodBinding methodBinding = node.resolveMethodBinding(); + + if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + String name = methodBinding.getName(); + if (name != null && WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(name)) { + acceptType = WebfluxUtils.extractSimpleNameArgument(node); + } + } + + if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + visitChildren = false; + } + return visitChildren; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java new file mode 100644 index 000000000..e104c3a55 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2018 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.requestmapping; + +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.MethodInvocation; + +/** + * @author Martin Lippert + */ +public class WebfluxContentTypeFinder extends ASTVisitor { + + private String contentType; + private ASTNode root; + + public WebfluxContentTypeFinder(ASTNode root) { + this.root = root; + } + + public String getContentType() { + return contentType; + } + + @Override + public boolean visit(MethodInvocation node) { + boolean visitChildren = true; + + if (node != this.root) { + IMethodBinding methodBinding = node.resolveMethodBinding(); + + if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + String name = methodBinding.getName(); + if (name != null && WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(name)) { + contentType = WebfluxUtils.extractSimpleNameArgument(node); + } + } + + if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + visitChildren = false; + } + } + return visitChildren; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java index 14593c14f..73950b090 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java @@ -75,8 +75,8 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider { String codeLensCommand = handlerInfo.getHttpMethod() != null ? handlerInfo.getHttpMethod() + " " : ""; codeLensCommand += handlerInfo.getPath(); - codeLensCommand += handlerInfo.getContentType() != null ? " Content-Type: " + handlerInfo.getContentType() : ""; - codeLensCommand += handlerInfo.getAcceptType() != null ? " Accept: " + handlerInfo.getAcceptType() : ""; + codeLensCommand += handlerInfo.getAcceptType() != null ? " - Accept: " + getMediaType(handlerInfo.getAcceptType()) : ""; + codeLensCommand += handlerInfo.getContentType() != null ? " - Content-Type: " + getMediaType(handlerInfo.getContentType()) : ""; codeLens.setCommand(new Command(codeLensCommand, null)); @@ -88,5 +88,19 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider { } } } + + protected String getMediaType(String handlerInfo) { + if (handlerInfo == null) { + return null; + } + + try { + MediaTypeMapping mediaType = MediaTypeMapping.valueOf(handlerInfo); + return mediaType.getMediaType(); + } + catch (IllegalArgumentException e) { + return handlerInfo; + } + } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java index a8a48ef55..bef4fe7ba 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java @@ -10,13 +10,10 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.requestmapping; -import java.util.List; - import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.QualifiedName; /** * @author Martin Lippert @@ -47,7 +44,7 @@ public class WebfluxMethodFinder extends ASTVisitor { method = name; } else if (name != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(name)) { - method = extractMethodValue(node); + method = WebfluxUtils.extractQualifiedNameArgument(node); } } @@ -58,18 +55,4 @@ public class WebfluxMethodFinder extends ASTVisitor { return visitChildren; } - private String extractMethodValue(MethodInvocation node) { - List arguments = node.arguments(); - if (arguments != null && arguments.size() > 0) { - Object object = arguments.get(0); - if (object instanceof QualifiedName) { - QualifiedName qualifiedName = (QualifiedName) object; - if (qualifiedName.getName() != null) { - return qualifiedName.getName().toString(); - } - } - } - return null; - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java index 20260238f..60a323295 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java @@ -41,7 +41,7 @@ public class WebfluxPathFinder extends ASTVisitor { if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); if (name != null && WebfluxUtils.REQUEST_PREDICATE_ALL_PATH_METHODS.contains(name)) { - path = WebfluxUtils.extractPath(node); + path = WebfluxUtils.extractStringLiteralArgument(node); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java index e9b494bb5..d7394dab6 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.Function; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; @@ -33,6 +34,9 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.TextDocument; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + /** * @author Martin Lippert */ @@ -87,12 +91,11 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { } protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List result) { - String foundPath = extractPathFromRouterFunction(node); - String path = extractPath(node, foundPath); + String path = extractPath(node); String httpMethod = extractMethod(node); - String contentType = null; - String acceptType = null; + String contentType = extractContentType(node); + String acceptType = extractAcceptType(node); int methodNameStart = node.getName().getStartPosition(); int invocationStart = node.getStartPosition(); @@ -111,19 +114,102 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { } } - private String extractPathFromRouterFunction(MethodInvocation routerInvocation) { + private String extractPath(MethodInvocation routerInvocation) { WebfluxPathFinder pathFinder = new WebfluxPathFinder(routerInvocation); routerInvocation.accept(pathFinder); String path = pathFinder.getPath(); if (path == null) path = ""; - return path; + return extractNestedValue(routerInvocation, path, (methodInvocationPathPrefix) -> { + IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + String methodName = methodBinding.getName(); + + if (WebfluxUtils.REQUEST_PREDICATE_PATH_METHOD.equals(methodName)) { + String additionalPath = WebfluxUtils.extractStringLiteralArgument(methodInvocationPathPrefix.getT1()); + if (additionalPath != null && additionalPath.length() > 0) { + return additionalPath + methodInvocationPathPrefix.getT2(); + } + } + + return methodInvocationPathPrefix.getT2(); + }); } - private String extractPath(ASTNode node, String path) { + private String extractMethod(MethodInvocation routerInvocation) { + WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation); + routerInvocation.accept(methodFinder); + + String method = methodFinder.getMethod(); + + return extractNestedValue(routerInvocation, method, (methodInvocationPathPrefix) -> { + IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + String methodName = methodBinding.getName(); + + if (WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(methodName)) { + String newMethod = WebfluxUtils.extractStringLiteralArgument(methodInvocationPathPrefix.getT1()); + if (method == null) { + return newMethod; + } + } + + return methodInvocationPathPrefix.getT2(); + }); + } + + private String extractAcceptType(MethodInvocation routerInvocation) { + String acceptType = null; + + WebfluxAcceptTypeFinder acceptTypeFinder = new WebfluxAcceptTypeFinder(); + List arguments = routerInvocation.arguments(); + for (Object argument : arguments) { + if (argument != null && argument instanceof ASTNode) { + ((ASTNode)argument).accept(acceptTypeFinder); + if (acceptTypeFinder.getAcceptType() != null) { + acceptType = acceptTypeFinder.getAcceptType(); + } + } + } + + return extractNestedValue(routerInvocation, acceptType, (methodInvocationPathPrefix) -> { + IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + String methodName = methodBinding.getName(); + + if (WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(methodName)) { + String newAcceptType = WebfluxUtils.extractSimpleNameArgument(methodInvocationPathPrefix.getT1()); + if (newAcceptType != null) { + return newAcceptType; + } + } + + return methodInvocationPathPrefix.getT2(); + }); + } + + private String extractContentType(MethodInvocation routerInvocation) { + WebfluxContentTypeFinder contentTypeFinder = new WebfluxContentTypeFinder(routerInvocation); + routerInvocation.accept(contentTypeFinder); + + String contentType = contentTypeFinder.getContentType(); + + return extractNestedValue(routerInvocation, contentType, (methodInvocationPathPrefix) -> { + IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + String methodName = methodBinding.getName(); + + if (WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(methodName)) { + String newContentType = WebfluxUtils.extractSimpleNameArgument(methodInvocationPathPrefix.getT1()); + if (contentType == null) { + return newContentType; + } + } + + return methodInvocationPathPrefix.getT2(); + }); + } + + private String extractNestedValue(ASTNode node, String value, Function, String> extractor) { if (node == null || node instanceof TypeDeclaration) { - return path; + return value; } if (node instanceof MethodInvocation) { @@ -132,38 +218,21 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { if (WebfluxUtils.ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); - if ("nest".equals(name)) { + if (WebfluxUtils.REQUEST_PREDICATE_NEST_METHOD.equals(name)) { List arguments = methodInvocation.arguments(); for (Object argument : arguments) { if (argument instanceof MethodInvocation) { MethodInvocation nestedMethod = (MethodInvocation) argument; - IMethodBinding nestedMethodBinding = nestedMethod.resolveMethodBinding(); - - String nestedMethodName = nestedMethodBinding.getName(); - if ("path".equals(nestedMethodName)) { - String additionalPath = WebfluxUtils.extractPath(nestedMethod); - if (additionalPath != null && additionalPath.length() > 0) { - path = additionalPath + path; - } - } + value = extractor.apply(Tuples.of(nestedMethod, value)); } - } } } } - return extractPath(node.getParent(), path); + return extractNestedValue(node.getParent(), value, extractor); } - private String extractMethod(MethodInvocation routerInvocation) { - WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation); - routerInvocation.accept(methodFinder); - - String method = methodFinder.getMethod(); - return method; - } - private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, String httpMethod, String contentType, String acceptType) { List arguments = node.arguments(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java index 6de785cda..51c1a7a1f 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java @@ -17,6 +17,8 @@ import java.util.Set; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.QualifiedName; +import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.StringLiteral; /** @@ -30,12 +32,15 @@ public class WebfluxUtils { public static final String REQUEST_PREDICATE_PATH_METHOD = "path"; public static final String REQUEST_PREDICATE_METHOD_METHOD = "method"; + public static final String REQUEST_PREDICATE_ACCEPT_TYPE_METHOD = "accept"; + public static final String REQUEST_PREDICATE_CONTENT_TYPE_METHOD = "contentType"; + public static final String REQUEST_PREDICATE_NEST_METHOD = "nest"; public static final Set REQUEST_PREDICATE_HTTPMETHOD_METHODS = new HashSet<>(Arrays.asList("GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS")); public static final Set REQUEST_PREDICATE_ALL_PATH_METHODS = new HashSet<>(Arrays.asList(REQUEST_PREDICATE_PATH_METHOD, "GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS")); - public static String extractPath(MethodInvocation node) { + public static String extractStringLiteralArgument(MethodInvocation node) { List arguments = node.arguments(); if (arguments != null && arguments.size() > 0) { Object object = arguments.get(0); @@ -47,6 +52,36 @@ public class WebfluxUtils { return null; } + public static String extractQualifiedNameArgument(MethodInvocation node) { + List arguments = node.arguments(); + if (arguments != null && arguments.size() > 0) { + Object object = arguments.get(0); + if (object instanceof QualifiedName) { + QualifiedName qualifiedName = (QualifiedName) object; + if (qualifiedName.getName() != null) { + return qualifiedName.getName().toString(); + } + } + } + return null; + } + + public static String extractSimpleNameArgument(MethodInvocation node) { + List arguments = node.arguments(); + if (arguments != null && arguments.size() > 0) { + Object object = arguments.get(0); + if (object instanceof SimpleName) { + SimpleName name = (SimpleName) object; + if (name.getFullyQualifiedName() != null) { + return name.getFullyQualifiedName().toString(); + } + } + } + return null; + } + + + public static boolean isRouteMethodInvocation(IMethodBinding methodBinding) { if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java index 786a535c7..d9a8a2a9a 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java @@ -53,10 +53,10 @@ public class WebFluxCodeLensProviderTest { assertEquals(4, codeLenses.size()); - assertTrue(containsCodeLens(codeLenses, "GET /hello", 25, 29, 25, 34)); - assertTrue(containsCodeLens(codeLenses, "POST /echo", 30, 29, 30, 33)); - assertTrue(containsCodeLens(codeLenses, "GET /quotes", 35, 29, 35, 41)); - assertTrue(containsCodeLens(codeLenses, "GET /quotes", 41, 29, 41, 40)); + assertTrue(containsCodeLens(codeLenses, "GET /hello - Accept: text/plain", 25, 29, 25, 34)); + assertTrue(containsCodeLens(codeLenses, "POST /echo - Accept: text/plain - Content-Type: text/plain", 30, 29, 30, 33)); + assertTrue(containsCodeLens(codeLenses, "GET /quotes - Accept: application/stream+json", 35, 29, 35, 41)); + assertTrue(containsCodeLens(codeLenses, "GET /quotes - Accept: application/json", 41, 29, 41, 40)); } private boolean containsCodeLens(List codeLenses, String commandTitle, int startLine, int startPosition, int endLine, int endPosition) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index 00d7b7d5c..4d6221074 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -46,8 +46,8 @@ public class WebFluxMappingSymbolProviderTest { String docUri = directory.toPath().resolve("src/main/java/org/test/UserController.java").toUri().toString(); List symbols = getSymbols(docUri); assertEquals(4, symbols.size()); - assertTrue(containsSymbol(symbols, "@/users", docUri, 19, 1, 19, 74)); - assertTrue(containsSymbol(symbols, "@/users/{username}", docUri, 24, 1, 24, 85)); + assertTrue(containsSymbol(symbols, "@/users", docUri, 13, 1, 13, 74)); + assertTrue(containsSymbol(symbols, "@/users/{username}", docUri, 18, 1, 18, 85)); List addons = getAdditionalInformation(docUri); assertNull(addons); @@ -73,15 +73,15 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("/hello", handlerInfo1.getPath()); assertEquals("GET", handlerInfo1.getHttpMethod()); assertNull(handlerInfo1.getContentType()); - assertNull(handlerInfo1.getAcceptType()); + assertEquals("TEXT_PLAIN", handlerInfo1.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo1.getHandlerClass()); assertEquals("public Mono hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/echo", "POST").get(0); assertEquals("/echo", handlerInfo2.getPath()); assertEquals("POST", handlerInfo2.getHttpMethod()); - assertNull(handlerInfo2.getContentType()); - assertNull(handlerInfo2.getAcceptType()); + assertEquals("TEXT_PLAIN", handlerInfo2.getContentType()); + assertEquals("TEXT_PLAIN", handlerInfo2.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo2.getHandlerClass()); assertEquals("public Mono echo(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); @@ -89,7 +89,7 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("/quotes", handlerInfo3.getPath()); assertEquals("GET", handlerInfo3.getHttpMethod()); assertNull(handlerInfo3.getContentType()); - assertNull(handlerInfo3.getAcceptType()); + assertEquals("APPLICATION_STREAM_JSON", handlerInfo3.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo3.getHandlerClass()); assertEquals("public Mono streamQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); @@ -97,7 +97,7 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("/quotes", handlerInfo4.getPath()); assertEquals("GET", handlerInfo4.getHttpMethod()); assertNull(handlerInfo4.getContentType()); - assertNull(handlerInfo4.getAcceptType()); + assertEquals("APPLICATION_JSON", handlerInfo4.getAcceptType()); assertEquals("org.test.QuoteHandler", handlerInfo4.getHandlerClass()); assertEquals("public Mono fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod()); } @@ -121,14 +121,14 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("/person/{id}", handlerInfo1.getPath()); assertEquals("GET", handlerInfo1.getHttpMethod()); assertNull(handlerInfo1.getContentType()); - assertNull(handlerInfo1.getAcceptType()); + assertEquals("APPLICATION_JSON", handlerInfo1.getAcceptType()); assertEquals("org.test.PersonHandler", handlerInfo1.getHandlerClass()); assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/", "POST").get(0); assertEquals("/person/", handlerInfo2.getPath()); assertEquals("POST", handlerInfo2.getHttpMethod()); - assertNull(handlerInfo2.getContentType()); + assertEquals("APPLICATION_JSON", handlerInfo2.getContentType()); assertNull(handlerInfo2.getAcceptType()); assertEquals("org.test.PersonHandler", handlerInfo2.getHandlerClass()); assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); @@ -137,7 +137,7 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("/person", handlerInfo3.getPath()); assertEquals("GET", handlerInfo3.getHttpMethod()); assertNull(handlerInfo3.getContentType()); - assertNull(handlerInfo3.getAcceptType()); + assertEquals("APPLICATION_JSON", handlerInfo3.getAcceptType()); assertEquals("org.test.PersonHandler", handlerInfo3.getHandlerClass()); assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); } diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/pom.xml b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/pom.xml index 930b1a47c..83db5d821 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/pom.xml +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.M1 + 2.0.0.RELEASE @@ -35,10 +35,6 @@ org.springframework.boot spring-boot-starter-webflux - - org.springframework.boot - spring-boot-starter-data-mongodb-reactive - @@ -50,42 +46,4 @@ - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java new file mode 100644 index 000000000..5634bed69 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java @@ -0,0 +1,34 @@ +package org.test; + +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +import static org.springframework.web.reactive.function.server.RequestPredicates.accept; +import static org.springframework.web.reactive.function.server.RequestPredicates.contentType; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.nest; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerResponse; + +@Configuration +public class RouterExperiments { + + @Bean + public RouterFunction superRoutingFunction() { + PersonHandler handler = new PersonHandler(); + + return nest(path("/super"), + nest(path("/something"), + nest(accept(APPLICATION_JSON), + route(GET("/{id}"), handler::getPerson) + .andRoute(method(HttpMethod.GET), handler::listPeople) + ).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson))); + } + +} diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUser.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUser.java deleted file mode 100644 index d25f38aa1..000000000 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUser.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.test; - -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; - -@Document -public class TradingUser { - - @Id - private String id; - - private String userName; - - private String fullName; - - public TradingUser() { - } - - public TradingUser(String id, String userName, String fullName) { - this.id = id; - this.userName = userName; - this.fullName = fullName; - } - - public TradingUser(String userName, String fullName) { - this.userName = userName; - this.fullName = fullName; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TradingUser that = (TradingUser) o; - - if (!id.equals(that.id)) return false; - return userName.equals(that.userName); - } - - @Override - public int hashCode() { - int result = id.hashCode(); - result = 31 * result + userName.hashCode(); - return result; - } -} - diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUserRepository.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUserRepository.java deleted file mode 100644 index 2cf539025..000000000 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/TradingUserRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.test; - -import reactor.core.publisher.Mono; - -import org.springframework.data.mongodb.repository.ReactiveMongoRepository; - -public interface TradingUserRepository extends ReactiveMongoRepository { - - Mono findByUserName(String userName); - -} diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/UserController.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/UserController.java index 64621ec86..9de96cbeb 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/UserController.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/UserController.java @@ -1,30 +1,24 @@ package org.test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + @RestController public class UserController { - private final TradingUserRepository tradingUserRepository; - - public UserController(TradingUserRepository tradingUserRepository) { - this.tradingUserRepository = tradingUserRepository; - } - @GetMapping(path = "/users", produces = MediaType.APPLICATION_JSON_VALUE) - public Flux listUsers() { - return this.tradingUserRepository.findAll(); + public Flux listUsers() { + return null; } @GetMapping(path = "/users/{username}", produces = MediaType.APPLICATION_JSON_VALUE) - public Mono showUsers(@PathVariable String username) { - return this.tradingUserRepository.findByUserName(username); + public Mono showUsers(@PathVariable String username) { + return null; } } \ No newline at end of file From bca56a21247dd9486968dc200250e74f073e2e55 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Thu, 8 Mar 2018 11:28:28 -0500 Subject: [PATCH 07/30] PT #155800737: Adopted lsp4j change in parsing CompletionItem message --- .../VscodeCompletionEngineAdapter.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java index acca5dabf..f04a2122c 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016, 2018 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -32,12 +32,14 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguage import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; import org.springframework.ide.vscode.commons.languageserver.util.SortKeys; import org.springframework.ide.vscode.commons.util.BadLocationException; -import org.springframework.ide.vscode.commons.util.Log; import org.springframework.ide.vscode.commons.util.Renderable; import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.text.TextDocument; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; +import com.google.gson.JsonPrimitive; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; @@ -47,6 +49,8 @@ import reactor.core.scheduler.Schedulers; */ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { + private static final Supplier LOG = Suppliers.memoize(() -> LoggerFactory.getLogger(VscodeCompletionEngineAdapter.class)); + public static class LazyCompletionResolver { private int nextId = 0; //Used to assign unique id to completion items. @@ -65,7 +69,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { try { resolveItem(doc, completion, unresolved); } catch (Exception e) { - Log.log(e); + LOG.get().error("{}", e); } }); return id; @@ -74,12 +78,12 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { public synchronized void resolveNow(CompletionItem unresolved) { Object id = unresolved.getData(); if (id!=null) { - Consumer resolver = resolvers.get(id); + Consumer resolver = resolvers.get(id instanceof JsonPrimitive ? ((JsonPrimitive)id).getAsString() : id); if (resolver!=null) { resolver.accept(unresolved); unresolved.setData(null); //No longer needed after item is resolved. } else { - Log.warn("Couldn't resolve completion item. Did it already get flushed from the resolver's cache? "+unresolved.getLabel()); + LOG.get().warn("Couldn't resolve completion item. Did it already get flushed from the resolver's cache? "+unresolved.getLabel()); } } } @@ -226,7 +230,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { return Optional.of(vscodeEdit); } } catch (Exception e) { - Log.log(e); + LOG.get().error("{}", e); return Optional.empty(); } } @@ -242,7 +246,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { return StringUtil.stripIndentation(refIndent, newText); } } catch (BadLocationException e) { - Log.log(e); + LOG.get().error("{}", e); } return newText; } From 75564b34cc6aff204a33e2d5ccd5d339c28373f5 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Thu, 8 Mar 2018 19:10:23 -0500 Subject: [PATCH 08/30] Switch Atom packages to TS --- atom-extensions/atom-bosh/.gitignore | 1 + .../lib/{main.js => bosh-yaml-client.ts} | 25 +- atom-extensions/atom-bosh/lib/main.ts | 3 + atom-extensions/atom-bosh/package.json | 24 +- atom-extensions/atom-bosh/properties.json | 2 +- atom-extensions/atom-bosh/tsconfig.json | 17 ++ atom-extensions/atom-bosh/tslint.json | 31 +++ .../atom-cf-manifest-yaml/.gitignore | 1 + .../atom-cf-manifest-yaml/lib/main.ts | 3 + ...in.js => manifest-yaml-language-client.ts} | 15 +- .../atom-cf-manifest-yaml/package.json | 16 +- .../atom-cf-manifest-yaml/properties.json | 2 +- .../atom-cf-manifest-yaml/tsconfig.json | 17 ++ .../atom-cf-manifest-yaml/tslint.json | 31 +++ atom-extensions/atom-commons/.babelrc | 15 -- atom-extensions/atom-commons/lib/index.js | 4 - .../lib/java-process-language-client.js | 217 ------------------ .../lib/java-process-language-client.ts | 163 +++++++++++++ atom-extensions/atom-commons/lib/main.ts | 10 + .../atom-commons/lib/sts-adapter.js | 20 -- .../atom-commons/lib/sts-adapter.ts | 38 +++ atom-extensions/atom-commons/package.json | 61 ++--- atom-extensions/atom-commons/tsconfig.json | 17 ++ atom-extensions/atom-commons/tslint.json | 31 +++ atom-extensions/atom-concourse/.gitignore | 1 + .../{main.js => concourse-ci-yaml-client.ts} | 15 +- atom-extensions/atom-concourse/lib/main.ts | 3 + atom-extensions/atom-concourse/package.json | 16 +- atom-extensions/atom-concourse/tsconfig.json | 17 ++ atom-extensions/atom-concourse/tslint.json | 31 +++ atom-extensions/atom-spring-boot/.gitignore | 1 + .../atom-spring-boot/lib/boot-sts-adapter.ts | 56 +++++ atom-extensions/atom-spring-boot/lib/main.js | 128 ----------- atom-extensions/atom-spring-boot/lib/main.ts | 3 + .../lib/spring-boot-language-client.ts | 75 ++++++ atom-extensions/atom-spring-boot/package.json | 17 +- .../atom-spring-boot/properties.json | 2 +- .../atom-spring-boot/tsconfig.json | 17 ++ atom-extensions/atom-spring-boot/tslint.json | 31 +++ concourse/tasks/build-atom-package.sh | 3 + 40 files changed, 700 insertions(+), 480 deletions(-) rename atom-extensions/atom-bosh/lib/{main.js => bosh-yaml-client.ts} (63%) create mode 100644 atom-extensions/atom-bosh/lib/main.ts create mode 100644 atom-extensions/atom-bosh/tsconfig.json create mode 100644 atom-extensions/atom-bosh/tslint.json create mode 100644 atom-extensions/atom-cf-manifest-yaml/lib/main.ts rename atom-extensions/atom-cf-manifest-yaml/lib/{main.js => manifest-yaml-language-client.ts} (70%) create mode 100644 atom-extensions/atom-cf-manifest-yaml/tsconfig.json create mode 100644 atom-extensions/atom-cf-manifest-yaml/tslint.json delete mode 100644 atom-extensions/atom-commons/.babelrc delete mode 100644 atom-extensions/atom-commons/lib/index.js delete mode 100644 atom-extensions/atom-commons/lib/java-process-language-client.js create mode 100644 atom-extensions/atom-commons/lib/java-process-language-client.ts create mode 100644 atom-extensions/atom-commons/lib/main.ts delete mode 100644 atom-extensions/atom-commons/lib/sts-adapter.js create mode 100644 atom-extensions/atom-commons/lib/sts-adapter.ts create mode 100644 atom-extensions/atom-commons/tsconfig.json create mode 100644 atom-extensions/atom-commons/tslint.json rename atom-extensions/atom-concourse/lib/{main.js => concourse-ci-yaml-client.ts} (73%) create mode 100644 atom-extensions/atom-concourse/lib/main.ts create mode 100644 atom-extensions/atom-concourse/tsconfig.json create mode 100644 atom-extensions/atom-concourse/tslint.json create mode 100644 atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts delete mode 100644 atom-extensions/atom-spring-boot/lib/main.js create mode 100644 atom-extensions/atom-spring-boot/lib/main.ts create mode 100644 atom-extensions/atom-spring-boot/lib/spring-boot-language-client.ts create mode 100644 atom-extensions/atom-spring-boot/tsconfig.json create mode 100644 atom-extensions/atom-spring-boot/tslint.json diff --git a/atom-extensions/atom-bosh/.gitignore b/atom-extensions/atom-bosh/.gitignore index 51786ff67..0b79f4de1 100644 --- a/atom-extensions/atom-bosh/.gitignore +++ b/atom-extensions/atom-bosh/.gitignore @@ -1,6 +1,7 @@ /.idea /node_modules /server +/build *.tgz *.iml *.log \ No newline at end of file diff --git a/atom-extensions/atom-bosh/lib/main.js b/atom-extensions/atom-bosh/lib/bosh-yaml-client.ts similarity index 63% rename from atom-extensions/atom-bosh/lib/main.js rename to atom-extensions/atom-bosh/lib/bosh-yaml-client.ts index 9549d9dd2..de10801b7 100644 --- a/atom-extensions/atom-bosh/lib/main.js +++ b/atom-extensions/atom-bosh/lib/bosh-yaml-client.ts @@ -1,21 +1,22 @@ -const path = require('path'); -const { JavaProcessLanguageClient } = require('@pivotal-tools/atom-languageclient-commons'); -const PROPERTIES = require('../properties.json'); +import * as path from 'path'; +import {JavaProcessLanguageClient} from '@pivotal-tools/atom-languageclient-commons'; +import {ActiveServer} from 'atom-languageclient'; +import {JVM} from '@pivotal-tools/jvm-launch-utils'; -class BoshYamlClient extends JavaProcessLanguageClient { + +export class BoshYamlClient extends JavaProcessLanguageClient { constructor() { //noinspection JSAnnotator super( - PROPERTIES.jarUrl, path.join(__dirname, '..', 'server'), 'bosh-language-server.jar' - ); + ); } - postInitialization(server) { + postInitialization(server: ActiveServer) { this.sendConfig(server); - this._disposable.add(atom.config.observe('bosh-yaml', () => this.sendConfig(server))); + (this)._disposable.add(atom.config.observe('bosh-yaml', () => this.sendConfig(server))); } getGrammarScopes() { @@ -37,7 +38,7 @@ class BoshYamlClient extends JavaProcessLanguageClient { super.activate(); } - launchVmArgs(jvm) { + launchVmArgs(jvm: JVM): Promise { return Promise.resolve([ '-Dorg.slf4j.simpleLogger.logFile=bosh-yaml.log', '-Dorg.slf4j.simpleLogger.defaultLogLevel=debug', @@ -45,10 +46,8 @@ class BoshYamlClient extends JavaProcessLanguageClient { } - sendConfig(server) { + sendConfig(server: ActiveServer) { server.connection.didChangeConfiguration({ settings: atom.config.get('bosh-yaml') }); } -} - -module.exports = new BoshYamlClient(); +} \ No newline at end of file diff --git a/atom-extensions/atom-bosh/lib/main.ts b/atom-extensions/atom-bosh/lib/main.ts new file mode 100644 index 000000000..6d7c31622 --- /dev/null +++ b/atom-extensions/atom-bosh/lib/main.ts @@ -0,0 +1,3 @@ +import {BoshYamlClient} from './bosh-yaml-client'; + +module.exports = new BoshYamlClient(); \ No newline at end of file diff --git a/atom-extensions/atom-bosh/package.json b/atom-extensions/atom-bosh/package.json index fbf34bace..852e1d429 100644 --- a/atom-extensions/atom-bosh/package.json +++ b/atom-extensions/atom-bosh/package.json @@ -1,26 +1,23 @@ { "name": "bosh-yaml", - "main": "./lib/main", "version": "0.1.5", "description": "Provides validation and content assist for various Bosh configuration files", "repository": "https://github.com/spring-projects/atom-bosh", "icon": "icon.png", "license": "MIT", "engines": { - "atom": ">=1.21.0" + "atom": ">=1.24.0" }, + "main": "./build/main", + "types": "./build/main.d.ts", "files": [ "grammars/", "settings/", "lib/", + "build/", "server/", "properties.json" ], - "dependencies": { - "atom-package-deps": "^4.6.0", - "download": "^6.2.5", - "@pivotal-tools/atom-languageclient-commons": "0.0.2" - }, "configSchema": { "bosh": { "type": "object", @@ -50,11 +47,22 @@ } } }, + "dependencies": { + "atom-package-deps": "^4.6.0", + "download": "^6.2.5", + "@pivotal-tools/atom-languageclient-commons": "0.0.4" + }, "devDependencies": { + "typescript": "^2.7.2", + "tslint": "^5.9.1", "coffeelint": "^1.10.1" }, "scripts": { - "clean": "rm -fr node_modules", + "clean": "rm -fr build", + "compile": "tsc", + "build": "npm run clean && npm run compile ", + "watch": "tsc -watch", + "lint": "tslint -c tslint.json 'lib/**/*.ts'", "postinstall": "node script.js" }, "package-deps": [ diff --git a/atom-extensions/atom-bosh/properties.json b/atom-extensions/atom-bosh/properties.json index d588ead1d..e705c39ea 100644 --- a/atom-extensions/atom-bosh/properties.json +++ b/atom-extensions/atom-bosh/properties.json @@ -1,3 +1,3 @@ { - "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/bosh-language-server-0.0.10-201711061741.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/bosh-language-server-0.1.5-201803080105.jar" } diff --git a/atom-extensions/atom-bosh/tsconfig.json b/atom-extensions/atom-bosh/tsconfig.json new file mode 100644 index 000000000..a333b271b --- /dev/null +++ b/atom-extensions/atom-bosh/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "build", + "lib": ["es7", "dom"], + "declaration": true, + "inlineSources": true, + "inlineSourceMap": true, + "strictNullChecks": true, + "noImplicitAny": true, + "baseUrl": "./" + }, + "include": [ + "lib/**/*.ts" + ] +} \ No newline at end of file diff --git a/atom-extensions/atom-bosh/tslint.json b/atom-extensions/atom-bosh/tslint.json new file mode 100644 index 000000000..068b76067 --- /dev/null +++ b/atom-extensions/atom-bosh/tslint.json @@ -0,0 +1,31 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "quotemark": false, + "object-literal-sort-keys": false, + "ordered-imports": false, + "member-ordering": false, + "one-line": false, + "interface-name": false, + "variable-name": false, + "max-classes-per-file": false, + "no-unused-expression": false, + "no-empty": false, + "one-variable-per-declaration": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast", + "check-module" + ] + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/atom-extensions/atom-cf-manifest-yaml/.gitignore b/atom-extensions/atom-cf-manifest-yaml/.gitignore index 51786ff67..0b79f4de1 100644 --- a/atom-extensions/atom-cf-manifest-yaml/.gitignore +++ b/atom-extensions/atom-cf-manifest-yaml/.gitignore @@ -1,6 +1,7 @@ /.idea /node_modules /server +/build *.tgz *.iml *.log \ No newline at end of file diff --git a/atom-extensions/atom-cf-manifest-yaml/lib/main.ts b/atom-extensions/atom-cf-manifest-yaml/lib/main.ts new file mode 100644 index 000000000..c8920a147 --- /dev/null +++ b/atom-extensions/atom-cf-manifest-yaml/lib/main.ts @@ -0,0 +1,3 @@ +import {ManifestYamlLanguageClient} from './manifest-yaml-language-client'; + +module.exports = new ManifestYamlLanguageClient(); \ No newline at end of file diff --git a/atom-extensions/atom-cf-manifest-yaml/lib/main.js b/atom-extensions/atom-cf-manifest-yaml/lib/manifest-yaml-language-client.ts similarity index 70% rename from atom-extensions/atom-cf-manifest-yaml/lib/main.js rename to atom-extensions/atom-cf-manifest-yaml/lib/manifest-yaml-language-client.ts index 929218105..b8c3c2821 100644 --- a/atom-extensions/atom-cf-manifest-yaml/lib/main.js +++ b/atom-extensions/atom-cf-manifest-yaml/lib/manifest-yaml-language-client.ts @@ -1,13 +1,12 @@ -const path = require('path'); -const { JavaProcessLanguageClient } = require('@pivotal-tools/atom-languageclient-commons'); -const PROPERTIES = require('../properties.json'); +import * as path from 'path'; +import { JavaProcessLanguageClient } from '@pivotal-tools/atom-languageclient-commons'; +import {JVM} from '@pivotal-tools/jvm-launch-utils'; -class ManifestYamlLanguageClient extends JavaProcessLanguageClient { +export class ManifestYamlLanguageClient extends JavaProcessLanguageClient { constructor() { //noinspection JSAnnotator super( - PROPERTIES.jarUrl, path.join(__dirname, '..', 'server'), 'cf-manifest-language-server.jar' ); @@ -33,7 +32,7 @@ class ManifestYamlLanguageClient extends JavaProcessLanguageClient { super.activate(); } - launchVmArgs(version) { + launchVmArgs(jvm: JVM) { return Promise.resolve([ '-Dorg.slf4j.simpleLogger.logFile=manifest-yaml.log', '-Dorg.slf4j.simpleLogger.defaultLogLevel=debug', @@ -41,6 +40,4 @@ class ManifestYamlLanguageClient extends JavaProcessLanguageClient { } -} - -module.exports = new ManifestYamlLanguageClient(); +} \ No newline at end of file diff --git a/atom-extensions/atom-cf-manifest-yaml/package.json b/atom-extensions/atom-cf-manifest-yaml/package.json index 24b9e9506..36faca44a 100644 --- a/atom-extensions/atom-cf-manifest-yaml/package.json +++ b/atom-extensions/atom-cf-manifest-yaml/package.json @@ -1,31 +1,39 @@ { "name": "cf-manifest-yaml", - "main": "./lib/main", "version": "0.1.5", "description": "Cloud Foundry Deployment Manifest YAML support for Atom", "repository": "https://github.com/spring-projects/atom-cf-manifest-yaml", "icon": "icon.png", "license": "MIT", "engines": { - "atom": ">=1.21.0" + "atom": ">=1.24.0" }, + "main": "./build/main", + "types": "./build/main.d.ts", "files": [ "grammars/", "settings/", "lib/", + "build/", "server/", "properties.json" ], "dependencies": { "atom-package-deps": "^4.6.0", "download": "^6.2.5", - "@pivotal-tools/atom-languageclient-commons": "0.0.2" + "@pivotal-tools/atom-languageclient-commons": "0.0.4" }, "devDependencies": { + "typescript": "^2.7.2", + "tslint": "^5.9.1", "coffeelint": "^1.10.1" }, "scripts": { - "clean": "rm -fr node_modules", + "clean": "rm -fr build", + "compile": "tsc", + "build": "npm run clean && npm run compile ", + "watch": "tsc -watch", + "lint": "tslint -c tslint.json 'lib/**/*.ts'", "postinstall": "node script.js" }, "package-deps": [ diff --git a/atom-extensions/atom-cf-manifest-yaml/properties.json b/atom-extensions/atom-cf-manifest-yaml/properties.json index e1897ba1a..8b84198ce 100644 --- a/atom-extensions/atom-cf-manifest-yaml/properties.json +++ b/atom-extensions/atom-cf-manifest-yaml/properties.json @@ -1,3 +1,3 @@ { - "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/manifest-yaml-language-server-0.0.10-201711061741.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/manifest-yaml-language-server-0.1.5-201803080105.jar" } diff --git a/atom-extensions/atom-cf-manifest-yaml/tsconfig.json b/atom-extensions/atom-cf-manifest-yaml/tsconfig.json new file mode 100644 index 000000000..a333b271b --- /dev/null +++ b/atom-extensions/atom-cf-manifest-yaml/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "build", + "lib": ["es7", "dom"], + "declaration": true, + "inlineSources": true, + "inlineSourceMap": true, + "strictNullChecks": true, + "noImplicitAny": true, + "baseUrl": "./" + }, + "include": [ + "lib/**/*.ts" + ] +} \ No newline at end of file diff --git a/atom-extensions/atom-cf-manifest-yaml/tslint.json b/atom-extensions/atom-cf-manifest-yaml/tslint.json new file mode 100644 index 000000000..068b76067 --- /dev/null +++ b/atom-extensions/atom-cf-manifest-yaml/tslint.json @@ -0,0 +1,31 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "quotemark": false, + "object-literal-sort-keys": false, + "ordered-imports": false, + "member-ordering": false, + "one-line": false, + "interface-name": false, + "variable-name": false, + "max-classes-per-file": false, + "no-unused-expression": false, + "no-empty": false, + "one-variable-per-declaration": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast", + "check-module" + ] + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/atom-extensions/atom-commons/.babelrc b/atom-extensions/atom-commons/.babelrc deleted file mode 100644 index 3b514bd56..000000000 --- a/atom-extensions/atom-commons/.babelrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "sourceMap": "inline", - "plugins": [ - ["add-module-exports", {}], - ["transform-async-to-generator", {}], - ["transform-decorators-legacy", {}], - ["transform-class-properties", {}], - ["transform-es2015-modules-commonjs", {"strictMode": false}], - ["transform-export-extensions", {}], - ["transform-do-expressions", {}], - ["transform-function-bind", {}], - ["transform-object-rest-spread", {}], - ["transform-flow-strip-types", {}], - ] -} \ No newline at end of file diff --git a/atom-extensions/atom-commons/lib/index.js b/atom-extensions/atom-commons/lib/index.js deleted file mode 100644 index e2b2e7c79..000000000 --- a/atom-extensions/atom-commons/lib/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import { JavaProcessLanguageClient } from './java-process-language-client'; -import { StsAdapter } from './sts-adapter'; - -export { JavaProcessLanguageClient, StsAdapter }; \ No newline at end of file diff --git a/atom-extensions/atom-commons/lib/java-process-language-client.js b/atom-extensions/atom-commons/lib/java-process-language-client.js deleted file mode 100644 index 173e53433..000000000 --- a/atom-extensions/atom-commons/lib/java-process-language-client.js +++ /dev/null @@ -1,217 +0,0 @@ -const cp = require('child_process'); -const fs = require('fs'); -const path = require('path'); -const url = require('url'); -const remote = require('remote-file-size'); -const PortFinder = require('portfinder'); -const net = require('net'); -const rpc = require('vscode-jsonrpc'); -const {AutoLanguageClient, DownloadFile} = require('atom-languageclient'); -const { Disposable } = require('atom'); -import { StsAdapter } from './sts-adapter'; - -import {findJdk, findJvm} from '@pivotal-tools/jvm-launch-utils'; - -export class JavaProcessLanguageClient extends AutoLanguageClient { - - DEBUG = false; - - constructor(serverDownloadUrl, serverHome, serverLauncherJar) { - super(); - - this.serverHome = serverHome; - this.serverDownloadUrl = serverDownloadUrl; - this.serverLauncherJar = serverLauncherJar; - } - - getServerJar() { - return path.resolve(this.serverHome, this.serverLauncherJar); - } - - showErrorMessage(detail, desc) { - const notification = atom.notifications.addError('Cannot start Language Server', { - dismissable: true, - detail: detail, - description: desc, - buttons: [{ - text: 'OK', - onDidClick: () => { - notification.dismiss() - }, - }] - }); - return Promise.reject(new Error(detail)); - } - - getInitializeParams(projectPath, process) { - const initParams = super.getInitializeParams(projectPath, process); - initParams.capabilities = { - workspace: { - executeCommand: { - } - } - }; - return initParams; - } - - startServerProcess () { - // //TODO: Remove when debugging is over - atom.config.set('core.debugLSP', true); - - let childProcess; - - if (this.DEBUG) { - return this.connectToLS(); - } - - return new Promise((resolve, reject) => { - let basePort = Math.floor(Math.random() * 10000) + 40000; - PortFinder.getPort({port: basePort}, (err, port) => { - this.server = net.createServer(socket => { - this.socket = socket; - resolve(childProcess); - }); - - this.server.listen(port, 'localhost', () => { - this.launchProcess(port).then(p => childProcess = p); - }); - }); - }); - } - - connectToLS() { - return new Promise(resolve => { - this.socket = net.connect({ - port: 5007 - }); - resolve({ - pid: -1, - kill: function() { - console.log('fake shutdown'); - } - }) - }); - } - - // Start adapters that are not shared between servers - startExclusiveAdapters(server) { - super.startExclusiveAdapters(server); - - const stsAdapter = this.createStsAdapter() || new StsAdapter(); - server.connection._onRequest({method: 'sts/moveCursor'}, params => stsAdapter.onMoveCursor(params)); - server.connection._onNotification({method: 'sts/progress'}, params => stsAdapter.onProgress(params)); - server.connection._onNotification({method: 'sts/highlight'}, params => stsAdapter.onHighlight(params)); - } - - preferJdk() { - return false; - } - - findJvm() { - return this.preferJdk() ? findJdk() : findJvm(); - } - - launchProcess(port) { - return this.findJvm() - .catch(error => { - return this.showErrorMessage("Error trying to find JVM", ""+error); - }) - .then(jvm => { - if (!jvm) { - return this.showErrorMessage("Couldn't locate java in $JAVA_HOME or $PATH"); - } - let version = jvm.getMajorVersion(); - if (version<8) { - return this.showErrorMessage( - 'No compatible Java Runtime Environment found', - 'The Java Runtime Environment is either below version "1.8" or is missing from the system' - ); - } - return this.launchVmArgs(jvm).then(args => { - args.push(`-Dserver.port=${port}`); - return this.doLaunchProcess( - jvm, - this.getServerJar(), - port, - args - ); - }); - }); - } - - launchVmArgs(jvm) { - return Promise.resolve([]); - } - - doLaunchProcess(jvm, launcher, port, args=[]) { - let vmArgs = args.concat([ - // Atom doesn't have lazy completion proposals support - completionItem/resolve message. Disable lazy completions - '-Dlsp.lazy.completions.disable=true', - '-Dlsp.completions.indentation.enable=true', - '-Dlsp.yaml.completions.errors.disable=true', - ]); - - this.logger.debug(`starting "${jvm.getJavaExecutable()} ${vmArgs.join('\n')}\n-jar ${launcher}"`); - return jvm.jarLaunch(launcher, vmArgs, { cwd: this.serverHome }); - } - - installServer () { - const localFileName = this.getServerJar(); - this.logger.log(`Downloading ${this.serverDownloadUrl} to ${localFileName}`); - return this.fileExists(this.serverHome) - .then(doesExist => { if (!doesExist) fs.mkdir(this.serverHome) }) - .then(() => this.remoteFileSize(this.serverDownloadUrl)) - .then((size) => DownloadFile(this.serverDownloadUrl, localFileName, (bytesDone, percent) => this.handleDownlaodPercentChange(bytesDone, size, percent), size)) - .then(() => this.fileExists(this.getServerJar())) - .then(doesExist => { if (!doesExist) throw Error(`Failed to install the ${this.getServerName()} language server`) }) - .then(() => this.handleServerInstalled()) - .then(() => Promise.resolve(true)); - } - - handleDownlaodPercentChange(bytesDone, size, percent) { - - } - - handleServerInstalled() { - - } - - preInitialization(connection) { - connection.onCustom('language/status', (e) => this.updateStatusBar(`${e.type.replace(/^Started$/, '')} ${e.message}`)); - } - - remoteFileSize(url) { - return new Promise((resolve, reject) => { - remote(url, (e,s) => { - if (e) { - reject(e); - } else { - resolve(s); - } - }); - }); - } - - fileExists (path) { - return new Promise((resolve, reject) => { - fs.access(path, fs.R_OK, error => { - resolve(!error || error.code !== 'ENOENT'); - }) - }) - } - - // Late wire-up of listeners after initialize method has been sent - postInitialization(server) { - server.disposable.add(new Disposable(() => { - if (this.server) { - this.server.close() - } - })); - } - - createStsAdapter() { - - } - -} - diff --git a/atom-extensions/atom-commons/lib/java-process-language-client.ts b/atom-extensions/atom-commons/lib/java-process-language-client.ts new file mode 100644 index 000000000..1006a7e43 --- /dev/null +++ b/atom-extensions/atom-commons/lib/java-process-language-client.ts @@ -0,0 +1,163 @@ +import * as path from 'path'; +import {getPort} from 'portfinder'; +import {Server, createServer, connect} from 'net'; +import {AtomEnvironment, Disposable} from 'atom'; +import {HighlightParams, ProgressParams, CursorMovementParams, StsAdapter} from './sts-adapter'; +import {ActiveServer, LanguageServerProcess} from 'atom-languageclient'; +import {AutoLanguageClient} from 'atom-languageclient'; +import {findJdk, findJvm, JVM} from '@pivotal-tools/jvm-launch-utils'; +import {InitializeParams} from 'vscode-languageserver-protocol'; + +export class JavaProcessLanguageClient extends AutoLanguageClient { + + DEBUG = false; + + private server: Server; + + constructor(protected serverHome: string, protected serverLauncherJar: string) { + super(); + } + + getServerJar(): string { + return path.resolve(this.serverHome, this.serverLauncherJar); + } + + showErrorMessage(detail: string, desc?: string): Promise { + const atomEnv: AtomEnvironment = atom; + const notification = atomEnv.notifications.addError('Cannot start Language Server', { + dismissable: true, + detail: detail, + description: desc, + buttons: [{ + text: 'OK', + onDidClick: () => { + notification.dismiss() + }, + }] + }); + return Promise.reject(new Error(detail)); + } + + protected getInitializeParams(projectPath: string, process: LanguageServerProcess): InitializeParams { + const initParams = super.getInitializeParams(projectPath, process); + initParams.capabilities = { + workspace: { + executeCommand: { + } + } + }; + return super.getInitializeParams(projectPath, process); + } + + protected startServerProcess(projectPath: string): LanguageServerProcess | Promise { + // TODO: Remove when debugging is over + const atomEnv: AtomEnvironment = atom; + atomEnv.config.set('core.debugLSP', true); + + let childProcess: LanguageServerProcess; + + if (this.DEBUG) { + return this.connectToLS(); + } + + return new Promise((resolve, reject) => { + let basePort = Math.floor(Math.random() * 10000) + 40000; + getPort({port: basePort}, (err, port) => { + this.server = createServer(socket => { + this.socket = socket; + resolve(childProcess); + }); + + this.server.listen(port, 'localhost', () => { + this.launchProcess(port).then(p => childProcess = p); + }); + }); + }); + } + + private connectToLS(): LanguageServerProcess | Promise { + return new Promise(resolve => { + this.socket = connect({ + port: 5007 + }); + resolve( { + pid: -1, + kill: () => { + console.log('fake shutdown'); + } + }) + }); + } + + // Start adapters that are not shared between servers + protected postInitialization(server: ActiveServer): void { + const stsAdapter = this.createStsAdapter() || new StsAdapter(); + (server.connection)._onRequest({method: 'sts/moveCursor'}, (params: CursorMovementParams) => stsAdapter.onMoveCursor(params)); + server.connection.onCustom('sts/progress', (params: ProgressParams) => stsAdapter.onProgress(params)); + server.connection.onCustom('sts/highlight', (params: HighlightParams) => stsAdapter.onHighlight(params)); + + server.disposable.add(new Disposable(() => { + if (this.server) { + this.server.close() + } + })); + + } + + preferJdk(): boolean { + return false; + } + + findJvm(): Promise { + return this.preferJdk() ? findJdk() : findJvm(); + } + + private launchProcess(port: number): Promise { + return this.findJvm() + .catch(error => { + return this.showErrorMessage("Error trying to find JVM", ""+error); + }) + .then(jvm => { + if (!jvm) { + return this.showErrorMessage("Couldn't locate java in $JAVA_HOME or $PATH"); + } + let version = jvm.getMajorVersion(); + if (version<8) { + return this.showErrorMessage( + 'No compatible Java Runtime Environment found', + 'The Java Runtime Environment is either below version "1.8" or is missing from the system' + ); + } + return this.launchVmArgs(jvm).then(args => { + args.push(`-Dserver.port=${port}`); + return this.doLaunchProcess( + jvm, + this.getServerJar(), + args + ); + }); + }); + } + + protected launchVmArgs(jvm: JVM): Promise { + return Promise.resolve([]); + } + + private doLaunchProcess(jvm: JVM, launcher: string, args: string[] =[]): LanguageServerProcess { + let vmArgs = args.concat([ + // Atom doesn't have lazy completion proposals support - completionItem/resolve message. Disable lazy completions + '-Dsts.lsp.client=atom', + '-Dlsp.completions.indentation.enable=true', + '-Dlsp.yaml.completions.errors.disable=true', + ]); + + this.logger.debug(`starting "${jvm.getJavaExecutable()} ${vmArgs.join('\n')}\n-jar ${launcher}"`); + return jvm.jarLaunch(launcher, vmArgs, { cwd: this.serverHome }); + } + + createStsAdapter(): StsAdapter | null { + return null; + } + +} + diff --git a/atom-extensions/atom-commons/lib/main.ts b/atom-extensions/atom-commons/lib/main.ts new file mode 100644 index 000000000..a196c7880 --- /dev/null +++ b/atom-extensions/atom-commons/lib/main.ts @@ -0,0 +1,10 @@ +import {JavaProcessLanguageClient} from './java-process-language-client'; +import {StsAdapter, CursorMovementParams, HighlightParams, ProgressParams} from './sts-adapter'; + +export { + JavaProcessLanguageClient, + StsAdapter, + CursorMovementParams, + HighlightParams, + ProgressParams +} \ No newline at end of file diff --git a/atom-extensions/atom-commons/lib/sts-adapter.js b/atom-extensions/atom-commons/lib/sts-adapter.js deleted file mode 100644 index 45c7e12ea..000000000 --- a/atom-extensions/atom-commons/lib/sts-adapter.js +++ /dev/null @@ -1,20 +0,0 @@ -import {Convert} from 'atom-languageclient'; - -export class StsAdapter { - - constructor() {} - - findEditors(uri) { - return atom.workspace.getTextEditors() - .filter(e => e && e.getPath() && Convert.pathToUri(e.getPath()) === uri); - } - - onMoveCursor(params) { - findEditors(params.uri).forEach(e => e.setCursorScreenPosition(Convert.positionToPoint(params.position))); - return { applied: true}; - } - - onProgress(params) {} - - onHighlight(params) {} -} diff --git a/atom-extensions/atom-commons/lib/sts-adapter.ts b/atom-extensions/atom-commons/lib/sts-adapter.ts new file mode 100644 index 000000000..649632c56 --- /dev/null +++ b/atom-extensions/atom-commons/lib/sts-adapter.ts @@ -0,0 +1,38 @@ +import {Convert} from 'atom-languageclient'; +import {AtomEnvironment, TextEditor} from 'atom'; +import {Position, Range, TextDocumentIdentifier} from 'vscode-languageserver-protocol'; + +export class StsAdapter { + + constructor() {} + + findEditors(uri: string): TextEditor[] { + const atomEnv: AtomEnvironment = atom; + return atomEnv.workspace.getTextEditors() + .filter(e => e && e.getPath() && Convert.pathToUri(e.getPath() || '') === uri); + } + + onMoveCursor(params: CursorMovementParams): any { + this.findEditors(params.uri).forEach(e => e.setCursorScreenPosition(Convert.positionToPoint(params.position))); + return {applied: true}; + } + + onProgress(params: ProgressParams): void {} + + onHighlight(params: HighlightParams): void {} +} + +export interface CursorMovementParams { + readonly uri: string; + readonly position: Position; +} + +export interface ProgressParams { + readonly id: string; + readonly statusMsg: string; +} + +export interface HighlightParams { + readonly doc: TextDocumentIdentifier; + readonly ranges: Range[]; +} diff --git a/atom-extensions/atom-commons/package.json b/atom-extensions/atom-commons/package.json index 6652e0363..9ddbb592b 100644 --- a/atom-extensions/atom-commons/package.json +++ b/atom-extensions/atom-commons/package.json @@ -1,56 +1,35 @@ { "name": "@pivotal-tools/atom-languageclient-commons", - "version": "0.0.2", + "version": "0.0.4", "description": "Atom language client commons for STS4 language servers", "repository": "https://github.com/spring-projects/sts4", "license": "MIT", "engines": { - "atom": ">=1.17.0" + "atom": ">=1.24.0" }, - "dependencies": { - "@pivotal-tools/jvm-launch-utils": "0.0.11", - "atom-languageclient": "0.8.0", - "decompress": "^4.2.0", - "portfinder": "^1.0.13", - "postinstall-build": "5.0.1", - "remote-file-size": "^3.0.3" - }, - "main": "./build/lib/index", + "main": "./build/main", + "types": "./build/main.d.ts", "files": [ - "build/" + "build/", + "lib/" ], "scripts": { "clean": "rm -rf build", - "compile": "babel lib --out-dir build/lib", - "postinstall": "postinstall-build --only-as-dependency build \"npm run compile\"", - "prepublish": "npm run clean && npm run compile", - "watch": "babel lib --out-dir build/lib -w" + "compile": "tsc", + "watch": "tsc -watch", + "lint": "tslint -c tslint.json 'lib/**/*.ts'", + "prepublish": "npm run clean && npm run compile" + }, + "dependencies": { + "@pivotal-tools/jvm-launch-utils": "0.0.11", + "atom-languageclient": "0.9.2", + "portfinder": "^1.0.13", + "@types/atom": "^1.24.1", + "@types/node": "^8.0.41", + "vscode-languageserver-protocol": "3.6.0-next.5" }, - "atomTranspilers": [ - { - "glob": "{lib}/**/*.js", - "transpiler": "atom-babel6-transpiler", - "options": { - "cacheKeyFiles": [ - "package.json", - ".babelrc" - ] - } - } - ], "devDependencies": { - "atom-babel6-transpiler": "0.0.3", - "babel-cli": "^6.24.0", - "babel-core": "6.22.1", - "babel-plugin-add-module-exports": "0.2.1", - "babel-plugin-transform-async-to-generator": "6.22.0", - "babel-plugin-transform-class-properties": "6.23.0", - "babel-plugin-transform-decorators-legacy": "1.3.4", - "babel-plugin-transform-do-expressions": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.23.0", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-function-bind": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.23.0" + "tslint": "^5.9.1", + "typescript": "^2.7.2" } } diff --git a/atom-extensions/atom-commons/tsconfig.json b/atom-extensions/atom-commons/tsconfig.json new file mode 100644 index 000000000..b22a85ff1 --- /dev/null +++ b/atom-extensions/atom-commons/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "build", + "lib": ["es7", "dom"], + "declaration": true, + "inlineSources": true, + "inlineSourceMap": true, + "strictNullChecks": true, + "noImplicitAny": true, + "baseUrl": "./" + }, + "include": [ + "lib/**/*.ts", + ] +} \ No newline at end of file diff --git a/atom-extensions/atom-commons/tslint.json b/atom-extensions/atom-commons/tslint.json new file mode 100644 index 000000000..068b76067 --- /dev/null +++ b/atom-extensions/atom-commons/tslint.json @@ -0,0 +1,31 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "quotemark": false, + "object-literal-sort-keys": false, + "ordered-imports": false, + "member-ordering": false, + "one-line": false, + "interface-name": false, + "variable-name": false, + "max-classes-per-file": false, + "no-unused-expression": false, + "no-empty": false, + "one-variable-per-declaration": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast", + "check-module" + ] + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/atom-extensions/atom-concourse/.gitignore b/atom-extensions/atom-concourse/.gitignore index 0dd84018c..9ad2c10c9 100644 --- a/atom-extensions/atom-concourse/.gitignore +++ b/atom-extensions/atom-concourse/.gitignore @@ -1,6 +1,7 @@ /.idea /node_modules /server +/build *.tgz *iml *.log \ No newline at end of file diff --git a/atom-extensions/atom-concourse/lib/main.js b/atom-extensions/atom-concourse/lib/concourse-ci-yaml-client.ts similarity index 73% rename from atom-extensions/atom-concourse/lib/main.js rename to atom-extensions/atom-concourse/lib/concourse-ci-yaml-client.ts index d8f0ff835..b075a8779 100644 --- a/atom-extensions/atom-concourse/lib/main.js +++ b/atom-extensions/atom-concourse/lib/concourse-ci-yaml-client.ts @@ -1,13 +1,12 @@ -const path = require('path'); -const { JavaProcessLanguageClient } = require('@pivotal-tools/atom-languageclient-commons'); -const PROPERTIES = require('../properties.json'); +import * as path from 'path'; +import { JavaProcessLanguageClient } from '@pivotal-tools/atom-languageclient-commons'; +import {JVM} from '@pivotal-tools/jvm-launch-utils'; -class ConcourseCiYamlClient extends JavaProcessLanguageClient { +export class ConcourseCiYamlClient extends JavaProcessLanguageClient { constructor() { //noinspection JSAnnotator super( - PROPERTIES.jarUrl, path.join(__dirname, '..', 'server'), 'concourse-language-server.jar' ); @@ -33,7 +32,7 @@ class ConcourseCiYamlClient extends JavaProcessLanguageClient { super.activate(); } - launchVmArgs(jvm) { + launchVmArgs(jvm: JVM) { return Promise.resolve([ '-Dorg.slf4j.simpleLogger.logFile=concourse-ci-yaml.log', '-Dorg.slf4j.simpleLogger.defaultLogLevel=debug', @@ -41,6 +40,4 @@ class ConcourseCiYamlClient extends JavaProcessLanguageClient { } -} - -module.exports = new ConcourseCiYamlClient(); +} \ No newline at end of file diff --git a/atom-extensions/atom-concourse/lib/main.ts b/atom-extensions/atom-concourse/lib/main.ts new file mode 100644 index 000000000..d441a0d1d --- /dev/null +++ b/atom-extensions/atom-concourse/lib/main.ts @@ -0,0 +1,3 @@ +import {ConcourseCiYamlClient} from './concourse-ci-yaml-client'; + +module.exports = new ConcourseCiYamlClient(); \ No newline at end of file diff --git a/atom-extensions/atom-concourse/package.json b/atom-extensions/atom-concourse/package.json index 80dcea653..e34da2604 100644 --- a/atom-extensions/atom-concourse/package.json +++ b/atom-extensions/atom-concourse/package.json @@ -1,17 +1,19 @@ { "name": "concourse-pipeline-yaml", - "main": "./lib/main", "version": "0.1.5", "description": "Provides validation and content assist for Concourse CI pipeline and task configuration yml files", "repository": "https://github.com/spring-projects/atom-concourse", "icon": "icon.png", "license": "MIT", "engines": { - "atom": ">=1.21.0" + "atom": ">=1.24.0" }, + "main": "./build/main", + "types": "./build/main.d.ts", "files": [ "grammars/", "settings/", + "build/", "lib/", "server/", "properties.json" @@ -19,13 +21,19 @@ "dependencies": { "atom-package-deps": "^4.6.0", "download": "^6.2.5", - "@pivotal-tools/atom-languageclient-commons": "0.0.2" + "@pivotal-tools/atom-languageclient-commons": "0.0.4" }, "devDependencies": { + "typescript": "^2.7.2", + "tslint": "^5.9.1", "coffeelint": "^1.10.1" }, "scripts": { - "clean": "rm -fr node_modules", + "clean": "rm -fr build", + "compile": "tsc", + "build": "npm run clean && npm run compile ", + "watch": "tsc -watch", + "lint": "tslint -c tslint.json 'lib/**/*.ts'", "postinstall": "node script.js" }, "package-deps": [ diff --git a/atom-extensions/atom-concourse/tsconfig.json b/atom-extensions/atom-concourse/tsconfig.json new file mode 100644 index 000000000..a333b271b --- /dev/null +++ b/atom-extensions/atom-concourse/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "build", + "lib": ["es7", "dom"], + "declaration": true, + "inlineSources": true, + "inlineSourceMap": true, + "strictNullChecks": true, + "noImplicitAny": true, + "baseUrl": "./" + }, + "include": [ + "lib/**/*.ts" + ] +} \ No newline at end of file diff --git a/atom-extensions/atom-concourse/tslint.json b/atom-extensions/atom-concourse/tslint.json new file mode 100644 index 000000000..068b76067 --- /dev/null +++ b/atom-extensions/atom-concourse/tslint.json @@ -0,0 +1,31 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "quotemark": false, + "object-literal-sort-keys": false, + "ordered-imports": false, + "member-ordering": false, + "one-line": false, + "interface-name": false, + "variable-name": false, + "max-classes-per-file": false, + "no-unused-expression": false, + "no-empty": false, + "one-variable-per-declaration": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast", + "check-module" + ] + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/atom-extensions/atom-spring-boot/.gitignore b/atom-extensions/atom-spring-boot/.gitignore index 38d57c0ad..2e6ca2885 100644 --- a/atom-extensions/atom-spring-boot/.gitignore +++ b/atom-extensions/atom-spring-boot/.gitignore @@ -1,3 +1,4 @@ .idea/ server/ node_modules/ +build/ diff --git a/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts b/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts new file mode 100644 index 000000000..d028a686f --- /dev/null +++ b/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts @@ -0,0 +1,56 @@ +import {StsAdapter, HighlightParams} from '@pivotal-tools/atom-languageclient-commons'; +import {Convert} from 'atom-languageclient'; +import { Range } from 'vscode-languageserver-protocol'; +import {TextEditor} from 'atom'; + +const BOOT_DATA_MARKER_TYPE: any = 'BootApp-Hint'; +const BOOT_HINT_GUTTER_NAME = 'boot-hint-gutter'; + +export class BootStsAdapter extends StsAdapter { + + constructor() { + super(); + } + + onHighlight(params: HighlightParams) { + this.findEditors(params.doc.uri).forEach(editor => this.markHintsForEditor(editor, params.ranges)); + } + + private markHintsForEditor(editor: TextEditor, ranges: Range[]) { + editor.findMarkers(BOOT_DATA_MARKER_TYPE).forEach(m => m.destroy()); + if (Array.isArray(ranges)) { + ranges.forEach(range => this.createHintMarker(editor, range)); + } + const gutter = editor.gutterWithName(BOOT_HINT_GUTTER_NAME); + if (gutter) { + if (!ranges || !ranges.length) { + gutter.hide(); + } else if (!gutter.isVisible()) { + gutter.show(); + } + } + } + + private createHintMarker(editor: TextEditor, range: Range) { + // Create marker model + const marker = editor.markBufferRange(Convert.lsRangeToAtomRange(range), BOOT_DATA_MARKER_TYPE); + + // Marker around the text in the editor + editor.decorateMarker(marker, { + type: 'highlight', + class: 'boot-hint' + }); + + // Marker in the diagnostic gutter + let gutter = editor.gutterWithName(BOOT_HINT_GUTTER_NAME); + if (!gutter) { + gutter = editor.addGutter({ + name: BOOT_HINT_GUTTER_NAME, + visible: false, + }); + } + const iconElement = document.createElement('span'); + iconElement.setAttribute('class', 'gutter-boot-hint'); + gutter.decorateMarker(marker, {item: iconElement}); + } +} \ No newline at end of file diff --git a/atom-extensions/atom-spring-boot/lib/main.js b/atom-extensions/atom-spring-boot/lib/main.js deleted file mode 100644 index 9e78051d2..000000000 --- a/atom-extensions/atom-spring-boot/lib/main.js +++ /dev/null @@ -1,128 +0,0 @@ -const path = require('path'); -const { JavaProcessLanguageClient, StsAdapter } = require('@pivotal-tools/atom-languageclient-commons'); -const { Convert } = require('atom-languageclient'); -const PROPERTIES = require('../properties.json'); - -const BOOT_DATA_MARKER_TYPE = 'BootApp-Hint'; -const BOOT_HINT_GUTTER_NAME = 'boot-hint-gutter'; - -class SpringBootLanguageClient extends JavaProcessLanguageClient { - - constructor() { - //noinspection JSAnnotator - super( - PROPERTIES.jarUrl, - path.join(__dirname, '..', 'server'), - 'spring-boot-language-server.jar' - ); - // this.DEBUG = true; - } - - postInitialization(server) { - this.sendConfig(server); - this._disposable.add(atom.config.observe('boot-java', () => this.sendConfig(server))); - } - - sendConfig(server) { - server.connection.didChangeConfiguration({ settings: {'boot-java': atom.config.get('boot-java') }}); - } - - getGrammarScopes() { - return ['source.java', 'source.boot-properties', 'source.boot-properties-yaml']; - } - - getLanguageName() { - return 'spring-boot'; - } - - getServerName() { - return 'Spring Boot'; - } - - activate() { - require('atom-package-deps') - .install('spring-boot') - .then(() => console.debug('All dependencies installed, good to go')); - super.activate(); - } - - preferJdk() { - return true; - } - - launchVmArgs(jvm) { - let vmargs = [ - // '-Xdebug', - // '-agentlib:jdwp=transport=dt_socket,server=y,address=7999,suspend=n', - '-Dorg.slf4j.simpleLogger.logFile=boot-java.log', - '-Dorg.slf4j.simpleLogger.defaultLogLevel=debug', - ]; - if (!jvm.isJdk()) { - this.showErrorMessage( - '"Boot-Java" Package Functionality Limited', - 'JAVA_HOME or PATH environment variable seems to point to a JRE. A JDK is required, hence Boot Hints are unavailable.' - ); - } - return Promise.resolve(vmargs); - } - - createStsAdapter() { - return new BootStsAdapter(); - } - - filterChangeWatchedFiles(filePath) { - return filePath.endsWith('.gradle') || filePath.endsWith(path.join('', 'pom.xml')); - } - -} - -class BootStsAdapter extends StsAdapter { - - constructor() { - super(); - } - - onHighlight(params) { - this.findEditors(params.doc.uri).forEach(editor => this.markHintsForEditor(editor, params.ranges)); - } - - markHintsForEditor(editor, ranges) { - editor.findMarkers(BOOT_DATA_MARKER_TYPE).forEach(m => m.destroy()); - if (Array.isArray(ranges)) { - ranges.forEach(range => this.createHintMarker(editor, range)); - } - const gutter = editor.gutterWithName(BOOT_HINT_GUTTER_NAME); - if (gutter) { - if (!ranges || !ranges.length) { - gutter.hide(); - } else if (!gutter.isVisible()) { - gutter.show(); - } - } - } - - createHintMarker(editor, range) { - // Create marker model - const marker = editor.markBufferRange(Convert.lsRangeToAtomRange(range), BOOT_DATA_MARKER_TYPE); - - // Marker around the text in the editor - editor.decorateMarker(marker, { - type: 'highlight', - class: 'boot-hint' - }); - - // Marker in the diagnostic gutter - let gutter = editor.gutterWithName(BOOT_HINT_GUTTER_NAME); - if (!gutter) { - gutter = editor.addGutter({ - name: BOOT_HINT_GUTTER_NAME, - visible: false, - }); - } - const iconElement = document.createElement('span'); - iconElement.setAttribute('class', 'gutter-boot-hint'); - gutter.decorateMarker(marker, {item: iconElement}); - } -} - -module.exports = new SpringBootLanguageClient(); diff --git a/atom-extensions/atom-spring-boot/lib/main.ts b/atom-extensions/atom-spring-boot/lib/main.ts new file mode 100644 index 000000000..d99dbed3a --- /dev/null +++ b/atom-extensions/atom-spring-boot/lib/main.ts @@ -0,0 +1,3 @@ +import {SpringBootLanguageClient} from './spring-boot-language-client'; + +module.exports = new SpringBootLanguageClient(); \ No newline at end of file diff --git a/atom-extensions/atom-spring-boot/lib/spring-boot-language-client.ts b/atom-extensions/atom-spring-boot/lib/spring-boot-language-client.ts new file mode 100644 index 000000000..1979d840e --- /dev/null +++ b/atom-extensions/atom-spring-boot/lib/spring-boot-language-client.ts @@ -0,0 +1,75 @@ +import * as path from 'path'; +import {JavaProcessLanguageClient} from '@pivotal-tools/atom-languageclient-commons'; +import {BootStsAdapter} from './boot-sts-adapter'; +import {ActiveServer} from 'atom-languageclient'; +import {JVM} from '@pivotal-tools/jvm-launch-utils'; + +export class SpringBootLanguageClient extends JavaProcessLanguageClient { + + constructor() { + //noinspection JSAnnotator + super( + path.join(__dirname, '..', 'server'), + 'spring-boot-language-server.jar' + ); + // this.DEBUG = true; + } + + protected postInitialization(server: ActiveServer) { + super.postInitialization(server); + this.sendConfig(server); + (this)._disposable.add(atom.config.observe('boot-java', () => this.sendConfig(server))); + } + + private sendConfig(server: ActiveServer) { + server.connection.didChangeConfiguration({ settings: {'boot-java': atom.config.get('boot-java') }}); + } + + getGrammarScopes() { + return ['source.java', 'source.boot-properties', 'source.boot-properties-yaml']; + } + + getLanguageName() { + return 'spring-boot'; + } + + getServerName() { + return 'Spring Boot'; + } + + activate() { + require('atom-package-deps') + .install('spring-boot') + .then(() => console.debug('All dependencies installed, good to go')); + super.activate(); + } + + preferJdk() { + return true; + } + + launchVmArgs(jvm: JVM) { + let vmargs = [ + // '-Xdebug', + // '-agentlib:jdwp=transport=dt_socket,server=y,address=7999,suspend=n', + '-Dorg.slf4j.simpleLogger.logFile=boot-java.log', + '-Dorg.slf4j.simpleLogger.defaultLogLevel=debug', + ]; + if (!jvm.isJdk()) { + this.showErrorMessage( + '"Boot-Java" Package Functionality Limited', + 'JAVA_HOME or PATH environment variable seems to point to a JRE. A JDK is required, hence Boot Hints are unavailable.' + ); + } + return Promise.resolve(vmargs); + } + + createStsAdapter() { + return new BootStsAdapter(); + } + + filterChangeWatchedFiles(filePath: string) { + return filePath.endsWith('.gradle') || filePath.endsWith(path.join('', 'pom.xml')); + } + +} diff --git a/atom-extensions/atom-spring-boot/package.json b/atom-extensions/atom-spring-boot/package.json index 1d034d6a9..81d663a7d 100644 --- a/atom-extensions/atom-spring-boot/package.json +++ b/atom-extensions/atom-spring-boot/package.json @@ -1,17 +1,19 @@ { "name": "spring-boot", - "main": "./lib/main", "version": "0.1.5", "description": "Spring Boot support for Atom", "repository": "https://github.com/spring-projects/atom-spring-boot", "icon": "icon.png", "license": "MIT", "engines": { - "atom": ">=1.21.0" + "atom": ">=1.24.0" }, + "main": "./build/main", + "types": "./build/main.d.ts", "files": [ "grammars/", "settings/", + "build/", "lib/", "server/", "styles/", @@ -25,16 +27,21 @@ } }, "dependencies": { - "@pivotal-tools/atom-languageclient-commons": "0.0.2", - "atom-languageclient": "0.8.0", + "@pivotal-tools/atom-languageclient-commons": "0.0.4", "atom-package-deps": "^4.6.0", "download": "^6.2.5" }, "devDependencies": { + "typescript": "^2.7.2", + "tslint": "^5.9.1", "coffeelint": "^1.10.1" }, "scripts": { - "clean": "rm -fr node_modules", + "clean": "rm -rf build", + "compile": "tsc", + "build": "npm run clean && npm run compile ", + "watch": "tsc -watch", + "lint": "tslint -c tslint.json 'lib/**/*.ts'", "postinstall": "node script.js" }, "package-deps": [ diff --git a/atom-extensions/atom-spring-boot/properties.json b/atom-extensions/atom-spring-boot/properties.json index fc5866d86..5f72a3b34 100644 --- a/atom-extensions/atom-spring-boot/properties.json +++ b/atom-extensions/atom-spring-boot/properties.json @@ -1,3 +1,3 @@ { - "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/spring-boot-language-server-0.1.5-201803022113.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/spring-boot-language-server-0.1.5-201803051440.jar" } diff --git a/atom-extensions/atom-spring-boot/tsconfig.json b/atom-extensions/atom-spring-boot/tsconfig.json new file mode 100644 index 000000000..a333b271b --- /dev/null +++ b/atom-extensions/atom-spring-boot/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "build", + "lib": ["es7", "dom"], + "declaration": true, + "inlineSources": true, + "inlineSourceMap": true, + "strictNullChecks": true, + "noImplicitAny": true, + "baseUrl": "./" + }, + "include": [ + "lib/**/*.ts" + ] +} \ No newline at end of file diff --git a/atom-extensions/atom-spring-boot/tslint.json b/atom-extensions/atom-spring-boot/tslint.json new file mode 100644 index 000000000..068b76067 --- /dev/null +++ b/atom-extensions/atom-spring-boot/tslint.json @@ -0,0 +1,31 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "quotemark": false, + "object-literal-sort-keys": false, + "ordered-imports": false, + "member-ordering": false, + "one-line": false, + "interface-name": false, + "variable-name": false, + "max-classes-per-file": false, + "no-unused-expression": false, + "no-empty": false, + "one-variable-per-declaration": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast", + "check-module" + ] + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/concourse/tasks/build-atom-package.sh b/concourse/tasks/build-atom-package.sh index bee5a4075..ebb7b06b3 100755 --- a/concourse/tasks/build-atom-package.sh +++ b/concourse/tasks/build-atom-package.sh @@ -11,6 +11,7 @@ fatjar_version=`cat fatjar/version` #cd $atom_commons #npm install +#npm run build cd $atom_package @@ -24,6 +25,8 @@ EOF npm install +npm run build + # push code to release repository cd $workdir From 1f219728a2fe41c8baa6c0af6806ee2697fb87d3 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Thu, 8 Mar 2018 19:46:30 -0500 Subject: [PATCH 09/30] Switch to Gradle 4.6 distro --- .../springframework/ide/vscode/commons/gradle/GradleCore.java | 4 ++-- .../ide/vscode/commons/gradle/GradleProjectTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleCore.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleCore.java index cef457221..f9af09e06 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleCore.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleCore.java @@ -76,8 +76,8 @@ public class GradleCore { */ ((DefaultGradleConnector) gradleConnector).daemonMaxIdleTime(1, TimeUnit.SECONDS); configuration.configure(gradleConnector); - // Use patched Gradle 4.3 distribution as a workaround for https://github.com/gradle/gradle/issues/2483 - gradleConnector.useDistribution(URI.create("http://s3-test.spring.io/sts4/custom-gradle-builds/gradle-4.3-build.zip")); + // Use patched Gradle 4.4 distribution or higher as a workaround for https://github.com/gradle/gradle/issues/2483 + gradleConnector.useGradleVersion("4.6"); connection = gradleConnector.connect(); return connection.getModel(modelType); } catch (GradleConnectionException e) { diff --git a/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java b/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java index 8e58dc89e..7def43ca1 100644 --- a/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java +++ b/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java @@ -83,7 +83,7 @@ public class GradleProjectTest { @Test public void outputFolder() throws Exception { GradleJavaProject project = getGradleProject("test-app-1"); - assertTrue(project.getClasspath().getOutputFolder().endsWith("bin")); + assertTrue(project.getClasspath().getOutputFolder().toString().contains("/bin")); } @Test From 125660ca3f1339c5cc3ae97afd0cda74e3724b02 Mon Sep 17 00:00:00 2001 From: Sam Bryant Date: Fri, 9 Mar 2018 08:14:47 +0000 Subject: [PATCH 10/30] update to new concourse domain --- atom-extensions/atom-concourse/README.md | 2 +- .../src/main/resources/desc/GetStep/get.md | 2 +- .../src/main/resources/desc/GitSource/ignore_paths.md | 4 ++-- .../src/main/resources/desc/GitSource/password.md | 2 +- .../src/main/resources/desc/GitSource/private_key.md | 2 +- .../src/main/resources/desc/Pipeline/groups.md | 2 +- .../src/main/resources/desc/PutStep/put.md | 6 +++--- .../src/main/resources/desc/PutStep/resource.md | 2 +- .../src/main/resources/desc/Resource/name.md | 2 +- .../src/main/resources/desc/TaskConfig/image_resource.md | 2 +- .../src/main/resources/desc/TaskConfig/inputs.md | 2 +- .../src/main/resources/desc/TaskConfig/outputs.md | 2 +- .../src/main/resources/desc/TaskStep/task.md | 2 +- vscode-extensions/vscode-concourse/README.md | 4 ++-- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/atom-extensions/atom-concourse/README.md b/atom-extensions/atom-concourse/README.md index 11e12d3f7..34cd347c8 100644 --- a/atom-extensions/atom-concourse/README.md +++ b/atom-extensions/atom-concourse/README.md @@ -2,7 +2,7 @@ [![macOS Build Status](https://travis-ci.org/spring-projects/atom-concourse.svg?branch=master)](https://travis-ci.org/spring-projects/atom-concourse) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1jvknxt9jhykgrxo?svg=true)](https://ci.appveyor.com/project/spring-projects/atom-concourse/branch/master) [![Dependency Status](https://david-dm.org/spring-projects/atom-concourse.svg)](https://david-dm.org/spring-projects/atom-concourse) This extension provides basic validation, content assist and hover infos -for editing Concourse [Pipeline](https://concourse.ci/pipelines.html) and [Task Configuration](https://concourse.ci/running-tasks.html) Files. +for editing Concourse [Pipeline](https://concourse-ci.org/pipelines.html) and [Task Configuration](https://concourse-ci.org/running-tasks.html) Files. It is recommended to use this extension package when `atom-ide-ui` atom extension package is installed. Thus, reconciling (error/warning markers) and hover support is fully functional. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/GetStep/get.md b/headless-services/concourse-language-server/src/main/resources/desc/GetStep/get.md index e8edb17eb..c55bf8c5a 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/GetStep/get.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/GetStep/get.md @@ -17,5 +17,5 @@ plan: get: string ``` -*Required.* The logical name of the resource being fetched. This name satisfies logical inputs to a [Task](https://concourse.ci/concepts.html#tasks), and may be referenced within the plan itself (e.g. in the `file` attribute of a `task` step). +*Required.* The logical name of the resource being fetched. This name satisfies logical inputs to a [Task](https://concourse-ci.org/concepts.html#tasks), and may be referenced within the plan itself (e.g. in the `file` attribute of a `task` step). diff --git a/headless-services/concourse-language-server/src/main/resources/desc/GitSource/ignore_paths.md b/headless-services/concourse-language-server/src/main/resources/desc/GitSource/ignore_paths.md index 7b829339a..1b9c4ba78 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/GitSource/ignore_paths.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/GitSource/ignore_paths.md @@ -3,8 +3,8 @@ to the specified files are ignored. Note that if you want to push commits that change these files via a `put`, the commit will still be "detected", as [`check` and `put` both introduce -versions](https://concourse.ci/pipeline-mechanics.html#collecting-versions). +versions](https://concourse-ci.org/pipeline-mechanics.html#collecting-versions). To avoid this you should define a second resource that you use for commits that change files that you don't want to feed back into your pipeline - think of one as read-only (with `ignore_paths`) and one as write-only (which -shouldn't need it). \ No newline at end of file +shouldn't need it). diff --git a/headless-services/concourse-language-server/src/main/resources/desc/GitSource/password.md b/headless-services/concourse-language-server/src/main/resources/desc/GitSource/password.md index 5bdec2ca5..3c1ec79b6 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/GitSource/password.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/GitSource/password.md @@ -1,3 +1,3 @@ *Optional.* Password for HTTP(S) auth when pulling/pushing. -Note: You can also use pipeline templating to hide this password in source control. (For more information: https://concourse.ci/fly-set-pipeline.html) +Note: You can also use pipeline templating to hide this password in source control. (For more information: https://concourse-ci.org/fly-set-pipeline.html) diff --git a/headless-services/concourse-language-server/src/main/resources/desc/GitSource/private_key.md b/headless-services/concourse-language-server/src/main/resources/desc/GitSource/private_key.md index 509214543..10999a77a 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/GitSource/private_key.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/GitSource/private_key.md @@ -9,4 +9,4 @@ Example: DWiJL+OFeg9kawcUL6hQ8JeXPhlImG6RTUffma9+iGQyyBMCGd1l -----END RSA PRIVATE KEY----- -Note: You can also use pipeline templating to hide this private key in source control. (For more information: https://concourse.ci/fly-set-pipeline.html) \ No newline at end of file +Note: You can also use pipeline templating to hide this private key in source control. (For more information: https://concourse-ci.org/fly-set-pipeline.html) diff --git a/headless-services/concourse-language-server/src/main/resources/desc/Pipeline/groups.md b/headless-services/concourse-language-server/src/main/resources/desc/Pipeline/groups.md index ca5c424f2..5152f9cb5 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/Pipeline/groups.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/Pipeline/groups.md @@ -17,5 +17,5 @@ A simple grouping for the pipeline above may look like: This would display two tabs at the top of the home page: "tests" and "deploy". Once you have added groups to your pipeline then all jobs must be in a group otherwise they will not be visible. -For a real world example of how groups can be used to simplify navigation and provide logical grouping, see the groups used at the top of the page in the [Concourse pipeline](https://ci.concourse.ci/). +For a real world example of how groups can be used to simplify navigation and provide logical grouping, see the groups used at the top of the page in the [Concourse pipeline](https://ci.concourse-ci.org/). diff --git a/headless-services/concourse-language-server/src/main/resources/desc/PutStep/put.md b/headless-services/concourse-language-server/src/main/resources/desc/PutStep/put.md index 4811bc0a5..38d66e462 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/PutStep/put.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/PutStep/put.md @@ -1,7 +1,7 @@ -Pushes to the given [Resource](https://concourse.ci/concepts.html#resources). +Pushes to the given [Resource](https://concourse-ci.org/concepts.html#resources). All artifacts collected during the plan's execution will be available in the working directory. -For example, the following plan fetches a repo using [get](https://concourse.ci/get-step.html) and pushes it to another repo (assuming `repo-develop` and `repo-master` are defined as `git` resources): +For example, the following plan fetches a repo using [get](https://concourse-ci.org/get-step.html) and pushes it to another repo (assuming `repo-develop` and `repo-master` are defined as `git` resources): ``` plan: @@ -34,4 +34,4 @@ plan: put: string ``` -Required. The logical name of the resource being pushed. The pushed resource will be available under this name after the push succeeds. \ No newline at end of file +Required. The logical name of the resource being pushed. The pushed resource will be available under this name after the push succeeds. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/PutStep/resource.md b/headless-services/concourse-language-server/src/main/resources/desc/PutStep/resource.md index 2d615d13d..51307373f 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/PutStep/resource.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/PutStep/resource.md @@ -1,3 +1,3 @@ *Optional.* Defaults to `name`. -The resource to update, as configured in [resources](https://concourse.ci/configuring-resources.html). +The resource to update, as configured in [resources](https://concourse-ci.org/configuring-resources.html). diff --git a/headless-services/concourse-language-server/src/main/resources/desc/Resource/name.md b/headless-services/concourse-language-server/src/main/resources/desc/Resource/name.md index 7c5ceaa24..4e11c8bda 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/Resource/name.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/Resource/name.md @@ -1 +1 @@ -*Required.* The name of the resource. This should be short and simple. This name will be referenced by [build plans](https://concourse.ci/build-plans.html) of jobs in the pipeline. \ No newline at end of file +*Required.* The name of the resource. This should be short and simple. This name will be referenced by [build plans](https://concourse-ci.org/build-plans.html) of jobs in the pipeline. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/image_resource.md b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/image_resource.md index e4704e722..854cc9819 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/image_resource.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/image_resource.md @@ -19,4 +19,4 @@ The following example configures the task to use the `golang:1.6` Docker image: You can use any resource that returns a filesystem in the correct format (a `/rootfs` directory and a `metadata.json` file in the top level) but normally this will be the [Docker Image resource](https://github.com/concourse/docker-image-resource). If you'd like to make a resource of your own that supports this please use that as a reference implementation for now. -If you want to use an artifact source within the plan containing an image, you must set the [image](https://concourse.ci/task-step.html#task-image) in the plan step instead. \ No newline at end of file +If you want to use an artifact source within the plan containing an image, you must set the [image](https://concourse-ci.org/task-step.html#task-image) in the plan step instead. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/inputs.md b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/inputs.md index 94b55bbae..edc7f9fa8 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/inputs.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/inputs.md @@ -1,3 +1,3 @@ *Required.* The expected set of inputs for the task. -This determines which artifacts will propagate into the task, as the [build plan](https://concourse.ci/build-plans.html) executes. If any specified inputs are not present, the task will end with an error, without running. +This determines which artifacts will propagate into the task, as the [build plan](https://concourse-ci.org/build-plans.html) executes. If any specified inputs are not present, the task will end with an error, without running. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/outputs.md b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/outputs.md index 0d7bee54e..34addcce4 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/outputs.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/outputs.md @@ -1,6 +1,6 @@ *Optional.* The artifacts produced by the task. -Each output configures a directory to make available to later steps in the [build plan](https://concourse.ci/build-plans.html). The directory will be automatically created before the task runs, and the task should place any artifacts it wants to export in the directory. +Each output configures a directory to make available to later steps in the [build plan](https://concourse-ci.org/build-plans.html). The directory will be automatically created before the task runs, and the task should place any artifacts it wants to export in the directory. For example, the following task and script would be used to propagate a built binary to later steps: diff --git a/headless-services/concourse-language-server/src/main/resources/desc/TaskStep/task.md b/headless-services/concourse-language-server/src/main/resources/desc/TaskStep/task.md index 2f4b0a502..a0e279f89 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/TaskStep/task.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/TaskStep/task.md @@ -1,4 +1,4 @@ -Executes a [Task](https://concourse.ci/concepts.html#tasks), either from a file fetched via the preceding steps, or with inlined configuration. +Executes a [Task](https://concourse-ci.org/concepts.html#tasks), either from a file fetched via the preceding steps, or with inlined configuration. task: string diff --git a/vscode-extensions/vscode-concourse/README.md b/vscode-extensions/vscode-concourse/README.md index ea07bf277..cf80c123e 100644 --- a/vscode-extensions/vscode-concourse/README.md +++ b/vscode-extensions/vscode-concourse/README.md @@ -1,7 +1,7 @@ # Concourse Pipeline and Task Editor for Visual Studio Code This extension provides validation, content assist and documentation hovers -for editing [Concourse](https://concourse.ci/) Pipeline and Task configuration files. +for editing [Concourse](https://concourse-ci.org/) Pipeline and Task configuration files. ## Usage @@ -63,7 +63,7 @@ to its corresponding definition. ## Limitations -This Vscode Extension is still a work in progress. At the moment only a select few of the [built-in resource-types](https://concourse.ci/resource-types.html) +This Vscode Extension is still a work in progress. At the moment only a select few of the [built-in resource-types](https://concourse-ci.org/resource-types.html) have been fully defined in the Editor's Schema. The resource-types that are already defined in the schema are: From 37e57e4759ab786ec47ad739668d3f3d295b7376 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Fri, 9 Mar 2018 11:11:07 +0100 Subject: [PATCH 11/30] updated nightly download page to include various p2 repos --- .../common/html/nightly-distributions.html | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/eclipse-distribution/common/html/nightly-distributions.html b/eclipse-distribution/common/html/nightly-distributions.html index ae8f3ed17..cbb3d88b5 100644 --- a/eclipse-distribution/common/html/nightly-distributions.html +++ b/eclipse-distribution/common/html/nightly-distributions.html @@ -21,13 +21,31 @@ Instead add them to the available update sites in your Eclipse/STS preferences or paste them into the "Install New Software" dialog.

-

+

STS4 Distribution:

+

STS4 language server extensions (this repository is meant to be used to ship updates of the language server extensions to existing STS4 installations. In production, the release version of this repository is used.) +

+ +

+

+

+ +

STS3 language server extensions (this repository is used by existing STS3 installations and can be used to update the embedded CF manifest language server that is already used by STS3 independent of general STS3 releases. In production, the release version of this repository is used.) +

+ +

+

+

+

Eclipse-based Distribution Builds

Spring Tool Suite 4 - based on Eclipse Photon Milestone Builds (4.8.0 Mx)

From 69da4a859dff520a5f2bcce7b00e5a4d73d01dd2 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Fri, 9 Mar 2018 11:11:42 +0100 Subject: [PATCH 12/30] updated default preferences for update schedule and line numbers --- .../plugin_customization.ini | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/eclipse-distribution/org.springframework.boot.ide.branding/plugin_customization.ini b/eclipse-distribution/org.springframework.boot.ide.branding/plugin_customization.ini index 87bfff6f5..b440c52fb 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding/plugin_customization.ini +++ b/eclipse-distribution/org.springframework.boot.ide.branding/plugin_customization.ini @@ -30,28 +30,21 @@ org.eclipse.core.resources/refresh.lightweight.enabled=true # Order help books in table of contents org.eclipse.help/HELP_DATA = helpData.xml +# enable line number ruler in all textual editors by default +org.eclipse.ui.editors/lineNumberRuler=true + # Disable M2Eclipse repository index download org.eclipse.m2e.core/eclipse.m2.updateIndexes=false - -# Disable Atlassian connector data usage tracking -com.atlassian.connector.eclipse.monitor.usage/com.atlassian.connector.eclipse.monitor.usage.enabled=false -com.atlassian.connector.eclipse.monitor.ui/com.atlassian.connector.eclipse.monitor.usage.enabled=false -com.atlassian.connector.eclipse.monitor.ui/com.atlassian.connector.eclipse.monitor.usage.first.time=false +org.eclipse.m2e.core/eclipse.m2.downloadSources=true # Disable Mylyn service message org.eclipse.mylyn.tasks.ui/org.eclipse.mylyn.tasks.ui.servicemessage.id=0 -# check for updates every Tuesday at 10am +# check for updates # automatic update options are defined in org.eclipse.equinox.p2.sdk.scheduler.PreferenceConstants org.eclipse.equinox.p2.ui.sdk.scheduler/enabled=true -org.eclipse.equinox.p2.ui.sdk.scheduler/schedule=on-schedule -org.eclipse.equinox.p2.ui.sdk.scheduler/day=Every Tuesday -org.eclipse.equinox.p2.ui.sdk.scheduler/hour=10\:00 AM - -# remind the user every 24 hours -org.eclipse.equinox.p2.ui.sdk.scheduler/remindOnSchedule=true -# see AutomaticUpdatesPopup, values can be "30 minutes", "Hour", "4 Hours" -org.eclipse.equinox.p2.ui.sdk.scheduler/remindElapsedTime=24 Hours +org.eclipse.equinox.p2.ui.sdk.scheduler/schedule=on-fuzzy-schedule +org.eclipse.equinox.p2.ui.sdk.scheduler/fuzzy_recurrence=Once a week # download updates before notifying the user org.eclipse.equinox.p2.ui.sdk.scheduler/download=false From 63820f8c7ad9373e688757997526e158731fa480 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Fri, 9 Mar 2018 09:02:29 -0800 Subject: [PATCH 13/30] Fix one more reference to old concourse domain that was missed --- .../src/main/resources/desc/GetStep/version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headless-services/concourse-language-server/src/main/resources/desc/GetStep/version.md b/headless-services/concourse-language-server/src/main/resources/desc/GetStep/version.md index 784a162a0..0743906f1 100644 --- a/headless-services/concourse-language-server/src/main/resources/desc/GetStep/version.md +++ b/headless-services/concourse-language-server/src/main/resources/desc/GetStep/version.md @@ -4,4 +4,4 @@ If set to `latest`, scheduling will just find the latest available version of a If set to `every`, builds will walk through all available versions of the resource. Note that if `passed` is also configured, it will only step through the versions satisfying the constraints. -If set to a specific version (e.g. `{ref: abcdef123}`), only that version will be used. Note that the version must be available and detected by the resource, otherwise the input will never be satisfied. You may want to use [check-resource](https://concourse.ci/fly-check-resource.html) to force detection of resource versions, if you need to use an older one that was never detected (as all newly configured resources start from the latest version). \ No newline at end of file +If set to a specific version (e.g. `{ref: abcdef123}`), only that version will be used. Note that the version must be available and detected by the resource, otherwise the input will never be satisfied. You may want to use [check-resource](https://concourse-ci.org/fly-check-resource.html) to force detection of resource versions, if you need to use an older one that was never detected (as all newly configured resources start from the latest version). \ No newline at end of file From 34af9a522138bb8ae9898a9f753855c98c27e1e2 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Fri, 9 Mar 2018 11:15:14 -0800 Subject: [PATCH 14/30] Add task config to publish only concourse-vsix --- concourse/tasks/publish-concourse-vsix-release.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 concourse/tasks/publish-concourse-vsix-release.yml diff --git a/concourse/tasks/publish-concourse-vsix-release.yml b/concourse/tasks/publish-concourse-vsix-release.yml new file mode 100644 index 000000000..043079137 --- /dev/null +++ b/concourse/tasks/publish-concourse-vsix-release.yml @@ -0,0 +1,11 @@ +inputs: +- name: sts4 +- name: s3-concourse-vsix-snapshot +platform: linux +run: + path: sts4/concourse/tasks/publish-vsix-releases.sh +image_resource: + type: docker-image + source: + repository: kdvolder/sts4-build-env + \ No newline at end of file From 208fc66e4293b01cdec1eb3fd17154da0774198c Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Fri, 9 Mar 2018 11:44:39 -0800 Subject: [PATCH 15/30] Add job to publish only concourse-vsix --- concourse/pipeline.yml | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index dbd35bb23..acb05873d 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -734,6 +734,52 @@ jobs: - put: version params: file: version/version +- name: publish-concourse-vsix-release + serial: true + plan: + - aggregate: + - get: tasks + - get: sts4 + passed: + - build-concourse-rc + - get: version + passed: + - build-concourse-rc + params: + bump: final + - get: s3-concourse-vsix-snapshot + passed: + - build-concourse-rc + - task: publish-release + file: tasks/concourse/tasks/publish-concourse-vsix-release.yml + input_mapping: + sts4: tasks + params: + vsce_token: ((vsce_token)) + on_failure: + put: slack-notification + params: + text: | + Concourse ${BUILD_PIPELINE_NAME}/${BUILD_JOB_NAME}/${BUILD_NAME} has failed! + on_success: + put: slack-notification + params: + channel: "#tools-team-internal" + text_file: version/version + text: | + STS 4 VScode Extensions $TEXT_FILE_CONTENT released + Releases now available on Vscode Marketplace: + • + - aggregate: + - put: sts4-out + params: + repository: sts4 + only_tag: true + tag: version/version + tag_prefix: V_ + - put: version + params: + file: version/version - name: bump-version-patch serial: true plan: @@ -1016,6 +1062,7 @@ groups: - build-consourse-vsix-snapshot - build-bosh-vsix-snapshot - build-spring-boot-vsix-snapshot + - publish-concourse-vsix-release - name: bump-versions jobs: - bump-version-patch From 8e5f755e52f825446e0c0b700a478bc6cec3fc2d Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 15:21:51 -0500 Subject: [PATCH 16/30] Atom publish concourse support --- concourse/pipeline.yml | 41 +++++++++++++++++++++++ concourse/tasks/publish-atom-releases.sh | 20 +++++++++++ concourse/tasks/publish-atom-releases.yml | 13 +++++++ 3 files changed, 74 insertions(+) create mode 100644 concourse/tasks/publish-atom-releases.sh create mode 100644 concourse/tasks/publish-atom-releases.yml diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index acb05873d..b770d0ba6 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -529,6 +529,46 @@ jobs: params: repository: out/atom-cf-manifest-yaml only_tag: true +- name: publish-atom-releases + serial: true + plan: + - aggregate: + - get: sts4 + - get: atom-concourse + trigger: true + passed: + - tag-atom-release + - task: publish-atom-releases + file: tasks/concourse/tasks/publish-atom-releases.yml + params: + atom_token: ((atom_token)) + on_failure: + put: slack-notification + params: + text: | + Concourse ${BUILD_PIPELINE_NAME}/${BUILD_JOB_NAME}/${BUILD_NAME} has failed! + on_success: + put: slack-notification + params: + channel: "#tools-team-internal" + text_file: version/version + text: | + STS 4 VScode Extensions $TEXT_FILE_CONTENT released + Releases now available on Vscode Marketplace: + • + • + • + • + - aggregate: + - put: sts4-out + params: + repository: sts4 + only_tag: true + tag: version/version + tag_prefix: V_ + - put: version + params: + file: version/version - name: build-concourse-rc plan: - aggregate: @@ -1083,6 +1123,7 @@ groups: - prepare-spring-boot-atom-rc - promote-fatjars-to-rc - tag-atom-release + - publish-atom-releases - name: setup jobs: - build-mvn-cache diff --git a/concourse/tasks/publish-atom-releases.sh b/concourse/tasks/publish-atom-releases.sh new file mode 100644 index 000000000..619d13e8c --- /dev/null +++ b/concourse/tasks/publish-atom-releases.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e +workdir=`pwd` + +atom_packages=`ls ${workdir}/atom-*` + +for atom_package in $atom_packages +do + echo "****************************************************************" + echo "*** Publishing : ${atom_package}" + echo "****************************************************************" + echo "" + echo "We are runing the following command:" + echo "" + echo " apm publish -p vsce_token --packagePath $vsix_file" + echo "" + tag=v$(cat package.json | jq -r ".version") + apm login --token $atom_token + apm publish --tag $tag +done diff --git a/concourse/tasks/publish-atom-releases.yml b/concourse/tasks/publish-atom-releases.yml new file mode 100644 index 000000000..7d733cc68 --- /dev/null +++ b/concourse/tasks/publish-atom-releases.yml @@ -0,0 +1,13 @@ +inputs: +- name: sts4 +- name: atom-concourse +params: + atom_token: atom_token_must_be_provided!!! +platform: linux +run: + path: sts4/concourse/tasks/publish-atom-releases.sh +image_resource: + type: docker-image + source: + repository: kdvolder/atom-apm + \ No newline at end of file From 1fd9e18b95d62bebd38a3f0455f44c01bb5f1f5a Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 15:39:15 -0500 Subject: [PATCH 17/30] Corrections to Atom concourse scripts --- concourse/pipeline.yml | 2 +- concourse/tasks/publish-atom-releases.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 concourse/tasks/publish-atom-releases.sh diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index b770d0ba6..e2fb775e5 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -539,7 +539,7 @@ jobs: passed: - tag-atom-release - task: publish-atom-releases - file: tasks/concourse/tasks/publish-atom-releases.yml + file: sts4/concourse/tasks/publish-atom-releases.yml params: atom_token: ((atom_token)) on_failure: diff --git a/concourse/tasks/publish-atom-releases.sh b/concourse/tasks/publish-atom-releases.sh old mode 100644 new mode 100755 From c93909f12f4dc6d417ca3d3e277bc06e9e341256 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 15:42:37 -0500 Subject: [PATCH 18/30] More corrections to Atom publish script --- concourse/tasks/publish-atom-releases.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/concourse/tasks/publish-atom-releases.sh b/concourse/tasks/publish-atom-releases.sh index 619d13e8c..64a9e7918 100755 --- a/concourse/tasks/publish-atom-releases.sh +++ b/concourse/tasks/publish-atom-releases.sh @@ -14,6 +14,7 @@ do echo "" echo " apm publish -p vsce_token --packagePath $vsix_file" echo "" + cd $workdir/$atom_package tag=v$(cat package.json | jq -r ".version") apm login --token $atom_token apm publish --tag $tag From f047d29dade49202fc358b7c057f2b49c8ed8f61 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 15:49:12 -0500 Subject: [PATCH 19/30] More corrections to Atom publish scripts --- concourse/tasks/publish-atom-releases.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/concourse/tasks/publish-atom-releases.sh b/concourse/tasks/publish-atom-releases.sh index 64a9e7918..ad8254bdb 100755 --- a/concourse/tasks/publish-atom-releases.sh +++ b/concourse/tasks/publish-atom-releases.sh @@ -2,18 +2,13 @@ set -e workdir=`pwd` -atom_packages=`ls ${workdir}/atom-*` +atom_packages=`ls -d ${workdir}/atom-*` for atom_package in $atom_packages do echo "****************************************************************" echo "*** Publishing : ${atom_package}" echo "****************************************************************" - echo "" - echo "We are runing the following command:" - echo "" - echo " apm publish -p vsce_token --packagePath $vsix_file" - echo "" cd $workdir/$atom_package tag=v$(cat package.json | jq -r ".version") apm login --token $atom_token From 5cd58e85bb476fbd31a96a3139989af37df879a9 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 15:53:32 -0500 Subject: [PATCH 20/30] More corrections for Atom publish scripts --- concourse/tasks/publish-atom-releases.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concourse/tasks/publish-atom-releases.sh b/concourse/tasks/publish-atom-releases.sh index ad8254bdb..6f3b11f35 100755 --- a/concourse/tasks/publish-atom-releases.sh +++ b/concourse/tasks/publish-atom-releases.sh @@ -2,7 +2,7 @@ set -e workdir=`pwd` -atom_packages=`ls -d ${workdir}/atom-*` +atom_packages=`ls -d atom-*` for atom_package in $atom_packages do From b4cacba513fb3957957dfbdf738b05df5c13cd74 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 16:08:34 -0500 Subject: [PATCH 21/30] Provide Atom access token to headless build --- concourse/tasks/publish-atom-releases.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/concourse/tasks/publish-atom-releases.sh b/concourse/tasks/publish-atom-releases.sh index 6f3b11f35..1fc068c9a 100755 --- a/concourse/tasks/publish-atom-releases.sh +++ b/concourse/tasks/publish-atom-releases.sh @@ -11,6 +11,7 @@ do echo "****************************************************************" cd $workdir/$atom_package tag=v$(cat package.json | jq -r ".version") - apm login --token $atom_token + export ATOM_ACCESS_TOKEN=$atom_token + # apm login --token $atom_token apm publish --tag $tag done From 014e8d0b8152366cfa792b28a69ea844e11627da Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 16:19:52 -0500 Subject: [PATCH 22/30] Finalize Atom publish scripts --- concourse/pipeline.yml | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index e2fb775e5..9f92fd210 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -551,24 +551,10 @@ jobs: put: slack-notification params: channel: "#tools-team-internal" - text_file: version/version text: | - STS 4 VScode Extensions $TEXT_FILE_CONTENT released - Releases now available on Vscode Marketplace: - • - • - • - • - - aggregate: - - put: sts4-out - params: - repository: sts4 - only_tag: true - tag: version/version - tag_prefix: V_ - - put: version - params: - file: version/version + STS 4 Atom Extensions $TEXT_FILE_CONTENT released + Releases now available on Atom Marketplace: + • - name: build-concourse-rc plan: - aggregate: From efe8049bbad8fd7bad0fc7ee915118033e72f484 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Fri, 9 Mar 2018 22:11:06 +0000 Subject: [PATCH 23/30] Bump version to 0.1.6 --- atom-extensions/atom-bosh/package.json | 2 +- atom-extensions/atom-cf-manifest-yaml/package.json | 2 +- atom-extensions/atom-concourse/package.json | 2 +- atom-extensions/atom-spring-boot/package.json | 2 +- headless-services/bosh-language-server/pom.xml | 2 +- headless-services/commons/commons-boot-app-cli/pom.xml | 2 +- headless-services/commons/commons-cf/pom.xml | 2 +- headless-services/commons/commons-gradle/pom.xml | 2 +- headless-services/commons/commons-java/pom.xml | 2 +- headless-services/commons/commons-language-server/pom.xml | 2 +- headless-services/commons/commons-maven/pom.xml | 2 +- headless-services/commons/commons-util/pom.xml | 2 +- headless-services/commons/commons-yaml/pom.xml | 2 +- headless-services/commons/java-properties/pom.xml | 2 +- headless-services/commons/language-server-test-harness/pom.xml | 2 +- headless-services/commons/pom.xml | 2 +- headless-services/concourse-language-server/pom.xml | 2 +- headless-services/manifest-yaml-language-server/pom.xml | 2 +- headless-services/spring-boot-language-server/pom.xml | 2 +- vscode-extensions/vscode-bosh/package.json | 2 +- vscode-extensions/vscode-concourse/package.json | 2 +- vscode-extensions/vscode-manifest-yaml/package.json | 2 +- vscode-extensions/vscode-spring-boot/package.json | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/atom-extensions/atom-bosh/package.json b/atom-extensions/atom-bosh/package.json index 852e1d429..cb0262a5f 100644 --- a/atom-extensions/atom-bosh/package.json +++ b/atom-extensions/atom-bosh/package.json @@ -1,6 +1,6 @@ { "name": "bosh-yaml", - "version": "0.1.5", + "version": "0.1.6", "description": "Provides validation and content assist for various Bosh configuration files", "repository": "https://github.com/spring-projects/atom-bosh", "icon": "icon.png", diff --git a/atom-extensions/atom-cf-manifest-yaml/package.json b/atom-extensions/atom-cf-manifest-yaml/package.json index 36faca44a..7a37af272 100644 --- a/atom-extensions/atom-cf-manifest-yaml/package.json +++ b/atom-extensions/atom-cf-manifest-yaml/package.json @@ -1,6 +1,6 @@ { "name": "cf-manifest-yaml", - "version": "0.1.5", + "version": "0.1.6", "description": "Cloud Foundry Deployment Manifest YAML support for Atom", "repository": "https://github.com/spring-projects/atom-cf-manifest-yaml", "icon": "icon.png", diff --git a/atom-extensions/atom-concourse/package.json b/atom-extensions/atom-concourse/package.json index e34da2604..6403267dc 100644 --- a/atom-extensions/atom-concourse/package.json +++ b/atom-extensions/atom-concourse/package.json @@ -1,6 +1,6 @@ { "name": "concourse-pipeline-yaml", - "version": "0.1.5", + "version": "0.1.6", "description": "Provides validation and content assist for Concourse CI pipeline and task configuration yml files", "repository": "https://github.com/spring-projects/atom-concourse", "icon": "icon.png", diff --git a/atom-extensions/atom-spring-boot/package.json b/atom-extensions/atom-spring-boot/package.json index 81d663a7d..55c0ae214 100644 --- a/atom-extensions/atom-spring-boot/package.json +++ b/atom-extensions/atom-spring-boot/package.json @@ -1,6 +1,6 @@ { "name": "spring-boot", - "version": "0.1.5", + "version": "0.1.6", "description": "Spring Boot support for Atom", "repository": "https://github.com/spring-projects/atom-spring-boot", "icon": "icon.png", diff --git a/headless-services/bosh-language-server/pom.xml b/headless-services/bosh-language-server/pom.xml index 8ff50bf3c..697cc4320 100644 --- a/headless-services/bosh-language-server/pom.xml +++ b/headless-services/bosh-language-server/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/commons/commons-boot-app-cli/pom.xml b/headless-services/commons/commons-boot-app-cli/pom.xml index 430dd3947..c78d26c67 100644 --- a/headless-services/commons/commons-boot-app-cli/pom.xml +++ b/headless-services/commons/commons-boot-app-cli/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-cf/pom.xml b/headless-services/commons/commons-cf/pom.xml index 7e608e38b..6a194b823 100644 --- a/headless-services/commons/commons-cf/pom.xml +++ b/headless-services/commons/commons-cf/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-gradle/pom.xml b/headless-services/commons/commons-gradle/pom.xml index d747295e5..30be7b8ea 100644 --- a/headless-services/commons/commons-gradle/pom.xml +++ b/headless-services/commons/commons-gradle/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-java/pom.xml b/headless-services/commons/commons-java/pom.xml index 642f11823..ec2677d4f 100644 --- a/headless-services/commons/commons-java/pom.xml +++ b/headless-services/commons/commons-java/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-language-server/pom.xml b/headless-services/commons/commons-language-server/pom.xml index b2529ba7b..0313e223b 100644 --- a/headless-services/commons/commons-language-server/pom.xml +++ b/headless-services/commons/commons-language-server/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-maven/pom.xml b/headless-services/commons/commons-maven/pom.xml index 6ee5b1fcc..6bee0cd22 100644 --- a/headless-services/commons/commons-maven/pom.xml +++ b/headless-services/commons/commons-maven/pom.xml @@ -10,7 +10,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-util/pom.xml b/headless-services/commons/commons-util/pom.xml index 7ed256b38..517295f82 100644 --- a/headless-services/commons/commons-util/pom.xml +++ b/headless-services/commons/commons-util/pom.xml @@ -7,7 +7,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-yaml/pom.xml b/headless-services/commons/commons-yaml/pom.xml index d9831a553..70398f55a 100644 --- a/headless-services/commons/commons-yaml/pom.xml +++ b/headless-services/commons/commons-yaml/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/java-properties/pom.xml b/headless-services/commons/java-properties/pom.xml index 1f44a463c..49baea0dd 100644 --- a/headless-services/commons/java-properties/pom.xml +++ b/headless-services/commons/java-properties/pom.xml @@ -7,7 +7,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/language-server-test-harness/pom.xml b/headless-services/commons/language-server-test-harness/pom.xml index a6a93027e..79a02669c 100644 --- a/headless-services/commons/language-server-test-harness/pom.xml +++ b/headless-services/commons/language-server-test-harness/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/pom.xml b/headless-services/commons/pom.xml index 9359b9607..b0c6d8a8d 100644 --- a/headless-services/commons/pom.xml +++ b/headless-services/commons/pom.xml @@ -6,7 +6,7 @@ org.springframework.ide.vscode commons-parent pom - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT commons-parent diff --git a/headless-services/concourse-language-server/pom.xml b/headless-services/concourse-language-server/pom.xml index 693d01de1..79b8e5f86 100644 --- a/headless-services/concourse-language-server/pom.xml +++ b/headless-services/concourse-language-server/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/manifest-yaml-language-server/pom.xml b/headless-services/manifest-yaml-language-server/pom.xml index cf666382d..b2f11c6cf 100644 --- a/headless-services/manifest-yaml-language-server/pom.xml +++ b/headless-services/manifest-yaml-language-server/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/spring-boot-language-server/pom.xml b/headless-services/spring-boot-language-server/pom.xml index 7c197b297..a9cc190b7 100644 --- a/headless-services/spring-boot-language-server/pom.xml +++ b/headless-services/spring-boot-language-server/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT ../commons/pom.xml diff --git a/vscode-extensions/vscode-bosh/package.json b/vscode-extensions/vscode-bosh/package.json index c0b814310..c6b11ed5e 100644 --- a/vscode-extensions/vscode-bosh/package.json +++ b/vscode-extensions/vscode-bosh/package.json @@ -3,7 +3,7 @@ "displayName": "Bosh Editor", "description": "Provides validation and content assist for various Bosh configuration files", "icon": "icon.png", - "version": "0.1.5", + "version": "0.1.6", "publisher": "Pivotal", "repository": { "type": "git", diff --git a/vscode-extensions/vscode-concourse/package.json b/vscode-extensions/vscode-concourse/package.json index 46dc50e2b..7079769de 100644 --- a/vscode-extensions/vscode-concourse/package.json +++ b/vscode-extensions/vscode-concourse/package.json @@ -3,7 +3,7 @@ "displayName": "Concourse CI Pipeline Editor", "description": "Provides validation and content assist for Concourse CI pipeline and task configuration yml files", "icon": "icon.png", - "version": "0.1.5", + "version": "0.1.6", "publisher": "Pivotal", "repository": { "type": "git", diff --git a/vscode-extensions/vscode-manifest-yaml/package.json b/vscode-extensions/vscode-manifest-yaml/package.json index c38b3c4e6..0159b1be9 100644 --- a/vscode-extensions/vscode-manifest-yaml/package.json +++ b/vscode-extensions/vscode-manifest-yaml/package.json @@ -3,7 +3,7 @@ "displayName": "Cloudfoundry Manifest YML Support", "description": "Adds linting, content assist and hoverinfo's for Cloudfoundry Deployment Manifests (a.k.a. `manifest.yml`) files.", "icon": "icon.png", - "version": "0.1.5", + "version": "0.1.6", "publisher": "Pivotal", "repository": { "type": "git", diff --git a/vscode-extensions/vscode-spring-boot/package.json b/vscode-extensions/vscode-spring-boot/package.json index 85df507ea..2f6980f68 100644 --- a/vscode-extensions/vscode-spring-boot/package.json +++ b/vscode-extensions/vscode-spring-boot/package.json @@ -3,7 +3,7 @@ "displayName": "Spring Boot Tools", "description": "Provides validation and content assist for Spring Boot `application.properties`, `application.yml` properties files. As well as Boot-specific support for `.java` files.", "icon": "spring-boot-logo.png", - "version": "0.1.5", + "version": "0.1.6", "publisher": "Pivotal", "repository": { "type": "git", From c543b6b87dd1c12c221de3999f1e03b78290f50d Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 9 Mar 2018 17:25:51 -0500 Subject: [PATCH 24/30] Fix slack notification message --- concourse/pipeline.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index 9f92fd210..6172b66a8 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -552,7 +552,7 @@ jobs: params: channel: "#tools-team-internal" text: | - STS 4 Atom Extensions $TEXT_FILE_CONTENT released + STS 4 Atom Extensions released Releases now available on Atom Marketplace: • - name: build-concourse-rc @@ -1103,6 +1103,11 @@ groups: - build-spring-boot-atom-package - name: atom-release jobs: + - atom-language-servers-test + - build-concourse-atom-package + - build-bosh-atom-package + - build-manifest-yaml-atom-package + - build-spring-boot-atom-package - prepare-bosh-atom-rc - prepare-concourse-atom-rc - prepare-manifest-yaml-atom-rc From 1adbab0ac0f71281ca5accd754e0938da6e716fe Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Fri, 9 Mar 2018 11:40:01 +0100 Subject: [PATCH 25/30] added additional media types, taken from spring 5 MediaType constants --- .../java/requestmapping/MediaTypeMapping.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java index f834f255d..a3ecae47c 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/MediaTypeMapping.java @@ -15,11 +15,30 @@ package org.springframework.ide.vscode.boot.java.requestmapping; */ public enum MediaTypeMapping { - TEXT_PLAIN("text/plain"), + ALL("*/*"), + APPLICATION_ATOM_XML("application/atom+xml"), + APPLICATION_FORM_URLENCODED("application/x-www-form-urlencoded"), APPLICATION_JSON("application/json"), - APPLICATION_STREAM_JSON("application/stream+json"); + APPLICATION_JSON_UTF8("application/json;charset=UTF-8"), + APPLICATION_OCTET_STREAM("application/octet-stream"), + APPLICATION_PDF("application/pdf"), + APPLICATION_PROBLEM_JSON("application/problem+json"), + APPLICATION_PROBLEM_JSON_UTF8("application/problem+json;charset=UTF-8"), + APPLICATION_PROBLEM_XML("application/problem+xml"), + APPLICATION_RSS_XML("application/rss+xml"), + APPLICATION_STREAM_JSON("application/stream+json"), + APPLICATION_XHTML_XML("application/xhtml+xml"), + APPLICATION_XML("application/xml"), + IMAGE_GIF("image/gif"), + IMAGE_JPEG("image/jpeg"), + IMAGE_PNG("image/png"), + MULTIPART_FORM_DATA("multipart/form-data"), + TEXT_EVENT_STREAM("text/event-stream"), + TEXT_HTML("text/html"), + TEXT_MARKDOWN("text/markdown"), + TEXT_PLAIN("text/plain"), + TEXT_XML("text/xml"); - private String mediaType; private MediaTypeMapping(String mediaType) { From 3023bc22e8badb8990d627099dabdb42db4fdf3b Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Sun, 11 Mar 2018 08:24:26 +0100 Subject: [PATCH 26/30] further improvements to webflux symbol and code lens analysis, including content and accept type identification --- .../WebfluxAcceptTypeFinder.java | 22 +-- .../WebfluxContentTypeFinder.java | 15 +- .../WebfluxHandlerCodeLensProvider.java | 25 +-- .../WebfluxHandlerInformation.java | 26 +-- .../requestmapping/WebfluxMethodFinder.java | 14 +- .../WebfluxRouterSymbolProvider.java | 149 ++++++++++-------- .../java/requestmapping/WebfluxUtils.java | 32 +++- .../test/WebFluxCodeLensProviderTest.java | 38 ++++- .../WebFluxMappingSymbolProviderTest.java | 95 +++++++---- ...terExperiments.java => NestedRouter1.java} | 11 +- .../src/main/java/org/test/NestedRouter2.java | 35 ++++ .../{NestedRouter.java => NestedRouter3.java} | 4 +- ...PersonHandler.java => PersonHandler1.java} | 2 +- .../main/java/org/test/PersonHandler2.java | 22 +++ .../main/java/org/test/PersonHandler3.java | 22 +++ 15 files changed, 354 insertions(+), 158 deletions(-) rename headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/{RouterExperiments.java => NestedRouter1.java} (85%) create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter2.java rename headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/{NestedRouter.java => NestedRouter3.java} (94%) rename headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/{PersonHandler.java => PersonHandler1.java} (94%) create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler2.java create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java index f711b7281..c9b5dfa98 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.requestmapping; +import java.util.LinkedHashSet; +import java.util.Set; + import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.MethodInvocation; @@ -19,32 +22,31 @@ import org.eclipse.jdt.core.dom.MethodInvocation; */ public class WebfluxAcceptTypeFinder extends ASTVisitor { - private String acceptType; + private Set acceptTypes; public WebfluxAcceptTypeFinder() { + this.acceptTypes = new LinkedHashSet<>(); } - public String getAcceptType() { - return acceptType; + public Set getAcceptTypes() { + return acceptTypes; } @Override public boolean visit(MethodInvocation node) { - boolean visitChildren = true; - IMethodBinding methodBinding = node.resolveMethodBinding(); if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); if (name != null && WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(name)) { - acceptType = WebfluxUtils.extractSimpleNameArgument(node); + String acceptType = WebfluxUtils.extractSimpleNameArgument(node); + if (acceptType != null) { + acceptTypes.add(acceptType); + } } } - if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { - visitChildren = false; - } - return visitChildren; + return !WebfluxUtils.isRouteMethodInvocation(methodBinding); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java index e104c3a55..2e8cf56db 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.requestmapping; +import java.util.LinkedHashSet; +import java.util.Set; + import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.IMethodBinding; @@ -20,15 +23,16 @@ import org.eclipse.jdt.core.dom.MethodInvocation; */ public class WebfluxContentTypeFinder extends ASTVisitor { - private String contentType; + private Set contentTypes; private ASTNode root; public WebfluxContentTypeFinder(ASTNode root) { this.root = root; + this.contentTypes = new LinkedHashSet<>(); } - public String getContentType() { - return contentType; + public Set getContentTypes() { + return contentTypes; } @Override @@ -41,7 +45,10 @@ public class WebfluxContentTypeFinder extends ASTVisitor { if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); if (name != null && WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(name)) { - contentType = WebfluxUtils.extractSimpleNameArgument(node); + String contentType = WebfluxUtils.extractSimpleNameArgument(node); + if (contentType != null) { + contentTypes.add(contentType); + } } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java index 73950b090..fc14555d9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerCodeLensProvider.java @@ -72,11 +72,16 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider { CodeLens codeLens = new CodeLens(); codeLens.setRange(document.toRange(node.getName().getStartPosition(), node.getName().getLength())); - String codeLensCommand = handlerInfo.getHttpMethod() != null ? handlerInfo.getHttpMethod() + " " : ""; + String httpMethod = WebfluxUtils.getStringRep(handlerInfo.getHttpMethods(), string -> string); + String codeLensCommand = httpMethod != null ? httpMethod + " " : ""; + codeLensCommand += handlerInfo.getPath(); + + String acceptType = WebfluxUtils.getStringRep(handlerInfo.getAcceptTypes(), WebfluxUtils::getMediaType); + codeLensCommand += acceptType != null ? " - Accept: " + acceptType : ""; - codeLensCommand += handlerInfo.getAcceptType() != null ? " - Accept: " + getMediaType(handlerInfo.getAcceptType()) : ""; - codeLensCommand += handlerInfo.getContentType() != null ? " - Content-Type: " + getMediaType(handlerInfo.getContentType()) : ""; + String contentType = WebfluxUtils.getStringRep(handlerInfo.getContentTypes(), WebfluxUtils::getMediaType); + codeLensCommand += contentType != null ? " - Content-Type: " + contentType : ""; codeLens.setCommand(new Command(codeLensCommand, null)); @@ -89,18 +94,4 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider { } } - protected String getMediaType(String handlerInfo) { - if (handlerInfo == null) { - return null; - } - - try { - MediaTypeMapping mediaType = MediaTypeMapping.valueOf(handlerInfo); - return mediaType.getMediaType(); - } - catch (IllegalArgumentException e) { - return handlerInfo; - } - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java index 7f7b34142..6e8c993df 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerInformation.java @@ -19,18 +19,18 @@ public class WebfluxHandlerInformation { private final String handlerMethod; private final String path; - private final String httpMethod; - private final String contentType; - private final String acceptType; + private final String[] httpMethods; + private final String[] contentTypes; + private final String[] acceptTypes; - public WebfluxHandlerInformation(String handlerClass, String handlerMethod, String path, String httpMethod, String contentType, String acceptType) { + public WebfluxHandlerInformation(String handlerClass, String handlerMethod, String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) { this.handlerClass = handlerClass; this.handlerMethod = handlerMethod; this.path = path; - this.httpMethod = httpMethod; - this.contentType = contentType; - this.acceptType = acceptType; + this.httpMethods = httpMethods; + this.contentTypes = contentTypes; + this.acceptTypes = acceptTypes; } public String getHandlerClass() { @@ -45,16 +45,16 @@ public class WebfluxHandlerInformation { return path; } - public String getHttpMethod() { - return httpMethod; + public String[] getHttpMethods() { + return httpMethods; } - public String getContentType() { - return contentType; + public String[] getContentTypes() { + return contentTypes; } - public String getAcceptType() { - return acceptType; + public String[] getAcceptTypes() { + return acceptTypes; } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java index bef4fe7ba..57cbd1a54 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.requestmapping; +import java.util.LinkedHashSet; +import java.util.Set; + import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.IMethodBinding; @@ -20,15 +23,16 @@ import org.eclipse.jdt.core.dom.MethodInvocation; */ public class WebfluxMethodFinder extends ASTVisitor { - private String method; + private Set methods; private ASTNode root; public WebfluxMethodFinder(ASTNode root) { this.root = root; + this.methods = new LinkedHashSet<>(); } - public String getMethod() { - return method; + public Set getMethods() { + return methods; } @Override @@ -41,10 +45,10 @@ public class WebfluxMethodFinder extends ASTVisitor { if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); if (name != null && WebfluxUtils.REQUEST_PREDICATE_HTTPMETHOD_METHODS.contains(name)) { - method = name; + methods.add(name); } else if (name != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(name)) { - method = WebfluxUtils.extractQualifiedNameArgument(node); + methods.add(WebfluxUtils.extractQualifiedNameArgument(node)); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java index d7394dab6..7dce4b632 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.function.Function; import org.eclipse.jdt.core.dom.ASTNode; @@ -34,9 +35,6 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.TextDocument; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - /** * @author Martin Lippert */ @@ -92,10 +90,10 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List result) { String path = extractPath(node); - String httpMethod = extractMethod(node); - String contentType = extractContentType(node); - String acceptType = extractAcceptType(node); + String[] httpMethods = extractMethods(node); + String[] contentTypes = extractContentTypes(node); + String[] acceptTypes = extractAcceptTypes(node); int methodNameStart = node.getName().getStartPosition(); int invocationStart = node.getStartPosition(); @@ -103,9 +101,10 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { if (path != null && path.length() > 0) { try { Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart))); - String label = "@" + (path.startsWith("/") ? path : ("/" + path)) + (httpMethod == null || httpMethod.isEmpty() ? "" : " -- " + httpMethod); + String label = "@" + (path.startsWith("/") ? path : ("/" + path)); + label += (httpMethods == null || httpMethods.length == 0 ? "" : " -- " + WebfluxUtils.getStringRep(httpMethods, string -> string)); - WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethod, contentType, acceptType); + WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethods, contentTypes, acceptTypes); result.add(new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), handler)); } catch (BadLocationException e) { @@ -118,98 +117,107 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { WebfluxPathFinder pathFinder = new WebfluxPathFinder(routerInvocation); routerInvocation.accept(pathFinder); - String path = pathFinder.getPath(); - if (path == null) path = ""; + List path = new ArrayList<>(); + String firstPath = pathFinder.getPath(); + if (firstPath != null) { + path.add(firstPath); + } - return extractNestedValue(routerInvocation, path, (methodInvocationPathPrefix) -> { - IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + extractNestedValue(routerInvocation, path, (methodInvocation) -> { + IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); String methodName = methodBinding.getName(); if (WebfluxUtils.REQUEST_PREDICATE_PATH_METHOD.equals(methodName)) { - String additionalPath = WebfluxUtils.extractStringLiteralArgument(methodInvocationPathPrefix.getT1()); + String additionalPath = WebfluxUtils.extractStringLiteralArgument(methodInvocation); if (additionalPath != null && additionalPath.length() > 0) { - return additionalPath + methodInvocationPathPrefix.getT2(); + return additionalPath; } } - - return methodInvocationPathPrefix.getT2(); + return null; }); + + StringBuilder result = new StringBuilder(); + path.stream().forEach(part -> result.insert(0, part)); + + return result.toString(); + } - private String extractMethod(MethodInvocation routerInvocation) { + private String[] extractMethods(MethodInvocation routerInvocation) { WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation); - routerInvocation.accept(methodFinder); - - String method = methodFinder.getMethod(); - - return extractNestedValue(routerInvocation, method, (methodInvocationPathPrefix) -> { - IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); - String methodName = methodBinding.getName(); - - if (WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(methodName)) { - String newMethod = WebfluxUtils.extractStringLiteralArgument(methodInvocationPathPrefix.getT1()); - if (method == null) { - return newMethod; - } - } - - return methodInvocationPathPrefix.getT2(); - }); - } - - private String extractAcceptType(MethodInvocation routerInvocation) { - String acceptType = null; - - WebfluxAcceptTypeFinder acceptTypeFinder = new WebfluxAcceptTypeFinder(); List arguments = routerInvocation.arguments(); for (Object argument : arguments) { if (argument != null && argument instanceof ASTNode) { - ((ASTNode)argument).accept(acceptTypeFinder); - if (acceptTypeFinder.getAcceptType() != null) { - acceptType = acceptTypeFinder.getAcceptType(); - } + ((ASTNode)argument).accept(methodFinder); + } + } + + final Set methods = methodFinder.getMethods(); + + extractNestedValue(routerInvocation, methods, (methodInvocation) -> { + IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); + String methodName = methodBinding.getName(); + + if (WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(methodName)) { + return WebfluxUtils.extractStringLiteralArgument(methodInvocation); + } + return null; + }); + + return (String[]) methods.toArray(new String[methods.size()]); + } + + private String[] extractAcceptTypes(MethodInvocation routerInvocation) { + WebfluxAcceptTypeFinder typeFinder = new WebfluxAcceptTypeFinder(); + List arguments = routerInvocation.arguments(); + for (Object argument : arguments) { + if (argument != null && argument instanceof ASTNode) { + ((ASTNode)argument).accept(typeFinder); } } - return extractNestedValue(routerInvocation, acceptType, (methodInvocationPathPrefix) -> { - IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + Set acceptTypes = typeFinder.getAcceptTypes(); + + extractNestedValue(routerInvocation, acceptTypes, (methodInvocation) -> { + IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); String methodName = methodBinding.getName(); if (WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(methodName)) { - String newAcceptType = WebfluxUtils.extractSimpleNameArgument(methodInvocationPathPrefix.getT1()); - if (newAcceptType != null) { - return newAcceptType; - } + return WebfluxUtils.extractSimpleNameArgument(methodInvocation); } - - return methodInvocationPathPrefix.getT2(); + return null; }); + + return (String[]) acceptTypes.toArray(new String[acceptTypes.size()]); } - private String extractContentType(MethodInvocation routerInvocation) { + private String[] extractContentTypes(MethodInvocation routerInvocation) { WebfluxContentTypeFinder contentTypeFinder = new WebfluxContentTypeFinder(routerInvocation); - routerInvocation.accept(contentTypeFinder); + List arguments = routerInvocation.arguments(); + for (Object argument : arguments) { + if (argument != null && argument instanceof ASTNode) { + ((ASTNode)argument).accept(contentTypeFinder); + } + } - String contentType = contentTypeFinder.getContentType(); + Set contentTypes = contentTypeFinder.getContentTypes(); - return extractNestedValue(routerInvocation, contentType, (methodInvocationPathPrefix) -> { - IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding(); + extractNestedValue(routerInvocation, contentTypes, (methodInvocation) -> { + IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); String methodName = methodBinding.getName(); if (WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(methodName)) { - String newContentType = WebfluxUtils.extractSimpleNameArgument(methodInvocationPathPrefix.getT1()); - if (contentType == null) { - return newContentType; - } + return WebfluxUtils.extractSimpleNameArgument(methodInvocation); } - - return methodInvocationPathPrefix.getT2(); + return null; }); + + return (String[]) contentTypes.toArray(new String[contentTypes.size()]); } - private String extractNestedValue(ASTNode node, String value, Function, String> extractor) { + private void extractNestedValue(ASTNode node, Collection values, Function extractor) { if (node == null || node instanceof TypeDeclaration) { - return value; + return; } if (node instanceof MethodInvocation) { @@ -223,17 +231,20 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { for (Object argument : arguments) { if (argument instanceof MethodInvocation) { MethodInvocation nestedMethod = (MethodInvocation) argument; - value = extractor.apply(Tuples.of(nestedMethod, value)); + String value = extractor.apply(nestedMethod); + if (value != null) { + values.add(value); + } } } } } } - return extractNestedValue(node.getParent(), value, extractor); + extractNestedValue(node.getParent(), values, extractor); } - private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, String httpMethod, String contentType, String acceptType) { + private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) { List arguments = node.arguments(); if (arguments != null) { @@ -249,7 +260,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { String handlerMethod = methodBinding.getMethodDeclaration().toString(); if (handlerMethod != null) handlerMethod = handlerMethod.trim(); - return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, httpMethod, contentType, acceptType); + return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, httpMethods, contentTypes, acceptTypes); } } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java index 51c1a7a1f..b8b11ba91 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java @@ -14,6 +14,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.Function; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.MethodInvocation; @@ -80,8 +81,6 @@ public class WebfluxUtils { return null; } - - public static boolean isRouteMethodInvocation(IMethodBinding methodBinding) { if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); @@ -97,8 +96,35 @@ public class WebfluxUtils { } return false; - } + public static String getMediaType(String constantRep) { + if (constantRep == null) { + return null; + } + + try { + MediaTypeMapping mediaType = MediaTypeMapping.valueOf(constantRep); + return mediaType.getMediaType(); + } + catch (IllegalArgumentException e) { + return constantRep; + } + } + + public static String getStringRep(String[] multipleTypes, Function valueConverter) { + if (multipleTypes == null || multipleTypes.length == 0) return null; + + StringBuilder result = new StringBuilder(valueConverter.apply(multipleTypes[0])); + for (int i = 1; i < multipleTypes.length; i++) { + result.append(", "); + result.append(valueConverter.apply(multipleTypes[i])); + } + + return result.toString(); + } + + + } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java index d9a8a2a9a..27d91e82c 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java @@ -41,7 +41,7 @@ public class WebFluxCodeLensProviderTest { } @Test - public void testRoutesCodeLenses() throws Exception { + public void testRoutesCodeLensesSimpleCase() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); @@ -59,6 +59,42 @@ public class WebFluxCodeLensProviderTest { assertTrue(containsCodeLens(codeLenses, "GET /quotes - Accept: application/json", 41, 29, 41, 40)); } + @Test + public void testRoutesCodeLensesNestedRoutes1() throws Exception { + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); + + String docUri = directory.toPath().resolve("src/main/java/org/test/PersonHandler1.java").toUri().toString(); + TextDocumentInfo doc = harness.getOrReadFile(new File(new URI(docUri)), LanguageId.JAVA.toString()); + TextDocumentInfo openedDoc = harness.openDocument(doc); + + List codeLenses = harness.getCodeLenses(openedDoc); + + assertEquals(3, codeLenses.size()); + + assertTrue(containsCodeLens(codeLenses, "GET /person/{id} - Accept: application/json", 9, 29, 9, 38)); + assertTrue(containsCodeLens(codeLenses, "POST /person/ - Content-Type: application/json", 13, 29, 13, 41)); + assertTrue(containsCodeLens(codeLenses, "GET /person - Accept: application/json", 17, 29, 17, 39)); + } + + @Test + public void testRoutesCodeLensesNestedRoutes2() throws Exception { + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); + + String docUri = directory.toPath().resolve("src/main/java/org/test/PersonHandler2.java").toUri().toString(); + TextDocumentInfo doc = harness.getOrReadFile(new File(new URI(docUri)), LanguageId.JAVA.toString()); + TextDocumentInfo openedDoc = harness.openDocument(doc); + + List codeLenses = harness.getCodeLenses(openedDoc); + + assertEquals(3, codeLenses.size()); + + assertTrue(containsCodeLens(codeLenses, "GET /person/{id} - Accept: application/json", 9, 29, 9, 38)); + assertTrue(containsCodeLens(codeLenses, "POST / - Accept: application/json - Content-Type: application/json, application/pdf", 13, 29, 13, 41)); + assertTrue(containsCodeLens(codeLenses, "GET, HEAD /person - Accept: text/plain, application/json", 17, 29, 17, 39)); + } + private boolean containsCodeLens(List codeLenses, String commandTitle, int startLine, int startPosition, int endLine, int endPosition) { for (CodeLens codeLens : codeLenses) { Command command = codeLens.getCommand(); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index 4d6221074..3acb1d4c5 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -15,6 +15,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @@ -71,43 +72,43 @@ public class WebFluxMappingSymbolProviderTest { WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/hello", "GET").get(0); assertEquals("/hello", handlerInfo1.getPath()); - assertEquals("GET", handlerInfo1.getHttpMethod()); - assertNull(handlerInfo1.getContentType()); - assertEquals("TEXT_PLAIN", handlerInfo1.getAcceptType()); + assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods())); + assertEquals(0, handlerInfo1.getContentTypes().length); + assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerInfo1.getAcceptTypes())); assertEquals("org.test.QuoteHandler", handlerInfo1.getHandlerClass()); assertEquals("public Mono hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/echo", "POST").get(0); assertEquals("/echo", handlerInfo2.getPath()); - assertEquals("POST", handlerInfo2.getHttpMethod()); - assertEquals("TEXT_PLAIN", handlerInfo2.getContentType()); - assertEquals("TEXT_PLAIN", handlerInfo2.getAcceptType()); + assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods())); + assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerInfo2.getContentTypes())); + assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerInfo2.getAcceptTypes())); assertEquals("org.test.QuoteHandler", handlerInfo2.getHandlerClass()); assertEquals("public Mono echo(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/quotes", "GET").get(0); assertEquals("/quotes", handlerInfo3.getPath()); - assertEquals("GET", handlerInfo3.getHttpMethod()); - assertNull(handlerInfo3.getContentType()); - assertEquals("APPLICATION_STREAM_JSON", handlerInfo3.getAcceptType()); + assertEquals("[GET]", Arrays.toString(handlerInfo3.getHttpMethods())); + assertEquals(0, handlerInfo3.getContentTypes().length); + assertEquals("[APPLICATION_STREAM_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes())); assertEquals("org.test.QuoteHandler", handlerInfo3.getHandlerClass()); assertEquals("public Mono streamQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "/quotes", "GET").get(1); assertEquals("/quotes", handlerInfo4.getPath()); - assertEquals("GET", handlerInfo4.getHttpMethod()); - assertNull(handlerInfo4.getContentType()); - assertEquals("APPLICATION_JSON", handlerInfo4.getAcceptType()); + assertEquals("[GET]", Arrays.toString(handlerInfo4.getHttpMethods())); + assertEquals(0, handlerInfo4.getContentTypes().length); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo4.getAcceptTypes())); assertEquals("org.test.QuoteHandler", handlerInfo4.getHandlerClass()); assertEquals("public Mono fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod()); } @Test - public void testNestedRoutesMappingSymbols() throws Exception { + public void testNestedRoutesMappingSymbols1() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); - String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter.java").toUri().toString(); + String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter1.java").toUri().toString(); List symbols = getSymbols(docUri); assertEquals(5, symbols.size()); assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 27, 6, 27, 45)); @@ -119,26 +120,66 @@ public class WebFluxMappingSymbolProviderTest { WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0); assertEquals("/person/{id}", handlerInfo1.getPath()); - assertEquals("GET", handlerInfo1.getHttpMethod()); - assertNull(handlerInfo1.getContentType()); - assertEquals("APPLICATION_JSON", handlerInfo1.getAcceptType()); - assertEquals("org.test.PersonHandler", handlerInfo1.getHandlerClass()); + assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods())); + assertEquals(0, handlerInfo1.getContentTypes().length); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes())); + assertEquals("org.test.PersonHandler1", handlerInfo1.getHandlerClass()); assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/", "POST").get(0); assertEquals("/person/", handlerInfo2.getPath()); - assertEquals("POST", handlerInfo2.getHttpMethod()); - assertEquals("APPLICATION_JSON", handlerInfo2.getContentType()); - assertNull(handlerInfo2.getAcceptType()); - assertEquals("org.test.PersonHandler", handlerInfo2.getHandlerClass()); + assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods())); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getContentTypes())); + assertEquals(0, handlerInfo2.getAcceptTypes().length); + assertEquals("org.test.PersonHandler1", handlerInfo2.getHandlerClass()); assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "GET").get(0); assertEquals("/person", handlerInfo3.getPath()); - assertEquals("GET", handlerInfo3.getHttpMethod()); - assertNull(handlerInfo3.getContentType()); - assertEquals("APPLICATION_JSON", handlerInfo3.getAcceptType()); - assertEquals("org.test.PersonHandler", handlerInfo3.getHandlerClass()); + assertEquals("[GET]", Arrays.toString(handlerInfo3.getHttpMethods())); + assertEquals(0, handlerInfo3.getContentTypes().length); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes())); + assertEquals("org.test.PersonHandler1", handlerInfo3.getHandlerClass()); + assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); + } + + @Test + public void testNestedRoutesMappingSymbols2() throws Exception { + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); + + String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter2.java").toUri().toString(); + List symbols = getSymbols(docUri); + assertEquals(5, symbols.size()); + assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 29, 6, 29, 45)); + assertTrue(containsSymbol(symbols, "@/ -- POST", docUri, 31, 6, 31, 117)); + assertTrue(containsSymbol(symbols, "@/person -- GET, HEAD", docUri, 30, 7, 30, 113)); + + List addons = getAdditionalInformation(docUri); + assertEquals(3, addons.size()); + + WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0); + assertEquals("/person/{id}", handlerInfo1.getPath()); + assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods())); + assertEquals(0, handlerInfo1.getContentTypes().length); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes())); + assertEquals("org.test.PersonHandler2", handlerInfo1.getHandlerClass()); + assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/", "POST").get(0); + assertEquals("/", handlerInfo2.getPath()); + assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods())); + assertEquals("[APPLICATION_JSON, APPLICATION_PDF]", Arrays.toString(handlerInfo2.getContentTypes())); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getAcceptTypes())); + assertEquals("org.test.PersonHandler2", handlerInfo2.getHandlerClass()); + assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "HEAD").get(0); + assertEquals("/person", handlerInfo3.getPath()); + assertEquals("[GET, HEAD]", Arrays.toString(handlerInfo3.getHttpMethods())); + assertEquals(0, handlerInfo3.getContentTypes().length); + assertEquals("[TEXT_PLAIN, APPLICATION_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes())); + assertEquals("org.test.PersonHandler2", handlerInfo3.getHandlerClass()); assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); } @@ -171,7 +212,7 @@ public class WebFluxMappingSymbolProviderTest { return addons.stream() .filter((obj) -> obj instanceof WebfluxHandlerInformation) .map((obj -> (WebfluxHandlerInformation) obj)) - .filter((addon) -> addon.getPath().equals(path) && addon.getHttpMethod().equals(httpMethod)) + .filter((addon) -> addon.getPath().equals(path) && Arrays.asList(addon.getHttpMethods()).contains(httpMethod)) .collect(Collectors.toList()); } diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter1.java similarity index 85% rename from headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter1.java index 5634bed69..e409ee4bb 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/RouterExperiments.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter1.java @@ -17,18 +17,17 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; @Configuration -public class RouterExperiments { +public class NestedRouter1 { @Bean - public RouterFunction superRoutingFunction() { - PersonHandler handler = new PersonHandler(); + public RouterFunction routingFunction1() { + PersonHandler1 handler = new PersonHandler1(); - return nest(path("/super"), - nest(path("/something"), + return nest(path("/person"), nest(accept(APPLICATION_JSON), route(GET("/{id}"), handler::getPerson) .andRoute(method(HttpMethod.GET), handler::listPeople) - ).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson))); + ).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson)); } } diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter2.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter2.java new file mode 100644 index 000000000..83ccffcf9 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter2.java @@ -0,0 +1,35 @@ +package org.test; + +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.http.MediaType.APPLICATION_PDF; +import static org.springframework.http.MediaType.TEXT_PLAIN; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +import static org.springframework.web.reactive.function.server.RequestPredicates.accept; +import static org.springframework.web.reactive.function.server.RequestPredicates.contentType; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.nest; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerResponse; + +@Configuration +public class NestedRouter2 { + + @Bean + public RouterFunction routingFunction2() { + PersonHandler2 handler = new PersonHandler2(); + + return nest(accept(APPLICATION_JSON), + nest(path("/person"), + route(GET("/{id}"), handler::getPerson) + .andRoute(method(HttpMethod.GET).and(method(HttpMethod.HEAD)).and(accept(TEXT_PLAIN)), handler::listPeople) + ).andRoute(POST("/").and(contentType(APPLICATION_JSON)).and(contentType(APPLICATION_PDF)), handler::createPerson)); + } + +} diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java similarity index 94% rename from headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter.java rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java index 89d063b17..3abe41fbe 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java @@ -17,11 +17,11 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; @Configuration -public class NestedRouter { +public class NestedRouter3 { @Bean public RouterFunction routingFunction() { - PersonHandler handler = new PersonHandler(); + PersonHandler3 handler = new PersonHandler3(); return nest(path("/person"), nest(accept(APPLICATION_JSON), diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler1.java similarity index 94% rename from headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler.java rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler1.java index a1bdb96b4..73ceec1e6 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler1.java @@ -5,7 +5,7 @@ import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; -public class PersonHandler { +public class PersonHandler1 { public Mono getPerson(ServerRequest request) { return ServerResponse.notFound().build(); diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler2.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler2.java new file mode 100644 index 000000000..d4d60aecc --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler2.java @@ -0,0 +1,22 @@ +package org.test; + +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +import reactor.core.publisher.Mono; + +public class PersonHandler2 { + + public Mono getPerson(ServerRequest request) { + return ServerResponse.notFound().build(); + } + + public Mono createPerson(ServerRequest request) { + return ServerResponse.notFound().build(); + } + + public Mono listPeople(ServerRequest request) { + return ServerResponse.notFound().build(); + } + +} diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java new file mode 100644 index 000000000..b1ec76362 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java @@ -0,0 +1,22 @@ +package org.test; + +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +import reactor.core.publisher.Mono; + +public class PersonHandler3 { + + public Mono getPerson(ServerRequest request) { + return ServerResponse.notFound().build(); + } + + public Mono createPerson(ServerRequest request) { + return ServerResponse.notFound().build(); + } + + public Mono listPeople(ServerRequest request) { + return ServerResponse.notFound().build(); + } + +} From 62f975d74cff68a52078b35b3bdece5de6a217d8 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Sun, 11 Mar 2018 20:08:46 +0100 Subject: [PATCH 27/30] added more complex nested webflux router case and extracted symbol generation logic for routes --- .../RequestMappingSymbolProvider.java | 11 ++--- .../boot/java/requestmapping/RouteUtils.java | 38 +++++++++++++++ .../WebfluxRouterSymbolProvider.java | 13 ++--- .../java/requestmapping/WebfluxUtils.java | 2 +- .../test/WebFluxCodeLensProviderTest.java | 19 ++++++++ .../WebFluxMappingSymbolProviderTest.java | 47 ++++++++++++++++++- .../src/main/java/org/test/NestedRouter3.java | 14 ++++-- .../main/java/org/test/PersonHandler3.java | 4 ++ 8 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java index a2c34fb5a..868b2dafd 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java @@ -28,8 +28,6 @@ import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; -import org.eclipse.lsp4j.SymbolInformation; -import org.eclipse.lsp4j.SymbolKind; import org.springframework.ide.vscode.boot.java.Annotations; import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; @@ -48,9 +46,11 @@ public class RequestMappingSymbolProvider implements SymbolProvider { Location location = new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength())); String[] path = getPath(node); String[] parentPath = getParentPath(node); - String[] method = getMethod(node); + String[] methods = getMethod(node); + String[] contentTypes = new String[0]; + String[] acceptTypes = new String[0]; - String methodStr = method == null || method.length == 0 ? "" : String.join(",", method); +// String methodStr = method == null || method.length == 0 ? "" : String.join(",", method); return (parentPath == null ? Stream.of("") : Arrays.stream(parentPath)).filter(Objects::nonNull) .flatMap(parent -> (path == null ? Stream.empty() : Arrays.stream(path)) @@ -62,8 +62,7 @@ public class RequestMappingSymbolProvider implements SymbolProvider { } return resultPath.startsWith("/") ? resultPath : "/" + resultPath; })) - .map(p -> "@" + p + (methodStr.isEmpty() ? "" : " -- " + methodStr)) - .map(symbolLabel -> new EnhancedSymbolInformation(new SymbolInformation(symbolLabel, SymbolKind.Interface, location), null)) + .map(p -> RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes, null)) .collect(Collectors.toList()); } catch (Exception e) { e.printStackTrace(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java new file mode 100644 index 000000000..52ea11dcc --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2018 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.requestmapping; + +import org.eclipse.lsp4j.Location; +import org.eclipse.lsp4j.SymbolInformation; +import org.eclipse.lsp4j.SymbolKind; +import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; + +/** + * @author Martin Lippert + */ +public class RouteUtils { + + public static EnhancedSymbolInformation createRouteSymbol(Location location, String path, + String[] httpMethods, String[] contentTypes, String[] acceptTypes, Object enhancedInformation) { + + if (path != null && path.length() > 0) { + String label = "@" + (path.startsWith("/") ? path : ("/" + path)); + label += (httpMethods == null || httpMethods.length == 0 ? "" : " -- " + WebfluxUtils.getStringRep(httpMethods, string -> string)); + + return new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), enhancedInformation); + } + else { + return null; + } + + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java index 7dce4b632..9f0ea3d65 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java @@ -28,8 +28,6 @@ import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; -import org.eclipse.lsp4j.SymbolInformation; -import org.eclipse.lsp4j.SymbolKind; import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; import org.springframework.ide.vscode.commons.util.BadLocationException; @@ -100,13 +98,12 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { if (path != null && path.length() > 0) { try { - Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart))); - String label = "@" + (path.startsWith("/") ? path : ("/" + path)); - label += (httpMethods == null || httpMethods.length == 0 ? "" : " -- " + WebfluxUtils.getStringRep(httpMethods, string -> string)); + Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart))); WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethods, contentTypes, acceptTypes); - - result.add(new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), handler)); + + result.add(RouteUtils.createRouteSymbol(location, path, httpMethods, contentTypes, acceptTypes, handler)); + } catch (BadLocationException e) { e.printStackTrace(); } @@ -159,7 +156,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { String methodName = methodBinding.getName(); if (WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(methodName)) { - return WebfluxUtils.extractStringLiteralArgument(methodInvocation); + return WebfluxUtils.extractQualifiedNameArgument(methodInvocation); } return null; }); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java index b8b11ba91..b51e4921e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java @@ -117,7 +117,7 @@ public class WebfluxUtils { StringBuilder result = new StringBuilder(valueConverter.apply(multipleTypes[0])); for (int i = 1; i < multipleTypes.length; i++) { - result.append(", "); + result.append(","); result.append(valueConverter.apply(multipleTypes[i])); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java index 27d91e82c..daf21949a 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxCodeLensProviderTest.java @@ -90,9 +90,28 @@ public class WebFluxCodeLensProviderTest { assertEquals(3, codeLenses.size()); + assertTrue(containsCodeLens(codeLenses, "GET /person/{id} - Accept: application/json", 9, 29, 9, 38)); + assertTrue(containsCodeLens(codeLenses, "POST / - Accept: application/json - Content-Type: application/json,application/pdf", 13, 29, 13, 41)); + assertTrue(containsCodeLens(codeLenses, "GET,HEAD /person - Accept: text/plain,application/json", 17, 29, 17, 39)); + } + + @Test + public void testRoutesCodeLensesNestedRoutes3() throws Exception { + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); + + String docUri = directory.toPath().resolve("src/main/java/org/test/PersonHandler3.java").toUri().toString(); + TextDocumentInfo doc = harness.getOrReadFile(new File(new URI(docUri)), LanguageId.JAVA.toString()); + TextDocumentInfo openedDoc = harness.openDocument(doc); + + List codeLenses = harness.getCodeLenses(openedDoc); + + assertEquals(6, codeLenses.size()); +/* assertTrue(containsCodeLens(codeLenses, "GET /person/{id} - Accept: application/json", 9, 29, 9, 38)); assertTrue(containsCodeLens(codeLenses, "POST / - Accept: application/json - Content-Type: application/json, application/pdf", 13, 29, 13, 41)); assertTrue(containsCodeLens(codeLenses, "GET, HEAD /person - Accept: text/plain, application/json", 17, 29, 17, 39)); +*/ } private boolean containsCodeLens(List codeLenses, String commandTitle, int startLine, int startPosition, int endLine, int endPosition) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index 3acb1d4c5..1d7ae6bdc 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -153,7 +153,7 @@ public class WebFluxMappingSymbolProviderTest { assertEquals(5, symbols.size()); assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 29, 6, 29, 45)); assertTrue(containsSymbol(symbols, "@/ -- POST", docUri, 31, 6, 31, 117)); - assertTrue(containsSymbol(symbols, "@/person -- GET, HEAD", docUri, 30, 7, 30, 113)); + assertTrue(containsSymbol(symbols, "@/person -- GET,HEAD", docUri, 30, 7, 30, 113)); List addons = getAdditionalInformation(docUri); assertEquals(3, addons.size()); @@ -183,6 +183,51 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); } + @Test + public void testNestedRoutesMappingSymbols3() throws Exception { + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI())); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()); + + String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter3.java").toUri().toString(); + List symbols = getSymbols(docUri); + assertEquals(8, symbols.size()); + + assertTrue(containsSymbol(symbols, "@/person/sub1/sub2/{id} -- GET", docUri, 29, 7, 29, 46)); + assertTrue(containsSymbol(symbols, "@/person/sub1/sub2 -- GET", docUri, 30, 8, 30, 61)); + assertTrue(containsSymbol(symbols, "@/person/sub1/sub2/nestedGet -- GET", docUri, 31, 9, 31, 56)); + assertTrue(containsSymbol(symbols, "@/person/sub1/andNestPath/andNestPathGET -- GET", docUri, 33, 5, 33, 54)); + assertTrue(containsSymbol(symbols, "@/person/ -- POST", docUri, 34, 5, 34, 82)); + assertTrue(containsSymbol(symbols, "@/nestedDelete -- DELETE", docUri, 35, 42, 35, 93)); +/* + List addons = getAdditionalInformation(docUri); + assertEquals(3, addons.size()); + + WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0); + assertEquals("/person/{id}", handlerInfo1.getPath()); + assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods())); + assertEquals(0, handlerInfo1.getContentTypes().length); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes())); + assertEquals("org.test.PersonHandler2", handlerInfo1.getHandlerClass()); + assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/", "POST").get(0); + assertEquals("/", handlerInfo2.getPath()); + assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods())); + assertEquals("[APPLICATION_JSON, APPLICATION_PDF]", Arrays.toString(handlerInfo2.getContentTypes())); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getAcceptTypes())); + assertEquals("org.test.PersonHandler2", handlerInfo2.getHandlerClass()); + assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "HEAD").get(0); + assertEquals("/person", handlerInfo3.getPath()); + assertEquals("[GET, HEAD]", Arrays.toString(handlerInfo3.getHttpMethods())); + assertEquals(0, handlerInfo3.getContentTypes().length); + assertEquals("[TEXT_PLAIN, APPLICATION_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes())); + assertEquals("org.test.PersonHandler2", handlerInfo3.getHandlerClass()); + assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); +*/ + } + private boolean containsSymbol(List symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) { for (Iterator iterator = symbols.iterator(); iterator.hasNext();) { SymbolInformation symbol = iterator.next(); diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java index 3abe41fbe..fc6a567ee 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/NestedRouter3.java @@ -24,10 +24,16 @@ public class NestedRouter3 { PersonHandler3 handler = new PersonHandler3(); return nest(path("/person"), - nest(accept(APPLICATION_JSON), - route(GET("/{id}"), handler::getPerson) - .andRoute(method(HttpMethod.GET), handler::listPeople) - ).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson)); + nest(path("/sub1"), + nest(path("/sub2"), + nest(accept(APPLICATION_JSON), + route(GET("/{id}"), handler::getPerson) + .andRoute(method(HttpMethod.GET), handler::listPeople)) + .andRoute(GET("/nestedGet"), handler::getPerson)) + .and(nest(path("/andNestPath"), + route(GET("/andNestPathGET"), handler::getPerson)))) + .andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson)) + .and(nest(method(HttpMethod.DELETE), route(path("/nestedDelete"), handler::deletePerson))); } } diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java index b1ec76362..a1a48331e 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-webflux-project/src/main/java/org/test/PersonHandler3.java @@ -19,4 +19,8 @@ public class PersonHandler3 { return ServerResponse.notFound().build(); } + public Mono deletePerson(ServerRequest request) { + return ServerResponse.notFound().build(); + } + } From 36ddd52f8297bfc795ead9d33a02836cffaeacfc Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Mon, 12 Mar 2018 14:35:04 +0100 Subject: [PATCH 28/30] take content and accept types into account for annotation-defined request mapping symbols --- .../RequestMappingSymbolProvider.java | 44 +++++++++- .../boot/java/requestmapping/RouteUtils.java | 6 ++ .../java/requestmapping/WebfluxUtils.java | 4 + .../RequestMappingSymbolProviderTest.java | 30 ++++--- .../WebFluxMappingSymbolProviderTest.java | 85 ++++++++++++------- .../org/test/RequestMappingMediaTypes.java | 44 ++++++++++ 6 files changed, 167 insertions(+), 46 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/RequestMappingMediaTypes.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java index 868b2dafd..bd611e553 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java @@ -47,10 +47,8 @@ public class RequestMappingSymbolProvider implements SymbolProvider { String[] path = getPath(node); String[] parentPath = getParentPath(node); String[] methods = getMethod(node); - String[] contentTypes = new String[0]; - String[] acceptTypes = new String[0]; - -// String methodStr = method == null || method.length == 0 ? "" : String.join(",", method); + String[] contentTypes = getContentTypes(node); + String[] acceptTypes = getAcceptTypes(node); return (parentPath == null ? Stream.of("") : Arrays.stream(parentPath)).filter(Objects::nonNull) .flatMap(parent -> (path == null ? Stream.empty() : Arrays.stream(path)) @@ -175,6 +173,44 @@ public class RequestMappingSymbolProvider implements SymbolProvider { } return null; } + + private String[] getAcceptTypes(Annotation node) { + if (node.isNormalAnnotation()) { + NormalAnnotation normNode = (NormalAnnotation) node; + List values = normNode.values(); + for (Iterator iterator = values.iterator(); iterator.hasNext();) { + Object object = iterator.next(); + if (object instanceof MemberValuePair) { + MemberValuePair pair = (MemberValuePair) object; + String valueName = pair.getName().getIdentifier(); + if (valueName != null && valueName.equals("consumes")) { + Expression expression = pair.getValue(); + return ASTUtils.getExpressionValueAsArray(expression); + } + } + } + } + return new String[0]; + } + + private String[] getContentTypes(Annotation node) { + if (node.isNormalAnnotation()) { + NormalAnnotation normNode = (NormalAnnotation) node; + List values = normNode.values(); + for (Iterator iterator = values.iterator(); iterator.hasNext();) { + Object object = iterator.next(); + if (object instanceof MemberValuePair) { + MemberValuePair pair = (MemberValuePair) object; + String valueName = pair.getName().getIdentifier(); + if (valueName != null && valueName.equals("produces")) { + Expression expression = pair.getValue(); + return ASTUtils.getExpressionValueAsArray(expression); + } + } + } + } + return new String[0]; + } @Override public Collection getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java index 52ea11dcc..0cc7a4436 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RouteUtils.java @@ -26,6 +26,12 @@ public class RouteUtils { if (path != null && path.length() > 0) { String label = "@" + (path.startsWith("/") ? path : ("/" + path)); label += (httpMethods == null || httpMethods.length == 0 ? "" : " -- " + WebfluxUtils.getStringRep(httpMethods, string -> string)); + + String acceptType = WebfluxUtils.getStringRep(acceptTypes, WebfluxUtils::getMediaType); + label += acceptType != null ? " - Accept: " + acceptType : ""; + + String contentType = WebfluxUtils.getStringRep(contentTypes, WebfluxUtils::getMediaType); + label += contentType != null ? " - Content-Type: " + contentType : ""; return new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), enhancedInformation); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java index b51e4921e..b42bd79b4 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java @@ -104,6 +104,10 @@ public class WebfluxUtils { } try { + if (constantRep.endsWith("_VALUE")) { + constantRep = constantRep.substring(0, constantRep.lastIndexOf("_VALUE")); + } + MediaTypeMapping mediaType = MediaTypeMapping.valueOf(constantRep); return mediaType.getMediaType(); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java index a4d0538c3..4b1b191af 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java @@ -38,7 +38,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testSimpleRequestMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString(); @@ -50,7 +49,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testParentRequestMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/ParentMappingClass.java").toUri().toString(); @@ -62,7 +60,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testEmptyPathWithParentRequestMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/ParentMappingClass2.java").toUri().toString(); @@ -74,7 +71,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testMultiRequestMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/MultiRequestMappingClass.java").toUri().toString(); @@ -87,7 +83,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testGetMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); @@ -98,7 +93,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testDeleteMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); @@ -109,7 +103,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testPostMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); @@ -120,7 +113,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testPutMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); @@ -131,7 +123,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testPatchMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); @@ -142,7 +133,6 @@ public class RequestMappingSymbolProviderTest { @Test public void testGetRequestMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); @@ -153,13 +143,31 @@ public class RequestMappingSymbolProviderTest { @Test public void testMultiRequestMethodMappingSymbol() throws Exception { harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMethodClass.java").toUri().toString(); List symbols = getSymbols(docUri); assertTrue(containsSymbol(symbols, "@/postAndPutHello -- POST,PUT", docUri, 36, 1, 36, 76)); } + + @Test + public void testMediaTypes() throws Exception { + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI())); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()); + + String docUri = directory.toPath().resolve("src/main/java/org/test/RequestMappingMediaTypes.java").toUri().toString(); + List symbols = getSymbols(docUri); + assertEquals(7, symbols.size()); + assertTrue(containsSymbol(symbols, "@/consume1 -- HEAD - Accept: testconsume", docUri, 8, 1, 8, 90)); + assertTrue(containsSymbol(symbols, "@/consume2 - Accept: text/plain", docUri, 13, 1, 13, 73)); + assertTrue(containsSymbol(symbols, "@/consume3 - Accept: text/plain,testconsumetype", docUri, 18, 1, 18, 94)); + assertTrue(containsSymbol(symbols, "@/produce1 - Content-Type: testproduce", docUri, 23, 1, 23, 60)); + assertTrue(containsSymbol(symbols, "@/produce2 - Content-Type: text/plain", docUri, 28, 1, 28, 73)); + assertTrue(containsSymbol(symbols, "@/produce3 - Content-Type: text/plain,testproducetype", docUri, 33, 1, 33, 94)); + assertTrue(containsSymbol(symbols, "@/everything - Accept: application/json,text/plain,testconsume - Content-Type: application/json", docUri, 38, 1, 38, 170)); + } + + private boolean containsSymbol(List symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) { for (Iterator iterator = symbols.iterator(); iterator.hasNext();) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index 1d7ae6bdc..ba361103d 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -62,10 +62,10 @@ public class WebFluxMappingSymbolProviderTest { String docUri = directory.toPath().resolve("src/main/java/org/test/QuoteRouter.java").toUri().toString(); List symbols = getSymbols(docUri); assertEquals(6, symbols.size()); - assertTrue(containsSymbol(symbols, "@/hello -- GET", docUri, 22, 5, 22, 70)); - assertTrue(containsSymbol(symbols, "@/echo -- POST", docUri, 23, 5, 23, 101)); - assertTrue(containsSymbol(symbols, "@/quotes -- GET", docUri, 24, 5, 24, 86)); - assertTrue(containsSymbol(symbols, "@/quotes -- GET", docUri, 25, 5, 25, 94)); + assertTrue(containsSymbol(symbols, "@/hello -- GET - Accept: text/plain", docUri, 22, 5, 22, 70)); + assertTrue(containsSymbol(symbols, "@/echo -- POST - Accept: text/plain - Content-Type: text/plain", docUri, 23, 5, 23, 101)); + assertTrue(containsSymbol(symbols, "@/quotes -- GET - Accept: application/json", docUri, 24, 5, 24, 86)); + assertTrue(containsSymbol(symbols, "@/quotes -- GET - Accept: application/stream+json", docUri, 25, 5, 25, 94)); List addons = getAdditionalInformation(docUri); assertEquals(4, addons.size()); @@ -111,9 +111,9 @@ public class WebFluxMappingSymbolProviderTest { String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter1.java").toUri().toString(); List symbols = getSymbols(docUri); assertEquals(5, symbols.size()); - assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 27, 6, 27, 45)); - assertTrue(containsSymbol(symbols, "@/person/ -- POST", docUri, 29, 6, 29, 83)); - assertTrue(containsSymbol(symbols, "@/person -- GET", docUri, 28, 7, 28, 60)); + assertTrue(containsSymbol(symbols, "@/person/{id} -- GET - Accept: application/json", docUri, 27, 6, 27, 45)); + assertTrue(containsSymbol(symbols, "@/person/ -- POST - Content-Type: application/json", docUri, 29, 6, 29, 83)); + assertTrue(containsSymbol(symbols, "@/person -- GET - Accept: application/json", docUri, 28, 7, 28, 60)); List addons = getAdditionalInformation(docUri); assertEquals(3, addons.size()); @@ -151,9 +151,9 @@ public class WebFluxMappingSymbolProviderTest { String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter2.java").toUri().toString(); List symbols = getSymbols(docUri); assertEquals(5, symbols.size()); - assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 29, 6, 29, 45)); - assertTrue(containsSymbol(symbols, "@/ -- POST", docUri, 31, 6, 31, 117)); - assertTrue(containsSymbol(symbols, "@/person -- GET,HEAD", docUri, 30, 7, 30, 113)); + assertTrue(containsSymbol(symbols, "@/person/{id} -- GET - Accept: application/json", docUri, 29, 6, 29, 45)); + assertTrue(containsSymbol(symbols, "@/ -- POST - Accept: application/json - Content-Type: application/json,application/pdf", docUri, 31, 6, 31, 117)); + assertTrue(containsSymbol(symbols, "@/person -- GET,HEAD - Accept: text/plain,application/json", docUri, 30, 7, 30, 113)); List addons = getAdditionalInformation(docUri); assertEquals(3, addons.size()); @@ -192,40 +192,63 @@ public class WebFluxMappingSymbolProviderTest { List symbols = getSymbols(docUri); assertEquals(8, symbols.size()); - assertTrue(containsSymbol(symbols, "@/person/sub1/sub2/{id} -- GET", docUri, 29, 7, 29, 46)); - assertTrue(containsSymbol(symbols, "@/person/sub1/sub2 -- GET", docUri, 30, 8, 30, 61)); + assertTrue(containsSymbol(symbols, "@/person/sub1/sub2/{id} -- GET - Accept: application/json", docUri, 29, 7, 29, 46)); + assertTrue(containsSymbol(symbols, "@/person/sub1/sub2 -- GET - Accept: application/json", docUri, 30, 8, 30, 61)); assertTrue(containsSymbol(symbols, "@/person/sub1/sub2/nestedGet -- GET", docUri, 31, 9, 31, 56)); assertTrue(containsSymbol(symbols, "@/person/sub1/andNestPath/andNestPathGET -- GET", docUri, 33, 5, 33, 54)); - assertTrue(containsSymbol(symbols, "@/person/ -- POST", docUri, 34, 5, 34, 82)); + assertTrue(containsSymbol(symbols, "@/person/ -- POST - Content-Type: application/json", docUri, 34, 5, 34, 82)); assertTrue(containsSymbol(symbols, "@/nestedDelete -- DELETE", docUri, 35, 42, 35, 93)); -/* + List addons = getAdditionalInformation(docUri); - assertEquals(3, addons.size()); + assertEquals(6, addons.size()); - WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0); - assertEquals("/person/{id}", handlerInfo1.getPath()); + WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/sub1/sub2/{id}", "GET").get(0); + assertEquals("/person/sub1/sub2/{id}", handlerInfo1.getPath()); assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods())); assertEquals(0, handlerInfo1.getContentTypes().length); assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes())); - assertEquals("org.test.PersonHandler2", handlerInfo1.getHandlerClass()); + assertEquals("org.test.PersonHandler3", handlerInfo1.getHandlerClass()); assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/", "POST").get(0); - assertEquals("/", handlerInfo2.getPath()); - assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods())); - assertEquals("[APPLICATION_JSON, APPLICATION_PDF]", Arrays.toString(handlerInfo2.getContentTypes())); + WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/sub1/sub2", "GET").get(0); + assertEquals("/person/sub1/sub2", handlerInfo2.getPath()); + assertEquals("[GET]", Arrays.toString(handlerInfo2.getHttpMethods())); + assertEquals(0, handlerInfo2.getContentTypes().length); assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getAcceptTypes())); - assertEquals("org.test.PersonHandler2", handlerInfo2.getHandlerClass()); - assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); + assertEquals("org.test.PersonHandler3", handlerInfo1.getHandlerClass()); + assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod()); - WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "HEAD").get(0); - assertEquals("/person", handlerInfo3.getPath()); - assertEquals("[GET, HEAD]", Arrays.toString(handlerInfo3.getHttpMethods())); + WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person/sub1/sub2/nestedGet", "GET").get(0); + assertEquals("/person/sub1/sub2/nestedGet", handlerInfo3.getPath()); + assertEquals("[GET]", Arrays.toString(handlerInfo3.getHttpMethods())); assertEquals(0, handlerInfo3.getContentTypes().length); - assertEquals("[TEXT_PLAIN, APPLICATION_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes())); - assertEquals("org.test.PersonHandler2", handlerInfo3.getHandlerClass()); - assertEquals("public Mono listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); -*/ + assertEquals(0, handlerInfo3.getAcceptTypes().length); + assertEquals("org.test.PersonHandler3", handlerInfo1.getHandlerClass()); + assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "/person/sub1/andNestPath/andNestPathGET", "GET").get(0); + assertEquals("/person/sub1/andNestPath/andNestPathGET", handlerInfo4.getPath()); + assertEquals("[GET]", Arrays.toString(handlerInfo4.getHttpMethods())); + assertEquals(0, handlerInfo4.getContentTypes().length); + assertEquals(0, handlerInfo4.getAcceptTypes().length); + assertEquals("org.test.PersonHandler3", handlerInfo4.getHandlerClass()); + assertEquals("public Mono getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo5 = getWebfluxHandler(addons, "/person/", "POST").get(0); + assertEquals("/person/", handlerInfo5.getPath()); + assertEquals("[POST]", Arrays.toString(handlerInfo5.getHttpMethods())); + assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo5.getContentTypes())); + assertEquals(0, handlerInfo5.getAcceptTypes().length); + assertEquals("org.test.PersonHandler3", handlerInfo5.getHandlerClass()); + assertEquals("public Mono createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo5.getHandlerMethod()); + + WebfluxHandlerInformation handlerInfo6 = getWebfluxHandler(addons, "/nestedDelete", "DELETE").get(0); + assertEquals("/nestedDelete", handlerInfo6.getPath()); + assertEquals("[DELETE]", Arrays.toString(handlerInfo6.getHttpMethods())); + assertEquals(0, handlerInfo6.getContentTypes().length); + assertEquals(0, handlerInfo6.getAcceptTypes().length); + assertEquals("org.test.PersonHandler3", handlerInfo6.getHandlerClass()); + assertEquals("public Mono deletePerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo6.getHandlerMethod()); } private boolean containsSymbol(List symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) { diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/RequestMappingMediaTypes.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/RequestMappingMediaTypes.java new file mode 100644 index 000000000..60a29bd36 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/RequestMappingMediaTypes.java @@ -0,0 +1,44 @@ +package org.test; + +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +public class RequestMappingMediaTypes { + + @RequestMapping(path="/consume1", consumes = "testconsume", method= {RequestMethod.HEAD}) + public String consume1() { + return "Hello"; + } + + @RequestMapping(path="/consume2", consumes = MediaType.TEXT_PLAIN_VALUE) + public String consume2() { + return "Hello"; + } + + @RequestMapping(path="/consume3", consumes = {MediaType.TEXT_PLAIN_VALUE, "testconsumetype"}) + public String consume3() { + return "Hello"; + } + + @RequestMapping(path="/produce1", produces = "testproduce") + public String produce1() { + return "Hello"; + } + + @RequestMapping(path="/produce2", produces = MediaType.TEXT_PLAIN_VALUE) + public String produce2() { + return "Hello"; + } + + @RequestMapping(path="/produce3", produces = {MediaType.TEXT_PLAIN_VALUE, "testproducetype"}) + public String produce3() { + return "Hello"; + } + + @RequestMapping(path="/everything", consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE, "testconsume"}, produces=MediaType.APPLICATION_JSON_VALUE) + public String everything() { + return "Hello"; + } + +} From 9ca8e66e7d37c494c5f6f353098a23b73dc30847 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Mon, 12 Mar 2018 14:53:06 +0100 Subject: [PATCH 29/30] fixed failing test, forgot to incorporate media types into that one --- .../requestmapping/test/WebFluxMappingSymbolProviderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index ba361103d..0d8586774 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -47,8 +47,8 @@ public class WebFluxMappingSymbolProviderTest { String docUri = directory.toPath().resolve("src/main/java/org/test/UserController.java").toUri().toString(); List symbols = getSymbols(docUri); assertEquals(4, symbols.size()); - assertTrue(containsSymbol(symbols, "@/users", docUri, 13, 1, 13, 74)); - assertTrue(containsSymbol(symbols, "@/users/{username}", docUri, 18, 1, 18, 85)); + assertTrue(containsSymbol(symbols, "@/users - Content-Type: application/json", docUri, 13, 1, 13, 74)); + assertTrue(containsSymbol(symbols, "@/users/{username} - Content-Type: application/json", docUri, 18, 1, 18, 85)); List addons = getAdditionalInformation(docUri); assertNull(addons); From 578bbf9021a5230b7d28186cc154c5880a0a838a Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Mon, 12 Mar 2018 16:38:38 +0100 Subject: [PATCH 30/30] updated versions of eclipse-language-server plugins to 0.1.6 --- .../org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF | 2 +- .../org.springframework.tooling.boot.ls/pom.xml | 4 ++-- .../src/org/springframework/tooling/boot/ls/Constants.java | 2 +- .../org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF | 2 +- .../org.springframework.tooling.bosh.ls/pom.xml | 4 ++-- .../src/org/springframework/tooling/bosh/ls/Constants.java | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../pom.xml | 4 ++-- .../tooling/cloudfoundry/manifest/ls/Constants.java | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../org.springframework.tooling.concourse.ls/pom.xml | 4 ++-- .../org/springframework/tooling/concourse/ls/Constants.java | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF index 732cc2700..47ab66e58 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Spring Boot Language Server Bundle-Vendor: Pivotal, Inc. Bundle-SymbolicName: org.springframework.tooling.boot.ls;singleton:=true -Bundle-Version: 0.1.5.qualifier +Bundle-Version: 0.1.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.boot.ls/pom.xml index cb88400dc..d4c919431 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/pom.xml @@ -12,14 +12,14 @@ org.springframework.tooling.boot.ls - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT eclipse-plugin org.springframework.ide.vscode spring-boot-language-server - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java index dd3df89d8..8e2f74812 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java @@ -16,7 +16,7 @@ package org.springframework.tooling.boot.ls; public class Constants { public static final String PLUGIN_ID = "org.springframework.tooling.boot.ls"; - public static final String LANGUAGE_SERVER_VERSION = "0.1.5-SNAPSHOT.jar"; + public static final String LANGUAGE_SERVER_VERSION = "0.1.6-SNAPSHOT.jar"; public static final String PREF_BOOT_HINTS = "boot-java.boot-hints.on"; diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF index 16c49a5f7..6d96420d5 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: BOSH Manifest Language Server Bundle-Vendor: Pivotal, Inc. Bundle-SymbolicName: org.springframework.tooling.bosh.ls;singleton:=true -Bundle-Version: 0.1.5.qualifier +Bundle-Version: 0.1.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml index 218addf31..8de901cde 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml @@ -12,14 +12,14 @@ org.springframework.tooling.bosh.ls - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT eclipse-plugin org.springframework.ide.vscode bosh-language-server - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT org.springframework.ide.eclipse diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/src/org/springframework/tooling/bosh/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.bosh.ls/src/org/springframework/tooling/bosh/ls/Constants.java index c8bceeb22..d4cbb5f66 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/src/org/springframework/tooling/bosh/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/src/org/springframework/tooling/bosh/ls/Constants.java @@ -16,6 +16,6 @@ package org.springframework.tooling.bosh.ls; public class Constants { public static final String PLUGIN_ID = "org.springframework.tooling.bosh.ls"; - public static final String LANGUAGE_SERVER_VERSION = "0.1.5-SNAPSHOT"; + public static final String LANGUAGE_SERVER_VERSION = "0.1.6-SNAPSHOT"; } diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF index 40a21a737..e8a9f412a 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Cloud Foundry Manifest Language Server Bundle-Vendor: Pivotal, Inc. Bundle-SymbolicName: org.springframework.tooling.cloudfoundry.manifest.ls;singleton:=true -Bundle-Version: 0.1.5.qualifier +Bundle-Version: 0.1.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml index 6e1a807da..40e137805 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml @@ -12,14 +12,14 @@ org.springframework.tooling.cloudfoundry.manifest.ls - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT eclipse-plugin org.springframework.ide.vscode manifest-yaml-language-server - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/src/org/springframework/tooling/cloudfoundry/manifest/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/src/org/springframework/tooling/cloudfoundry/manifest/ls/Constants.java index 34a9c9e34..6d748db39 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/src/org/springframework/tooling/cloudfoundry/manifest/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/src/org/springframework/tooling/cloudfoundry/manifest/ls/Constants.java @@ -16,6 +16,6 @@ package org.springframework.tooling.cloudfoundry.manifest.ls; public class Constants { public static final String PLUGIN_ID = "org.springframework.tooling.cloudfoundry.manifest.ls"; - public static final String LANGUAGE_SERVER_VERSION = "0.1.5-SNAPSHOT.jar"; + public static final String LANGUAGE_SERVER_VERSION = "0.1.6-SNAPSHOT.jar"; } diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF index 125520bb8..1f76e9263 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Concourse Pipeline Language Server Bundle-Vendor: Pivotal, Inc. Bundle-SymbolicName: org.springframework.tooling.concourse.ls;singleton:=true -Bundle-Version: 0.1.5.qualifier +Bundle-Version: 0.1.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml index f77aa4a62..56b775c0c 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml @@ -12,14 +12,14 @@ org.springframework.tooling.concourse.ls - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT eclipse-plugin org.springframework.ide.vscode concourse-language-server - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT org.springframework.ide.eclipse diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls/src/org/springframework/tooling/concourse/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.concourse.ls/src/org/springframework/tooling/concourse/ls/Constants.java index 8b09972fc..8cc4bd2db 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls/src/org/springframework/tooling/concourse/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls/src/org/springframework/tooling/concourse/ls/Constants.java @@ -16,6 +16,6 @@ package org.springframework.tooling.concourse.ls; public class Constants { public static final String PLUGIN_ID = "org.springframework.tooling.concourse.ls"; - public static final String LANGUAGE_SERVER_VERSION = "0.1.5-SNAPSHOT"; + public static final String LANGUAGE_SERVER_VERSION = "0.1.6-SNAPSHOT"; }