From 66290f0dca754128af4ee25e5105ac2fe615b264 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Mon, 26 Feb 2018 11:43:21 +0100 Subject: [PATCH] added http method support to webflux symbol provider --- .../requestmapping/WebfluxMethodFinder.java | 75 +++++++++++++++++++ .../requestmapping/WebfluxPathFinder.java | 20 ++--- .../WebfluxRouterSymbolProvider.java | 49 +++--------- .../java/requestmapping/WebfluxUtils.java | 69 +++++++++++++++++ 4 files changed, 161 insertions(+), 52 deletions(-) create mode 100644 headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java create mode 100644 headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java diff --git a/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java new file mode 100644 index 000000000..a8a48ef55 --- /dev/null +++ b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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 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 + */ +public class WebfluxMethodFinder extends ASTVisitor { + + private String method; + private ASTNode root; + + public WebfluxMethodFinder(ASTNode root) { + this.root = root; + } + + public String getMethod() { + return method; + } + + @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_HTTPMETHOD_METHODS.contains(name)) { + method = name; + } + else if (name != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(name)) { + method = extractMethodValue(node); + } + } + + if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + visitChildren = false; + } + } + 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/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java index 1a5761cbf..20260238f 100644 --- a/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java +++ b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java @@ -38,25 +38,17 @@ public class WebfluxPathFinder extends ASTVisitor { if (node != this.root) { IMethodBinding methodBinding = node.resolveMethodBinding(); - if (WebfluxRouterSymbolProvider.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); - if (name != null && WebfluxRouterSymbolProvider.REQUEST_PREDICATE_PATH_METHODS.contains(name)) { - path = WebfluxRouterSymbolProvider.extractPath(node); + if (name != null && WebfluxUtils.REQUEST_PREDICATE_ALL_PATH_METHODS.contains(name)) { + path = WebfluxUtils.extractPath(node); } } - if (WebfluxRouterSymbolProvider.ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if ("route".equals(name)) { - visitChildren = false; - } - } - else if (WebfluxRouterSymbolProvider.ROUTER_FUNCTION_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if ("andRoute".equals(name)) { - visitChildren = false; - } + if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + visitChildren = false; } + } return visitChildren; } diff --git a/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java index 3fd355a3d..db3af6d1f 100644 --- a/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java +++ b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java @@ -11,11 +11,8 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; @@ -25,7 +22,6 @@ import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; @@ -40,12 +36,6 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; */ public class WebfluxRouterSymbolProvider implements SymbolProvider { - public static final String ROUTER_FUNCTION_TYPE = "org.springframework.web.reactive.function.server.RouterFunction"; - public static final String ROUTER_FUNCTIONS_TYPE = "org.springframework.web.reactive.function.server.RouterFunctions"; - public static final String REQUEST_PREDICATES_TYPE = "org.springframework.web.reactive.function.server.RequestPredicates"; - - public static final Set REQUEST_PREDICATE_PATH_METHODS = new HashSet<>(Arrays.asList("path", "GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS")); - @Override public Collection getSymbols(Annotation node, ITypeBinding typeBinding, Collection metaAnnotations, TextDocument doc) { @@ -63,7 +53,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { if (returnType != null) { ITypeBinding resolvedBinding = returnType.resolveBinding(); if (resolvedBinding != null) { - if (ROUTER_FUNCTION_TYPE.equals(resolvedBinding.getBinaryName())) { + if (WebfluxUtils.ROUTER_FUNCTION_TYPE.equals(resolvedBinding.getBinaryName())) { return getSymbolsForRouterFunction(methodDeclaration, doc); } } @@ -82,17 +72,8 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { public boolean visit(MethodInvocation node) { IMethodBinding methodBinding = node.resolveMethodBinding(); - if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if ("route".equals(name)) { - extractMappingSymbol(node, doc, result); - } - } - else if (ROUTER_FUNCTION_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if ("andRoute".equals(name)) { - extractMappingSymbol(node, doc, result); - } + if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + extractMappingSymbol(node, doc, result); } return super.visit(node); @@ -141,7 +122,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { MethodInvocation methodInvocation = (MethodInvocation) node; IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); - if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + if (WebfluxUtils.ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { String name = methodBinding.getName(); if ("nest".equals(name)) { List arguments = methodInvocation.arguments(); @@ -152,7 +133,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { String nestedMethodName = nestedMethodBinding.getName(); if ("path".equals(nestedMethodName)) { - String additionalPath = extractPath(nestedMethod); + String additionalPath = WebfluxUtils.extractPath(nestedMethod); if (additionalPath != null && additionalPath.length() > 0) { path = additionalPath + path; } @@ -167,20 +148,12 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider { return extractPath(node.getParent(), path); } - protected static String extractPath(MethodInvocation node) { - List arguments = node.arguments(); - if (arguments != null && arguments.size() > 0) { - Object object = arguments.get(0); - if (object instanceof StringLiteral) { - String path = ((StringLiteral) object).getLiteralValue(); - return path; - } - } - return null; - } - - private String extractMethod(MethodInvocation node) { - return null; + private String extractMethod(MethodInvocation routerInvocation) { + WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation); + routerInvocation.accept(methodFinder); + + String method = methodFinder.getMethod(); + return method; } } diff --git a/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java new file mode 100644 index 000000000..6de785cda --- /dev/null +++ b/headless-services/commons/commons-boot/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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 java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.StringLiteral; + +/** + * @author Martin Lippert + */ +public class WebfluxUtils { + + public static final String ROUTER_FUNCTION_TYPE = "org.springframework.web.reactive.function.server.RouterFunction"; + public static final String ROUTER_FUNCTIONS_TYPE = "org.springframework.web.reactive.function.server.RouterFunctions"; + public static final String REQUEST_PREDICATES_TYPE = "org.springframework.web.reactive.function.server.RequestPredicates"; + + public static final String REQUEST_PREDICATE_PATH_METHOD = "path"; + public static final String REQUEST_PREDICATE_METHOD_METHOD = "method"; + + 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) { + List arguments = node.arguments(); + if (arguments != null && arguments.size() > 0) { + Object object = arguments.get(0); + if (object instanceof StringLiteral) { + String path = ((StringLiteral) object).getLiteralValue(); + return path; + } + } + return null; + } + + public static boolean isRouteMethodInvocation(IMethodBinding methodBinding) { + if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + String name = methodBinding.getName(); + if ("route".equals(name)) { + return true; + } + } + else if (ROUTER_FUNCTION_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + String name = methodBinding.getName(); + if ("andRoute".equals(name)) { + return true; + } + } + + return false; + + } + + +}