From 705d81f9453b0f109c2e82e8322584d54525fe5f Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 27 Jul 2018 17:43:48 -0400 Subject: [PATCH 01/14] PT #159371605: Implicitly autowired constructor boot hint and hover --- .../languageserver/testharness/Editor.java | 14 +- .../autowired/AutowiredHoverProvider.java | 215 +++++++++++------- .../ConditionalsLiveHoverProvider.java | 15 +- .../java/handlers/BootJavaHoverProvider.java | 61 ++++- .../boot/java/handlers/HoverProvider.java | 23 +- .../AbstractInjectedIntoHoverProvider.java | 10 +- .../livehover/ActiveProfilesProvider.java | 15 +- .../BeanInjectedIntoHoverProvider.java | 22 -- .../ComponentInjectionsHoverProvider.java | 47 +--- .../RequestMappingHoverProvider.java | 15 +- .../ide/vscode/boot/java/utils/ASTUtils.java | 19 +- .../boot/java/value/ValueHoverProvider.java | 12 - .../test/AutowiredHoverProviderTest.java | 161 +++++++++++++ .../ComponentInjectionsHoverProviderTest.java | 12 +- 14 files changed, 393 insertions(+), 248 deletions(-) diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java index 85351652f..62a9c5dc2 100644 --- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java +++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java @@ -600,18 +600,26 @@ public class Editor { } public void assertTrimmedHover(String hoverOver, String expectedHover) throws Exception { - int hoverPosition = getHoverPosition(hoverOver,1); + assertTrimmedHover(hoverOver, 1, expectedHover); + } + + public void assertTrimmedHover(String hoverOver, int occurence, String expectedHover) throws Exception { + int hoverPosition = getHoverPosition(hoverOver,occurence); Hover hover = harness.getHover(doc, doc.toPosition(hoverPosition)); assertEquals(expectedHover.trim(), hoverString(hover).trim()); } - public void assertNoHover(String hoverOver) throws Exception { - int hoverPosition = getRawText().indexOf(hoverOver) + hoverOver.length() / 2; + public void assertNoHover(String hoverOver, int occurence) throws Exception { + int hoverPosition = getHoverPosition(hoverOver,occurence); Hover hover = harness.getHover(doc, doc.toPosition(hoverPosition)); List> contents = hover.getContents().getLeft(); assertTrue(contents.toString(), contents.isEmpty()); } + public void assertNoHover(String hoverOver) throws Exception { + assertNoHover(hoverOver, 1); + } + /** * Verifies an expected textSnippet is contained in the hover text that is * computed when hovering mouse at position at the end of first occurrence of diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java index aedb86d9e..b19aa07dc 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java @@ -20,6 +20,7 @@ import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.MarkerAnnotation; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.TypeDeclaration; @@ -40,6 +41,7 @@ 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.java.IType; +import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.text.TextDocument; @@ -63,109 +65,116 @@ public class AutowiredHoverProvider implements HoverProvider { } @Override - public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + public Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + LiveBean definedBean = getDefinedBeanForTypeDeclaration(ASTUtils.findDeclaringType(annotation)); + // Annotation is MarkerNode, parent is some field, method, variable declaration node. + ASTNode declarationNode = annotation.getParent(); try { - LiveBean definedBean = getDefinedBean(annotation); - if (definedBean != null) { - for (SpringBootApp app : runningApps) { - try { - List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean).collect(Collectors.toList()); + Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength()); + return getLiveHoverHints(project, declarationNode, hoverRange, runningApps, definedBean); + } catch (BadLocationException e) { + log.error("", e); + } + return null; + } - if (!relevantBeans.isEmpty()) { - for (LiveBean bean : relevantBeans) { - String[] dependencies = bean.getDependencies(); - if (dependencies != null && dependencies.length > 0) { - Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength()); - return ImmutableList.of(hoverRange); - } - } - } - } - catch (Exception e) { - log.error("", e); - } + private Collection getLiveHoverHints(IJavaProject project, ASTNode declarationNode, Range range, + SpringBootApp[] runningApps, LiveBean definedBean) { + if (declarationNode != null && definedBean != null) { + for (SpringBootApp app : runningApps) { + List relevantBeans = getRelevantAutowiredBeans(project, declarationNode, app, definedBean); + if (!relevantBeans.isEmpty()) { + return ImmutableList.of(range); } } } - catch (Exception e) { - log.error("", e); - } - return null; } @Override public Hover provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - if (runningApps.length > 0) { + LiveBean definedBean = getDefinedBeanForTypeDeclaration(ASTUtils.findDeclaringType(annotation)); + // Annotation is MarkerNode, parent is some field, method, variable declaration node. + ASTNode declarationNode = annotation.getParent(); + return provideHover(definedBean, declarationNode, offset, doc, project, runningApps); + } + + private Hover provideHover(LiveBean definedBean, ASTNode declarationNode, int offset, TextDocument doc, + IJavaProject project, SpringBootApp[] runningApps) { + if (definedBean != null && runningApps.length > 0) { StringBuilder hover = new StringBuilder(); - LiveBean definedBean = getDefinedBean(annotation); - if (definedBean != null) { + boolean hasContent = false; - boolean hasContent = false; + for (SpringBootApp app : runningApps) { - for (SpringBootApp app : runningApps) { - LiveBeansModel beans = app.getBeans(); - List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean).collect(Collectors.toList()); + List autowiredBeans = getRelevantAutowiredBeans(project, declarationNode, app, definedBean); - if (!relevantBeans.isEmpty()) { - List allDependencyBeans = relevantBeans.stream() - .flatMap(b -> Arrays.stream(b.getDependencies())) - .distinct() - .flatMap(d -> beans.getBeansOfName(d).stream()) - .collect(Collectors.toList()); - - if (!allDependencyBeans.isEmpty()) { - - // parent is marker node, grandparent is some field, method, variable declaration node. - ASTNode declarationNode = node.getParent().getParent(); - List autowiredBeans = findAutowiredBeans(project, declarationNode, allDependencyBeans); - if (autowiredBeans.isEmpty()) { - // Show all relevant dependency beans - autowiredBeans = allDependencyBeans; - } - - if (!autowiredBeans.isEmpty()) { - if (!hasContent) { - hasContent = true; - } else { - hover.append(" \n \n"); - } - hover.append("**Autowired → "); - if (LiveHoverUtils.doBeansFitInline(autowiredBeans, MAX_INLINE_BEANS_STRING_LENGTH, INLINE_BEANS_STRING_SEPARATOR)) { - hover.append(autowiredBeans.stream().map(b -> LiveHoverUtils.showBeanInline(server, project, b)).collect(Collectors.joining(INLINE_BEANS_STRING_SEPARATOR))); - hover.append("**\n"); - } else { - hover.append(autowiredBeans.size()); - hover.append(" beans**\n"); - } + if (!autowiredBeans.isEmpty()) { + if (!hasContent) { + hasContent = true; + } else { + hover.append(" \n \n"); + } + hover.append("**Autowired → "); + if (LiveHoverUtils.doBeansFitInline(autowiredBeans, MAX_INLINE_BEANS_STRING_LENGTH, + INLINE_BEANS_STRING_SEPARATOR)) { + hover.append(autowiredBeans.stream().map(b -> LiveHoverUtils.showBeanInline(server, project, b)) + .collect(Collectors.joining(INLINE_BEANS_STRING_SEPARATOR))); + hover.append("**\n"); + } else { + hover.append(autowiredBeans.size()); + hover.append(" beans**\n"); + } // if (autowiredBeans.size() == 1) { // hover.append(LiveHoverUtils.showBeanIdAndTypeInline(server, project, autowiredBeans.get(0))); // } else { // hover.append(autowiredBeans.size()); // hover.append(" beans**\n"); // } - hover.append(autowiredBeans.stream() - .map(b -> "- " + LiveHoverUtils.showBeanWithResource(server, b, " ", project)) - .collect(Collectors.joining("\n")) - ); - hover.append("\n \n"); - hover.append(LiveHoverUtils.niceAppName(app)); - } - } - } + hover.append(autowiredBeans.stream() + .map(b -> "- " + LiveHoverUtils.showBeanWithResource(server, b, " ", project)) + .collect(Collectors.joining("\n"))); + hover.append("\n \n"); + hover.append(LiveHoverUtils.niceAppName(app)); + } - } - if (hasContent) { - return new Hover(ImmutableList.of(Either.forLeft(hover.toString()))); - } + } + if (hasContent) { + return new Hover(ImmutableList.of(Either.forLeft(hover.toString()))); } } return null; } + private List getRelevantAutowiredBeans(IJavaProject project, ASTNode declarationNode, SpringBootApp app, LiveBean definedBean) { + LiveBeansModel beans = app.getBeans(); + List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean) + .collect(Collectors.toList()); + + if (!relevantBeans.isEmpty()) { + List allDependencyBeans = relevantBeans.stream() + .flatMap(b -> Arrays.stream(b.getDependencies())).distinct() + .flatMap(d -> beans.getBeansOfName(d).stream()).collect(Collectors.toList()); + + if (!allDependencyBeans.isEmpty()) { + + List autowiredBeans = findAutowiredBeans(project, declarationNode, + allDependencyBeans); + if (autowiredBeans.isEmpty()) { + // Show all relevant dependency beans + autowiredBeans = allDependencyBeans; + } else { + return autowiredBeans; + } + } + } + + return Collections.emptyList(); + } + @SuppressWarnings("unchecked") private List findAutowiredBeans(IJavaProject project, ASTNode declarationNode, Collection beans) { if (declarationNode instanceof MethodDeclaration) { @@ -198,6 +207,9 @@ public class AutowiredHoverProvider implements HoverProvider { .map(subType -> matchBeans(project, beans, subType.getFullyQualifiedName())) .filter(relevantBeans -> !relevantBeans.isEmpty()) .blockFirst(); + if (relevant == null) { + relevant = Collections.emptyList(); + } } } } @@ -213,40 +225,71 @@ public class AutowiredHoverProvider implements HoverProvider { } } - private LiveBean getDefinedBean(Annotation autowiredAnnotation) { - TypeDeclaration declaringType = ASTUtils.findDeclaringType(autowiredAnnotation); + private LiveBean getDefinedBeanForTypeDeclaration(TypeDeclaration declaringType) { if (declaringType != null) { for (Annotation annotation : ASTUtils.getAnnotations(declaringType)) { if (AnnotationHierarchies.isSubtypeOf(annotation, Annotations.COMPONENT)) { return ComponentInjectionsHoverProvider.getDefinedBeanForComponent(annotation); } } - //TODO: handler below is an attempt to do something that may work in many cases, but is probably - // missing logics for special cases where annotation attributes on the declaring type matter. + // TODO: handler below is an attempt to do something that may work in many + // cases, but is probably + // missing logics for special cases where annotation attributes on the declaring + // type matter. ITypeBinding beanType = declaringType.resolveBinding(); - if (beanType!=null) { + if (beanType != null) { String beanTypeName = beanType.getName(); if (StringUtil.hasText(beanTypeName)) { return LiveBean.builder() .id(Character.toLowerCase(beanTypeName.charAt(0)) + beanTypeName.substring(1)) - .type(beanTypeName) - .build(); + .type(beanTypeName).build(); } } - return null; } return null; } @Override - public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, - TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - return null; + public Hover provideHover(MethodDeclaration methodDeclaration, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { + LiveBean definedBean = getDefinedBeanForImplicitAutowiredConstructor(methodDeclaration); + return provideHover(definedBean, methodDeclaration, offset, doc, project, runningApps); } @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, SpringBootApp[] runningApps) { + public Collection getLiveHoverHints(IJavaProject project, MethodDeclaration methodDeclaration, TextDocument doc, + SpringBootApp[] runningApps) { + LiveBean definedBean = getDefinedBeanForImplicitAutowiredConstructor(methodDeclaration); + try { + Range hoverRange = doc.toRange(methodDeclaration.getName().getStartPosition(), methodDeclaration.getName().getLength()); + return getLiveHoverHints(project, methodDeclaration, hoverRange, runningApps, definedBean); + } catch (BadLocationException e) { + log.error("", e); + } return null; } + private LiveBean getDefinedBeanForImplicitAutowiredConstructor(MethodDeclaration methodDeclaration) { + if (methodDeclaration.isConstructor() && !methodDeclaration.parameters().isEmpty()) { + TypeDeclaration typeDeclaration = ASTUtils.findDeclaringType(methodDeclaration); + if (typeDeclaration != null && ASTUtils.hasExactlyOneConstructor(typeDeclaration) && !hasAutowiredAnnotation(methodDeclaration)) { + return getDefinedBeanForTypeDeclaration(typeDeclaration); + } + } + return null; + } + + private boolean hasAutowiredAnnotation(MethodDeclaration constructor) { + List modifiers = constructor.modifiers(); + for (Object modifier : modifiers) { + if (modifier instanceof MarkerAnnotation) { + ITypeBinding typeBinding = ((MarkerAnnotation) modifier).resolveTypeBinding(); + if (typeBinding != null) { + String fqName = typeBinding.getQualifiedName(); + return Annotations.AUTOWIRED.equals(fqName) || Annotations.INJECT.equals(fqName); + } + } + } + return false; + } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java index 20775004b..fa6ea4256 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java @@ -28,7 +28,6 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.springframework.ide.vscode.boot.java.handlers.HoverProvider; import org.springframework.ide.vscode.boot.java.livehover.LiveHoverUtils; import org.springframework.ide.vscode.commons.boot.app.cli.LiveConditional; -import org.springframework.ide.vscode.commons.boot.app.cli.LocalSpringBootApp; import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.util.Log; @@ -50,7 +49,7 @@ public class ConditionalsLiveHoverProvider implements HoverProvider { } @Override - public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + public Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { try { Optional> val = getMatchedLiveConditionals(annotation, runningApps); if (val.isPresent()) { @@ -156,16 +155,4 @@ public class ConditionalsLiveHoverProvider implements HoverProvider { return false; } - @Override - public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, - TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - return null; - } - - @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, - SpringBootApp[] runningApps) { - return null; - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java index 0c6ebe255..1908b3036 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MarkerAnnotation; +import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.NodeFinder; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SimpleName; @@ -140,6 +141,19 @@ public class BootJavaHoverProvider implements HoverHandler { return super.visit(node); } + + @Override + public boolean visit(MethodDeclaration node) { + try { + extractLiveHintsForMethod(node, document, runningBootApps, result); + } catch (Exception e) { + Log.log(e); + } + + return super.visit(node); + } + + }); } } catch (Exception e) { @@ -149,13 +163,33 @@ public class BootJavaHoverProvider implements HoverHandler { }); } + protected void extractLiveHintsForMethod(MethodDeclaration methodDeclaration, TextDocument doc, + SpringBootApp[] runningApps, Collection result) { + Collection providers = this.hoverProviders.getAll(); + if (!providers.isEmpty()) { + for (HoverProvider provider : providers) { + getProject(doc).ifPresent(project -> { + if (hasActuatorDependency(project)) { + Collection hints = provider.getLiveHoverHints(project, methodDeclaration, doc, runningApps); + if (hints!=null) { + result.addAll(hints); + } + } else { + //Do nothing... we don't want a highlight for the 'no actuator warning' + //ASTUtils.nameRange(doc, annotation).ifPresent(result::add); + } + }); + } + } + } + protected void extractLiveHintsForType(TypeDeclaration typeDeclaration, TextDocument doc, SpringBootApp[] runningApps, Collection result) { Collection providers = this.hoverProviders.getAll(); if (!providers.isEmpty()) { for (HoverProvider provider : providers) { getProject(doc).ifPresent(project -> { if (hasActuatorDependency(project)) { - Collection hints = provider.getLiveHoverHints(typeDeclaration, doc, runningApps); + Collection hints = provider.getLiveHoverHints(project, typeDeclaration, doc, runningApps); if (hints!=null) { result.addAll(hints); } @@ -175,7 +209,7 @@ public class BootJavaHoverProvider implements HoverHandler { for (HoverProvider provider : this.hoverProviders.get(type)) { getProject(doc).ifPresent(project -> { if (hasActuatorDependency(project)) { - Collection hints = provider.getLiveHoverHints(annotation, doc, runningApps); + Collection hints = provider.getLiveHoverHints(project, annotation, doc, runningApps); if (hints!=null) { result.addAll(hints); } @@ -215,10 +249,29 @@ public class BootJavaHoverProvider implements HoverHandler { } // then do additional AST node coverage - if (node instanceof SimpleName && node.getParent() instanceof TypeDeclaration) { - return provideHoverForTypeDeclaration(node, (TypeDeclaration) node.getParent(), offset, doc, project); + if (node instanceof SimpleName) { + ASTNode parent = node.getParent(); + if (parent instanceof TypeDeclaration) { + return provideHoverForTypeDeclaration(node, (TypeDeclaration) parent, offset, doc, project); + } else if (parent instanceof MethodDeclaration) { + return provideHoverForMethodDeclaration((MethodDeclaration) parent, offset, doc, project); + } } + return null; + } + private Hover provideHoverForMethodDeclaration(MethodDeclaration methodDeclaration, int offset, TextDocument doc, + IJavaProject project) { + SpringBootApp[] runningApps = getRunningSpringApps(project); + if (runningApps.length > 0) { + for (HoverProvider provider : this.hoverProviders.getAll()) { + Hover hover = provider.provideHover(methodDeclaration, offset, doc, project, runningApps); + if (hover!=null) { + //TODO: compose multiple hovers somehow instead of just returning the first one? + return hover; + } + } + } return null; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/HoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/HoverProvider.java index 4dcf3598a..948bed6a5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/HoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/HoverProvider.java @@ -15,6 +15,7 @@ import java.util.Collection; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Range; @@ -27,10 +28,24 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; */ public interface HoverProvider { - Hover provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps); - Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps); + default Hover provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { + return null; + } + default Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { + return null; + } + default Hover provideHover(MethodDeclaration methodDeclaration, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { + return null; + } - Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps); - Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, SpringBootApp[] runningApps); + default Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + return null; + } + default Collection getLiveHoverHints(IJavaProject project,TypeDeclaration typeDeclaration, TextDocument doc, SpringBootApp[] runningApps) { + return null; + } + default Collection getLiveHoverHints(IJavaProject project, MethodDeclaration methodDeclaration, TextDocument doc, SpringBootApp[] runningApps) { + return null; + } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java index 59c746984..13c861fc5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java @@ -29,7 +29,6 @@ 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.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.util.Log; import org.springframework.ide.vscode.commons.util.text.TextDocument; @@ -44,7 +43,7 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider } @Override - public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + public Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { // Highlight if any running app contains an instance of this component try { if (runningApps.length > 0) { @@ -89,7 +88,6 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider for (LiveBean bean : relevantBeans) { addInjectedInto(definedBean, hover, beans, bean, project); - addAutomaticallyWiredContructor(hover, annotation, beans, bean, project); } } } @@ -103,12 +101,6 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider protected abstract LiveBean getDefinedBean(Annotation annotation); - protected void addAutomaticallyWiredContructor(StringBuilder hover, Annotation annotation, LiveBeansModel beans, LiveBean bean, IJavaProject project) { - //This doesn't really belong here, but it accomodates Martin's additional logic to handle implicitly - //@Autowired constructor. - //This does nothing by default as its really only relevant to @Component annotation report. - } - protected void addInjectedInto(LiveBean definedBean, StringBuilder hover, LiveBeansModel beans, LiveBean bean, IJavaProject project) { hover.append("\n\n"); List dependers = beans.getBeansDependingOn(bean.getId()); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ActiveProfilesProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ActiveProfilesProvider.java index a4f674ac3..aa65941a3 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ActiveProfilesProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ActiveProfilesProvider.java @@ -22,7 +22,6 @@ import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.jsonrpc.messages.Either; @@ -81,7 +80,7 @@ public class ActiveProfilesProvider implements HoverProvider { } @Override - public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + public Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { if (runningApps.length > 0) { Builder ranges = ImmutableList.builder(); nameRange(doc, annotation).ifPresent(ranges::add); @@ -130,16 +129,4 @@ public class ActiveProfilesProvider implements HoverProvider { } } - @Override - public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, - TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - return null; - } - - @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, - SpringBootApp[] runningApps) { - return null; - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/BeanInjectedIntoHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/BeanInjectedIntoHoverProvider.java index 9786a7d33..c1ac6966d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/BeanInjectedIntoHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/BeanInjectedIntoHoverProvider.java @@ -10,24 +10,14 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.livehover; -import java.util.Collection; import java.util.Optional; -import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Annotation; -import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.lsp4j.Hover; -import org.eclipse.lsp4j.Range; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents; import org.springframework.ide.vscode.boot.java.utils.ASTUtils; -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.java.IJavaProject; -import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.util.Optionals; -import org.springframework.ide.vscode.commons.util.text.TextDocument; public class BeanInjectedIntoHoverProvider extends AbstractInjectedIntoHoverProvider { @@ -76,16 +66,4 @@ public class BeanInjectedIntoHoverProvider extends AbstractInjectedIntoHoverProv ); } - @Override - public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, - TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - return null; - } - - @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, - SpringBootApp[] runningApps) { - return null; - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java index db255328b..dfcbb832d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java @@ -20,8 +20,6 @@ import java.util.stream.Stream; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.MarkerAnnotation; -import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Range; @@ -46,49 +44,6 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP super(server); } - @Override - protected void addAutomaticallyWiredContructor(StringBuilder hover, Annotation annotation, LiveBeansModel beans, LiveBean bean, IJavaProject project) { - TypeDeclaration typeDecl = ASTUtils.findDeclaringType(annotation); - if (typeDecl != null) { - MethodDeclaration[] constructors = ASTUtils.findConstructors(typeDecl); - - if (constructors != null && constructors.length == 1 && !hasAutowiredAnnotation(constructors[0])) { - String[] dependencies = bean.getDependencies(); - - if (dependencies != null && dependencies.length > 0) { - hover.append("\n\n"); - hover.append(LiveHoverUtils.showBean(bean) + " got autowired with:\n\n"); - - boolean firstDependency = true; - for (String injectedBean : dependencies) { - if (!firstDependency) { - hover.append("\n"); - } - List dependencyBeans = beans.getBeansOfName(injectedBean); - for (LiveBean dependencyBean : dependencyBeans) { - hover.append("- " + LiveHoverUtils.showBeanWithResource(server, dependencyBean, " ", project)); - } - firstDependency = false; - } - } - } - } - } - - private boolean hasAutowiredAnnotation(MethodDeclaration constructor) { - List modifiers = constructor.modifiers(); - for (Object modifier : modifiers) { - if (modifier instanceof MarkerAnnotation) { - ITypeBinding typeBinding = ((MarkerAnnotation) modifier).resolveTypeBinding(); - if (typeBinding != null) { - String fqName = typeBinding.getQualifiedName(); - return Annotations.AUTOWIRED.equals(fqName) || Annotations.INJECT.equals(fqName); - } - } - } - return false; - } - @Override protected LiveBean getDefinedBean(Annotation annotation) { return getDefinedBeanForComponent(annotation); @@ -132,7 +87,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP } @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, + public Collection getLiveHoverHints(IJavaProject project, TypeDeclaration typeDeclaration, TextDocument doc, SpringBootApp[] runningApps) { if (runningApps.length > 0 && !isComponentAnnotatedType(typeDeclaration)) { try { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java index 01e9370c5..2e763c506 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java @@ -22,7 +22,6 @@ import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.MarkedString; import org.eclipse.lsp4j.Range; @@ -55,7 +54,7 @@ public class RequestMappingHoverProvider implements HoverProvider { } @Override - public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { + public Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { try { if (runningApps.length > 0) { List> val = getRequestMappingMethodFromRunningApp(annotation, runningApps); @@ -173,16 +172,4 @@ public class RequestMappingHoverProvider implements HoverProvider { } } - @Override - public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset, - TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - return null; - } - - @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, - SpringBootApp[] runningApps) { - return null; - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ASTUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ASTUtils.java index c7394b8e2..567c8b87a 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ASTUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ASTUtils.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.utils; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -128,8 +127,7 @@ public class ASTUtils { return Optional.empty(); } - public static TypeDeclaration findDeclaringType(Annotation annotation) { - ASTNode node = annotation; + public static TypeDeclaration findDeclaringType(ASTNode node) { while (node != null && !(node instanceof TypeDeclaration)) { node = node.getParent(); } @@ -137,20 +135,21 @@ public class ASTUtils { return node != null ? (TypeDeclaration) node : null; } - public static MethodDeclaration[] findConstructors(TypeDeclaration typeDecl) { - List constructors = new ArrayList<>(); - + public static boolean hasExactlyOneConstructor(TypeDeclaration typeDecl) { + boolean oneFound = false; MethodDeclaration[] methods = typeDecl.getMethods(); for (MethodDeclaration methodDeclaration : methods) { if (methodDeclaration.isConstructor()) { - constructors.add(methodDeclaration); + if (oneFound) { + return false; + } else { + oneFound = true; + } } } - - return constructors.toArray(new MethodDeclaration[constructors.size()]); + return oneFound; } - public static MethodDeclaration getAnnotatedMethod(Annotation annotation) { ASTNode parent = annotation.getParent(); if (parent instanceof MethodDeclaration) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueHoverProvider.java index 9f104c6b4..9a29cebfe 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueHoverProvider.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.value; -import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -67,11 +66,6 @@ public class ValueHoverProvider implements HoverProvider { return null; } - @Override - public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { - return null; - } - private Hover provideHover(String value, int offset, int nodeStartOffset, TextDocument doc, SpringBootApp[] runningApps) { try { @@ -206,10 +200,4 @@ public class ValueHoverProvider implements HoverProvider { return null; } - @Override - public Collection getLiveHoverHints(TypeDeclaration typeDeclaration, TextDocument doc, - SpringBootApp[] runningApps) { - return null; - } - } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java index 1deba0edf..c43871115 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java @@ -415,4 +415,165 @@ public class AutowiredHoverProviderTest { ); } + @Test + public void implicitAutowiringSingleConstructor() throws Exception { + LiveBeansModel beans = LiveBeansModel.builder() + .add(LiveBean.builder() + .id("someComponent") + .type("com.example.SomeComponent") + .dependencies("dependencyA", "dependencyB") + .build() + ) + .add(LiveBean.builder() + .id("dependencyA") + .type("com.example.DependencyA") + .build() + ) + .add(LiveBean.builder() + .id("dependencyB") + .type("com.example.DependencyB") + .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 SomeComponent {\n" + + "\n" + + " private DepedencyA depA;\n" + + " private DepedencyB depB;\n" + + "\n" + + " public SomeComponent(DependencyA depA, DependencyB depB) {\n" + + " this.depA = depA;\n" + + " this.depB = depB;\n" + + " }\n" + + "}\n" + ); + + editor.assertHighlights("@Component", "SomeComponent"); + + editor.assertTrimmedHover("SomeComponent", 2, + "**Autowired → `dependencyA` `dependencyB`**\n" + + "- Bean: `dependencyA` \n" + + " Type: `com.example.DependencyA`\n" + + "- Bean: `dependencyB` \n" + + " Type: `com.example.DependencyB`\n" + + " \n" + + "Process [PID=111, name=`the-app`]\n" + ); + } + + @Test + public void noImplicitAutowiringForConstructorFromNonBean() throws Exception { + LiveBeansModel beans = LiveBeansModel.builder() + .add(LiveBean.builder() + .id("someOtherComponent") + .type("com.example.SomeOtherComponent") + .dependencies("dependencyA", "dependencyB") + .build() + ) + .add(LiveBean.builder() + .id("dependencyA") + .type("com.example.DependencyA") + .build() + ) + .add(LiveBean.builder() + .id("dependencyB") + .type("com.example.DependencyB") + .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" + + "public class SomeComponent {\n" + + "\n" + + " private DepedencyA depA;\n" + + " private DepedencyB depB;\n" + + "\n" + + " public SomeComponent(DependencyA depA, DependencyB depB) {\n" + + " this.depA = depA;\n" + + " this.depB = depB;\n" + + " }\n" + + "}\n" + ); + + editor.assertHighlights(); + + for (int i = 1; i < 2; i++) { + editor.assertNoHover("SomeComponent", i); + } + } + + @Test + public void noImplicitAutowiringForMultipleConstructors() throws Exception { + LiveBeansModel beans = LiveBeansModel.builder() + .add(LiveBean.builder() + .id("someComponent") + .type("com.example.SomeComponent") + .dependencies("dependencyA", "dependencyB") + .build() + ) + .add(LiveBean.builder() + .id("dependencyA") + .type("com.example.DependencyA") + .build() + ) + .add(LiveBean.builder() + .id("dependencyB") + .type("com.example.DependencyB") + .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 SomeComponent {\n" + + "\n" + + " private DepedencyA depA;\n" + + " private DepedencyB depB;\n" + + "\n" + + " public SomeComponent() {\n" + + " }\n" + + "\n" + + " public SomeComponent(DependencyA depA, DependencyB depB) {\n" + + " this.depA = depA;\n" + + " this.depB = depB;\n" + + " }\n" + + "}\n" + ); + + editor.assertHighlights("@Component"); + for (int i = 1; i < 3; i++) { + editor.assertNoHover("SomeComponent", i); + } + } + } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java index cef834e18..1301aa66b 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java @@ -516,22 +516,14 @@ public class ComponentInjectionsHoverProviderTest { " }\n" + "}\n" ); - editor.assertHighlights("@Component"); + editor.assertHighlights("@Component", "AutowiredClass"); editor.assertTrimmedHover("@Component", "**Injection report for Bean [id: autowiredClass, type: `com.example.AutowiredClass`]**\n" + "\n" + "Process [PID=111, name=`the-app`]:\n" + "\n" + "Bean [id: autowiredClass, type: `com.example.AutowiredClass`] exists but is **Not injected anywhere**\n" + - "\n\n" + - "Bean [id: autowiredClass, type: `com.example.AutowiredClass`] got autowired with:\n" + - "\n" + - "- Bean: `dependencyA` \n" + - " Type: `com.example.DependencyA` \n" + - " Resource: `" + Paths.get("com/example/DependencyA.class") + "`\n" + - "- Bean: `dependencyB` \n" + - " Type: `com.example.DependencyB` \n" + - " Resource: `com/example/DependencyB.class`" + "\n\n" ); } From c38cfd052f3f2883b835de220392ffae55d4654f Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Mon, 30 Jul 2018 12:48:07 +0200 Subject: [PATCH 02/14] added target for eclipse 4.9 builds --- .../common/html/nightly-distributions.html | 16 +- .../org.springframework.boot.ide.product | 109 +++++++ .../p2.inf | 23 ++ .../pom.xml | 285 ++++++++++++++++++ .../spring-tool-suite-4-dmg-config-e4.8.json | 10 + .../category.xml | 206 +++++++++++++ .../pom.xml | 153 ++++++++++ eclipse-distribution/pom.xml | 84 ++++++ 8 files changed, 875 insertions(+), 11 deletions(-) create mode 100644 eclipse-distribution/org.springframework.boot.ide.product.e49/org.springframework.boot.ide.product create mode 100644 eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf create mode 100644 eclipse-distribution/org.springframework.boot.ide.product.e49/pom.xml create mode 100644 eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.8.json create mode 100644 eclipse-distribution/org.springframework.boot.ide.repository.e49/category.xml create mode 100644 eclipse-distribution/org.springframework.boot.ide.repository.e49/pom.xml diff --git a/eclipse-distribution/common/html/nightly-distributions.html b/eclipse-distribution/common/html/nightly-distributions.html index 9a145dc4f..3855e7c18 100644 --- a/eclipse-distribution/common/html/nightly-distributions.html +++ b/eclipse-distribution/common/html/nightly-distributions.html @@ -23,7 +23,8 @@

