first prototype to display request mapping information from running apps as hover on source code

This commit is contained in:
Martin Lippert
2017-08-23 16:35:51 +02:00
parent 4bdeec295a
commit a6d10441f8
2 changed files with 150 additions and 0 deletions

View File

@@ -41,6 +41,13 @@ public class BootJavaHoverProvider implements HoverHandler {
private static final String SPRING_VALUE = "org.springframework.beans.factory.annotation.Value";
private static final String SPRING_REQUEST_MAPPING = "org.springframework.web.bind.annotation.RequestMapping";
private static final String SPRING_GET_MAPPING = "org.springframework.web.bind.annotation.GetMapping";
private static final String SPRING_POST_MAPPING = "org.springframework.web.bind.annotation.PostMapping";
private static final String SPRING_PUT_MAPPING = "org.springframework.web.bind.annotation.PutMapping";
private static final String SPRING_DELETE_MAPPING = "org.springframework.web.bind.annotation.DeleteMapping";
private static final String SPRING_PATCH_MAPPING = "org.springframework.web.bind.annotation.PatchMapping";
private JavaProjectFinder projectFinder;
private SimpleLanguageServer server;
@@ -123,6 +130,13 @@ public class BootJavaHoverProvider implements HoverHandler {
private CompletableFuture<Hover> provideHoverForSpringAnnotation(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc) {
if (type.getQualifiedName().equals(SPRING_VALUE)) {
return new ValueHoverProvider().provideHoverForValueAnnotation(node, annotation, type, offset, doc);
} else if (type.getQualifiedName().equals(SPRING_REQUEST_MAPPING)
|| type.getQualifiedName().equals(SPRING_GET_MAPPING)
|| type.getQualifiedName().equals(SPRING_POST_MAPPING)
|| type.getQualifiedName().equals(SPRING_PUT_MAPPING)
|| type.getQualifiedName().equals(SPRING_DELETE_MAPPING)
|| type.getQualifiedName().equals(SPRING_PATCH_MAPPING)) {
return new RequestMappingHoverProvider().provideHoverForRequestMappingAnnotation(node, annotation, type, offset, doc);
}
return null;

View File

@@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2017 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.hover;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.json.JSONObject;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
*/
public class RequestMappingHoverProvider {
public CompletableFuture<Hover> provideHoverForRequestMappingAnnotation(ASTNode node, Annotation annotation,
ITypeBinding type, int offset, TextDocument doc) {
return provideHover(annotation, doc);
}
private CompletableFuture<Hover> provideHover(Annotation annotation, TextDocument doc) {
try {
JSONObject[] mappings = getRequestMappingsFromProcesses();
List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
for (int i = 0; i < mappings.length; i++) {
addHoverContent(mappings[i], hoverContent, annotation);
}
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
Hover hover = new Hover();
hover.setContents(hoverContent);
hover.setRange(hoverRange);
return CompletableFuture.completedFuture(hover);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void addHoverContent(JSONObject jsonObject, List<Either<String, MarkedString>> hoverContent, Annotation annotation) {
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext()) {
String key = keys.next();
if (doesMatch(annotation, key)) {
hoverContent.add(Either.forLeft(key));
hoverContent.add(Either.forLeft(jsonObject.get(key).toString()));
}
}
}
private boolean doesMatch(Annotation annotation, String key) {
String mappingPath = null;
if (annotation instanceof SingleMemberAnnotation) {
Expression valueContent = ((SingleMemberAnnotation) annotation).getValue();
if (valueContent instanceof StringLiteral) {
mappingPath = ((StringLiteral)valueContent).getLiteralValue();
}
}
else if (annotation instanceof NormalAnnotation) {
List<?> values = ((NormalAnnotation) annotation).values();
for (Object value : values) {
if (value instanceof MemberValuePair) {
String name = ((MemberValuePair)value).getName().toString();
if (name != null && name.equals("value")) {
Expression valueContent = ((MemberValuePair)value).getValue();
if (valueContent instanceof StringLiteral) {
mappingPath = ((StringLiteral)valueContent).getLiteralValue();
}
}
}
}
}
return mappingPath != null ? key.contains(mappingPath) : false;
}
public JSONObject[] getRequestMappingsFromProcesses() {
List<JSONObject> result = new ArrayList<>();
try {
Map<String, SpringBootApp> apps = SpringBootApp.getAllRunningJavaApps();
Iterator<SpringBootApp> appsIter = apps.values().iterator();
while (appsIter.hasNext()) {
SpringBootApp app = appsIter.next();
if (app.isSpringBootApp()) {
String mappings = app.getRequestMappings();
if (mappings != null) {
JSONObject requestMappings = new JSONObject(mappings);
if (requestMappings != null) {
result.add(requestMappings);
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return result.toArray(new JSONObject[result.size()]);
}
}