From b5f9c3e505f74536f789a3a7bbd7f8890861a6be Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Tue, 21 Aug 2018 12:54:32 -0400 Subject: [PATCH] PT #159915886: Match more than one bean for collections --- .../autowired/AutowiredHoverProvider.java | 54 ++++++------------ .../test/AutowiredHoverProviderTest.java | 57 +++++++++++++++++++ 2 files changed, 74 insertions(+), 37 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 3b81627f5..1fbdcb52a 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 @@ -210,25 +210,19 @@ public class AutowiredHoverProvider implements HoverProvider { FieldDeclaration fieldDeclaration = (FieldDeclaration)declarationNode; ITypeBinding fieldType = fieldDeclaration.getType().resolveBinding(); if (fieldType != null) { - LiveBean matchedBean = matchBean(project, beans, fieldType, fieldDeclaration.modifiers()); - if (matchedBean != null) { - return ImmutableList.of(matchedBean); - } + return matchBeans(project, beans, fieldType, fieldDeclaration.modifiers()); } } else if (declarationNode instanceof SingleVariableDeclaration) { SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration)declarationNode; ITypeBinding varType = singleVariableDeclaration.getType().resolveBinding(); if (varType != null) { - LiveBean matchedBean = matchBean(project, beans, varType, singleVariableDeclaration.modifiers()); - if (matchedBean != null) { - return ImmutableList.of(matchedBean); - } + return matchBeans(project, beans, varType, singleVariableDeclaration.modifiers()); } } return Collections.emptyList(); } - private static LiveBean matchBean(IJavaProject project, Collection beans, ITypeBinding typeBinding, List modifiers) { + private static List matchBeans(IJavaProject project, Collection beans, ITypeBinding typeBinding, List modifiers) { Optional beanId = ASTUtils.beanId(modifiers); Collection searchScope = beanId.isPresent() ? beans.stream() @@ -237,7 +231,7 @@ public class AutowiredHoverProvider implements HoverProvider { .map(bean -> (Collection) ImmutableList.of(bean)) .orElse(ImmutableList.of()) : beans; - return matchBeanByTypeOrCollection(project, searchScope, typeBinding); + return matchBeansByTypeOrCollection(project, searchScope, typeBinding); } private static boolean isInstanceOfCollection(ITypeBinding typeBinding) { @@ -257,31 +251,30 @@ public class AutowiredHoverProvider implements HoverProvider { } } - private static LiveBean matchBeanByTypeOrCollection(IJavaProject project, Collection beans, ITypeBinding type) { + private static List matchBeansByTypeOrCollection(IJavaProject project, Collection beans, ITypeBinding type) { if (isInstanceOfCollection(type)) { // Raw collections shouldn't match any beans - return type.getTypeArguments().length == 1 ? matchBeanByType(project, beans, type.getTypeArguments()[0].getQualifiedName()) : null; + return type.getTypeArguments().length == 1 ? matchBeansByType(project, beans, type.getTypeArguments()[0].getQualifiedName(), false) : ImmutableList.of(); } else if (type.isArray() && type.getDimensions() == 1) { - return matchBeanByType(project, beans, type.getElementType().getQualifiedName()); + return matchBeansByType(project, beans, type.getElementType().getQualifiedName(), false); } else { - return matchBeanByType(project, beans, type.getQualifiedName()); + return matchBeansByType(project, beans, type.getQualifiedName(), true); } } - private static LiveBean matchBeanByType(IJavaProject project, Collection beans, String fqName) { + private static List matchBeansByType(IJavaProject project, Collection beans, String fqName, boolean allowOneMatchOnly) { if (fqName != null) { - List matches = matchBeansByFQName(project, beans, fqName, true); - if (!matches.isEmpty()) { - return matches.size() == 1 ? matches.get(0) : LiveHoverUtils.CANT_MATCH_PROPER_BEAN; + if (allowOneMatchOnly) { + List matches = beans.stream().filter(b -> AutowiredHoverProvider.isCompatibleBeanType(project, b, fqName)) + .limit(2).collect(Collectors.toList()); + if (!matches.isEmpty()) { + return matches.size() == 1 ? matches : ImmutableList.of(LiveHoverUtils.CANT_MATCH_PROPER_BEAN); + } } else { - matches = beans.stream().filter(b -> AutowiredHoverProvider.isCompatibleBeanType(project, b, fqName)) - .limit(2).collect(Collectors.toList()); - if (!matches.isEmpty()) { - return matches.size() == 1 ? matches.get(0) : LiveHoverUtils.CANT_MATCH_PROPER_BEAN; - } + return beans.stream().filter(b -> AutowiredHoverProvider.isCompatibleBeanType(project, b, fqName)).collect(Collectors.toList()); } } - return null; + return ImmutableList.of(); } private static boolean isCompatibleBeanType(IJavaProject jp, LiveBean bean, String bindingQualifiedName) { @@ -301,19 +294,6 @@ public class AutowiredHoverProvider implements HoverProvider { return false; } - - private static List matchBeansByFQName(IJavaProject project, Collection beans, String fqName, boolean allDots) { - if (fqName != null) { - 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(); - } - } - private LiveBean getDefinedBeanForTypeDeclaration(TypeDeclaration declaringType) { if (declaringType != null) { for (Annotation annotation : ASTUtils.getAnnotations(declaringType)) { 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 4da0a4dfe..bdc812104 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 @@ -1170,6 +1170,63 @@ public class AutowiredHoverProviderTest { ); } + @Test + public void arrayWiredBeans() 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.beans.factory.annotation.Autowired;\n" + + "import org.springframework.stereotype.Component;\n" + + "\n" + + "@Component\n" + + "public class SomeComponent {\n" + + "\n" + + " @Autowired\n" + + " private IDependency[] a;\n" + + "\n" + + " public SomeComponent() {\n" + + " }\n" + + "\n" + + "}\n" + ); + + editor.assertHighlights("@Component", "@Autowired"); + editor.assertTrimmedHover("@Autowired", 1, + "**Autowired `someComponent` ← `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 multiDimensionalArrayWiredBean() throws Exception { LiveBeansModel beans = LiveBeansModel.builder()