STS4 Distribution:

@@ -48,10 +49,10 @@

Eclipse-based Distribution Builds

-

Spring Tool Suite 4 - based on Eclipse Photon Milestone Builds (4.8.0 Mx)

-
+

Spring Tool Suite 4 - based on Eclipse 2018-09 Milestone Builds (4.9.0) - and beyond

+

Spring Tools 4 - Visual Studio Code Extensions

@@ -68,13 +69,6 @@ $('#atom').load('atom-packages/atom-packages-snippet.html'); -

No longer updated...

-

Spring Tool Suite 4 - based on Eclipse Oxygen.2 (4.7.2)

-
- - diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e49/org.springframework.boot.ide.product b/eclipse-distribution/org.springframework.boot.ide.product.e49/org.springframework.boot.ide.product new file mode 100644 index 000000000..867949d75 --- /dev/null +++ b/eclipse-distribution/org.springframework.boot.ide.product.e49/org.springframework.boot.ide.product @@ -0,0 +1,109 @@ + + + + + + + + + -product org.springframework.boot.ide.branding.sts4 +--launcher.defaultAction +openFile + -Dosgi.requiredJavaVersion=1.8 +--add-modules=ALL-SYSTEM +-Xms40m + -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts -Xdock:icon=../Resources/sts4.icns + -Xmx1200m + + + -Xmx1200m + + + -Xmx1200m + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf b/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf new file mode 100644 index 000000000..0800c2a57 --- /dev/null +++ b/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf @@ -0,0 +1,23 @@ +instructions.configure=\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.eclipse.org/releases/2018-09,name:2018-09);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.eclipse.org/releases/2018-09,name:2018-09);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9,name:Spring Tool Suite 4);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9,name:Spring Tool Suite 4);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations,name:Spring Tools 4 Language Servers for Eclipse);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations,name:Spring Tools 4 Language Servers for Eclipse); + +instructions.unconfigure=\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.eclipse.org/releases/2018-09);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.eclipse.org/releases/2018-09);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations); + + # Bug 530093: make sure we have latest version of a.jre.javase included with product + requires.3.namespace=org.eclipse.equinox.p2.iu + requires.3.name=a.jre.javase + requires.3.range=[9.0.0,9.0.0] + requires.4.namespace=org.eclipse.equinox.p2.iu + requires.4.name=config.a.jre.javase + requires.4.range=[9.0.0,9.0.0] diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e49/pom.xml b/eclipse-distribution/org.springframework.boot.ide.product.e49/pom.xml new file mode 100644 index 000000000..d1effaa8e --- /dev/null +++ b/eclipse-distribution/org.springframework.boot.ide.product.e49/pom.xml @@ -0,0 +1,285 @@ + + + 4.0.0 + + + org.springframework.boot.ide + org.springframework.boot.ide + 4.0.0-SNAPSHOT + ../pom.xml + + + org.springframework.boot.ide.product + + eclipse-repository + + + ${accessKey} + ${secretKey} + + + + + + + org.apache.maven.plugins + maven-install-plugin + + + default-install + none + + + + + + org.eclipse.tycho + tycho-p2-repository-plugin + ${tycho-version} + + false + + + + + org.eclipse.tycho + tycho-p2-publisher-plugin + ${tycho-version} + + true + + + + + org.eclipse.tycho + target-platform-configuration + ${tycho-version} + + JavaSE-9 + + + + + org.eclipse.tycho + tycho-p2-director-plugin + ${tycho-version} + + + materialize-products + + materialize-products + + package + + + archive-products + + archive-products + + verify + + + + + + org.springframework.boot.ide.branding.sts4 + sts-${unqualifiedVersion}.${p2.qualifier} + + SpringToolSuite4.app + + spring-tool-suite-4-${unqualifiedVersion}.${p2.qualifier}-${dist.target} + + + + tar.gz + tar.gz + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + + osx-app-signing + package + + ${skip.osx.signing} + + + + + + + + + + + + + + + + + run + + + + + osx-dmg-creation + verify + + + + + + + + + + + + + + run + + + + + osx-dmg-signing + verify + + ${skip.osx.signing} + + + + + + + + + + + + + + + + + + + run + + + + + upload-product-bundles + deploy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + update-nightly-downloads + deploy + + ${skip.update-nightly-download-page} + + + + + + + + + + + + + + + + + + run + + + + + + + org.springframework.build + org.springframework.build.aws.ant + 3.1.0.RELEASE + + + net.java.dev.jets3t + jets3t + 0.8.1 + + + ant-contrib + ant-contrib + 20020829 + + + + + + + + diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.8.json b/eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.8.json new file mode 100644 index 000000000..c86b0023f --- /dev/null +++ b/eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.8.json @@ -0,0 +1,10 @@ +{ + "title": "Spring Tool Suite 4", + "icon": "../org.springframework.boot.ide.branding/sts4.icns", + "contents": [ + { "x": 192, "y": 100, "type": "file", "path": "target/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app" }, + { "x": 448, "y": 100, "type": "link", "path": "/Applications" }, + { "x": 1000, "y": 2000, "type": "file", "path": "../org.springframework.boot.ide.branding/sts4.icns", "name": ".VolumeIcon.icns" } + ], + "format": "UDZO" +} diff --git a/eclipse-distribution/org.springframework.boot.ide.repository.e49/category.xml b/eclipse-distribution/org.springframework.boot.ide.repository.e49/category.xml new file mode 100644 index 000000000..b145883a2 --- /dev/null +++ b/eclipse-distribution/org.springframework.boot.ide.repository.e49/category.xml @@ -0,0 +1,206 @@ + + + + Spring Tool Suite 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse-distribution/org.springframework.boot.ide.repository.e49/pom.xml b/eclipse-distribution/org.springframework.boot.ide.repository.e49/pom.xml new file mode 100644 index 000000000..5bf988898 --- /dev/null +++ b/eclipse-distribution/org.springframework.boot.ide.repository.e49/pom.xml @@ -0,0 +1,153 @@ + + + 4.0.0 + + + org.springframework.boot.ide + org.springframework.boot.ide + 4.0.0-SNAPSHOT + ../pom.xml + + + org.springframework.boot.ide.repository + + eclipse-repository + + + ${accessKey} + ${secretKey} + + + + + + + org.apache.maven.plugins + maven-install-plugin + + + default-install + none + + + + + + org.apache.maven.plugins + maven-install-plugin + + + default-install + none + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + + zip-sts-repository + install + + + + + + + + + + + + + + + + + + + + + + + run + + + + + upload-sts-repository + deploy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + org.springframework.build + org.springframework.build.aws.ant + 3.1.0.RELEASE + + + net.java.dev.jets3t + jets3t + 0.8.1 + + + ant-contrib + ant-contrib + 20020829 + + + + + + + + diff --git a/eclipse-distribution/pom.xml b/eclipse-distribution/pom.xml index 7cb661a53..962210bc8 100644 --- a/eclipse-distribution/pom.xml +++ b/eclipse-distribution/pom.xml @@ -294,6 +294,90 @@ + + e49 + + e4.9.0 + e4.9 + 2018-09 + 2018-09 (4.9.0) + 2018-09 + 4.9 + e49 + + + + photon + p2 + http://download.eclipse.org/releases/2018-09/ + + + staging + p2 + http://download.eclipse.org/staging/2018-09/ + + + orbit + p2 + http://download.eclipse.org/tools/orbit/downloads/drops/S20180710163057/repository + + + latest-m2e + p2 + http://download.eclipse.org/technology/m2e/releases/1.8 + + + maven-extras-mirror + p2 + http://download.springsource.com/release/TOOLS/third-party/m2e-sts310-signed/ + + + maven-egit + p2 + http://repo1.maven.org/maven2/.m2e/connectors/m2eclipse-egit/0.15.1/N/LATEST + + + maven-wro4j + p2 + http://download.jboss.org/jbosstools/updates/m2e-wro4j/ + + + maven-devtools + p2 + http://dist.springsource.com/release/TOOLS/mavendevtools/ + + + maven-dependency-support + p2 + http://ianbrandt.github.io/m2e-maven-dependency-plugin/ + + + ansi-console + p2 + http://www.mihai-nita.net/eclipse + + + xtext-base + p2 + http://download.eclipse.org/modeling/tmf/xtext/updates/milestones/ + + + lsp4e + p2 + http://download.eclipse.org/lsp4e/snapshots/ + + + + + org.springframework.boot.ide.product.e49 + org.springframework.boot.ide.repository.e49 + + + build.springsource.com From 59617075bc4511f972bb00885bb06d17e92c53b3 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Mon, 30 Jul 2018 13:13:21 +0200 Subject: [PATCH 03/14] updated dmg config file name --- ...-config-e4.8.json => spring-tool-suite-4-dmg-config-e4.9.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename eclipse-distribution/org.springframework.boot.ide.product.e49/{spring-tool-suite-4-dmg-config-e4.8.json => spring-tool-suite-4-dmg-config-e4.9.json} (100%) diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.8.json b/eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.9.json similarity index 100% rename from eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.8.json rename to eclipse-distribution/org.springframework.boot.ide.product.e49/spring-tool-suite-4-dmg-config-e4.9.json From 5480b1812a27071c9a3fa2e882751883aa98db06 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Mon, 30 Jul 2018 10:36:25 -0400 Subject: [PATCH 04/14] PT #159352937: Rework Injection hover content --- .../autowired/AutowiredHoverProvider.java | 48 ++++--- .../AbstractInjectedIntoHoverProvider.java | 121 +++++++++++------- .../ComponentInjectionsHoverProvider.java | 35 +---- .../boot/java/livehover/LiveHoverUtils.java | 14 +- .../test/AutowiredHoverProviderTest.java | 15 ++- .../BeanInjectedIntoHoverProviderTest.java | 69 ++++------ .../test/BeansByTypeHoverProviderTest.java | 30 ++--- .../ComponentInjectionsHoverProviderTest.java | 98 ++++++-------- 8 files changed, 201 insertions(+), 229 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java index b19aa07dc..add03f263 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java @@ -55,7 +55,7 @@ public class AutowiredHoverProvider implements HoverProvider { final static Logger log = LoggerFactory.getLogger(AutowiredHoverProvider.class); - private static final int MAX_INLINE_BEANS_STRING_LENGTH = 50; + private static final int MAX_INLINE_BEANS_STRING_LENGTH = 60; private static final String INLINE_BEANS_STRING_SEPARATOR = " "; private BootJavaLanguageServerComponents server; @@ -66,14 +66,16 @@ public class AutowiredHoverProvider implements HoverProvider { @Override public Collection getLiveHoverHints(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) { - LiveBean definedBean = getDefinedBeanForTypeDeclaration(ASTUtils.findDeclaringType(annotation)); - // Annotation is MarkerNode, parent is some field, method, variable declaration node. - ASTNode declarationNode = annotation.getParent(); - try { - Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength()); - return getLiveHoverHints(project, declarationNode, hoverRange, runningApps, definedBean); - } catch (BadLocationException e) { - log.error("", e); + if (runningApps.length > 0) { + LiveBean definedBean = getDefinedBeanForTypeDeclaration(ASTUtils.findDeclaringType(annotation)); + // Annotation is MarkerNode, parent is some field, method, variable declaration node. + ASTNode declarationNode = annotation.getParent(); + try { + Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength()); + return getLiveHoverHints(project, declarationNode, hoverRange, runningApps, definedBean); + } catch (BadLocationException e) { + log.error("", e); + } } return null; } @@ -94,15 +96,18 @@ public class AutowiredHoverProvider implements HoverProvider { @Override public Hover provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - LiveBean definedBean = getDefinedBeanForTypeDeclaration(ASTUtils.findDeclaringType(annotation)); - // Annotation is MarkerNode, parent is some field, method, variable declaration node. - ASTNode declarationNode = annotation.getParent(); - return provideHover(definedBean, declarationNode, offset, doc, project, runningApps); + if (runningApps.length > 0) { + LiveBean definedBean = getDefinedBeanForTypeDeclaration(ASTUtils.findDeclaringType(annotation)); + // Annotation is MarkerNode, parent is some field, method, variable declaration node. + ASTNode declarationNode = annotation.getParent(); + return provideHover(definedBean, declarationNode, offset, doc, project, runningApps); + } + return null; } private Hover provideHover(LiveBean definedBean, ASTNode declarationNode, int offset, TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) { - if (definedBean != null && runningApps.length > 0) { + if (definedBean != null) { StringBuilder hover = new StringBuilder(); @@ -118,15 +123,21 @@ public class AutowiredHoverProvider implements HoverProvider { } else { hover.append(" \n \n"); } - hover.append("**Autowired → "); - if (LiveHoverUtils.doBeansFitInline(autowiredBeans, MAX_INLINE_BEANS_STRING_LENGTH, + hover.append("**Autowired `"); + hover.append(definedBean.getId()); + hover.append("` → "); + if (LiveHoverUtils.doBeansFitInline(autowiredBeans, MAX_INLINE_BEANS_STRING_LENGTH - definedBean.getId().length(), INLINE_BEANS_STRING_SEPARATOR)) { hover.append(autowiredBeans.stream().map(b -> LiveHoverUtils.showBeanInline(server, project, b)) .collect(Collectors.joining(INLINE_BEANS_STRING_SEPARATOR))); hover.append("**\n"); } else { hover.append(autowiredBeans.size()); - hover.append(" beans**\n"); + hover.append(" bean"); + if (autowiredBeans.size() > 1) { + hover.append('s'); + } + hover.append("**\n"); } // if (autowiredBeans.size() == 1) { // hover.append(LiveHoverUtils.showBeanIdAndTypeInline(server, project, autowiredBeans.get(0))); @@ -151,8 +162,7 @@ public class AutowiredHoverProvider implements HoverProvider { private List getRelevantAutowiredBeans(IJavaProject project, ASTNode declarationNode, SpringBootApp app, LiveBean definedBean) { LiveBeansModel beans = app.getBeans(); - List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean) - .collect(Collectors.toList()); + List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean); if (!relevantBeans.isEmpty()) { List allDependencyBeans = relevantBeans.stream() diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java index 13c861fc5..8e166424e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/AbstractInjectedIntoHoverProvider.java @@ -11,6 +11,7 @@ package org.springframework.ide.vscode.boot.java.livehover; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -22,6 +23,8 @@ import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents; import org.springframework.ide.vscode.boot.java.handlers.HoverProvider; import org.springframework.ide.vscode.boot.java.utils.ASTUtils; @@ -29,13 +32,17 @@ 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.text.TextDocument; import com.google.common.collect.ImmutableList; public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider { + private static Logger LOG = LoggerFactory.getLogger(AbstractInjectedIntoHoverProvider.class); + + private static final int MAX_INLINE_BEANS_STRING_LENGTH = 60; + private static final String INLINE_BEANS_STRING_SEPARATOR = " "; + protected BootJavaLanguageServerComponents server; public AbstractInjectedIntoHoverProvider(BootJavaLanguageServerComponents server) { @@ -58,7 +65,7 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider } } } catch (Exception e) { - Log.log(e); + LOG.error("", e); } return ImmutableList.of(); } @@ -70,52 +77,80 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider LiveBean definedBean = getDefinedBean(annotation); if (definedBean != null) { - StringBuilder hover = new StringBuilder(); - hover.append("**Injection report for " + LiveHoverUtils.showBean(definedBean) + "**\n\n"); - - boolean hasInterestingApp = false; - for (SpringBootApp app : runningApps) { - LiveBeansModel beans = app.getBeans(); - List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean).collect(Collectors.toList()); - - if (!relevantBeans.isEmpty()) { - if (!hasInterestingApp) { - hasInterestingApp = true; - } else { - hover.append("\n\n"); - } - hover.append(LiveHoverUtils.niceAppName(app) + ":"); - - for (LiveBean bean : relevantBeans) { - addInjectedInto(definedBean, hover, beans, bean, project); - } - } - } - if (hasInterestingApp) { - return new Hover(ImmutableList.of(Either.forLeft(hover.toString()))); - } + return assembleHover(project, runningApps, definedBean); } } return null; } + protected Hover assembleHover(IJavaProject project, SpringBootApp[] runningApps, LiveBean definedBean) { + StringBuilder hover = new StringBuilder(); + + boolean hasContent = false; + + for (SpringBootApp app : runningApps) { + + List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean); + + if (!relevantBeans.isEmpty()) { + List injectedBeans = getRelevantInjectedIntoBeans(project, app, definedBean, relevantBeans); + + if (!hasContent) { + hasContent = true; + } else { + hover.append(" \n \n"); + } + + if (injectedBeans.isEmpty()) { + hover.append("**Injected `"); + hover.append(definedBean.getId()); + hover.append("` → _not injected anywhere_** \n"); + } else { + hover.append("**Injected `"); + hover.append(definedBean.getId()); + hover.append("` → "); + if (LiveHoverUtils.doBeansFitInline(injectedBeans, MAX_INLINE_BEANS_STRING_LENGTH - definedBean.getId().length(), + INLINE_BEANS_STRING_SEPARATOR)) { + hover.append(injectedBeans.stream().map(b -> LiveHoverUtils.showBeanInline(server, project, b)) + .collect(Collectors.joining(INLINE_BEANS_STRING_SEPARATOR))); + hover.append("**\n"); + } else { + hover.append(injectedBeans.size()); + hover.append(" bean"); + if (injectedBeans.size() > 1) { + hover.append('s'); + } + hover.append("**\n"); + } + hover.append(injectedBeans.stream() + .map(b -> "- " + LiveHoverUtils.showBeanWithResource(server, b, " ", project)) + .collect(Collectors.joining("\n"))); + hover.append("\n \n"); + } + hover.append(LiveHoverUtils.niceAppName(app)); + } + + } + if (hasContent) { + return new Hover(ImmutableList.of(Either.forLeft(hover.toString()))); + } else { + return null; + } + + } + + protected List getRelevantInjectedIntoBeans(IJavaProject project, SpringBootApp app, LiveBean definedBean, List relevantBeans) { + LiveBeansModel beans = app.getBeans(); + if (relevantBeans != null) { + return relevantBeans.stream() + .flatMap(b -> beans.getBeansDependingOn(b.getId()).stream()) + .distinct() + .collect(Collectors.toList()); + + } + return Collections.emptyList(); + } + protected abstract LiveBean getDefinedBean(Annotation annotation); - protected void addInjectedInto(LiveBean definedBean, StringBuilder hover, LiveBeansModel beans, LiveBean bean, IJavaProject project) { - hover.append("\n\n"); - List dependers = beans.getBeansDependingOn(bean.getId()); - if (dependers.isEmpty()) { - hover.append(LiveHoverUtils.showBean(bean) + " exists but is **Not injected anywhere**\n"); - } else { - hover.append(LiveHoverUtils.showBean(bean) + " injected into:\n\n"); - boolean firstDependency = true; - for (LiveBean dependingBean : dependers) { - if (!firstDependency) { - hover.append("\n"); - } - hover.append("- " + LiveHoverUtils.showBeanWithResource(server, dependingBean, " ", project)); - firstDependency = false; - } - } - } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java index dfcbb832d..aa6d9da57 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java @@ -14,7 +14,6 @@ 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; import org.eclipse.jdt.core.dom.ASTNode; @@ -23,16 +22,15 @@ import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; 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.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.TextDocument; @@ -40,6 +38,8 @@ import com.google.common.collect.ImmutableList; public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverProvider { + private static Logger LOG = LoggerFactory.getLogger(ComponentInjectionsHoverProvider.class); + public ComponentInjectionsHoverProvider(BootJavaLanguageServerComponents server) { super(server); } @@ -101,7 +101,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP } } } catch (Exception e) { - Log.log(e); + LOG.error("", e); } } return ImmutableList.of(); @@ -115,30 +115,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP LiveBean definedBean = getDefinedBeanForType(typeDeclaration, null); if (definedBean != null) { - StringBuilder hover = new StringBuilder(); - hover.append("**Injection report for " + LiveHoverUtils.showBean(definedBean) + "**\n\n"); - - boolean hasInterestingApp = false; - for (SpringBootApp app : runningApps) { - LiveBeansModel beans = app.getBeans(); - List relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean).collect(Collectors.toList()); - - if (!relevantBeans.isEmpty()) { - if (!hasInterestingApp) { - hasInterestingApp = true; - } else { - hover.append("\n\n"); - } - hover.append(LiveHoverUtils.niceAppName(app) + ":"); - - for (LiveBean bean : relevantBeans) { - addInjectedInto(definedBean, hover, beans, bean, project); - } - } - } - if (hasInterestingApp) { - return new Hover(ImmutableList.of(Either.forLeft(hover.toString()))); - } + return assembleHover(project, runningApps, definedBean); } } return null; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java index 4851bb21c..f8365c374 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java @@ -11,8 +11,10 @@ package org.springframework.ide.vscode.boot.java.livehover; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Optional; -import java.util.stream.Stream; +import java.util.stream.Collectors; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents; import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory; @@ -131,20 +133,20 @@ public class LiveHoverUtils { } public static boolean hasRelevantBeans(SpringBootApp app, LiveBean definedBean) { - return findRelevantBeans(app, definedBean).findAny().isPresent(); + return findRelevantBeans(app, definedBean).stream().findAny().isPresent(); } - public static Stream findRelevantBeans(SpringBootApp app, LiveBean definedBean) { + public static List findRelevantBeans(SpringBootApp app, LiveBean definedBean) { LiveBeansModel beansModel = app.getBeans(); if (beansModel != null) { - Stream relevantBeans = beansModel.getBeansOfName(definedBean.getId()).stream(); + List relevantBeans = beansModel.getBeansOfName(definedBean.getId()); String type = definedBean.getType(); if (type != null) { - relevantBeans = relevantBeans.filter(bean -> type.equals(bean.getType(true))); + relevantBeans = relevantBeans.stream().filter(bean -> type.equals(bean.getType(true))).collect(Collectors.toList()); } return relevantBeans; } - return Stream.empty(); + return Collections.emptyList(); } public static String niceAppName(SpringBootApp app) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java index c43871115..098a99075 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java @@ -146,7 +146,7 @@ public class AutowiredHoverProviderTest { editor.assertHighlights("@Component", "@Inject"); editor.assertTrimmedHover("@Inject", - "**Autowired → `dependencyA`**\n" + + "**Autowired `autowiredClass` → `dependencyA`**\n" + "- Bean: `dependencyA` \n" + " Type: `com.example.DependencyA` \n" + " Resource: `" + Paths.get("com/example/DependencyA.class") + "`\n" + @@ -201,7 +201,7 @@ public class AutowiredHoverProviderTest { editor.assertHighlights("@Component", "@Autowired"); editor.assertTrimmedHover("@Autowired", - "**Autowired → `dependencyA` `dependencyB`**\n" + + "**Autowired `autowiredClass` → `dependencyA` `dependencyB`**\n" + "- Bean: `dependencyA` \n" + " Type: `com.example.DependencyA` \n" + " Resource: `" + Paths.get("com/example/DependencyA.class") + "`\n" + @@ -352,11 +352,11 @@ public class AutowiredHoverProviderTest { Editor editor = harness.newEditor(LanguageId.JAVA, FOO_IMPL_CONTENTS); editor.assertHighlights("@Component", "@Autowired", "@Autowired"); editor.assertHoverContains("@Autowired", 1, - "**Autowired → `superBean`**\n" + + "**Autowired `defaultFoo` → `superBean`**\n" + "- Bean: `superBean` \n" + " Type: `com.example.FooImplementation`"); editor.assertHoverContains("@Autowired", 2, - "**Autowired → `scheduler`**\n" + + "**Autowired `defaultFoo` → `scheduler`**\n" + "- Bean: `scheduler` \n" + " Type: `org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler`"); } @@ -406,12 +406,13 @@ public class AutowiredHoverProviderTest { ); editor.assertHighlights("@Controller", "@Autowired"); editor.assertHoverContains("@Autowired", - "**Autowired → `restTemplate`**\n" + + "**Autowired `myController` → `restTemplate`**\n" + "- Bean: `restTemplate` \n" + " Type: `org.springframework.web.client.RestTemplate`" ); editor.assertHoverContains("@Controller", - "**Injection report for Bean [id: myController, type: `com.example.MyController`]**" + "**Injected `myController` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -463,7 +464,7 @@ public class AutowiredHoverProviderTest { editor.assertHighlights("@Component", "SomeComponent"); editor.assertTrimmedHover("SomeComponent", 2, - "**Autowired → `dependencyA` `dependencyB`**\n" + + "**Autowired `someComponent` → `dependencyA` `dependencyB`**\n" + "- Bean: `dependencyA` \n" + " Type: `com.example.DependencyA`\n" + "- Bean: `dependencyB` \n" + diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeanInjectedIntoHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeanInjectedIntoHoverProviderTest.java index a995fe702..e126497e9 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeanInjectedIntoHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeanInjectedIntoHoverProviderTest.java @@ -95,11 +95,8 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: myFoo]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: myFoo, type: `hello.FooImplementation`] exists but is **Not injected anywhere**\n" + "**Injected `myFoo` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -154,11 +151,8 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: beanId]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: beanId, type: `hello.FooImplementation`] exists but is **Not injected anywhere**\n" + "**Injected `beanId` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } } @@ -209,14 +203,11 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: fooImplementation]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `hello.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController`**\n" + "- Bean: `myController` \n" + - " Type: `hello.MyController`\n" + " Type: `hello.MyController`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -269,14 +260,11 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: fooImplementation]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `hello.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController`**\n" + "- Bean: `myController` \n" + - " Type: `hello.MyController`\n" + " Type: `hello.MyController`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -323,15 +311,12 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: fooImplementation]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `hello.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController`**\n" + "- Bean: `myController` \n" + " Type: `hello.MyController` \n" + - " Resource: `" + Paths.get("hello/MyController.class") + "`" + " Resource: `" + Paths.get("hello/MyController.class") + "`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -377,15 +362,12 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: fooImplementation]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `hello.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController`**\n" + "- Bean: `myController` \n" + " Type: `hello.MyController` \n" + - " Resource: `hello/MyController.class`" + " Resource: `hello/MyController.class`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -435,16 +417,13 @@ public class BeanInjectedIntoHoverProviderTest { ); editor.assertHighlights("@Bean"); editor.assertTrimmedHover("@Bean", - "**Injection report for Bean [id: fooImplementation]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `hello.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController` `otherBean`**\n" + "- Bean: `myController` \n" + " Type: `hello.MyController`\n" + "- Bean: `otherBean` \n" + - " Type: `hello.OtherBean`\n" + " Type: `hello.OtherBean`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeansByTypeHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeansByTypeHoverProviderTest.java index cea6fc61f..e80574434 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeansByTypeHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/BeansByTypeHoverProviderTest.java @@ -134,14 +134,11 @@ public class BeansByTypeHoverProviderTest { ); 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" + + "**Injected `scannedRandomClass` → `randomOtherBean`**\n" + "- Bean: `randomOtherBean` \n" + - " Type: `randomOtherBeanType`" + " Type: `randomOtherBeanType`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -190,14 +187,12 @@ public class BeansByTypeHoverProviderTest { ); editor.assertHighlights("ScannedFunctionClass"); editor.assertTrimmedHover("ScannedFunctionClass", - "**Injection report for Bean [id: scannedFunctionClass, type: `com.example.ScannedFunctionClass`]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: scannedFunctionClass, type: `com.example.ScannedFunctionClass`] injected into:\n" + - "\n" + + "**Injected `scannedFunctionClass` → 1 bean**\n" + "- Bean: `org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration` \n" + - " Type: `org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration`" + " Type: `org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" + ); } @@ -233,11 +228,8 @@ public class BeansByTypeHoverProviderTest { ); 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" + "**Injected `fooImplementation` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java index 1301aa66b..3d7f6d1dc 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java @@ -12,7 +12,6 @@ package org.springframework.ide.vscode.boot.java.livehover.test; import static org.junit.Assert.assertTrue; -import java.nio.file.Paths; import java.time.Duration; import org.junit.Before; @@ -107,11 +106,8 @@ public class ComponentInjectionsHoverProviderTest { ); 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" + "**Injected `fooImplementation` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -159,14 +155,11 @@ public class ComponentInjectionsHoverProviderTest { ); 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`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController`**\n" + "- Bean: `myController` \n" + - " Type: `com.example.MyController`" + " Type: `com.example.MyController`\n" + + " \n" + + "Process [PID=111, name=`the-app`]\n" ); } @@ -214,16 +207,13 @@ public class ComponentInjectionsHoverProviderTest { ); 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`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController` `otherBean`**\n" + "- Bean: `myController` \n" + " Type: `com.example.MyController`\n" + "- Bean: `otherBean` \n" + - " Type: `com.example.OtherBean`" + " Type: `com.example.OtherBean`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -273,25 +263,21 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@Component"); editor.assertTrimmedHover("@Component", - "**Injection report for Bean [id: fooImplementation, type: `com.example.FooImplementation`]**\n" + - "\n" + - "Process [PID=1001, name=`app-instance-1`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `com.example.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController` `otherBean`**\n" + "- Bean: `myController` \n" + " Type: `com.example.MyController`\n" + "- Bean: `otherBean` \n" + " Type: `com.example.OtherBean`\n" + - "\n" + - "Process [PID=1002, name=`app-instance-2`]:\n" + - "\n" + - "Bean [id: fooImplementation, type: `com.example.FooImplementation`] injected into:\n" + - "\n" + + " \n" + + "Process [PID=1001, name=`app-instance-1`]" + + " \n \n" + + "**Injected `fooImplementation` → `myController` `otherBean`**\n" + "- Bean: `myController` \n" + " Type: `com.example.MyController`\n" + "- Bean: `otherBean` \n" + - " Type: `com.example.OtherBean`\n" + " Type: `com.example.OtherBean`\n" + + " \n" + + "Process [PID=1002, name=`app-instance-2`]" ); } @@ -344,14 +330,11 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@Component"); editor.assertHoverExactText("@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`] injected into:\n" + - "\n" + + "**Injected `fooImplementation` → `myController`**\n" + "- Bean: `myController` \n" + - " Type: `com.example.MyController`" + " Type: `com.example.MyController`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -404,14 +387,11 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@Component"); editor.assertTrimmedHover("@Component", - "**Injection report for Bean [id: alternateFooImplementation, type: `com.example.FooImplementation`]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: alternateFooImplementation, type: `com.example.FooImplementation`] injected into:\n" + - "\n" + + "**Injected `alternateFooImplementation` → `otherBean`**\n" + "- Bean: `otherBean` \n" + - " Type: `com.example.OtherBean`\n" + " Type: `com.example.OtherBean`\n" + + " \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -451,7 +431,7 @@ public class ComponentInjectionsHoverProviderTest { " }\n" + "}\n" ); - editor.assertHighlights(/*MONE*/); + editor.assertHighlights(/*NONE*/); editor.assertNoHover("@Component"); } @@ -518,12 +498,8 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@Component", "AutowiredClass"); editor.assertTrimmedHover("@Component", - "**Injection report for Bean [id: autowiredClass, type: `com.example.AutowiredClass`]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: autowiredClass, type: `com.example.AutowiredClass`] exists but is **Not injected anywhere**\n" + - "\n\n" + "**Injected `autowiredClass` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]\n" ); } @@ -570,11 +546,8 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@Component", "@Autowired"); editor.assertTrimmedHover("@Component", - "**Injection report for Bean [id: autowiredClass, type: `com.example.AutowiredClass`]**\n" + - "\n" + - "Process [PID=111, name=`the-app`]:\n" + - "\n" + - "Bean [id: autowiredClass, type: `com.example.AutowiredClass`] exists but is **Not injected anywhere**\n" + "**Injected `autowiredClass` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]\n" ); } @@ -613,7 +586,8 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@SpringBootApplication"); editor.assertHoverContains("@SpringBootApplication", - "**Injection report for Bean [id: demoApplication, type: `com.example.DemoApplication`]**" + "**Injected `demoApplication` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -654,7 +628,8 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@SpringBootApplication"); editor.assertHoverContains("@SpringBootApplication", - "**Injection report for Bean [id: demoApplication.InnerClass, type: `com.example.DemoApplication.InnerClass`]**" + "**Injected `demoApplication.InnerClass` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } @@ -698,7 +673,8 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@SpringBootApplication"); editor.assertHoverContains("@SpringBootApplication", - "**Injection report for Bean [id: demoApplication.InnerClass.InnerInnerClass, type: `com.example.DemoApplication.InnerClass.InnerInnerClass`]**" + "**Injected `demoApplication.InnerClass.InnerInnerClass` → _not injected anywhere_** \n" + + "Process [PID=111, name=`the-app`]" ); } } From 21e0543730283df8de69526e9abf896d81a51889 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Tue, 31 Jul 2018 00:26:02 -0400 Subject: [PATCH 05/14] PT #159307292: Anonymous inner class bean type wiring --- .../boot/app/cli/livebean/LiveBean.java | 5 +- .../autowired/AutowiredHoverProvider.java | 12 ++- .../ComponentInjectionsHoverProvider.java | 14 +++- .../test/AutowiredHoverProviderTest.java | 75 +++++++++++++++++++ 4 files changed, 97 insertions(+), 9 deletions(-) diff --git a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java index e21badb98..ead218549 100644 --- a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java +++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java @@ -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 @@ -103,9 +103,6 @@ public class LiveBean { type = type.substring(0, chop); } } - - // convert inner classes from $ to . notation - type = type.replace('$', '.'); } return type; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java index add03f263..2e7550575 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java @@ -209,12 +209,12 @@ public class AutowiredHoverProvider implements HoverProvider { if (type != null) { String fqName = type.getQualifiedName(); if (fqName != null) { - relevant = matchBeans(project, beans, fqName); + relevant = matchBeans(project, beans, fqName, true); if (relevant.isEmpty()) { IType indexType = project.findType(fqName); if (indexType != null) { relevant = project.allSubtypesOf(indexType) - .map(subType -> matchBeans(project, beans, subType.getFullyQualifiedName())) + .map(subType -> matchBeans(project, beans, subType.getFullyQualifiedName(), false)) .filter(relevantBeans -> !relevantBeans.isEmpty()) .blockFirst(); if (relevant == null) { @@ -227,9 +227,13 @@ public class AutowiredHoverProvider implements HoverProvider { return relevant; } - private List matchBeans(IJavaProject project, Collection beans, String fqName) { + private List matchBeans(IJavaProject project, Collection beans, String fqName, boolean allDots) { if (fqName != null) { - return beans.stream().filter(b -> fqName.equals(b.getType(true))).collect(Collectors.toList()); + if (allDots) { + return beans.stream().filter(b -> fqName.equals(b.getType(true).replace('$', '.'))).collect(Collectors.toList()); + } else { + return beans.stream().filter(b -> fqName.equals(b.getType(true))).collect(Collectors.toList()); + } } else { return Collections.emptyList(); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java index aa6d9da57..cc78b3544 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java @@ -61,7 +61,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP if (beanType != null) { String id = getBeanId(annotation, beanType); if (StringUtil.hasText(id)) { - return LiveBean.builder().id(id).type(beanType.getQualifiedName()).build(); + return LiveBean.builder().id(id).type(getBeanType(beanType).toString()).build(); } } } @@ -86,6 +86,18 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP }); } + private static StringBuilder getBeanType(ITypeBinding beanType) { + ITypeBinding declaringClass = beanType.getDeclaringClass(); + if (declaringClass == null) { + return new StringBuilder(beanType.getQualifiedName()); + } else { + StringBuilder sb = getBeanType(declaringClass); + sb.append('$'); + sb.append(beanType.getName()); + return sb; + } + } + @Override public Collection getLiveHoverHints(IJavaProject project, TypeDeclaration typeDeclaration, TextDocument doc, SpringBootApp[] runningApps) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java index 098a99075..fed26d0a7 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java @@ -14,6 +14,8 @@ import static org.junit.Assert.assertTrue; import java.nio.file.Paths; import java.time.Duration; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.junit.Before; import org.junit.Test; @@ -84,6 +86,34 @@ public class AutowiredHoverProviderTest { "}\n" ); + p.createType("com.example.RuntimeBeanFactory", + Stream.of( + "package com.example;", + "public interface RuntimeBeanFactory {", + "void createRuntimeBean(String info);", + "}" + ).collect(Collectors.joining("\n")) + ); + + p.createType("com.example.SomeComponent", + Stream.of("package com.example;", + "", + "import org.springframework.context.annotation.Bean;", + "", +// "@Component", + "public class SomeComponent {", + "", + "@Bean", + "public RuntimeBeanFactory getBeanFactory() {", + "\treturn new RuntimeBeanFactory() {", + "\t\tpublic void createRuntimeBean(String info){}", + "\t};", + "}", + "", + "}" + ).collect(Collectors.joining("\n")) + ); + p.createType("com.example.FooImplementation", FOO_IMPL_CONTENTS); }; @@ -577,4 +607,49 @@ public class AutowiredHoverProviderTest { } } + @Test + public void anonymousInnerClassBeanWiring() throws Exception { + LiveBeansModel beans = LiveBeansModel.builder() + .add(LiveBean.builder() + .id("anotherComponent") + .type("com.example.AnotherComponent") + .dependencies("anonymousBeanFactory") + .build() + ) + .add(LiveBean.builder() + .id("anonymousBeanFactory") + .type("com.example.SomeComponent$1") + .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.beans.factory.annotation.Autowired;\n" + + "import org.springframework.stereotype.Component;\n" + + "\n" + + "@Component\n" + + "public class AnotherComponent {\n" + + "\n" + + " @Autowired\n" + + " RuntimeBeanFactory beanFactory;\n" + + "}\n" + ); + + editor.assertHighlights("@Component", "@Autowired"); + editor.assertTrimmedHover("@Autowired", 1, + "**Autowired `anotherComponent` → `anonymousBeanFactory`**\n" + + "- Bean: `anonymousBeanFactory` \n" + + " Type: `com.example.SomeComponent$1`\n" + + " \n" + + "Process [PID=111, name=`the-app`]\n" + ); + } } From 92fbe9ecddc61deacb93266e98b39bf9ebb12f39 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Tue, 31 Jul 2018 01:43:00 -0400 Subject: [PATCH 06/14] Inner class bean id is equal to bean type --- .../java/livehover/ComponentInjectionsHoverProvider.java | 5 ++--- .../ide/vscode/boot/java/livehover/LiveHoverUtils.java | 7 ++++++- .../test/ComponentInjectionsHoverProviderTest.java | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java index cc78b3544..65c4e473b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/ComponentInjectionsHoverProvider.java @@ -74,9 +74,8 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP String typeName = beanType.getName(); ITypeBinding declaringClass = beanType.getDeclaringClass(); - while (declaringClass != null) { - typeName = declaringClass.getName() + "." + typeName; - declaringClass = declaringClass.getDeclaringClass(); + if (declaringClass != null) { + return getBeanType(beanType).toString(); } if (StringUtil.hasText(typeName)) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java index f8365c374..338610b64 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/LiveHoverUtils.java @@ -142,7 +142,12 @@ public class LiveHoverUtils { List relevantBeans = beansModel.getBeansOfName(definedBean.getId()); String type = definedBean.getType(); if (type != null) { - relevantBeans = relevantBeans.stream().filter(bean -> type.equals(bean.getType(true))).collect(Collectors.toList()); + // TODO: check if we should check for bean type rather than id that we build ourselves based on type +// if (relevantBeans.isEmpty()) { +// relevantBeans = beansModel.getBeansOfType(type); +// } else { + relevantBeans = relevantBeans.stream().filter(bean -> type.equals(bean.getType(true))).collect(Collectors.toList()); +// } } return relevantBeans; } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java index 3d7f6d1dc..49e1e07e1 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/livehover/test/ComponentInjectionsHoverProviderTest.java @@ -595,7 +595,7 @@ public class ComponentInjectionsHoverProviderTest { public void componentFromInnerClass() throws Exception { LiveBeansModel beans = LiveBeansModel.builder() .add(LiveBean.builder() - .id("demoApplication.InnerClass") + .id("com.example.DemoApplication$InnerClass") .type("com.example.DemoApplication$InnerClass") .build() ) @@ -628,7 +628,7 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@SpringBootApplication"); editor.assertHoverContains("@SpringBootApplication", - "**Injected `demoApplication.InnerClass` → _not injected anywhere_** \n" + + "**Injected `com.example.DemoApplication$InnerClass` → _not injected anywhere_** \n" + "Process [PID=111, name=`the-app`]" ); } @@ -637,7 +637,7 @@ public class ComponentInjectionsHoverProviderTest { public void componentFromInnerInnerClass() throws Exception { LiveBeansModel beans = LiveBeansModel.builder() .add(LiveBean.builder() - .id("demoApplication.InnerClass.InnerInnerClass") + .id("com.example.DemoApplication$InnerClass$InnerInnerClass") .type("com.example.DemoApplication$InnerClass$InnerInnerClass") .build() ) @@ -673,7 +673,7 @@ public class ComponentInjectionsHoverProviderTest { ); editor.assertHighlights("@SpringBootApplication"); editor.assertHoverContains("@SpringBootApplication", - "**Injected `demoApplication.InnerClass.InnerInnerClass` → _not injected anywhere_** \n" + + "**Injected `com.example.DemoApplication$InnerClass$InnerInnerClass` → _not injected anywhere_** \n" + "Process [PID=111, name=`the-app`]" ); } From 007b2c5f95d6441e3dfa3e073c61488bb9f9163d Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Tue, 31 Jul 2018 14:08:51 +0200 Subject: [PATCH 07/14] fixed logic around specific project name setting --- .../boot/java/handlers/RunningAppMatcher.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java index cb91bd6af..a67198dcc 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java @@ -33,19 +33,28 @@ public class RunningAppMatcher { return RunningAppMatcher.doesProjectMatch(app, project); }).collect(CollectorUtil.toImmutableList()); - if (matchedProjects.size() > 0) { - return matchedProjects; - } + return matchedProjects; } return apps; } private static boolean doesProjectMatch(SpringBootApp app, IJavaProject project) { - if (doesProjectNameMatch(app, project)) return true; - if (doesProjectThinJarWrapperMatch(app, project)) return true; - if (doesClasspathMatch(app, project)) return true; + if (hasProjectName(app, project)) { + return doesProjectNameMatch(app, project); + } + else { + return doesProjectThinJarWrapperMatch(app, project) || doesClasspathMatch(app, project); + } + } - return false; + public static boolean hasProjectName(SpringBootApp app, IJavaProject project) { + try { + String projectName = app.getSystemProperty("spring.boot.project.name"); + return projectName != null && projectName.trim().length() > 0; + } + catch (Exception e) { + return false; + } } public static boolean doesProjectNameMatch(SpringBootApp app, IJavaProject project) { From e62661cf5efe37628359c7c32c05838375a104ac Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Tue, 31 Jul 2018 14:09:28 +0200 Subject: [PATCH 08/14] use "latest" update site for continuous updates instead of version-specific one --- .../org.springframework.boot.ide.product.e49/p2.inf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf b/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf index 0800c2a57..27e8d9201 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf +++ b/eclipse-distribution/org.springframework.boot.ide.product.e49/p2.inf @@ -1,16 +1,16 @@ instructions.configure=\ org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.eclipse.org/releases/2018-09,name:2018-09);\ org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.eclipse.org/releases/2018-09,name:2018-09);\ - org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9,name:Spring Tool Suite 4);\ - org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9,name:Spring Tool Suite 4);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/latest,name:Spring Tool Suite 4);\ + org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/latest,name:Spring Tool Suite 4);\ org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations,name:Spring Tools 4 Language Servers for Eclipse);\ org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations,name:Spring Tools 4 Language Servers for Eclipse); instructions.unconfigure=\ org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.eclipse.org/releases/2018-09);\ org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.eclipse.org/releases/2018-09);\ - org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9);\ - org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.9);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/latest);\ + org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/latest);\ org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations);\ org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations); From 71b47ff286ca3eda07b0ae5a2d282ed4d1d11843 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Tue, 31 Jul 2018 15:53:23 +0200 Subject: [PATCH 09/14] do not take thin jar launcher mapping and classpath matching into account when identifying projects --- .../ide/vscode/boot/java/handlers/RunningAppMatcher.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java index a67198dcc..ecd74d1cc 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/RunningAppMatcher.java @@ -42,9 +42,7 @@ public class RunningAppMatcher { if (hasProjectName(app, project)) { return doesProjectNameMatch(app, project); } - else { - return doesProjectThinJarWrapperMatch(app, project) || doesClasspathMatch(app, project); - } + return true; } public static boolean hasProjectName(SpringBootApp app, IJavaProject project) { From e350da8ab7264576814006ef833ec779ecc69726 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 13 Jul 2018 20:10:11 -0400 Subject: [PATCH 10/14] Boot hints first trial --- .../spring-boot-language-server/build.sh | 2 +- .../commons-vscode/icons/boot-icon.svg | 8 ++++++++ .../commons-vscode/src/highlight-service.ts | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 vscode-extensions/commons-vscode/icons/boot-icon.svg diff --git a/headless-services/spring-boot-language-server/build.sh b/headless-services/spring-boot-language-server/build.sh index 995aac236..9c5bf4644 100755 --- a/headless-services/spring-boot-language-server/build.sh +++ b/headless-services/spring-boot-language-server/build.sh @@ -4,4 +4,4 @@ set -e -f ../pom.xml \ -pl spring-boot-language-server \ -am \ - clean install + clean install -DskipTests diff --git a/vscode-extensions/commons-vscode/icons/boot-icon.svg b/vscode-extensions/commons-vscode/icons/boot-icon.svg new file mode 100644 index 000000000..3183d7108 --- /dev/null +++ b/vscode-extensions/commons-vscode/icons/boot-icon.svg @@ -0,0 +1,8 @@ + + + + + Asset 1 + + \ No newline at end of file diff --git a/vscode-extensions/commons-vscode/src/highlight-service.ts b/vscode-extensions/commons-vscode/src/highlight-service.ts index cd7915166..a6e4b4310 100644 --- a/vscode-extensions/commons-vscode/src/highlight-service.ts +++ b/vscode-extensions/commons-vscode/src/highlight-service.ts @@ -28,9 +28,18 @@ export class HighlightService { constructor() { this.DECORATION = VSCode.window.createTextEditorDecorationType({ // textDecoration: "underline", - gutterIconPath: path.resolve(__dirname, "../icons/boot-icon.png"), - gutterIconSize: "contain", - outline: "#32BA56 dotted thin" + // gutterIconPath: path.resolve(__dirname, "../icons/boot-icon.png"), + // gutterIconSize: "contain", + // outline: "#32BA56 dotted thin", + before: { + contentIconPath: path.resolve(__dirname, "../icons/boot-12.png"), + margin: '2px 2px 0px 0px' + }, + backgroundColor: 'rgba(109,179,63,0.25)', + borderColor: 'rgba(109,179,63,0.25)', + borderSpacing: '4px', + borderRadius: '4px', + borderWidth: '4px' }); this.highlights = new Map(); } @@ -49,6 +58,7 @@ export class HighlightService { let highlights : Range[] = this.highlights.get(uri) || []; let decorations = highlights.map(hl => toDecoration(hl)); editor.setDecorations(this.DECORATION, decorations); + editor.setDecorations(this.DECORATION, decorations); } } } From a25238d40a8ac58908c637d4a943f55aa7d9d3ca Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Tue, 17 Jul 2018 16:06:48 -0400 Subject: [PATCH 11/14] Atom boot-hint marker --- .../atom-spring-boot/lib/boot-sts-adapter.ts | 25 +++++++++++++++++- .../styles/hints.atom-text-editor.less | 26 ++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts b/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts index 37f036a5e..2c0bb9532 100644 --- a/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts +++ b/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts @@ -8,9 +8,10 @@ const BOOT_HINT_GUTTER_NAME = 'boot-hint-gutter'; const DECORATION_OPTIONS: DecorationOptions = { type: 'highlight', class: 'boot-hint', - gutterName: BOOT_HINT_GUTTER_NAME + // gutterName: BOOT_HINT_GUTTER_NAME }; + export class BootStsAdapter extends StsAdapter { constructor() { @@ -23,6 +24,10 @@ export class BootStsAdapter extends StsAdapter { private markHintsForEditor(editor: TextEditor, ranges: Range[]) { editor.getDecorations(DECORATION_OPTIONS).map(decoration => decoration.getMarker()).forEach(m => m.destroy()); + editor.getDecorations({ + type: 'block', + class: 'boot-hint-icon' + }).map(decoration => decoration.getMarker()).forEach(m => m.destroy()); if (Array.isArray(ranges)) { ranges.forEach(range => this.createHintMarker(editor, range)); } @@ -37,12 +42,30 @@ export class BootStsAdapter extends StsAdapter { } private createHintMarker(editor: TextEditor, range: Range) { + // Create marker model const marker = editor.markBufferRange(Convert.lsRangeToAtomRange(range)); // Marker around the text in the editor editor.decorateMarker(marker, DECORATION_OPTIONS); + const element = document.createElement('img'); + // element.textContent = '🐲'; + element.src = 'atom://spring-boot/styles/boot-icon.png'; + + const AUX_DECORATION_OPTIONS: DecorationOptions = { + type: 'block', + position: 'before', + item: element, + class: 'boot-hint-icon' + }; + const auxMarker = editor.markBufferRange(Convert.lsRangeToAtomRange({ + start: range.start, + end: range.start + })); + + editor.decorateMarker(auxMarker, AUX_DECORATION_OPTIONS); + // Marker in the diagnostic gutter let gutter = editor.gutterWithName(BOOT_HINT_GUTTER_NAME); if (!gutter) { diff --git a/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less b/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less index 2ef68d7c5..1514f6461 100644 --- a/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less +++ b/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less @@ -1,9 +1,29 @@ .boot-hint .region { - border-color: #32BA56; - border-style: dotted; - border-width: 1px; + background-color: rgba(109,179,63,0.25); + border-color: rgba(109,179,63,0.25); + border-radius: 4px; + border-spacing: 4px; } +.boot-hint-icon { + //background-image: url("atom://spring-boot/styles/boot-icon.png"); + //width: 10px; + //height: 10px; + display: inline; +} + +//.boot-hint .region::before { +// content: url("atom://spring-boot/styles/boot-icon.png"); +// display: block; +//} + +//before: { +// contentIconPath: path.resolve(__dirname, "../icons/boot-12.png"), +// margin: '0px 2px 0px 0px', +// height: '18pt' +//}, + + atom-text-editor.editor { .gutter-boot-hint:before { content: url("atom://spring-boot/styles/boot-icon.png"); From 83dc563ea7ed169fa02bd5187d87efbba979c099 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Wed, 18 Jul 2018 19:13:09 -0400 Subject: [PATCH 12/14] Attempt to update eclipse boot hints --- .../plugin.xml | 38 +++++++++--------- .../commons-vscode/icons/boot-12.png | Bin 0 -> 1996 bytes .../commons-vscode/icons/boot-16.png | Bin 0 -> 2376 bytes .../commons-vscode/icons/boot.png | Bin 0 -> 11039 bytes 4 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 vscode-extensions/commons-vscode/icons/boot-12.png create mode 100644 vscode-extensions/commons-vscode/icons/boot-16.png create mode 100644 vscode-extensions/commons-vscode/icons/boot.png diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml index 69f72c3e0..0008b87b0 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml @@ -2,28 +2,28 @@ - + + annotationType="org.springframework.tooling.bootinfo" + colorPreferenceKey="STS4BootMarkerIndicationColor" + colorPreferenceValue="219,236,207" + contributesToHeader="false" + highlightPreferenceKey="STS4BootMarkerHighlighting" + highlightPreferenceValue="true" + icon="icons/boot-icon.png" + label="Boot Dynamic Info" + overviewRulerPreferenceKey="STS4BootMarkerIndicationInOverviewRuler" + overviewRulerPreferenceValue="true" + presentationLayer="4" + showInNextPrevDropdownToolbarAction="false" + textPreferenceKey="STS4BootMarkerIndication" + textPreferenceValue="true" + textStylePreferenceKey="STS4BootMarkerTextStyle" + verticalRulerPreferenceKey="STS4BootMarkerIndicationInVerticalRuler" + verticalRulerPreferenceValue="true"> P71qdNG4Zhg0M>$uE-t=A0s#Q*dW!Jj`#0e=o!ZFphClY=4qBf~ zu5nf|QaK-BUBzzA92r3#qPrspxA0>`pL#Do?X|ONTdwlK_);vV%Qd_1w`3U@FRBeW zvCV&0G#czTFm_^p&GF@*t`?LzSd|f58%JY5QRXiRFQY;Jy~Hl!-hPtPR0)>97Yqm+6pbj+nQJ>vH_BP+~?7FRtjgCqLU%^z!& zXlFp5uj6}CK*z-;`p(lKKZv6FEtb2w%#YvU65c%|J7p9RezpBp7ii~Um4RWR~Qv0F|je?as9eH z>drA;r3w=VNYvY##)s(TCF;(Qv%{l|o7L(KBF64U;V zDGGl+mkyVgUb|45qt%r|%dB$UE#ghAG!E}uzeYC!_Q5^V?A$M^q2`m}q-uVjhqAV9 zzrF`lAkM~CuA-YyCuQ9XhSd8N7WoXq?@kMr{JML!DNM>qWPNrfN2Pfk*!ZGFe!HSq z&>Hm^<6V$3=)nHk990NHvq4k$R76#r_D0?V$2k_rEsvvlRjlZc$9JH6~3G5Jm> zpiMAoF$?-ScDDXx7(v51!_-#Jd8@9$hTn7genPm5N{%2vThdNBdWp_&YSM@iiU;-` z#QfxF`*!(Wp%u2e95Z6iZmW!3wc6nshI_{{RlS{O*t1;%4sVw}if9a*GPU))J)wK4 zHL!OnVo4xHh)kpjSI0Bo2hO%6Jq~%^*5vtc=3o#x6%QjpCZV5SmUS0&>&+jTeIKai znn8bB#=E%??ihU7Ox2Zj0W3~f3efc~LbDcf7V_Dq?c1ov%a7V$P@hp>POH1!aOWwEFGGr(-J>LKfv0z+3=v&574AeB-bwrF}F=wfw0GKAe-JG zkU*K{mv`!^67)Y_mxOW50zd_lM!5yA6+GU5DzS9CUcg~5JI-#6!XI5?3QLjxU+x6X zS8e&(=L43w9_N75sBP@ut(MLLJWCswrj zIRXGE&)3r*6WC}S#74?2pvmU1%|By6^WRs^-!lKV|F#3GtE&gpIZd)rQIfIVI2nGo zP-EPk>uRJk%Pd9TMRDJopm)6zk-rw_ichEgLywvc?PKCkZf!%zv0EOq63WNdZo;9R z;{w-#Dc&%K`}NV%Fq%7^CYHodzAUB?rIHNj{Xt*sQD59>rw(>eP zCZn#oqj&o&ydy+LYOZI2K%1ks#zCO!FBve)BLxhY`}P0`lBgSOp9aPl#cJVGAU2CI z6)!kRFT5Q_T?273BxvBQ$Vwh22R4R6+CtLh_il^V4z&G(QiJq`m><@Ua9+)NP|1kQ zJNw(OpJ`9THT;VMcaG)db}_ELFYRY96y`lQg%rj;(#qe`24!uD pLLlK5)+h^$EM_+MI|1o%3^6Y4-vzUs_Te%C;EwS|-`Ep*;!iU*g+KrR literal 0 HcmV?d00001 diff --git a/vscode-extensions/commons-vscode/icons/boot-16.png b/vscode-extensions/commons-vscode/icons/boot-16.png new file mode 100644 index 0000000000000000000000000000000000000000..15035059d106a1be816663540b5b0eecd410b0fc GIT binary patch literal 2376 zcmeH{c{JNw9>9O0XzfMqDXl8Cl^{`+s!(cAL{Lh_QmNR>Q+rWM(JGA!ZRqQ0Yk7(& zwN@?lD30>fQhPOoC$+pFiDWV}@6372%$fOT{+oNg_q(0%=X>t?-g|DQqx~fzep!A1 z0EDcq;0TTt<80Bx+#IbjF&7K~hj;?b%^d?V7yvLB$U%8tmq$sMv_u3bof<+0>7_-! zFcnf3%6HK#BQ+<^%s_+j*3hYwE55Xip+`Rs8R)hglsQ;9#_3RsCAvErlN42d5t%k2 zoqfo!JT<1MYC_seaa_4uzE)(UTNKz_JL|U*xBZy)&)#ZUz^#7uiWv$1*dMC ziU&kX=HbN~xcJxd^V9g^yrZVP_dm}PYRZpN;T~1fd=>4)XVnc^Clbi1&~1%H&5U6f zxgXg%QCX4SQ_>mL-Kg)rwPkeZZD#Wo!sh#M1`hdTi@Z$HCk({Kz?t;c7%N(QIPu)i zt8pvasd!C3=3fd6QjT?}WF(eZn$gIMtlH0)MY(0Lvdh+qS`WS#zH)ZS6IZ@6Y$GTI z8&j~6T%#u=O4;!GyWvSSZoHLF**OkVnr|p;`%XPWQgOt%G-zdVV!KfN5gye?+Uafl zcCOq^BXO)O^!T zZcEn5GIOgWNBuS{(>yTZrU@D_F4NO8iei%~!&f2Jw7f6~=wwWmu^la6zE0eiN}sqK zWO3CPHh$2Wt&1oxwwO6bYAN+*>#Es$AU{=U2*19gG;oH&TJ8#gIpt`QL;GRCCP6iMLn54;O(%@FK7|V z1pJRhqIIc+A^5i4baS1dwU|o+@bXE? z@0Eh3hx_?vc?`Bwr|PCV!Fg730`p_L>$DC!XkmaUf-1jEixd@VA}WY_`!Wsu|~1HAf=sksSNyCEvhcygAO5#$si0 zL&@yE4-~^AFUXCXHmGkTN;N<7mvx78Uo0HvbPBnZ8ErWZmEcW{zy{;7QL( zI(^(lWvm~JqOqH_l`dPI&}-jy=dV~Q4#GWIt`RU;T{GrRXR)%m!OhHrHpMOh%sA)h zARn7c@E(kSdNe0E5^CiZ0RRHxf7>8{P$JDq@+jkXO+3YuvBmqEa+Z_AWYt9l1M&5!PikP+@SGJw);0H~OYT$;PnOI#zY;AOCWO!8A&4}IaXggx3LlpMt z`+SFZdD2twq+L>kWIe@*%1N;a_a7CMJRsn6vu*o*YU?7x^9sEjGoCJrwLV11I9_$i zte_C4cAM$ErFjIx$j7O17AP(%GV12{&kO1Fg}jm4%}i@=ECKHCuLJ9N)kJEo zYwq=qH!tXhHUj>!0ns7sc>x1sF_i}fCJWEB1p^$0Pfg|^$Wn#uN%SY!#}aklVCqKV zVAoQ<#t5vy{B~Do`@m<;)RZGFTqAw2Mfw?H!u>b~fN1L&XllbWb#$F|^bPfN3?WcW nZ9PM6?IdFI!tVfFh;N{O%)bXV-<|X10D!fHJ^Y7@-nah>;1N5k literal 0 HcmV?d00001 diff --git a/vscode-extensions/commons-vscode/icons/boot.png b/vscode-extensions/commons-vscode/icons/boot.png new file mode 100644 index 0000000000000000000000000000000000000000..4ca59b805c72f08f24ea1bc4dd3e4f54a3c25a73 GIT binary patch literal 11039 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
Wvwk;*0sa+NdVgx^QzI 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 T`1;2y9Gtw2igc}%S@{0}&bIWY literal 0 HcmV?d00001 From cc756ba2d473b36080dd19fa10620f898626ec24 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Mon, 23 Jul 2018 16:37:03 -0400 Subject: [PATCH 13/14] New boot-hints for Eclipse client --- .../plugin.xml | 1 - .../eclipse/commons/BootInlineAnnotation.java | 55 ++++++++++++++ .../LanguageServerCommonsActivator.java | 3 + .../commons/STS4LanguageClientImpl.java | 75 ++++++++++++++++++- 4 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml index 0008b87b0..cf580e9d0 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml @@ -13,7 +13,6 @@ contributesToHeader="false" highlightPreferenceKey="STS4BootMarkerHighlighting" highlightPreferenceValue="true" - icon="icons/boot-icon.png" label="Boot Dynamic Info" overviewRulerPreferenceKey="STS4BootMarkerIndicationInOverviewRuler" overviewRulerPreferenceValue="true" diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java new file mode 100644 index 000000000..3120dd27f --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2018 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.tooling.ls.eclipse.commons; + +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.inlined.LineContentAnnotation; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; + +/** + * Boot icon inlined annotation + * + * @author Alex Boyko + * + */ +public class BootInlineAnnotation extends LineContentAnnotation { + + private static final int SPACING = 2; + + public BootInlineAnnotation(Position pos, ISourceViewer viewer) { + super(pos, viewer); + } + + @Override + protected int drawAndComputeWidth(GC gc, StyledText textWidget, int offset, int length, Color color, int x, int y) { + FontMetrics fontMetrics = gc.getFontMetrics(); + int height = fontMetrics.getHeight(); + + Image bootImage = LanguageServerCommonsActivator.getInstance().getImageRegistry().get(LanguageServerCommonsActivator.BOOT_ICON_2X_KEY); + Rectangle bootImgBounds = bootImage.getBounds(); + int width = (int) Math.round(bootImgBounds.width / (double) bootImgBounds.height * height); + + Rectangle backgroundRect = new Rectangle(x, y, width + SPACING, fontMetrics.getHeight()); + gc.setBackground(textWidget.getBackground()); + gc.fillRectangle(backgroundRect); + + gc.drawImage(bootImage, bootImgBounds.x, bootImgBounds.y, bootImgBounds.width, bootImgBounds.height, x, y, width, height); + + return backgroundRect.width; + } + +} \ No newline at end of file diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java index 5588de19c..382f95889 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java @@ -26,6 +26,8 @@ public class LanguageServerCommonsActivator extends AbstractUIPlugin { public static final String PLUGIN_ID = "org.springframework.tooling.ls.eclipse.commons"; + public static final String BOOT_ICON_2X_KEY = "boot-icon-key"; + private static LanguageServerCommonsActivator instance; public LanguageServerCommonsActivator() { @@ -35,6 +37,7 @@ public class LanguageServerCommonsActivator extends AbstractUIPlugin { public void start(BundleContext context) throws Exception { instance = this; super.start(context); + getImageRegistry().put(BOOT_ICON_2X_KEY, getImageDescriptor("icons/boot-icon@2x.png")); } public final static ImageDescriptor getImageDescriptor(String path) { diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java index 9269b7be5..f084f9229 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java @@ -14,8 +14,11 @@ import java.lang.reflect.Method; import java.net.URI; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.CompletableFuture; import org.eclipse.core.runtime.IProgressMonitor; @@ -24,11 +27,16 @@ import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationPainter; +import org.eclipse.jface.text.source.IAnnotationAccess; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.IAnnotationModelExtension; import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.inlined.AbstractInlinedAnnotation; +import org.eclipse.jface.text.source.inlined.InlinedAnnotationSupport; import org.eclipse.lsp4e.LSPEclipseUtils; import org.eclipse.lsp4e.LanguageClientImpl; import org.eclipse.lsp4e.LanguageServiceAccessor; @@ -114,7 +122,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La IDocument doc = sourceViewer.getDocument(); if (sourceViewer!=null) { if (doc!=null && annotationModel instanceof IAnnotationModelExtension) { - updateAnnotations(target, doc, (IAnnotationModelExtension) annotationModel); + updateAnnotations(target, sourceViewer, (IAnnotationModelExtension) annotationModel); } } } @@ -137,8 +145,11 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La */ private Map currentAnnotations = new HashMap<>(); - private synchronized void updateAnnotations(String target, IDocument doc, IAnnotationModelExtension annotationModel) { + private Map viewerInlinedAnnotationSupport = new WeakHashMap<>(); + + private synchronized void updateAnnotations(String target, ISourceViewer sourceViewer, IAnnotationModelExtension annotationModel) { if (target!=null) { + IDocument doc = sourceViewer.getDocument(); Collection infos = LanguageServiceAccessor.getLSPDocumentInfosFor(doc, (x) -> true); for (LSPDocumentInfo docInfo : infos) { URI uri = docInfo.getFileUri(); @@ -147,14 +158,72 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La if (toRemove==null) { toRemove = new Annotation[0]; } - Map newAnnotations = createAnnotations(doc, currentHighlights.get(target)); + List highlights = currentHighlights.get(target); + Map newAnnotations = createAnnotations(doc, highlights); annotationModel.replaceAnnotations(toRemove, newAnnotations); currentAnnotations.put(target, newAnnotations.keySet().toArray(new Annotation[newAnnotations.size()])); + updateInlinedAnnotations(sourceViewer, highlights); } } } } + private void updateInlinedAnnotations(final ISourceViewer sourceViewer, List highlights) { + InlinedAnnotationSupport support = viewerInlinedAnnotationSupport.get(sourceViewer); + if (support == null) { + final InlinedAnnotationSupport inlinedSupport = new InlinedAnnotationSupport(); + inlinedSupport.install(sourceViewer, createAnnotationPainter(sourceViewer)); + viewerInlinedAnnotationSupport.put(sourceViewer, inlinedSupport); + sourceViewer.getTextWidget().addDisposeListener((e) -> { + inlinedSupport.uninstall(); + viewerInlinedAnnotationSupport.remove(sourceViewer); + }); + support = inlinedSupport; + } + Set annotations = new HashSet<>(); + if (highlights==null) { + highlights = ImmutableList.of(); + } + IDocument doc = sourceViewer.getDocument(); + for (Range rng : highlights) { + try { + int start = LSPEclipseUtils.toOffset(rng.getStart(), doc); + Position colorPos = new Position(start, 0); + BootInlineAnnotation colorAnnotation = support.findExistingAnnotation(colorPos); + if (colorAnnotation == null) { + colorAnnotation = new BootInlineAnnotation(colorPos, sourceViewer); + } + annotations.add(colorAnnotation); + } catch (BadLocationException e) { + //ignore invalid highlights + } + } + support.updateAnnotations(annotations); + } + + private static AnnotationPainter createAnnotationPainter(ISourceViewer viewer) { + IAnnotationAccess annotationAccess = new IAnnotationAccess() { + @Override + public Object getType(Annotation annotation) { + return annotation.getType(); + } + + @Override + public boolean isMultiLine(Annotation annotation) { + return true; + } + + @Override + public boolean isTemporary(Annotation annotation) { + return true; + } + + }; + AnnotationPainter painter = new AnnotationPainter(viewer, annotationAccess); + ((ITextViewerExtension2) viewer).addPainter(painter); + return painter; + } + private Map createAnnotations(IDocument doc, List highlights) { ImmutableMap.Builder annotations = ImmutableMap.builder(); if (highlights==null) { From 819ae52acf6ad3ec40117c097de466b2ba16d03f Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Wed, 1 Aug 2018 15:28:13 -0400 Subject: [PATCH 14/14] Finalize boot-hint optics change --- .../atom-spring-boot/lib/boot-sts-adapter.ts | 25 +----------------- .../styles/hints.atom-text-editor.less | 22 +++------------ .../icons/boot.png | Bin .../eclipse/commons/BootInlineAnnotation.java | 2 +- .../LanguageServerCommonsActivator.java | 4 +-- .../commons/STS4LanguageClientImpl.java | 3 ++- .../spring-boot-language-server/build.sh | 2 +- .../commons-vscode/icons/boot-12.png | Bin 1996 -> 0 bytes .../commons-vscode/icons/boot-12h.png | Bin 0 -> 696 bytes .../commons-vscode/icons/boot-16.png | Bin 2376 -> 0 bytes .../commons-vscode/icons/boot-icon.svg | 8 ------ .../commons-vscode/src/highlight-service.ts | 6 +---- 12 files changed, 11 insertions(+), 61 deletions(-) rename {vscode-extensions/commons-vscode => eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons}/icons/boot.png (100%) delete mode 100644 vscode-extensions/commons-vscode/icons/boot-12.png create mode 100644 vscode-extensions/commons-vscode/icons/boot-12h.png delete mode 100644 vscode-extensions/commons-vscode/icons/boot-16.png delete mode 100644 vscode-extensions/commons-vscode/icons/boot-icon.svg diff --git a/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts b/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts index 2c0bb9532..37f036a5e 100644 --- a/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts +++ b/atom-extensions/atom-spring-boot/lib/boot-sts-adapter.ts @@ -8,10 +8,9 @@ const BOOT_HINT_GUTTER_NAME = 'boot-hint-gutter'; const DECORATION_OPTIONS: DecorationOptions = { type: 'highlight', class: 'boot-hint', - // gutterName: BOOT_HINT_GUTTER_NAME + gutterName: BOOT_HINT_GUTTER_NAME }; - export class BootStsAdapter extends StsAdapter { constructor() { @@ -24,10 +23,6 @@ export class BootStsAdapter extends StsAdapter { private markHintsForEditor(editor: TextEditor, ranges: Range[]) { editor.getDecorations(DECORATION_OPTIONS).map(decoration => decoration.getMarker()).forEach(m => m.destroy()); - editor.getDecorations({ - type: 'block', - class: 'boot-hint-icon' - }).map(decoration => decoration.getMarker()).forEach(m => m.destroy()); if (Array.isArray(ranges)) { ranges.forEach(range => this.createHintMarker(editor, range)); } @@ -42,30 +37,12 @@ export class BootStsAdapter extends StsAdapter { } private createHintMarker(editor: TextEditor, range: Range) { - // Create marker model const marker = editor.markBufferRange(Convert.lsRangeToAtomRange(range)); // Marker around the text in the editor editor.decorateMarker(marker, DECORATION_OPTIONS); - const element = document.createElement('img'); - // element.textContent = '🐲'; - element.src = 'atom://spring-boot/styles/boot-icon.png'; - - const AUX_DECORATION_OPTIONS: DecorationOptions = { - type: 'block', - position: 'before', - item: element, - class: 'boot-hint-icon' - }; - const auxMarker = editor.markBufferRange(Convert.lsRangeToAtomRange({ - start: range.start, - end: range.start - })); - - editor.decorateMarker(auxMarker, AUX_DECORATION_OPTIONS); - // Marker in the diagnostic gutter let gutter = editor.gutterWithName(BOOT_HINT_GUTTER_NAME); if (!gutter) { diff --git a/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less b/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less index 1514f6461..3a4ace587 100644 --- a/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less +++ b/atom-extensions/atom-spring-boot/styles/hints.atom-text-editor.less @@ -3,27 +3,11 @@ border-color: rgba(109,179,63,0.25); border-radius: 4px; border-spacing: 4px; + //border-color: #32BA56; + //border-style: dotted; + //border-width: 1px; } -.boot-hint-icon { - //background-image: url("atom://spring-boot/styles/boot-icon.png"); - //width: 10px; - //height: 10px; - display: inline; -} - -//.boot-hint .region::before { -// content: url("atom://spring-boot/styles/boot-icon.png"); -// display: block; -//} - -//before: { -// contentIconPath: path.resolve(__dirname, "../icons/boot-12.png"), -// margin: '0px 2px 0px 0px', -// height: '18pt' -//}, - - atom-text-editor.editor { .gutter-boot-hint:before { content: url("atom://spring-boot/styles/boot-icon.png"); diff --git a/vscode-extensions/commons-vscode/icons/boot.png b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/icons/boot.png similarity index 100% rename from vscode-extensions/commons-vscode/icons/boot.png rename to eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/icons/boot.png diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java index 3120dd27f..eb5fdc71d 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/BootInlineAnnotation.java @@ -39,7 +39,7 @@ public class BootInlineAnnotation extends LineContentAnnotation { FontMetrics fontMetrics = gc.getFontMetrics(); int height = fontMetrics.getHeight(); - Image bootImage = LanguageServerCommonsActivator.getInstance().getImageRegistry().get(LanguageServerCommonsActivator.BOOT_ICON_2X_KEY); + Image bootImage = LanguageServerCommonsActivator.getInstance().getImageRegistry().get(LanguageServerCommonsActivator.BOOT_KEY); Rectangle bootImgBounds = bootImage.getBounds(); int width = (int) Math.round(bootImgBounds.width / (double) bootImgBounds.height * height); diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java index 382f95889..519652e5d 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerCommonsActivator.java @@ -26,7 +26,7 @@ public class LanguageServerCommonsActivator extends AbstractUIPlugin { public static final String PLUGIN_ID = "org.springframework.tooling.ls.eclipse.commons"; - public static final String BOOT_ICON_2X_KEY = "boot-icon-key"; + public static final String BOOT_KEY = "boot-key"; private static LanguageServerCommonsActivator instance; @@ -37,7 +37,7 @@ public class LanguageServerCommonsActivator extends AbstractUIPlugin { public void start(BundleContext context) throws Exception { instance = this; super.start(context); - getImageRegistry().put(BOOT_ICON_2X_KEY, getImageDescriptor("icons/boot-icon@2x.png")); + getImageRegistry().put(BOOT_KEY, getImageDescriptor("icons/boot.png")); } public final static ImageDescriptor getImageDescriptor(String path) { diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java index f084f9229..cca0bd791 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java @@ -188,7 +188,8 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La for (Range rng : highlights) { try { int start = LSPEclipseUtils.toOffset(rng.getStart(), doc); - Position colorPos = new Position(start, 0); + int end = LSPEclipseUtils.toOffset(rng.getEnd(), doc); + Position colorPos = new Position(start, end - start); BootInlineAnnotation colorAnnotation = support.findExistingAnnotation(colorPos); if (colorAnnotation == null) { colorAnnotation = new BootInlineAnnotation(colorPos, sourceViewer); diff --git a/headless-services/spring-boot-language-server/build.sh b/headless-services/spring-boot-language-server/build.sh index 9c5bf4644..995aac236 100755 --- a/headless-services/spring-boot-language-server/build.sh +++ b/headless-services/spring-boot-language-server/build.sh @@ -4,4 +4,4 @@ set -e -f ../pom.xml \ -pl spring-boot-language-server \ -am \ - clean install -DskipTests + clean install diff --git a/vscode-extensions/commons-vscode/icons/boot-12.png b/vscode-extensions/commons-vscode/icons/boot-12.png deleted file mode 100644 index aeabf950b994c68c8397efbd2d6ebc081d638bec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1996 zcmeHHdpOg382?ReP71qdNG4Zhg0M>$uE-t=A0s#Q*dW!Jj`#0e=o!ZFphClY=4qBf~ zu5nf|QaK-BUBzzA92r3#qPrspxA0>`pL#Do?X|ONTdwlK_);vV%Qd_1w`3U@FRBeW zvCV&0G#czTFm_^p&GF@*t`?LzSd|f58%JY5QRXiRFQY;Jy~Hl!-hPtPR0)>97Yqm+6pbj+nQJ>vH_BP+~?7FRtjgCqLU%^z!& zXlFp5uj6}CK*z-;`p(lKKZv6FEtb2w%#YvU65c%|J7p9RezpBp7ii~Um4RWR~Qv0F|je?as9eH z>drA;r3w=VNYvY##)s(TCF;(Qv%{l|o7L(KBF64U;V zDGGl+mkyVgUb|45qt%r|%dB$UE#ghAG!E}uzeYC!_Q5^V?A$M^q2`m}q-uVjhqAV9 zzrF`lAkM~CuA-YyCuQ9XhSd8N7WoXq?@kMr{JML!DNM>qWPNrfN2Pfk*!ZGFe!HSq z&>Hm^<6V$3=)nHk990NHvq4k$R76#r_D0?V$2k_rEsvvlRjlZc$9JH6~3G5Jm> zpiMAoF$?-ScDDXx7(v51!_-#Jd8@9$hTn7genPm5N{%2vThdNBdWp_&YSM@iiU;-` z#QfxF`*!(Wp%u2e95Z6iZmW!3wc6nshI_{{RlS{O*t1;%4sVw}if9a*GPU))J)wK4 zHL!OnVo4xHh)kpjSI0Bo2hO%6Jq~%^*5vtc=3o#x6%QjpCZV5SmUS0&>&+jTeIKai znn8bB#=E%??ihU7Ox2Zj0W3~f3efc~LbDcf7V_Dq?c1ov%a7V$P@hp>POH1!aOWwEFGGr(-J>LKfv0z+3=v&574AeB-bwrF}F=wfw0GKAe-JG zkU*K{mv`!^67)Y_mxOW50zd_lM!5yA6+GU5DzS9CUcg~5JI-#6!XI5?3QLjxU+x6X zS8e&(=L43w9_N75sBP@ut(MLLJWCswrj zIRXGE&)3r*6WC}S#74?2pvmU1%|By6^WRs^-!lKV|F#3GtE&gpIZd)rQIfIVI2nGo zP-EPk>uRJk%Pd9TMRDJopm)6zk-rw_ichEgLywvc?PKCkZf!%zv0EOq63WNdZo;9R z;{w-#Dc&%K`}NV%Fq%7^CYHodzAUB?rIHNj{Xt*sQD59>rw(>eP zCZn#oqj&o&ydy+LYOZI2K%1ks#zCO!FBve)BLxhY`}P0`lBgSOp9aPl#cJVGAU2CI z6)!kRFT5Q_T?273BxvBQ$Vwh22R4R6+CtLh_il^V4z&G(QiJq`m><@Ua9+)NP|1kQ zJNw(OpJ`9THT;VMcaG)db}_ELFYRY96y`lQg%rj;(#qe`24!uD pLLlK5)+h^$EM_+MI|1o%3^6Y4-vzUs_Te%C;EwS|-`Ep*;!iU*g+KrR diff --git a/vscode-extensions/commons-vscode/icons/boot-12h.png b/vscode-extensions/commons-vscode/icons/boot-12h.png new file mode 100644 index 0000000000000000000000000000000000000000..3e4d5295afb12eef9f4d93ab41801b7f0e2c1f98 GIT binary patch literal 696 zcmeAS@N?(olHy`uVBq!ia0vp^d_c^@!3-o*<7!?2DVB6cUq=Rpjs4tz5?O(K#^NA% zCx&(BWL^T3dz%_P8LEKrS&T6|4-R5m|luUZ`ovf6v}hBlm=7=0UgO%f1EY zyfgN><{bCPKkb!$)IIx{N8TyVtV8aZ2i!6bx#a;BA8{|b2<%06}FRr zAsbK<A?v9wR> z@!davW}5we`r&Zc^Iy3iBU;v&80G!^7pu8)aX{*}khtXbtqYR)H@E|1k71{$i(?4K zb>6eAPE3vrtQYvX&*;f=t!OFHP+Z}mCFFHJ=fc88Lf`Ef_Hf%UJe)CO+S4f&ubY_V zj!2p-ryN_$T)^ZxH>BqEbnc(>al8tLd3v9@uU}+VhMZ!4D)v{^UmaO+v85H6v~D--S+nwfJ4YqH$G`{d@2yzSg>dl&6y`V${r zdorc!ROjl~#Vrro`YP*umd@sOU^WlT)Vx|Xefott3}+N%pVsI(_=bFM9O0XzfMqDXl8Cl^{`+s!(cAL{Lh_QmNR>Q+rWM(JGA!ZRqQ0Yk7(& zwN@?lD30>fQhPOoC$+pFiDWV}@6372%$fOT{+oNg_q(0%=X>t?-g|DQqx~fzep!A1 z0EDcq;0TTt<80Bx+#IbjF&7K~hj;?b%^d?V7yvLB$U%8tmq$sMv_u3bof<+0>7_-! zFcnf3%6HK#BQ+<^%s_+j*3hYwE55Xip+`Rs8R)hglsQ;9#_3RsCAvErlN42d5t%k2 zoqfo!JT<1MYC_seaa_4uzE)(UTNKz_JL|U*xBZy)&)#ZUz^#7uiWv$1*dMC ziU&kX=HbN~xcJxd^V9g^yrZVP_dm}PYRZpN;T~1fd=>4)XVnc^Clbi1&~1%H&5U6f zxgXg%QCX4SQ_>mL-Kg)rwPkeZZD#Wo!sh#M1`hdTi@Z$HCk({Kz?t;c7%N(QIPu)i zt8pvasd!C3=3fd6QjT?}WF(eZn$gIMtlH0)MY(0Lvdh+qS`WS#zH)ZS6IZ@6Y$GTI z8&j~6T%#u=O4;!GyWvSSZoHLF**OkVnr|p;`%XPWQgOt%G-zdVV!KfN5gye?+Uafl zcCOq^BXO)O^!T zZcEn5GIOgWNBuS{(>yTZrU@D_F4NO8iei%~!&f2Jw7f6~=wwWmu^la6zE0eiN}sqK zWO3CPHh$2Wt&1oxwwO6bYAN+*>#Es$AU{=U2*19gG;oH&TJ8#gIpt`QL;GRCCP6iMLn54;O(%@FK7|V z1pJRhqIIc+A^5i4baS1dwU|o+@bXE? z@0Eh3hx_?vc?`Bwr|PCV!Fg730`p_L>$DC!XkmaUf-1jEixd@VA}WY_`!Wsu|~1HAf=sksSNyCEvhcygAO5#$si0 zL&@yE4-~^AFUXCXHmGkTN;N<7mvx78Uo0HvbPBnZ8ErWZmEcW{zy{;7QL( zI(^(lWvm~JqOqH_l`dPI&}-jy=dV~Q4#GWIt`RU;T{GrRXR)%m!OhHrHpMOh%sA)h zARn7c@E(kSdNe0E5^CiZ0RRHxf7>8{P$JDq@+jkXO+3YuvBmqEa+Z_AWYt9l1M&5!PikP+@SGJw);0H~OYT$;PnOI#zY;AOCWO!8A&4}IaXggx3LlpMt z`+SFZdD2twq+L>kWIe@*%1N;a_a7CMJRsn6vu*o*YU?7x^9sEjGoCJrwLV11I9_$i zte_C4cAM$ErFjIx$j7O17AP(%GV12{&kO1Fg}jm4%}i@=ECKHCuLJ9N)kJEo zYwq=qH!tXhHUj>!0ns7sc>x1sF_i}fCJWEB1p^$0Pfg|^$Wn#uN%SY!#}aklVCqKV zVAoQ<#t5vy{B~Do`@m<;)RZGFTqAw2Mfw?H!u>b~fN1L&XllbWb#$F|^bPfN3?WcW nZ9PM6?IdFI!tVfFh;N{O%)bXV-<|X10D!fHJ^Y7@-nah>;1N5k diff --git a/vscode-extensions/commons-vscode/icons/boot-icon.svg b/vscode-extensions/commons-vscode/icons/boot-icon.svg deleted file mode 100644 index 3183d7108..000000000 --- a/vscode-extensions/commons-vscode/icons/boot-icon.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - Asset 1 - - \ No newline at end of file diff --git a/vscode-extensions/commons-vscode/src/highlight-service.ts b/vscode-extensions/commons-vscode/src/highlight-service.ts index a6e4b4310..e55545b4c 100644 --- a/vscode-extensions/commons-vscode/src/highlight-service.ts +++ b/vscode-extensions/commons-vscode/src/highlight-service.ts @@ -27,12 +27,8 @@ export class HighlightService { constructor() { this.DECORATION = VSCode.window.createTextEditorDecorationType({ - // textDecoration: "underline", - // gutterIconPath: path.resolve(__dirname, "../icons/boot-icon.png"), - // gutterIconSize: "contain", - // outline: "#32BA56 dotted thin", before: { - contentIconPath: path.resolve(__dirname, "../icons/boot-12.png"), + contentIconPath: path.resolve(__dirname, "../icons/boot-12h.png"), margin: '2px 2px 0px 0px' }, backgroundColor: 'rgba(109,179,63,0.25)',