Merge branch 'master' into request-mappings
# Conflicts: # headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java # headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java # headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/project/harness/MockRunningAppProvider.java # headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java # headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootAppTest.java
This commit is contained in:
@@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>${commons-io-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -25,6 +25,8 @@ import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -54,8 +56,8 @@ public class AutowiredHoverProvider implements HoverProvider {
|
||||
|
||||
for (SpringBootAppProvider bootApp : runningApps) {
|
||||
try {
|
||||
String liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && liveBeans.length() > 0) {
|
||||
LiveBeansModel liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && !liveBeans.isEmpty()) {
|
||||
addLiveHoverContent(annotation, doc, liveBeans, bootApp, hoverContent);
|
||||
}
|
||||
}
|
||||
@@ -85,8 +87,8 @@ public class AutowiredHoverProvider implements HoverProvider {
|
||||
try {
|
||||
for (SpringBootApp bootApp : runningApps) {
|
||||
try {
|
||||
String liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && liveBeans.length() > 0) {
|
||||
LiveBeansModel liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && !liveBeans.isEmpty()) {
|
||||
Range range = getLiveHoverHint(annotation, doc, liveBeans);
|
||||
if (range != null) {
|
||||
return ImmutableList.of(range);
|
||||
@@ -105,14 +107,11 @@ public class AutowiredHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Range getLiveHoverHint(Annotation annotation, TextDocument doc, String liveBeansJSON) {
|
||||
public Range getLiveHoverHint(Annotation annotation, TextDocument doc, LiveBeansModel beansModel) {
|
||||
try {
|
||||
String type = findDeclaredType(annotation);
|
||||
if (type != null && liveBeansJSON != null) {
|
||||
|
||||
LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
|
||||
if (type != null && beansModel != null) {
|
||||
LiveBean[] beansOfType = beansModel.getBeansOfType(type);
|
||||
|
||||
if (beansOfType.length > 0) {
|
||||
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
|
||||
return hoverRange;
|
||||
@@ -126,11 +125,9 @@ public class AutowiredHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addLiveHoverContent(Annotation annotation, TextDocument doc, String liveBeansJSON, SpringBootAppProvider bootApp, List<Either<String, MarkedString>> hoverContent) {
|
||||
public void addLiveHoverContent(Annotation annotation, TextDocument doc, LiveBeansModel beansModel, SpringBootAppProvider bootApp, List<Either<String, MarkedString>> hoverContent) {
|
||||
String type = findDeclaredType(annotation);
|
||||
if (type != null && liveBeansJSON != null) {
|
||||
|
||||
LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
|
||||
if (type != null && beansModel != null) {
|
||||
LiveBean[] beansOfType = beansModel.getBeansOfType(type);
|
||||
|
||||
if (beansOfType.length > 0) {
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* 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.autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class LiveBeansModel {
|
||||
|
||||
public static LiveBeansModel parse(String json) {
|
||||
LiveBeansModel model = new LiveBeansModel();
|
||||
|
||||
try {
|
||||
JSONArray mainArray = new JSONArray(json);
|
||||
|
||||
for (int i = 0; i < mainArray.length(); i++) {
|
||||
JSONObject appContext = mainArray.getJSONObject(i);
|
||||
if (appContext == null) continue;
|
||||
|
||||
JSONArray beansArray = appContext.optJSONArray("beans");
|
||||
if (beansArray == null) continue;
|
||||
|
||||
for (int j = 0; j < beansArray.length(); j++) {
|
||||
JSONObject beanObject = beansArray.getJSONObject(j);
|
||||
if (beanObject == null) continue;
|
||||
|
||||
LiveBean bean = LiveBean.parse(beanObject);
|
||||
if (bean != null) {
|
||||
model.add(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private final ConcurrentMap<String, List<LiveBean>> beansViaType;
|
||||
private final ConcurrentMap<String, List<LiveBean>> beansViaName;
|
||||
|
||||
protected LiveBeansModel() {
|
||||
this.beansViaType = new ConcurrentHashMap<>();
|
||||
this.beansViaName = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public LiveBean[] getBeansOfType(String fullyQualifiedType) {
|
||||
List<LiveBean> result = beansViaType.get(fullyQualifiedType);
|
||||
return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
|
||||
}
|
||||
|
||||
public LiveBean[] getBeansOfName(String beanName) {
|
||||
List<LiveBean> result = beansViaName.get(beanName);
|
||||
return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
|
||||
}
|
||||
|
||||
protected void add(LiveBean bean) {
|
||||
String type = bean.getType();
|
||||
if (type != null) {
|
||||
beansViaType.computeIfAbsent(type, (t) -> new ArrayList<>()).add(bean);
|
||||
}
|
||||
|
||||
String name = bean.getId();
|
||||
if (name != null) {
|
||||
beansViaName.computeIfAbsent(name, (n) -> new ArrayList<>()).add(bean);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,12 +10,14 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.autowired;
|
||||
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public interface SpringBootAppProvider {
|
||||
|
||||
public String getBeans() throws Exception;
|
||||
public LiveBeansModel getBeans() throws Exception;
|
||||
public String getProcessID();
|
||||
public String getProcessName();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.boot.java.autowired;
|
||||
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
@@ -24,7 +25,7 @@ public class SpringBootAppProviderImpl implements SpringBootAppProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBeans() throws Exception {
|
||||
public LiveBeansModel getBeans() throws Exception {
|
||||
return bootApp.getBeans();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ import org.eclipse.lsp4j.MarkedString;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.Constants;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.LiveBean;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProvider;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProviderImpl;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -68,8 +68,8 @@ public class ComponentHoverProvider implements HoverProvider {
|
||||
List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
|
||||
for (SpringBootAppProvider bootApp : runningApps) {
|
||||
try {
|
||||
String liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && liveBeans.length() > 0) {
|
||||
LiveBeansModel liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && !liveBeans.isEmpty()) {
|
||||
addLiveHoverContent(typeDecl, doc, liveBeans, bootApp, hoverContent);
|
||||
}
|
||||
}
|
||||
@@ -101,8 +101,8 @@ public class ComponentHoverProvider implements HoverProvider {
|
||||
try {
|
||||
for (SpringBootApp bootApp : runningApps) {
|
||||
try {
|
||||
String liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && liveBeans.length() > 0) {
|
||||
LiveBeansModel liveBeans = bootApp.getBeans();
|
||||
if (liveBeans != null && !liveBeans.isEmpty()) {
|
||||
Range range = getLiveHoverHint(annotation, doc, liveBeans);
|
||||
if (range != null) {
|
||||
return ImmutableList.of(range);
|
||||
@@ -121,13 +121,11 @@ public class ComponentHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Range getLiveHoverHint(Annotation annotation, TextDocument doc, String liveBeansJSON) {
|
||||
public Range getLiveHoverHint(Annotation annotation, TextDocument doc, LiveBeansModel beansModel) {
|
||||
try {
|
||||
TypeDeclaration type = findDeclaredType(annotation);
|
||||
if (type != null && liveBeansJSON != null) {
|
||||
if (type != null && beansModel != null) {
|
||||
String typeName = type.resolveBinding().getQualifiedName();
|
||||
|
||||
LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
|
||||
LiveBean[] beansOfType = beansModel.getBeansOfType(typeName);
|
||||
|
||||
if (beansOfType.length > 0) {
|
||||
@@ -160,11 +158,9 @@ public class ComponentHoverProvider implements HoverProvider {
|
||||
}
|
||||
|
||||
|
||||
public void addLiveHoverContent(TypeDeclaration declaringType, TextDocument doc, String liveBeansJSON, SpringBootAppProvider bootApp, List<Either<String, MarkedString>> hoverContent) {
|
||||
public void addLiveHoverContent(TypeDeclaration declaringType, TextDocument doc, LiveBeansModel beansModel, SpringBootAppProvider bootApp, List<Either<String, MarkedString>> hoverContent) {
|
||||
String type = declaringType.resolveBinding().getQualifiedName();
|
||||
if (type != null && liveBeansJSON != null) {
|
||||
|
||||
LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
|
||||
if (type != null && beansModel != null) {
|
||||
LiveBean[] beansOfType = beansModel.getBeansOfType(type);
|
||||
|
||||
if (beansOfType.length > 0) {
|
||||
|
||||
@@ -96,9 +96,20 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
|
||||
|
||||
private void addHoverContent(List<RunningAppConditional> conditions,
|
||||
List<Either<String, MarkedString>> hoverContent) throws Exception {
|
||||
for (RunningAppConditional condition : conditions) {
|
||||
for (int i = 0; i < conditions.size(); i++) {
|
||||
RunningAppConditional condition = conditions.get(i);
|
||||
hoverContent.add(Either.forLeft("Condition: " + condition.condition));
|
||||
hoverContent.add(Either.forLeft("Message: " + condition.message));
|
||||
|
||||
// If there is more than one instances show process information
|
||||
if (conditions.size() > 1) {
|
||||
hoverContent.add(Either.forLeft("Process ID: " + condition.app.getProcessID()));
|
||||
hoverContent.add(Either.forLeft("Process Name: " + condition.app.getProcessName()));
|
||||
}
|
||||
|
||||
if (i < conditions.size() - 1) {
|
||||
hoverContent.add(Either.forLeft("---"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,16 +128,21 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
|
||||
public Optional<List<RunningAppConditional>> parse(Annotation annotation, SpringBootApp[] runningApps) {
|
||||
|
||||
try {
|
||||
List<RunningAppConditional> allConditionals = new ArrayList<>();
|
||||
for (SpringBootApp app : runningApps) {
|
||||
String autoConfigRecord = app.getAutoConfigReport();
|
||||
if (autoConfigRecord != null) {
|
||||
JSONObject autoConfigJson = new JSONObject(autoConfigRecord);
|
||||
List<RunningAppConditional> conditionalsFromPositiveMatches = getConditionals(annotation, autoConfigJson);
|
||||
if(!conditionalsFromPositiveMatches.isEmpty()) {
|
||||
return Optional.of(conditionalsFromPositiveMatches);
|
||||
List<RunningAppConditional> conditionalsFromPositiveMatches = getConditionals(app, annotation,
|
||||
autoConfigJson);
|
||||
if (!conditionalsFromPositiveMatches.isEmpty()) {
|
||||
allConditionals.addAll(conditionalsFromPositiveMatches);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!allConditionals.isEmpty()) {
|
||||
return Optional.of(allConditionals);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
@@ -135,12 +151,13 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param app
|
||||
* @param annotation
|
||||
* @param autoConfigJson
|
||||
* @return non-null list of conditionals parsed from an autoconfig report. List
|
||||
* may be empty.
|
||||
*/
|
||||
private List<RunningAppConditional> getConditionals(Annotation annotation,
|
||||
private List<RunningAppConditional> getConditionals(SpringBootApp app, Annotation annotation,
|
||||
JSONObject autoConfigJson) {
|
||||
List<RunningAppConditional> conditions = new ArrayList<>();
|
||||
|
||||
@@ -152,7 +169,7 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
|
||||
JSONArray matchList = (JSONArray) positiveMatches.get(positiveMatchKey);
|
||||
matchList.forEach((match) -> {
|
||||
if (match instanceof JSONObject) {
|
||||
getMatchedCondition((JSONObject) match, annotation)
|
||||
getMatchedCondition(app, (JSONObject) match, annotation)
|
||||
.ifPresent((condition) -> conditions.add(condition));
|
||||
}
|
||||
});
|
||||
@@ -203,13 +220,14 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Optional<RunningAppConditional> getMatchedCondition(JSONObject conditionJson, Annotation annotation) {
|
||||
protected Optional<RunningAppConditional> getMatchedCondition(SpringBootApp app, JSONObject conditionJson,
|
||||
Annotation annotation) {
|
||||
if (conditionJson != null) {
|
||||
String condition = (String) conditionJson.get("condition");
|
||||
String message = (String) conditionJson.get("message");
|
||||
String annotationName = annotation.resolveTypeBinding().getName();
|
||||
if (message.contains(annotationName)) {
|
||||
return Optional.of(new RunningAppConditional(condition, message));
|
||||
return Optional.of(new RunningAppConditional(app, condition, message));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
@@ -220,10 +238,12 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
|
||||
|
||||
public final String condition;
|
||||
public final String message;
|
||||
public final SpringBootApp app;
|
||||
|
||||
public RunningAppConditional(String condition, String message) {
|
||||
public RunningAppConditional(SpringBootApp app, String condition, String message) {
|
||||
this.condition = condition;
|
||||
this.message = message;
|
||||
this.app = app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,27 +13,15 @@ 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.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ArrayInitializer;
|
||||
import org.eclipse.jdt.core.dom.Expression;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.QualifiedName;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Hover;
|
||||
import org.eclipse.lsp4j.MarkedString;
|
||||
@@ -66,7 +54,7 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
public Collection<Range> getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
|
||||
try {
|
||||
if (runningApps.length > 0) {
|
||||
Optional<Tuple2<RequestMapping, SpringBootApp>> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
|
||||
Optional<List<Tuple2<RequestMapping, SpringBootApp>>> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
|
||||
if (val.isPresent()) {
|
||||
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
|
||||
return ImmutableList.of(hoverRange);
|
||||
@@ -85,7 +73,7 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
try {
|
||||
List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
|
||||
|
||||
Optional<Tuple2<RequestMapping, SpringBootApp>> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
|
||||
Optional<List<Tuple2<RequestMapping, SpringBootApp>>> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
|
||||
|
||||
if (val.isPresent()) {
|
||||
addHoverContent(val.get(), hoverContent);
|
||||
@@ -105,20 +93,22 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Optional<Tuple2<RequestMapping, SpringBootApp>> getRequestMappingMethodFromRunningApp(Annotation annotation,
|
||||
private Optional<List<Tuple2<RequestMapping, SpringBootApp>>> getRequestMappingMethodFromRunningApp(Annotation annotation,
|
||||
SpringBootApp[] runningApps) {
|
||||
|
||||
try {
|
||||
List<Tuple2<RequestMapping, SpringBootApp>> results = new ArrayList<>();
|
||||
for (SpringBootApp app : runningApps) {
|
||||
Collection<RequestMapping> mappings = app.getRequestMappings();
|
||||
if (mappings!=null && !mappings.isEmpty()) {
|
||||
return mappings.stream()
|
||||
.filter(rm -> matchesAnnotation(annotation, rm))
|
||||
if (mappings != null && !mappings.isEmpty()) {
|
||||
mappings.stream()
|
||||
// .filter(rm -> matchesAnnotation(annotation, rm))
|
||||
.filter(rm -> methodMatchesAnnotation(annotation, rm))
|
||||
.map(rm -> Tuples.of(rm, app))
|
||||
.findFirst();
|
||||
.findFirst().ifPresent(t -> results.add(t));
|
||||
}
|
||||
}
|
||||
return Optional.of(results);
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
@@ -135,7 +125,7 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
return binding.getDeclaringClass().getQualifiedName().equals(rqClassName)
|
||||
&& binding.getName().equals(rm.getMethodName())
|
||||
&& Arrays.equals(Arrays.stream(binding.getParameterTypes())
|
||||
.map(t -> t.getQualifiedName())
|
||||
.map(t -> t.getTypeDeclaration().getQualifiedName())
|
||||
.toArray(String[]::new),
|
||||
rm.getMethodParameters());
|
||||
} else if (parent instanceof TypeDeclaration) {
|
||||
@@ -145,157 +135,154 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addHoverContent(Tuple2<RequestMapping, SpringBootApp> mappingMethod, List<Either<String, MarkedString>> hoverContent) throws Exception {
|
||||
String processId = mappingMethod.getT2().getProcessID();
|
||||
String processName = mappingMethod.getT2().getProcessName();
|
||||
String port = mappingMethod.getT2().getPort();
|
||||
String host = mappingMethod.getT2().getHost();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
private void addHoverContent(List<Tuple2<RequestMapping, SpringBootApp>> mappingMethods, List<Either<String, MarkedString>> hoverContent) throws Exception {
|
||||
for (int i = 0; i < mappingMethods.size(); i++) {
|
||||
Tuple2<RequestMapping, SpringBootApp> mappingMethod = mappingMethods.get(i);
|
||||
|
||||
Arrays.stream(mappingMethod.getT1().getSplitPath()).forEach(path -> {
|
||||
String processId = mappingMethod.getT2().getProcessID();
|
||||
String processName = mappingMethod.getT2().getProcessName();
|
||||
String port = mappingMethod.getT2().getPort();
|
||||
String host = mappingMethod.getT2().getHost();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
String url = UrlUtil.createUrl(host, port, path);
|
||||
Arrays.stream(mappingMethod.getT1().getSplitPath()).forEach(path -> {
|
||||
|
||||
if (builder.length() > 0) {
|
||||
builder.append("\n");
|
||||
}
|
||||
builder.append("Path: ");
|
||||
builder.append("[");
|
||||
builder.append(path);
|
||||
builder.append("]");
|
||||
builder.append("(");
|
||||
builder.append(url);
|
||||
builder.append(")");
|
||||
String url = UrlUtil.createUrl(host, port, path);
|
||||
|
||||
});
|
||||
|
||||
hoverContent.add(Either.forLeft(builder.toString()));
|
||||
hoverContent.add(Either.forLeft("Process ID: " + processId));
|
||||
hoverContent.add(Either.forLeft("Process Name: " + processName));
|
||||
}
|
||||
|
||||
protected String getRequestMethod(SingleMemberAnnotation annotation) {
|
||||
ITypeBinding type = annotation.resolveTypeBinding();
|
||||
if (type != null) {
|
||||
switch (type.getQualifiedName()) {
|
||||
case Constants.SPRING_GET_MAPPING:
|
||||
return "GET";
|
||||
case Constants.SPRING_POST_MAPPING:
|
||||
return "POST";
|
||||
case Constants.SPRING_DELETE_MAPPING:
|
||||
return "DELETE";
|
||||
case Constants.SPRING_PUT_MAPPING:
|
||||
return "PUT";
|
||||
case Constants.SPRING_PATCH_MAPPING:
|
||||
return "PATCH";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean matchesAnnotation(Annotation annotation, RequestMapping rm) {
|
||||
String[] mappingPath = null;
|
||||
Set<String> methods = null;
|
||||
if (annotation instanceof SingleMemberAnnotation) {
|
||||
SingleMemberAnnotation singleAnnotation = (SingleMemberAnnotation) annotation;
|
||||
Expression valueContent = singleAnnotation.getValue();
|
||||
if (valueContent instanceof StringLiteral) {
|
||||
mappingPath = new String[] { ((StringLiteral)valueContent).getLiteralValue() };
|
||||
}
|
||||
String method = getRequestMethod(singleAnnotation);
|
||||
if (method != null) {
|
||||
methods = new HashSet<>();
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
else if (annotation instanceof NormalAnnotation) {
|
||||
List<?> values = ((NormalAnnotation) annotation).values();
|
||||
for (Object value : values) {
|
||||
if (value instanceof MemberValuePair) {
|
||||
MemberValuePair pair = (MemberValuePair)value;
|
||||
String name = pair.getName().toString();
|
||||
switch (name) {
|
||||
case "value":
|
||||
case "path":
|
||||
mappingPath = getPaths(pair.getValue());
|
||||
break;
|
||||
case "method":
|
||||
methods = getRequestMethod(pair.getValue());
|
||||
break;
|
||||
}
|
||||
if (builder.length() > 0) {
|
||||
builder.append("\n");
|
||||
}
|
||||
builder.append("[");
|
||||
builder.append(url);
|
||||
builder.append("]");
|
||||
builder.append("(");
|
||||
builder.append(url);
|
||||
builder.append(")");
|
||||
|
||||
});
|
||||
|
||||
hoverContent.add(Either.forLeft(builder.toString()));
|
||||
hoverContent.add(Either.forLeft("Process ID: " + processId));
|
||||
hoverContent.add(Either.forLeft("Process Name: " + processName));
|
||||
if (i < mappingMethods.size() - 1) {
|
||||
// Three dashes == line separator in Markdown
|
||||
hoverContent.add(Either.forLeft("---"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mappingPath != null) {
|
||||
if (Arrays.equals(mappingPath, rm.getSplitPath())) {
|
||||
if (methods == null || methods.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return methods.equals(rm.getRequestMethods());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private static String getExpressionValueAsString(Expression exp) {
|
||||
if (exp instanceof StringLiteral) {
|
||||
return ((StringLiteral)exp).getLiteralValue();
|
||||
} else if (exp instanceof QualifiedName) {
|
||||
return getExpressionValueAsString(((QualifiedName)exp).getName());
|
||||
} else if (exp instanceof SimpleName) {
|
||||
return ((SimpleName)exp).getIdentifier();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// protected String getRequestMethod(SingleMemberAnnotation annotation) {
|
||||
// ITypeBinding type = annotation.resolveTypeBinding();
|
||||
// if (type != null) {
|
||||
// switch (type.getQualifiedName()) {
|
||||
// case Constants.SPRING_GET_MAPPING:
|
||||
// return "GET";
|
||||
// case Constants.SPRING_POST_MAPPING:
|
||||
// return "POST";
|
||||
// case Constants.SPRING_DELETE_MAPPING:
|
||||
// return "DELETE";
|
||||
// case Constants.SPRING_PUT_MAPPING:
|
||||
// return "PUT";
|
||||
// case Constants.SPRING_PATCH_MAPPING:
|
||||
// return "PATCH";
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// private boolean matchesAnnotation(Annotation annotation, RequestMapping rm) {
|
||||
// String[] mappingPath = null;
|
||||
// Set<String> methods = null;
|
||||
// if (annotation instanceof SingleMemberAnnotation) {
|
||||
// SingleMemberAnnotation singleAnnotation = (SingleMemberAnnotation) annotation;
|
||||
// Expression valueContent = singleAnnotation.getValue();
|
||||
// if (valueContent instanceof StringLiteral) {
|
||||
// mappingPath = new String[] { ((StringLiteral)valueContent).getLiteralValue() };
|
||||
// }
|
||||
// String method = getRequestMethod(singleAnnotation);
|
||||
// if (method != null) {
|
||||
// methods = new HashSet<>();
|
||||
// methods.add(method);
|
||||
// }
|
||||
// }
|
||||
// else if (annotation instanceof NormalAnnotation) {
|
||||
// List<?> values = ((NormalAnnotation) annotation).values();
|
||||
// for (Object value : values) {
|
||||
// if (value instanceof MemberValuePair) {
|
||||
// MemberValuePair pair = (MemberValuePair)value;
|
||||
// String name = pair.getName().toString();
|
||||
// switch (name) {
|
||||
// case "value":
|
||||
// case "path":
|
||||
// mappingPath = getPaths(pair.getValue());
|
||||
// break;
|
||||
// case "method":
|
||||
// methods = getRequestMethod(pair.getValue());
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// if (mappingPath != null) {
|
||||
// if (Arrays.equals(mappingPath, rm.getSplitPath())) {
|
||||
// if (methods == null || methods.isEmpty()) {
|
||||
// return true;
|
||||
// } else {
|
||||
// return methods.equals(rm.getRequestMethods());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// private static String getExpressionValueAsString(Expression exp) {
|
||||
// if (exp instanceof StringLiteral) {
|
||||
// return ((StringLiteral)exp).getLiteralValue();
|
||||
// } else if (exp instanceof QualifiedName) {
|
||||
// return getExpressionValueAsString(((QualifiedName)exp).getName());
|
||||
// } else if (exp instanceof SimpleName) {
|
||||
// return ((SimpleName)exp).getIdentifier();
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// private static String[] getPaths(Expression exp) {
|
||||
// if (exp instanceof ArrayInitializer) {
|
||||
// ArrayInitializer array = (ArrayInitializer) exp;
|
||||
// return ((List<Expression>)array.expressions()).stream()
|
||||
// .map(e -> getExpressionValueAsString(e))
|
||||
// .filter(Objects::nonNull)
|
||||
// .toArray(String[]::new);
|
||||
// } else {
|
||||
// String rm = getExpressionValueAsString(exp);
|
||||
// if (rm != null) {
|
||||
// return new String[] { rm };
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// private static Set<String> getRequestMethod(Expression exp) {
|
||||
// if (exp instanceof ArrayInitializer) {
|
||||
// ArrayInitializer array = (ArrayInitializer) exp;
|
||||
// return ((List<Expression>)array.expressions()).stream()
|
||||
// .map(e -> getExpressionValueAsString(e))
|
||||
// .filter(Objects::nonNull)
|
||||
// .collect(Collectors.toSet());
|
||||
// } else {
|
||||
// String rm = getExpressionValueAsString(exp);
|
||||
// if (rm != null) {
|
||||
// HashSet<String> methods = new HashSet<>();
|
||||
// methods.add(rm);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static String[] getPaths(Expression exp) {
|
||||
if (exp instanceof ArrayInitializer) {
|
||||
ArrayInitializer array = (ArrayInitializer) exp;
|
||||
return ((List<Expression>)array.expressions()).stream()
|
||||
.map(e -> getExpressionValueAsString(e))
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(String[]::new);
|
||||
} else {
|
||||
String rm = getExpressionValueAsString(exp);
|
||||
if (rm != null) {
|
||||
return new String[] { rm };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<String> getRequestMethod(Expression exp) {
|
||||
if (exp instanceof ArrayInitializer) {
|
||||
ArrayInitializer array = (ArrayInitializer) exp;
|
||||
return ((List<Expression>)array.expressions()).stream()
|
||||
.map(e -> getExpressionValueAsString(e))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
} else {
|
||||
String rm = getExpressionValueAsString(exp);
|
||||
if (rm != null) {
|
||||
HashSet<String> methods = new HashSet<>();
|
||||
methods.add(rm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class RequestMappingMethod {
|
||||
|
||||
public final SpringBootApp app;
|
||||
public final RequestMapping requestMapping;
|
||||
|
||||
public RequestMappingMethod(RequestMapping requestMapping, SpringBootApp app) {
|
||||
this.requestMapping = requestMapping;
|
||||
this.app = app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.AutowiredHoverProvider;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
@@ -82,7 +83,7 @@ public class AutowiredHoverProviderTest {
|
||||
AutowiredHoverProvider provider = new AutowiredHoverProvider();
|
||||
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath()));
|
||||
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
|
||||
assertNotNull(hint);
|
||||
|
||||
assertEquals(11, hint.getStart().getLine());
|
||||
@@ -106,7 +107,7 @@ public class AutowiredHoverProviderTest {
|
||||
ASTNode node = NodeFinder.perform(cu, offset, 0).getParent();
|
||||
|
||||
AutowiredHoverProvider provider = new AutowiredHoverProvider();
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, (String)null);
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(null));
|
||||
assertNull(hint);
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ public class AutowiredHoverProviderTest {
|
||||
AutowiredHoverProvider provider = new AutowiredHoverProvider();
|
||||
String beansJSON = new String(Files.readAllBytes(new File(directory, "wrong-runtime-bean-information.json").toPath()));
|
||||
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
|
||||
assertNull(hint);
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ public class AutowiredHoverProviderTest {
|
||||
ASTNode node = NodeFinder.perform(cu, offset, 0).getParent();
|
||||
|
||||
AutowiredHoverProvider provider = new AutowiredHoverProvider();
|
||||
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath()));
|
||||
LiveBeansModel beansModel = LiveBeansModel.parse(new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath())));
|
||||
|
||||
SpringBootAppProvider bootApp = new SpringBootAppProvider() {
|
||||
@Override
|
||||
@@ -160,8 +161,8 @@ public class AutowiredHoverProviderTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBeans() throws Exception {
|
||||
return beansJSON;
|
||||
public LiveBeansModel getBeans() throws Exception {
|
||||
return beansModel;
|
||||
}
|
||||
};
|
||||
CompletableFuture<Hover> hoverFuture = provider.provideHover(null, (Annotation)node, null, offset, document, new SpringBootAppProvider[] {bootApp});
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProvider;
|
||||
import org.springframework.ide.vscode.boot.java.beans.ComponentHoverProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
@@ -82,7 +83,7 @@ public class ComponentHoverProviderTest {
|
||||
ComponentHoverProvider provider = new ComponentHoverProvider();
|
||||
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information-automatically-wired.json").toPath()));
|
||||
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
|
||||
assertNotNull(hint);
|
||||
|
||||
assertEquals(10, hint.getStart().getLine());
|
||||
@@ -108,7 +109,7 @@ public class ComponentHoverProviderTest {
|
||||
ComponentHoverProvider provider = new ComponentHoverProvider();
|
||||
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath()));
|
||||
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
|
||||
Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
|
||||
assertNull(hint);
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ public class ComponentHoverProviderTest {
|
||||
ASTNode node = NodeFinder.perform(cu, offset, 0).getParent();
|
||||
|
||||
ComponentHoverProvider provider = new ComponentHoverProvider();
|
||||
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information-automatically-wired.json").toPath()));
|
||||
LiveBeansModel beansModel = LiveBeansModel.parse(new String(Files.readAllBytes(new File(directory, "runtime-bean-information-automatically-wired.json").toPath())));
|
||||
|
||||
SpringBootAppProvider bootApp = new SpringBootAppProvider() {
|
||||
@Override
|
||||
@@ -141,8 +142,8 @@ public class ComponentHoverProviderTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBeans() throws Exception {
|
||||
return beansJSON;
|
||||
public LiveBeansModel getBeans() throws Exception {
|
||||
return beansModel;
|
||||
}
|
||||
};
|
||||
CompletableFuture<Hover> hoverFuture = provider.provideHover(null, (Annotation) node, null, 0, document, new SpringBootAppProvider[] {bootApp});
|
||||
|
||||
@@ -136,6 +136,66 @@ public class ConditionalsLiveHoverTest {
|
||||
+ "Message: @ConditionalOnExpression (#{true}) resulted in true");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultipleAppsLiveHover() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-conditionals-live-hover/").toURI());
|
||||
String docUri = "file://" + directory.getAbsolutePath()
|
||||
+ "/src/main/java/example/ConditionalOnMissingBeanConfig.java";
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder().isSpringBootApp(true).port("1000").processId("70000").host("cfapps.io")
|
||||
.processName("test-conditionals-live-hover")
|
||||
.getAutoConfigReport(
|
||||
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
|
||||
.build();
|
||||
|
||||
mockAppProvider.builder().isSpringBootApp(true).port("1001").processId("80000").host("cfapps.io")
|
||||
.processName("test-conditionals-live-hover")
|
||||
.getAutoConfigReport(
|
||||
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
|
||||
.build();
|
||||
|
||||
mockAppProvider.builder().isSpringBootApp(true).port("1002").processId("90000").host("cfapps.io")
|
||||
.processName("test-conditionals-live-hover")
|
||||
.getAutoConfigReport(
|
||||
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
|
||||
.build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
|
||||
|
||||
|
||||
editor.assertHoverContains("@ConditionalOnMissingBean", "Condition: OnBeanCondition\n" + "\n"
|
||||
+ "Message: @ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\n" +
|
||||
"\n" +
|
||||
"Process ID: 70000\n" +
|
||||
"\n" +
|
||||
"Process Name: test-conditionals-live-hover\n" +
|
||||
"\n" +
|
||||
"---\n" +
|
||||
"\n" +
|
||||
"Condition: OnBeanCondition\n" + "\n"
|
||||
+ "Message: @ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\n" +
|
||||
"\n" +
|
||||
"Process ID: 80000\n" +
|
||||
"\n" +
|
||||
"Process Name: test-conditionals-live-hover\n" +
|
||||
"\n" +
|
||||
"---\n" +
|
||||
"\n" +
|
||||
"Condition: OnBeanCondition\n" + "\n"
|
||||
+ "Message: @ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\n" +
|
||||
"\n" +
|
||||
"Process ID: 90000\n" +
|
||||
"\n" +
|
||||
"Process Name: test-conditionals-live-hover");
|
||||
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testMultipleLiveHoverHints() throws Exception {
|
||||
//
|
||||
|
||||
@@ -62,7 +62,7 @@ public class RequestMappingLiveHoverTest {
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
|
||||
editor.assertHoverContains("@RequestMapping(\"/hello-world\")", "Path: [/hello-world](http://cfapps.io:1111/hello-world)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(\"/hello-world\")", "[http://cfapps.io:1111/hello-world](http://cfapps.io:1111/hello-world)\n" +
|
||||
"\n" +
|
||||
"Process ID: 22022\n" +
|
||||
"\n" +
|
||||
@@ -94,13 +94,13 @@ public class RequestMappingLiveHoverTest {
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
|
||||
editor.assertHoverContains("@RequestMapping(\"/hello\")", "Path: [/hello](http://cfapps.io:999/hello)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(\"/hello\")", "[http://cfapps.io:999/hello](http://cfapps.io:999/hello)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(\"/goodbye\")", "Path: [/goodbye](http://cfapps.io:999/goodbye)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(\"/goodbye\")", "[http://cfapps.io:999/goodbye](http://cfapps.io:999/goodbye)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
@@ -133,7 +133,7 @@ public class RequestMappingLiveHoverTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteMappingHoverHintMethod1() throws Exception {
|
||||
public void testSimpleMethodHoverHintMethod1() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
@@ -171,7 +171,7 @@ public class RequestMappingLiveHoverTest {
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@DeleteMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
editor.assertHoverContains("@DeleteMapping(\"/greetings\")", "[http://cfapps.io:999/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
@@ -198,7 +198,7 @@ public class RequestMappingLiveHoverTest {
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.deleteGreetings()\"}}")
|
||||
"{\"{[/greetings],methods=[DELETE]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.deleteGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
@@ -213,7 +213,7 @@ public class RequestMappingLiveHoverTest {
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@DeleteMapping(\"/greetings\")\n" +
|
||||
"public void deleteGreetings() {\n" +
|
||||
"public void deleteGreetings(int n) {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
@@ -223,8 +223,11 @@ public class RequestMappingLiveHoverTest {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetMappingHoverHintMethod1() throws Exception {
|
||||
public void testNoHoverHintMethod() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
@@ -241,56 +244,7 @@ public class RequestMappingLiveHoverTest {
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.greetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import java.lang.String;\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.GetMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@GetMapping(\"/greetings\")\n" +
|
||||
"public String greetings() {\n" +
|
||||
"return \"Greetings!\";\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@GetMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappingHoverHintMethod2() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[DELETE]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.greetings()\"}}")
|
||||
"{\"{[/greetings],methods=[PUT]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.updateGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
@@ -300,194 +254,13 @@ public class RequestMappingLiveHoverTest {
|
||||
"\n" +
|
||||
"import java.lang.String;\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.GetMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@GetMapping(\"/greetings\")\n" +
|
||||
"public String greetings() {\n" +
|
||||
"return \"Greetings!\";\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertNoHover("@GetMapping(\"/greetings\")");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPostMappingHoverHintMethod1() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[POST]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.createGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.PostMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@PostMapping(\"/greetings\")\n" +
|
||||
"public void createGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@PostMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPostMappingHoverHintMethod2() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.createGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.PostMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@PostMapping(\"/greetings\")\n" +
|
||||
"public void createGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertNoHover("@PostMapping(\"/greetings\")");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutMappingHoverHintMethod1() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[PUT]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.updateGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.PutMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@PutMapping(\"/greetings\")\n" +
|
||||
"public void updateGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@PutMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutMappingHoverHintMethod2() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.updateGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.PutMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@PutMapping(\"/greetings\")\n" +
|
||||
"public void updateGreetings() {\n" +
|
||||
"public String updateGreetings(int n) {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
@@ -497,188 +270,6 @@ public class RequestMappingLiveHoverTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchMappingHoverHintMethod1() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[PATCH]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.patchGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.PatchMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@PatchMapping(\"/greetings\")\n" +
|
||||
"public void patchGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@PatchMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchMappingHoverHintMethod2() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.patchGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.PatchMapping;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@PatchMapping(\"/greetings\")\n" +
|
||||
"public void patchGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertNoHover("@PatchMapping(\"/greetings\")");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiRequestMethodMappingHoverHintMethod1() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[POST,PUT]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.updateGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value=\"/greetings\", method={POST, PUT})\n" +
|
||||
"public void updateGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/greetings\", method={POST, PUT})", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiRequestMethodMappingHoverHintMethod2() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings],methods=[POST,PUT,PATCH]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.updateGreetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value=\"/greetings\", method={POST, PUT})\n" +
|
||||
"public void updateGreetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertNoHover("@RequestMapping(value=\"/greetings\", method={POST, PUT})");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiPathMappingHoverHintMethod1() throws Exception {
|
||||
|
||||
@@ -719,8 +310,8 @@ public class RequestMappingLiveHoverTest {
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"Path: [/hello](http://cfapps.io:999/hello)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)", "[http://cfapps.io:999/greetings](http://cfapps.io:999/greetings)\n" +
|
||||
"[http://cfapps.io:999/hello](http://cfapps.io:999/hello)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
@@ -728,50 +319,6 @@ public class RequestMappingLiveHoverTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiPathMappingHoverHintMethod2() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/greetings || /hello || /helloAgain],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.greetings()\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)\n" +
|
||||
"public String greetings() {\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertNoHover("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodMatchingHoverHintMethod1() throws Exception {
|
||||
|
||||
@@ -816,7 +363,7 @@ public class RequestMappingLiveHoverTest {
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "Path: [/find](http://cfapps.io:999/find)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
@@ -868,7 +415,7 @@ public class RequestMappingLiveHoverTest {
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "Path: [/find](http://cfapps.io:999/find)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
@@ -921,7 +468,7 @@ public class RequestMappingLiveHoverTest {
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "Path: [/find](http://cfapps.io:999/find)\n" +
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
@@ -929,5 +476,280 @@ public class RequestMappingLiveHoverTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildCardMethodMatchingHoverHint() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String,java.util.Map<java.lang.String, java.util.Map<java.lang.String, ? extends java.lang.Integer>>)\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.http.ResponseEntity;\n" +
|
||||
"import java.lang.String;\n" +
|
||||
"import java.lang.Integer;\n" +
|
||||
"import java.util.Map;\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value=\"/find\", method=GET)\n" +
|
||||
"public Object set(String p1, Map<String, Map<String, ? extends Integer>> p2) {\n" +
|
||||
"return null;\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayMethodMatchingHoverHint() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String[])\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.http.ResponseEntity;\n" +
|
||||
"import java.lang.String;\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value=\"/find\", method=GET)\n" +
|
||||
"public Object set(String[] p) {\n" +
|
||||
"return null;\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiDimensionalArrayMethodMatchingHoverHint() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String[][])\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.http.ResponseEntity;\n" +
|
||||
"import java.lang.String;\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value=\"/find\", method=GET)\n" +
|
||||
"public Object set(String[][] p) {\n" +
|
||||
"return null;\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarArgsMethodMatchingHoverHint() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
|
||||
// Build a mock running boot app
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("999")
|
||||
.processId("76543")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String...)\"}}")
|
||||
. build();
|
||||
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.http.ResponseEntity;\n" +
|
||||
"import java.lang.String;\n" +
|
||||
"import org.springframework.stereotype.Controller;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;\n" +
|
||||
"import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
|
||||
"\n" +
|
||||
"@Controller\n" +
|
||||
"public class RestApi {\n" +
|
||||
"\n" +
|
||||
"@RequestMapping(value=\"/find\", method=GET)\n" +
|
||||
"public Object set(String... p) {\n" +
|
||||
"return null;\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"}",
|
||||
docUri);
|
||||
|
||||
editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
|
||||
"\n" +
|
||||
"Process ID: 76543\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleAppsLiveHover() throws Exception {
|
||||
|
||||
File directory = new File(
|
||||
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
|
||||
String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
|
||||
|
||||
// Build three different instances of the same app running on different ports with different process IDs
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("1000")
|
||||
.processId("70000")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
|
||||
. build();
|
||||
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("1001")
|
||||
.processId("80000")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
|
||||
. build();
|
||||
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.port("1002")
|
||||
.processId("90000")
|
||||
.host("cfapps.io")
|
||||
.processName("test-request-mapping-live-hover")
|
||||
// Ugly, but this is real JSON copied from a real live running app. We want the
|
||||
// mock app to return realistic results if possible
|
||||
.getRequestMappings(
|
||||
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
|
||||
. build();
|
||||
harness.intialize(directory);
|
||||
|
||||
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
|
||||
editor.assertHoverContains("@RequestMapping(\"/hello\")", "[http://cfapps.io:1000/hello](http://cfapps.io:1000/hello)\n" +
|
||||
"\n" +
|
||||
"Process ID: 70000\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover\n" +
|
||||
"\n" +
|
||||
"---\n" +
|
||||
"\n" +
|
||||
"[http://cfapps.io:1001/hello](http://cfapps.io:1001/hello)\n" +
|
||||
"\n" +
|
||||
"Process ID: 80000\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover\n" +
|
||||
"\n" +
|
||||
"---\n" +
|
||||
"\n" +
|
||||
"[http://cfapps.io:1002/hello](http://cfapps.io:1002/hello)\n" +
|
||||
"\n" +
|
||||
"Process ID: 90000\n" +
|
||||
"\n" +
|
||||
"Process Name: test-request-mapping-live-hover");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.mockito.Mockito;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
|
||||
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.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -67,7 +68,7 @@ public class MockRunningAppProvider {
|
||||
}
|
||||
|
||||
public MockAppBuilder beans(String beans) throws Exception {
|
||||
when(app.getBeans()).thenReturn(beans);
|
||||
when(app.getBeans()).thenReturn(LiveBeansModel.parse(beans));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sun</groupId>
|
||||
|
||||
@@ -34,7 +34,9 @@ import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMapping;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMappingImpl1;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -174,7 +176,7 @@ public class SpringBootApp {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getBeans() throws Exception {
|
||||
private String getBeansJson() throws Exception {
|
||||
Object result = getActuatorDataFromAttribute("org.springframework.boot:type=Endpoint,name=beansEndpoint", "Data");
|
||||
if (result != null) {
|
||||
String beans = new ObjectMapper().writeValueAsString(result);
|
||||
@@ -190,6 +192,14 @@ public class SpringBootApp {
|
||||
return null;
|
||||
}
|
||||
|
||||
public LiveBeansModel getBeans() throws Exception {
|
||||
String json = getBeansJson();
|
||||
if (StringUtil.hasText(json)) {
|
||||
return LiveBeansModel.parse(json);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Collection<RequestMapping> parseRequestMappingsJson(String json) {
|
||||
JSONObject obj = new JSONObject(json);
|
||||
Iterator<String> keys = obj.keys();
|
||||
|
||||
@@ -8,37 +8,17 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.autowired;
|
||||
package org.springframework.ide.vscode.commons.boot.app.cli.livebean;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class LiveBean {
|
||||
|
||||
public static LiveBean parse(JSONObject beansJSON) {
|
||||
String id = beansJSON.optString("bean");
|
||||
String type = beansJSON.optString("type");
|
||||
String scope = beansJSON.optString("scope");
|
||||
String resource = beansJSON.optString("resource");
|
||||
|
||||
JSONArray aliasesJSON = beansJSON.getJSONArray("aliases");
|
||||
String[] aliases = new String[aliasesJSON.length()];
|
||||
for (int i = 0; i < aliasesJSON.length(); i++) {
|
||||
aliases[i] = aliasesJSON.optString(i);
|
||||
}
|
||||
|
||||
JSONArray dependenciesJSON = beansJSON.getJSONArray("dependencies");
|
||||
String[] dependencies = new String[dependenciesJSON.length()];
|
||||
for (int i = 0; i < dependenciesJSON.length(); i++) {
|
||||
dependencies[i] = dependenciesJSON.optString(i);
|
||||
}
|
||||
|
||||
return new LiveBean(id, aliases, scope, type, resource, dependencies);
|
||||
}
|
||||
|
||||
private final String id;
|
||||
private final String[] aliases;
|
||||
private final String scope;
|
||||
@@ -0,0 +1,185 @@
|
||||
/*******************************************************************************
|
||||
* 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.commons.boot.app.cli.livebean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class LiveBeansModel {
|
||||
|
||||
interface Parser {
|
||||
LiveBeansModel parse(String json) throws Exception;
|
||||
}
|
||||
|
||||
private static class Boot15Parser implements Parser {
|
||||
@Override
|
||||
public LiveBeansModel parse(String json) throws Exception {
|
||||
LiveBeansModel model = new LiveBeansModel();
|
||||
JSONArray mainArray = new JSONArray(json);
|
||||
for (int i = 0; i < mainArray.length(); i++) {
|
||||
JSONObject appContext = mainArray.getJSONObject(i);
|
||||
if (appContext == null) continue;
|
||||
|
||||
JSONArray beansArray = appContext.optJSONArray("beans");
|
||||
if (beansArray == null) continue;
|
||||
|
||||
for (int j = 0; j < beansArray.length(); j++) {
|
||||
JSONObject beanObject = beansArray.getJSONObject(j);
|
||||
if (beanObject == null) continue;
|
||||
|
||||
LiveBean bean = parseBean(beanObject);
|
||||
if (bean != null) {
|
||||
model.add(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
private LiveBean parseBean(JSONObject beansJSON) {
|
||||
String id = beansJSON.optString("bean");
|
||||
String type = beansJSON.optString("type");
|
||||
String scope = beansJSON.optString("scope");
|
||||
String resource = beansJSON.optString("resource");
|
||||
|
||||
JSONArray aliasesJSON = beansJSON.getJSONArray("aliases");
|
||||
String[] aliases = new String[aliasesJSON.length()];
|
||||
for (int i = 0; i < aliasesJSON.length(); i++) {
|
||||
aliases[i] = aliasesJSON.optString(i);
|
||||
}
|
||||
|
||||
JSONArray dependenciesJSON = beansJSON.getJSONArray("dependencies");
|
||||
String[] dependencies = new String[dependenciesJSON.length()];
|
||||
for (int i = 0; i < dependenciesJSON.length(); i++) {
|
||||
dependencies[i] = dependenciesJSON.optString(i);
|
||||
}
|
||||
|
||||
return new LiveBean(id, aliases, scope, type, resource, dependencies);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Boot20Parser implements Parser {
|
||||
@Override
|
||||
public LiveBeansModel parse(String json) throws Exception {
|
||||
LiveBeansModel model = new LiveBeansModel();
|
||||
JSONObject mainObject = new JSONObject(json);
|
||||
JSONObject beansObject = mainObject.getJSONObject("beans");
|
||||
for (String id : beansObject.keySet()) {
|
||||
JSONObject beanObject = beansObject.getJSONObject(id);
|
||||
System.out.println(beanObject.toString(3));
|
||||
LiveBean bean = parseBean(id, beanObject);
|
||||
if (bean!=null) {
|
||||
model.add(bean);
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private LiveBean parseBean(String id, JSONObject beansJSON) {
|
||||
String type = beansJSON.optString("type");
|
||||
String scope = beansJSON.optString("scope");
|
||||
String resource = beansJSON.optString("resource");
|
||||
|
||||
JSONArray aliasesJSON = beansJSON.getJSONArray("aliases");
|
||||
String[] aliases = new String[aliasesJSON.length()];
|
||||
for (int i = 0; i < aliasesJSON.length(); i++) {
|
||||
aliases[i] = aliasesJSON.optString(i);
|
||||
}
|
||||
|
||||
JSONArray dependenciesJSON = beansJSON.getJSONArray("dependencies");
|
||||
String[] dependencies = new String[dependenciesJSON.length()];
|
||||
for (int i = 0; i < dependenciesJSON.length(); i++) {
|
||||
dependencies[i] = dependenciesJSON.optString(i);
|
||||
}
|
||||
|
||||
return new LiveBean(id, aliases, scope, type, resource, dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Parser[] PARSERS = {
|
||||
new Boot15Parser(),
|
||||
new Boot20Parser(),
|
||||
};
|
||||
|
||||
public static LiveBeansModel parse(String json) {
|
||||
List<Exception> exceptions = new ArrayList<>(PARSERS.length);
|
||||
if (StringUtil.hasText(json)) {
|
||||
for (Parser parser : PARSERS) {
|
||||
try {
|
||||
LiveBeansModel model = parser.parse(json);
|
||||
if (model==null) {
|
||||
throw new NullPointerException("Parser returned a null model (it should not!)");
|
||||
}
|
||||
return model; //good!
|
||||
} catch (Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Only getting here if none of the parsers worked... So if at least one parser works,
|
||||
// we won't log any exceptions.
|
||||
for (Exception e : exceptions) {
|
||||
Log.log(e);
|
||||
}
|
||||
return new LiveBeansModel(); // allways return at least an empty model.
|
||||
}
|
||||
|
||||
private final ConcurrentMap<String, List<LiveBean>> beansViaType;
|
||||
private final ConcurrentMap<String, List<LiveBean>> beansViaName;
|
||||
|
||||
protected LiveBeansModel() {
|
||||
this.beansViaType = new ConcurrentHashMap<>();
|
||||
this.beansViaName = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public LiveBean[] getBeansOfType(String fullyQualifiedType) {
|
||||
List<LiveBean> result = beansViaType.get(fullyQualifiedType);
|
||||
return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
|
||||
}
|
||||
|
||||
public LiveBean[] getBeansOfName(String beanName) {
|
||||
List<LiveBean> result = beansViaName.get(beanName);
|
||||
return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
|
||||
}
|
||||
|
||||
protected void add(LiveBean bean) {
|
||||
String type = bean.getType();
|
||||
if (type != null) {
|
||||
beansViaType.computeIfAbsent(type, (t) -> new ArrayList<>()).add(bean);
|
||||
}
|
||||
|
||||
String name = bean.getId();
|
||||
if (name != null) {
|
||||
beansViaName.computeIfAbsent(name, (n) -> new ArrayList<>()).add(bean);
|
||||
}
|
||||
}
|
||||
|
||||
public Stream<LiveBean> getAllBeans() {
|
||||
return beansViaName.values().stream().flatMap(Collection::stream);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return !getAllBeans().findAny().isPresent();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,15 +8,16 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.autowired.test;
|
||||
package org.springframework.ide.vscode.commons.boot.app.cli;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.LiveBean;
|
||||
import org.springframework.ide.vscode.boot.java.autowired.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
@@ -25,7 +26,7 @@ public class LiveBeansModelTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleModel() throws Exception {
|
||||
String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/simple-live-beans-model.json"));
|
||||
String json = IOUtils.toString(getResourceAsStream("/live-beans-models/simple-live-beans-model.json"));
|
||||
LiveBeansModel model = LiveBeansModel.parse(json);
|
||||
|
||||
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
|
||||
@@ -49,7 +50,7 @@ public class LiveBeansModelTest {
|
||||
|
||||
@Test
|
||||
public void testEmptyModel() throws Exception {
|
||||
String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/empty-live-beans-model.json"));
|
||||
String json = IOUtils.toString(getResourceAsStream("/live-beans-models/empty-live-beans-model.json"));
|
||||
LiveBeansModel model = LiveBeansModel.parse(json);
|
||||
|
||||
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
|
||||
@@ -58,11 +59,15 @@ public class LiveBeansModelTest {
|
||||
|
||||
@Test
|
||||
public void testTotallyEmptyModel() throws Exception {
|
||||
String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/totally-empty-live-beans-model.json"));
|
||||
String json = IOUtils.toString(getResourceAsStream("/live-beans-models/totally-empty-live-beans-model.json"));
|
||||
LiveBeansModel model = LiveBeansModel.parse(json);
|
||||
|
||||
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
|
||||
assertEquals(0, bean.length);
|
||||
}
|
||||
|
||||
private InputStream getResourceAsStream(String string) {
|
||||
return LiveBeansModelTest.class.getResourceAsStream(string);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,23 +12,27 @@ package org.springframework.ide.vscode.commons.boot.app.cli;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMapping;
|
||||
import org.springframework.ide.vscode.commons.util.AsyncProcess;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.ExternalCommand;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.test.ACondition;
|
||||
@@ -37,25 +41,36 @@ import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class SpringBootAppTest {
|
||||
|
||||
// private static final String appName = "actuator-client-15-test-subject"; // Boot 1.5 test app
|
||||
private static final String appName = "actuator-client-20-test-subject"; //Boot 2.0 test app
|
||||
// private static final String appName = "actuator-client-20-thin-test-subject"; //Boot 2.0 test app with THIN launcher
|
||||
private static final String[] appNames = {
|
||||
"actuator-client-15-test-subject", // Boot 1.5 test app
|
||||
"actuator-client-20-test-subject", //Boot 2.0 test app
|
||||
"actuator-client-20-thin-test-subject", // Like the Boot 2.0 app, but packaged with thin launcher instead of fatjar
|
||||
};
|
||||
|
||||
private static final Duration TIMEOUT = Duration.ofSeconds(30); // in CI build starting the app takes longer than 10s sometimes.
|
||||
//Output from CI build: Started ActuatorClientTestSubjectApplication in 22.962 seconds (JVM running for 26.028)
|
||||
private static final Duration TIMEOUT = Duration.ofSeconds(60); // in CI build starting the app takes a while, starting several in parallel takes even longer
|
||||
|
||||
private static final List<String> TEST_PROFILES = ImmutableList.of("testing", "funny", "cameleon");
|
||||
|
||||
private static AsyncProcess testAppRunner;
|
||||
private static SpringBootApp testApp;
|
||||
private static List<AsyncProcess> testAppRunners;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupClass() throws Exception {
|
||||
testAppRunner = startTestApplication(SpringBootAppTest.class.getResource("/"+appName+"-0.0.1-SNAPSHOT.jar"));
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
testApp = getAppContaining(appName);
|
||||
assertNotNull(testApp);
|
||||
});
|
||||
testAppRunners = Arrays.asList(appNames).stream().map(appName -> {
|
||||
try {
|
||||
return startTestApplication(SpringBootAppTest.class.getResource("/boot-apps/"+appName+"-0.0.1-SNAPSHOT.jar"));
|
||||
} catch (Exception e) {
|
||||
throw ExceptionUtil.unchecked(e);
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
for (AsyncProcess process : testAppRunners) {
|
||||
process.kill();
|
||||
}
|
||||
testAppRunners = null;
|
||||
}
|
||||
|
||||
private static AsyncProcess startTestApplication(URL jarUrl) throws Exception {
|
||||
@@ -73,95 +88,127 @@ public class SpringBootAppTest {
|
||||
);
|
||||
}
|
||||
|
||||
private static SpringBootApp getAppContaining(String nameFragment) throws Exception {
|
||||
return SpringBootApp.getAllRunningJavaApps().values().stream().filter(app -> app.getProcessName().contains(nameFragment)).findAny().get();
|
||||
private SpringBootApp getAppContaining(String nameFragment) {
|
||||
try {
|
||||
return SpringBootApp.getAllRunningJavaApps().values().stream().filter(app -> app.getProcessName().contains(nameFragment)).findAny().get();
|
||||
} catch (Exception e) {
|
||||
throw ExceptionUtil.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
testAppRunner.kill();
|
||||
@Ignore @Test public void dumpJvmInfo() throws Exception {
|
||||
//Ignored because this test may have timing issues. Still useful to
|
||||
// run locally and inspect dump results, but may need some tweaking.
|
||||
for (String appName : appNames) {
|
||||
SpringBootApp testApp = getAppContaining(appName);
|
||||
testApp.dumpJvmInfo();
|
||||
System.out.println("======================================");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllJavaApps() throws Exception {
|
||||
@Test public void getAllJavaApps() throws Exception {
|
||||
Map<String, SpringBootApp> allApps = SpringBootApp.getAllRunningJavaApps();
|
||||
Optional<SpringBootApp> myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
|
||||
assertTrue(myProcess.isPresent());
|
||||
}
|
||||
|
||||
@Test public void dumpJvmInfo() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, this::getRequestMappings);
|
||||
testApp.dumpJvmInfo();
|
||||
// SpringBootApp app = getAppContaining("language-server.jar");
|
||||
// app.dumpJvmInfo();
|
||||
for (String appName : appNames) {
|
||||
Optional<SpringBootApp> myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
|
||||
assertTrue(appName, myProcess.isPresent());
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void getAllBootApps() throws Exception {
|
||||
Map<String, SpringBootApp> allApps = SpringBootApp.getAllRunningSpringApps();
|
||||
Optional<SpringBootApp> myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
|
||||
assertTrue(myProcess.isPresent());
|
||||
for (String appName : appNames) {
|
||||
Optional<SpringBootApp> myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
|
||||
assertTrue(myProcess.isPresent());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPort() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
int port = Integer.parseInt(testApp.getPort());
|
||||
assertTrue(port > 0);
|
||||
// System.out.println("port = "+port);
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
int port = Integer.parseInt(testApp.getPort());
|
||||
assertTrue(port > 0);
|
||||
// System.out.println("port = "+port);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<SpringBootApp> getTestApps() throws Exception {
|
||||
return ACondition.waitForValue(TIMEOUT, () -> Arrays.asList(appNames).stream()
|
||||
.map(this::getAppContaining)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHost() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String host = testApp.getHost();
|
||||
assertTrue(StringUtil.hasText(host));
|
||||
// System.out.println("host = "+host);
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
System.err.println("getHost for "+testApp);
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String host = testApp.getHost();
|
||||
assertTrue(StringUtil.hasText(host));
|
||||
System.out.println("host = "+host);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEnvironment() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String env = testApp.getEnvironment();
|
||||
assertNonEmptyJsonObject(env);
|
||||
System.out.println("env = "+new JSONObject(env).toString(3));
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String env = testApp.getEnvironment();
|
||||
assertNonEmptyJsonObject(env);
|
||||
System.out.println("env = "+new JSONObject(env).toString(3));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBeans() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String beans = testApp.getBeans();
|
||||
assertNonEmptyJsonObject(beans);
|
||||
// System.out.println("beans = "+beans);
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
try {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
LiveBeansModel beansModel = testApp.getBeans();
|
||||
assertTrue(beansModel.getAllBeans().findAny().isPresent());
|
||||
// System.out.println("beans = "+beans);
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
//Make it easier to identify the culprit of failing test
|
||||
throw new RuntimeException("Failed for: "+testApp.getProcessName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestMappings() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
Collection<RequestMapping> result = testApp.getRequestMappings();
|
||||
assertTrue(result != null && !result.isEmpty());
|
||||
// System.out.println("requestMappings = "+result);
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
Collection<RequestMapping> result = testApp.getRequestMappings();
|
||||
assertTrue(result != null && !result.isEmpty());
|
||||
// System.out.println("requestMappings = "+result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAutoConfigReport() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String result = testApp.getAutoConfigReport();
|
||||
assertNonEmptyJsonObject(result);
|
||||
// System.out.println("autoconfreport = "+result);
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String result = testApp.getAutoConfigReport();
|
||||
assertNonEmptyJsonObject(result);
|
||||
// System.out.println("autoconfreport = "+result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProfiles() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
List<String> result = testApp.getActiveProfiles();
|
||||
assertEquals(ImmutableList.copyOf(TEST_PROFILES), result);
|
||||
});
|
||||
for (SpringBootApp testApp : getTestApps()) {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
List<String> result = testApp.getActiveProfiles();
|
||||
assertEquals(ImmutableList.copyOf(TEST_PROFILES), result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void assertNonEmptyJsonObject(String jsonData) {
|
||||
|
||||
@@ -108,15 +108,24 @@ public class JLRMethodParser {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (Character.isJavaIdentifierPart(ch)) {
|
||||
currentParameter.append(ch);
|
||||
}
|
||||
currentParameter.append(ch);
|
||||
}
|
||||
}
|
||||
if (currentParameter.length() > 0) {
|
||||
parameters.add(currentParameter.toString());
|
||||
}
|
||||
return parameters.toArray(new String[parameters.size()]);
|
||||
return parameters.stream()
|
||||
.map(p -> {
|
||||
int genericStart = p.indexOf('<');
|
||||
int genericEnd = p.lastIndexOf('>');
|
||||
if (genericStart < genericEnd) {
|
||||
return p.substring(0, genericStart) + p.substring(genericEnd + 1);
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
})
|
||||
.map(p -> p.replaceAll("\\.\\.\\.", "[]"))
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,14 +14,13 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
|
||||
/**
|
||||
* Composite project manager that acts a single project manager but consissts of many project managers
|
||||
* Composite project manager that acts a single project manager but consists of many project managers
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
@@ -48,7 +47,7 @@ public class CompositeJavaProjectFinder implements JavaProjectFinder {
|
||||
|
||||
@Override
|
||||
public Optional<IJavaProject> find(TextDocumentIdentifier doc) {
|
||||
return projectFinders.stream().map(finder -> finder.find(doc)).filter(Optional::isPresent).findFirst().orElse(null);
|
||||
return projectFinders.stream().map(finder -> finder.find(doc)).filter(Optional::isPresent).findFirst().orElseGet(() -> Optional.empty());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
package org.springframework.ide.vscode.commons.util.test;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
@@ -44,5 +46,14 @@ public class ACondition {
|
||||
} while (System.currentTimeMillis()-startTime < timeout_millis);
|
||||
throw ExceptionUtil.exception(lastException);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retries fecthing a value until it succeeds without an error, or until timeout exceeded.
|
||||
*/
|
||||
public static <T> T waitForValue(Duration timeout, Callable<T> provider) throws Exception {
|
||||
AtomicReference<T> result = new AtomicReference<>(null);
|
||||
waitFor(timeout, () -> result.set(provider.call()));
|
||||
return result.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
<reactor-version>3.0.5.RELEASE</reactor-version>
|
||||
<reactor-netty>0.6.0.RELEASE</reactor-netty>
|
||||
<cloudfoundry-client-version>2.4.0.RELEASE</cloudfoundry-client-version>
|
||||
<commons-io-version>2.4</commons-io-version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
||||
Reference in New Issue
Block a user