Merge branch 'master' of https://github.com/spring-projects/sts4
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.getAcceptType() != null ? " - Accept: " + getMediaType(handlerInfo.getAcceptType()) : "";
|
||||
codeLensCommand += handlerInfo.getContentType() != null ? " - Content-Type: " + getMediaType(handlerInfo.getContentType()) : "";
|
||||
|
||||
codeLens.setCommand(new Command(codeLensCommand, null));
|
||||
|
||||
resultAccumulator.add(codeLens);
|
||||
} catch (BadLocationException e) {
|
||||
@@ -81,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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,10 +91,12 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
|
||||
}
|
||||
|
||||
protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List<EnhancedSymbolInformation> result) {
|
||||
String foundPath = extractPathFromRouterFunction(node);
|
||||
String path = extractPath(node, foundPath);
|
||||
String path = extractPath(node);
|
||||
String httpMethod = extractMethod(node);
|
||||
|
||||
String contentType = extractContentType(node);
|
||||
String acceptType = extractAcceptType(node);
|
||||
|
||||
int methodNameStart = node.getName().getStartPosition();
|
||||
int invocationStart = node.getStartPosition();
|
||||
|
||||
@@ -99,7 +105,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) {
|
||||
@@ -108,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<Tuple2<MethodInvocation, String>, String> extractor) {
|
||||
if (node == null || node instanceof TypeDeclaration) {
|
||||
return path;
|
||||
return value;
|
||||
}
|
||||
|
||||
if (node instanceof MethodInvocation) {
|
||||
@@ -129,39 +218,22 @@ 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 symbol) {
|
||||
private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, String httpMethod, String contentType, String acceptType) {
|
||||
List<?> arguments = node.arguments();
|
||||
|
||||
if (arguments != null) {
|
||||
@@ -177,7 +249,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> REQUEST_PREDICATE_HTTPMETHOD_METHODS = new HashSet<>(Arrays.asList("GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS"));
|
||||
public static final Set<String> 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();
|
||||
|
||||
@@ -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 - 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<? extends CodeLens> codeLenses, String commandTitle, int startLine, int startPosition, int endLine, int endPosition) {
|
||||
|
||||
@@ -46,8 +46,8 @@ public class WebFluxMappingSymbolProviderTest {
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/UserController.java").toUri().toString();
|
||||
List<? extends SymbolInformation> 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<? extends Object> addons = getAdditionalInformation(docUri);
|
||||
assertNull(addons);
|
||||
@@ -69,23 +69,35 @@ public class WebFluxMappingSymbolProviderTest {
|
||||
List<? extends Object> 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());
|
||||
assertEquals("TEXT_PLAIN", handlerInfo1.getAcceptType());
|
||||
assertEquals("org.test.QuoteHandler", handlerInfo1.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> 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());
|
||||
assertEquals("TEXT_PLAIN", handlerInfo2.getContentType());
|
||||
assertEquals("TEXT_PLAIN", handlerInfo2.getAcceptType());
|
||||
assertEquals("org.test.QuoteHandler", handlerInfo2.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> 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());
|
||||
assertEquals("APPLICATION_STREAM_JSON", handlerInfo3.getAcceptType());
|
||||
assertEquals("org.test.QuoteHandler", handlerInfo3.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> 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());
|
||||
assertEquals("APPLICATION_JSON", handlerInfo4.getAcceptType());
|
||||
assertEquals("org.test.QuoteHandler", handlerInfo4.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod());
|
||||
}
|
||||
@@ -105,18 +117,27 @@ public class WebFluxMappingSymbolProviderTest {
|
||||
List<? extends Object> 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());
|
||||
assertEquals("APPLICATION_JSON", handlerInfo1.getAcceptType());
|
||||
assertEquals("org.test.PersonHandler", handlerInfo1.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> 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());
|
||||
assertEquals("APPLICATION_JSON", handlerInfo2.getContentType());
|
||||
assertNull(handlerInfo2.getAcceptType());
|
||||
assertEquals("org.test.PersonHandler", handlerInfo2.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> 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());
|
||||
assertEquals("APPLICATION_JSON", handlerInfo3.getAcceptType());
|
||||
assertEquals("org.test.PersonHandler", handlerInfo3.getHandlerClass());
|
||||
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> 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<WebfluxHandlerInformation> getWebfluxHandler(List<? extends Object> addons, String symbol) {
|
||||
private List<WebfluxHandlerInformation> getWebfluxHandler(List<? extends Object> 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.M1</version>
|
||||
<version>2.0.0.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -50,42 +46,4 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -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<ServerResponse> 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)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.test;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
|
||||
|
||||
public interface TradingUserRepository extends ReactiveMongoRepository<TradingUser, String> {
|
||||
|
||||
Mono<TradingUser> findByUserName(String userName);
|
||||
|
||||
}
|
||||
@@ -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<TradingUser> listUsers() {
|
||||
return this.tradingUserRepository.findAll();
|
||||
public Flux<Object> listUsers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@GetMapping(path = "/users/{username}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Mono<TradingUser> showUsers(@PathVariable String username) {
|
||||
return this.tradingUserRepository.findByUserName(username);
|
||||
public Mono<Object> showUsers(@PathVariable String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user