Merge branch 'master' of github.com:spring-projects/sts4
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -14,6 +14,7 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
@@ -60,7 +61,7 @@ public abstract class AnnotationHierarchies {
|
||||
|
||||
public static Set<String> getTransitiveSuperAnnotations(ITypeBinding typeBinding) {
|
||||
Set<String> seen = new HashSet<>();
|
||||
findTransitiveSupers(typeBinding, seen);
|
||||
findTransitiveSupers(typeBinding, seen).collect(Collectors.toList());
|
||||
return seen;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.livehover;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -27,21 +28,18 @@ import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
|
||||
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
|
||||
import org.springframework.ide.vscode.boot.java.utils.FunctionUtils;
|
||||
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.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.util.function.Tuple3;
|
||||
|
||||
public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverProvider {
|
||||
|
||||
public ComponentInjectionsHoverProvider(BootJavaLanguageServerComponents server) {
|
||||
@@ -135,8 +133,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
|
||||
@Override
|
||||
public Collection<Range> getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc,
|
||||
SpringBootApp[] runningApps) {
|
||||
Tuple3<String, String, DocumentRegion> functionBean = FunctionUtils.getFunctionBean(typeDeclaration, doc);
|
||||
if (functionBean != null && runningApps.length > 0) {
|
||||
if (runningApps.length > 0 && !isComponentAnnotatedType(typeDeclaration)) {
|
||||
try {
|
||||
LiveBean definedBean = getDefinedBeanForType(typeDeclaration, null);
|
||||
if (definedBean != null) {
|
||||
@@ -157,8 +154,8 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
|
||||
@Override
|
||||
public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset,
|
||||
TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) {
|
||||
Tuple3<String, String, DocumentRegion> functionBean = FunctionUtils.getFunctionBean(typeDeclaration, doc);
|
||||
if (functionBean != null && runningApps.length > 0) {
|
||||
|
||||
if (runningApps.length > 0 && !isComponentAnnotatedType(typeDeclaration)) {
|
||||
|
||||
LiveBean definedBean = getDefinedBeanForType(typeDeclaration, null);
|
||||
if (definedBean != null) {
|
||||
@@ -191,4 +188,26 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isComponentAnnotatedType(TypeDeclaration typeDeclaration) {
|
||||
List<?> modifiers = typeDeclaration.modifiers();
|
||||
for (Object modifier : modifiers) {
|
||||
if (modifier instanceof Annotation) {
|
||||
ITypeBinding typeBinding = ((Annotation) modifier).resolveTypeBinding();
|
||||
return isComponentAnnotation(typeBinding);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isComponentAnnotation(ITypeBinding type) {
|
||||
Set<String> transitiveSuperAnnotations = AnnotationHierarchies.getTransitiveSuperAnnotations(type);
|
||||
for (String annotationType : transitiveSuperAnnotations) {
|
||||
if (Annotations.COMPONENT.equals(annotationType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.ide.vscode.project.harness.BootJavaLanguageServerHarn
|
||||
import org.springframework.ide.vscode.project.harness.MockRunningAppProvider;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
|
||||
public class FunctionInjectionsHoverProviderTest {
|
||||
public class BeansByTypeHoverProviderTest {
|
||||
|
||||
private BootJavaLanguageServerHarness harness;
|
||||
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
|
||||
@@ -45,7 +45,53 @@ public class FunctionInjectionsHoverProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeButNotAFunction() throws Exception {
|
||||
public void typeButNotABean() throws Exception {
|
||||
LiveBeansModel beans = LiveBeansModel.builder()
|
||||
.add(LiveBean.builder()
|
||||
.id("scannedRandomClass")
|
||||
.type("com.example.ScannedRandomClass")
|
||||
.build()
|
||||
)
|
||||
.add(LiveBean.builder()
|
||||
.id("randomOtherBean")
|
||||
.type("randomOtherBeanType")
|
||||
.dependencies("scannedRandomClass")
|
||||
.build()
|
||||
)
|
||||
.add(LiveBean.builder()
|
||||
.id("irrelevantBean")
|
||||
.type("com.example.IrrelevantBean")
|
||||
.dependencies("myController")
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.processId("111")
|
||||
.processName("the-app")
|
||||
.beans(beans)
|
||||
.build();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import java.io.Serializable;\n" +
|
||||
"\n" +
|
||||
"public class ClassNoBean implements Serializable {\n" +
|
||||
"\n" +
|
||||
" public String apply(String t) {\n" +
|
||||
" return t.toUpperCase();\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
"}\n" +
|
||||
""
|
||||
);
|
||||
editor.assertHighlights();
|
||||
editor.assertNoHover("ClassNoBean");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeWithGeneralBean() throws Exception {
|
||||
LiveBeansModel beans = LiveBeansModel.builder()
|
||||
.add(LiveBean.builder()
|
||||
.id("scannedRandomClass")
|
||||
@@ -86,8 +132,17 @@ public class FunctionInjectionsHoverProviderTest {
|
||||
"}\n" +
|
||||
""
|
||||
);
|
||||
editor.assertHighlights();
|
||||
editor.assertNoHover("ScannedRandomClass");
|
||||
editor.assertHighlights("ScannedRandomClass");
|
||||
editor.assertTrimmedHover("ScannedRandomClass",
|
||||
"**Injection report for Bean [id: scannedRandomClass, type: `com.example.ScannedRandomClass`]**\n" +
|
||||
"\n" +
|
||||
"Process [PID=111, name=`the-app`]:\n" +
|
||||
"\n" +
|
||||
"Bean [id: scannedRandomClass, type: `com.example.ScannedRandomClass`] injected into:\n" +
|
||||
"\n" +
|
||||
"- Bean: randomOtherBean \n" +
|
||||
" Type: `randomOtherBeanType`"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,4 +200,46 @@ public class FunctionInjectionsHoverProviderTest {
|
||||
" Type: `org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration`"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalBeanLiveHoverAvoidOverlapWithAnnotation() throws Exception {
|
||||
LiveBeansModel beans = LiveBeansModel.builder()
|
||||
.add(LiveBean.builder()
|
||||
.id("fooImplementation")
|
||||
.type("com.example.FooImplementation")
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.processId("111")
|
||||
.processName("the-app")
|
||||
.beans(beans)
|
||||
.build();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA,
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.stereotype.Component;\n" +
|
||||
"\n" +
|
||||
"@Component\n" +
|
||||
"public class FooImplementation implements Foo {\n" +
|
||||
"\n" +
|
||||
" @Override\n" +
|
||||
" public void doSomeFoo() {\n" +
|
||||
" System.out.println(\"Foo do do do!\");\n" +
|
||||
" }\n" +
|
||||
"}\n"
|
||||
);
|
||||
editor.assertHighlights("@Component");
|
||||
editor.assertTrimmedHover("@Component",
|
||||
"**Injection report for Bean [id: fooImplementation, type: `com.example.FooImplementation`]**\n" +
|
||||
"\n" +
|
||||
"Process [PID=111, name=`the-app`]:\n" +
|
||||
"\n" +
|
||||
"Bean [id: fooImplementation, type: `com.example.FooImplementation`] exists but is **Not injected anywhere**\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -14,6 +14,10 @@ To install it in vscode follow these steps:
|
||||
- Press `CTRL-SHIFT-P` and type 'vsix' in the search box
|
||||
- Select the `Extensions: Install from vsix file` command
|
||||
- Install the `.vsix` you downloaded earlier.
|
||||
|
||||
**IMPORTANT**: Take care not to install multiple versions of the extension at once.
|
||||
Vscode will not complain but it leads to unpredictable outcomes. So if you have
|
||||
a prior version already installed make sure to uninstall it first!
|
||||
|
||||
## Bulding and Running
|
||||
|
||||
|
||||
Reference in New Issue
Block a user