diff --git a/atom-extensions/atom-bosh/package.json b/atom-extensions/atom-bosh/package.json index fb9351eac..41ec35694 100644 --- a/atom-extensions/atom-bosh/package.json +++ b/atom-extensions/atom-bosh/package.json @@ -50,7 +50,7 @@ "dependencies": { "atom-package-deps": "^4.6.0", "download": "^6.2.5", - "@pivotal-tools/atom-languageclient-commons": "0.0.8" + "@pivotal-tools/atom-languageclient-commons": "0.0.9" }, "devDependencies": { "typescript": "^2.7.2", diff --git a/atom-extensions/atom-bosh/properties.json b/atom-extensions/atom-bosh/properties.json index e705c39ea..1ce2d8c26 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.1.5-201803080105.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/bosh-language-server-0.6.0-201808212257.jar" } diff --git a/atom-extensions/atom-cf-manifest-yaml/package.json b/atom-extensions/atom-cf-manifest-yaml/package.json index 7725f2ae2..f5aef0246 100644 --- a/atom-extensions/atom-cf-manifest-yaml/package.json +++ b/atom-extensions/atom-cf-manifest-yaml/package.json @@ -19,7 +19,7 @@ "properties.json" ], "dependencies": { - "@pivotal-tools/atom-languageclient-commons": "0.0.8", + "@pivotal-tools/atom-languageclient-commons": "0.0.9", "atom-package-deps": "^4.6.0", "download": "^6.2.5" }, diff --git a/atom-extensions/atom-cf-manifest-yaml/properties.json b/atom-extensions/atom-cf-manifest-yaml/properties.json index 1bb9070ed..9646c2cb3 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.2.1-201805102140.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/manifest-yaml-language-server-0.6.0-201808212257.jar" } diff --git a/atom-extensions/atom-commons/package.json b/atom-extensions/atom-commons/package.json index 63cdad899..25ca8275f 100644 --- a/atom-extensions/atom-commons/package.json +++ b/atom-extensions/atom-commons/package.json @@ -1,6 +1,6 @@ { "name": "@pivotal-tools/atom-languageclient-commons", - "version": "0.0.8", + "version": "0.0.9", "description": "Atom language client commons for STS4 language servers", "repository": "https://github.com/spring-projects/sts4", "license": "MIT", @@ -22,7 +22,7 @@ }, "dependencies": { "@pivotal-tools/jvm-launch-utils": "0.0.11", - "atom-languageclient": "0.9.5", + "atom-languageclient": "0.9.6", "portfinder": "^1.0.13", "@types/atom": "^1.24.1", "@types/node": "^8.0.41", diff --git a/atom-extensions/atom-concourse/package.json b/atom-extensions/atom-concourse/package.json index 7490dc1b9..192293f5c 100644 --- a/atom-extensions/atom-concourse/package.json +++ b/atom-extensions/atom-concourse/package.json @@ -21,7 +21,7 @@ "dependencies": { "atom-package-deps": "^4.6.0", "download": "^6.2.5", - "@pivotal-tools/atom-languageclient-commons": "0.0.8" + "@pivotal-tools/atom-languageclient-commons": "0.0.9" }, "devDependencies": { "typescript": "^2.7.2", diff --git a/atom-extensions/atom-concourse/properties.json b/atom-extensions/atom-concourse/properties.json index bbf65bc61..58a4ef86f 100644 --- a/atom-extensions/atom-concourse/properties.json +++ b/atom-extensions/atom-concourse/properties.json @@ -1,3 +1,3 @@ { - "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/concourse-language-server-0.1.5-201802272051.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/concourse-language-server-0.6.0-201808212257.jar" } diff --git a/atom-extensions/atom-spring-boot/package.json b/atom-extensions/atom-spring-boot/package.json index d6cef73cd..c30439e40 100644 --- a/atom-extensions/atom-spring-boot/package.json +++ b/atom-extensions/atom-spring-boot/package.json @@ -29,11 +29,26 @@ "type": "boolean", "default": false, "description": "Enable/Disable detecting changes of running Spring Boot applications" + }, + "remote-apps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "jmxurl": { + "type": "string" + }, + "host": { + "type": "string" + } + } + }, + "description": "Array of jmx urls pointing to remote spring boot applications to poll for live hover information. A typical url looks something like this: `service:jmx:rmi://localhost:9111/jndi/rmi://localhost:9111/jmxrmi`" } }, "dependencies": { - "atom-languageclient": "0.9.5", - "@pivotal-tools/atom-languageclient-commons": "0.0.8", + "atom-languageclient": "0.9.6", + "@pivotal-tools/atom-languageclient-commons": "0.0.9", "atom-package-deps": "^4.6.0", "download": "^6.2.5" }, diff --git a/atom-extensions/atom-spring-boot/properties.json b/atom-extensions/atom-spring-boot/properties.json index 2a4f68698..e84581c81 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.4.0-201807190033.jar" + "jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/spring-boot-language-server-0.6.0-201808212257.jar" } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java index ebf5c51f3..41ea8d7a8 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java @@ -23,6 +23,7 @@ import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.lsp4j.CodeLens; +import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.MarkedString; import org.eclipse.lsp4j.Range; @@ -34,9 +35,9 @@ import org.springframework.ide.vscode.boot.java.livehover.LiveHoverUtils; import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp; import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMapping; import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.Renderable; import org.springframework.ide.vscode.commons.util.Renderables; +import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; @@ -51,6 +52,8 @@ public class RequestMappingHoverProvider implements HoverProvider { private static final Logger log = LoggerFactory.getLogger(RequestMappingHoverProvider.class); + private static final int CODE_LENS_LIMIT = 3; + @Override public Hover provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { @@ -64,17 +67,38 @@ public class RequestMappingHoverProvider implements HoverProvider { List> val = getRequestMappingMethodFromRunningApp(annotation, runningApps); if (!val.isEmpty()) { Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength()); - return ImmutableList.of(new CodeLens(hoverRange)); + List urls = getUrls(val); + return assembleCodeLenses(hoverRange, urls); } } } - catch (BadLocationException e) { + catch (Exception e) { log.error("", e); } return null; } + private Collection assembleCodeLenses(Range range, List urls) { + + Collection lenses = new ArrayList<>(); + + if (urls != null) { + int limit = urls.size() > CODE_LENS_LIMIT ? CODE_LENS_LIMIT : urls.size(); + + for (int i = 0; i < limit; i++) { + CodeLens codeLens = createCodeLensForRequestMapping(range, urls.get(i)); + lenses.add(codeLens); + } + + if (urls.size() > CODE_LENS_LIMIT) { + CodeLens codeLens = createCodeLensForRemaining(range, urls.size() - CODE_LENS_LIMIT); + lenses.add(codeLens); + } + } + return lenses; + } + private Hover provideHover(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { try { @@ -153,6 +177,30 @@ public class RequestMappingHoverProvider implements HoverProvider { return false; } + private List getUrls(List> mappingMethods) throws Exception { + List urls = new ArrayList<>(); + for (int i = 0; i < mappingMethods.size(); i++) { + Tuple2 mappingMethod = mappingMethods.get(i); + + String port = mappingMethod.getT2().getPort(); + String host = mappingMethod.getT2().getHost(); + + String[] paths = mappingMethod.getT1().getSplitPath(); + if (paths==null || paths.length==0) { + //Technically, this means the path 'predicate' is unconstrained, meaning any path matches. + //So this is not quite the same as the case where path=""... but... + //It is better for us to show one link where any path is allowed, versus showing no links where any link is allowed. + //So we'll pretend this is the same as path="" as that gives a working link. + paths = new String[] {""}; + } + for (String path : paths) { + String url = UrlUtil.createUrl(host, port, path); + urls.add(url); + } + } + return urls; + } + private void addHoverContent(List> mappingMethods, List> hoverContent) throws Exception { for (int i = 0; i < mappingMethods.size(); i++) { Tuple2 mappingMethod = mappingMethods.get(i); @@ -189,4 +237,40 @@ public class RequestMappingHoverProvider implements HoverProvider { } } + private CodeLens createCodeLensForRequestMapping(Range range, String content) { + CodeLens codeLens = new CodeLens(); + codeLens.setRange(range); + Command cmd = new Command(); + + if (StringUtil.hasText(content)) { + codeLens.setData(content); + cmd.setTitle(content); + +// cmd.setCommand("editor.action.openLink"); + // Show hover for now, as it contains a link. Ideally the command to set is a vscode + // one that jumps to URL directly + cmd.setCommand("org.springframework.showHoverAtPosition"); + cmd.setArguments(ImmutableList.of(range.getStart())); + } + + codeLens.setCommand(cmd); + + return codeLens; + } + + private CodeLens createCodeLensForRemaining(Range range, int remaining) { + CodeLens codeLens = new CodeLens(); + codeLens.setRange(range); + Command cmd = new Command(); + + cmd.setTitle(remaining + " more..."); + + cmd.setCommand("org.springframework.showHoverAtPosition"); + cmd.setArguments(ImmutableList.of(range.getStart())); + + codeLens.setCommand(cmd); + + return codeLens; + } + }