From 1263093c583b1459f504ace3d76a1e129e33b6db Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Tue, 2 Jan 2018 08:48:52 +0100 Subject: [PATCH] function bean symbols now generated if function interface is found in inheritance hierarchy --- .../boot/java/beans/BeansSymbolProvider.java | 62 ++++++++++++------- .../test/SpringIndexerFunctionBeansTest.java | 33 ++++++++++ .../test/FunctionFromSpecializedClass.java | 10 +++ .../FunctionFromSpecializedInterface.java | 10 +++ .../java/org/test/LoopedFunctionClass.java | 4 ++ .../main/java/org/test/LoopedInterface1.java | 6 ++ .../main/java/org/test/LoopedInterface2.java | 4 ++ .../org/test/SpecializedFunctionClass.java | 6 ++ .../test/SpecializedFunctionInterface.java | 6 ++ 9 files changed, 119 insertions(+), 22 deletions(-) create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java create mode 100644 headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java index e30ca4d66..2058ae07e 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.boot.java.beans; import java.util.Collection; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -74,6 +73,7 @@ public class BeansSymbolProvider implements SymbolProvider { @Override public Collection getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) { + // this checks function beans that are defined as implementations of Function interfaces Tuple3 functionBean = getFunctionBean(typeDeclaration, doc); if (functionBean != null) { try { @@ -90,33 +90,51 @@ public class BeansSymbolProvider implements SymbolProvider { } protected Tuple3 getFunctionBean(TypeDeclaration typeDeclaration, TextDocument doc) { - List interfaceTypes = typeDeclaration.superInterfaceTypes(); - if (interfaceTypes != null && interfaceTypes.size() > 0) { - for (Object interfaceType : interfaceTypes) { - Type type = (Type) interfaceType; - String simplifiedType = null; + ITypeBinding resolvedType = typeDeclaration.resolveBinding(); + if (resolvedType != null) { + return getFunctionBean(typeDeclaration, doc, resolvedType); + } + else { + return null; + } + } - if (type.isParameterizedType()) { - ParameterizedType paramType = (ParameterizedType) type; - Type simpleType = paramType.getType(); - ITypeBinding typeBinding = simpleType.resolveBinding(); - simplifiedType = typeBinding.getBinaryName(); - } - else { - simplifiedType = type.resolveBinding().getQualifiedName(); - } + private Tuple3 getFunctionBean(TypeDeclaration typeDeclaration, TextDocument doc, + ITypeBinding resolvedType) { - if (FUNCTION_FUNCTION_TYPE.equals(simplifiedType) || FUNCTION_CONSUMER_TYPE.equals(simplifiedType) - || FUNCTION_SUPPLIER_TYPE.equals(simplifiedType)) { - String beanName = getBeanName(typeDeclaration); - String beanType = type.resolveBinding().getName(); - DocumentRegion region = ASTUtils.nodeRegion(doc, typeDeclaration.getName()); + ITypeBinding[] interfaces = resolvedType.getInterfaces(); + for (ITypeBinding resolvedInterface : interfaces) { + String simplifiedType = null; + if (resolvedInterface.isParameterizedType()) { + simplifiedType = resolvedInterface.getBinaryName(); + } + else { + simplifiedType = resolvedType.getQualifiedName(); + } - return Tuples.of(beanName, beanType, region); + if (FUNCTION_FUNCTION_TYPE.equals(simplifiedType) || FUNCTION_CONSUMER_TYPE.equals(simplifiedType) + || FUNCTION_SUPPLIER_TYPE.equals(simplifiedType)) { + String beanName = getBeanName(typeDeclaration); + String beanType = resolvedInterface.getName(); + DocumentRegion region = ASTUtils.nodeRegion(doc, typeDeclaration.getName()); + + return Tuples.of(beanName, beanType, region); + } + else { + Tuple3 result = getFunctionBean(typeDeclaration, doc, resolvedInterface); + if (result != null) { + return result; } } } - return null; + + ITypeBinding superclass = resolvedType.getSuperclass(); + if (superclass != null) { + return getFunctionBean(typeDeclaration, doc, superclass); + } + else { + return null; + } } protected Collection> getBeanNames(Annotation node, TextDocument doc) { diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java index ac32c0579..a560746ed 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java @@ -69,6 +69,39 @@ public class SpringIndexerFunctionBeansTest { ); } + @Test + public void testScanSpecializedFunctionClass() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/FunctionFromSpecializedClass.java", + symbol("FunctionFromSpecializedClass", "@> 'functionFromSpecializedClass' (@Bean) Function") + ); + } + + @Test + public void testScanSpecializedFunctionInterface() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/FunctionFromSpecializedInterface.java", + symbol("FunctionFromSpecializedInterface", "@> 'functionFromSpecializedInterface' (@Bean) Function") + ); + } + + @Test + public void testScanInconsistentInterfaceHierarchy() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/LoopedFunctionClass.java"); + } //////////////////////////////// // harness code diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java new file mode 100644 index 000000000..b2d69778d --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java @@ -0,0 +1,10 @@ +package org.test; + +public class FunctionFromSpecializedClass extends SpecializedFunctionClass { + + @Override + public String apply(String t) { + return null; + } + +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java new file mode 100644 index 000000000..079fcc143 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java @@ -0,0 +1,10 @@ +package org.test; + +public class FunctionFromSpecializedInterface implements SpecializedFunctionInterface { + + @Override + public String apply(String t) { + return null; + } + +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java new file mode 100644 index 000000000..dc1dceb93 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java @@ -0,0 +1,4 @@ +package org.test; + +public class LoopedFunctionClass implements LoopedInterface1 { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java new file mode 100644 index 000000000..d08a23aaf --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java @@ -0,0 +1,6 @@ +package org.test; + +import java.util.function.Function; + +public interface LoopedInterface1 extends LoopedInterface2 { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java new file mode 100644 index 000000000..490a4fecf --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java @@ -0,0 +1,4 @@ +package org.test; + +public interface LoopedInterface2 extends LoopedInterface1 { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java new file mode 100644 index 000000000..021211a65 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java @@ -0,0 +1,6 @@ +package org.test; + +import java.util.function.Function; + +public abstract class SpecializedFunctionClass implements Function { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java new file mode 100644 index 000000000..3388dba99 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java @@ -0,0 +1,6 @@ +package org.test; + +import java.util.function.Function; + +public interface SpecializedFunctionInterface extends Function { +}