added type compatibility checks for beans

This commit is contained in:
Martin Lippert
2023-03-30 22:10:17 +02:00
parent 71bac8a787
commit c653d3cab6
13 changed files with 123 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2032 VMware, Inc.
* Copyright (c) 2023 VMware, 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
@@ -10,6 +10,10 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.index;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.lsp4j.Location;
public class Bean {
@@ -18,13 +22,15 @@ public class Bean {
private final String type;
private final Location location;
private final InjectionPoint[] injectionPoints;
private final Set<String> supertypes;
public Bean(String name, String type, Location location, InjectionPoint[] injectionPoints) {
public Bean(String name, String type, Location location, InjectionPoint[] injectionPoints, String[] supertypes) {
this.name = name;
this.type = type;
this.location = location;
this.injectionPoints = injectionPoints;
this.supertypes = new HashSet<>(Arrays.asList(supertypes));
}
public String getName() {
@@ -42,5 +48,9 @@ public class Bean {
public InjectionPoint[] getInjectionPoints() {
return injectionPoints;
}
public boolean isTypeCompatibleWith(String type) {
return supertypes.contains(type);
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2032 VMware, Inc.
* Copyright (c) 2023 VMware, 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

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2032 VMware, Inc.
* Copyright (c) 2023 VMware, 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
@@ -28,8 +28,8 @@ public class SpringMetamodelIndex {
return this.beans.stream().filter(bean -> bean.getName().equals(name)).collect(Collectors.toList()).toArray(new Bean[0]);
}
public void registerBean(String name, String type, Location location, InjectionPoint[] injectionPoints) {
Bean bean = new Bean(name, type, location, injectionPoints);
public void registerBean(String name, String type, Location location, InjectionPoint[] injectionPoints, String[] supertypes) {
Bean bean = new Bean(name, type, location, injectionPoints, supertypes);
this.beans.add(bean);
}

View File

@@ -12,7 +12,9 @@ package org.springframework.ide.vscode.boot.java.beans;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
@@ -91,7 +93,11 @@ public class BeansSymbolProvider extends AbstractSymbolProvider {
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
InjectionPoint[] injectionPoints = findInjectionPoints(node, doc);
springIndex.registerBean(nameAndRegion.getT1(), beanType.getQualifiedName(), location, injectionPoints);
Set<String> supertypes = new HashSet<>();
ASTUtils.findSupertypes(beanType, supertypes);
springIndex.registerBean(nameAndRegion.getT1(), beanType.getQualifiedName(), location, injectionPoints, (String[]) supertypes.toArray(new String[supertypes.size()]));
} catch (BadLocationException e) {
log.error("", e);

View File

@@ -12,7 +12,9 @@ package org.springframework.ide.vscode.boot.java.beans;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jdt.core.dom.ASTNode;
@@ -93,7 +95,11 @@ public class ComponentSymbolProvider extends AbstractSymbolProvider {
}
InjectionPoint[] injectionPoints = findInjectionPoints(node, doc);
springIndex.registerBean(beanName, beanType.getQualifiedName(), location, injectionPoints);
Set<String> supertypes = new HashSet<>();
ASTUtils.findSupertypes(beanType, supertypes);
springIndex.registerBean(beanName, beanType.getQualifiedName(), location, injectionPoints, (String[]) supertypes.toArray(new String[supertypes.size()]));
return new EnhancedSymbolInformation(symbol, addon);
}

View File

@@ -15,6 +15,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
@@ -344,4 +345,41 @@ public class ASTUtils {
return result;
}
public static void findSupertypes(ITypeBinding binding, Set<String> supertypesCollector) {
// interfaces
ITypeBinding[] interfaces = binding.getInterfaces();
for (ITypeBinding resolvedInterface : interfaces) {
String simplifiedType = null;
if (resolvedInterface.isParameterizedType()) {
simplifiedType = resolvedInterface.getBinaryName();
}
else {
simplifiedType = resolvedInterface.getQualifiedName();
}
if (simplifiedType != null) {
supertypesCollector.add(simplifiedType);
findSupertypes(resolvedInterface, supertypesCollector);
}
}
// superclasses
ITypeBinding superclass = binding.getSuperclass();
if (superclass != null) {
String simplifiedType = null;
if (superclass.isParameterizedType()) {
simplifiedType = superclass.getBinaryName();
}
else {
simplifiedType = superclass.getQualifiedName();
}
if (simplifiedType != null) {
supertypesCollector.add(simplifiedType);
findSupertypes(superclass, supertypesCollector);
}
}
}
}

View File

@@ -11,7 +11,9 @@
package org.springframework.ide.vscode.boot.metamodel.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.util.concurrent.CompletableFuture;
@@ -202,4 +204,21 @@ public class SpringMetamodelIndexerBeansTest {
assertEquals(ip2Location, injectionPoints[1].getLocation());
}
@Test
void testBeansWithSupertypes() {
Bean[] beans = springIndex.getBeans("beanWithSupertypes");
assertEquals(1, beans.length);
assertTrue(beans[0].isTypeCompatibleWith("java.lang.Object"));
assertTrue(beans[0].isTypeCompatibleWith("org.test.supertypes.AbstractBeanWithSupertypes"));
assertTrue(beans[0].isTypeCompatibleWith("org.test.supertypes.Interface1OfBeanWithSupertypes"));
assertTrue(beans[0].isTypeCompatibleWith("org.test.supertypes.Interface2OfBeanWithSupertypes"));
assertTrue(beans[0].isTypeCompatibleWith("org.test.supertypes.InterfaceOfAbstractBean"));
assertTrue(beans[0].isTypeCompatibleWith("org.test.supertypes.BaseClassOfAbstractBeanWithSupertypes"));
assertFalse(beans[0].isTypeCompatibleWith("java.lang.String"));
assertFalse(beans[0].isTypeCompatibleWith("java.util.Comparator"));
}
}

View File

@@ -0,0 +1,11 @@
package org.test;
import org.springframework.stereotype.Component;
import org.test.supertypes.AbstractBeanWithSupertypes;
import org.test.supertypes.Interface1OfBeanWithSupertypes;
import org.test.supertypes.Interface2OfBeanWithSupertypes;
@Component
public class BeanWithSupertypes extends AbstractBeanWithSupertypes implements Interface1OfBeanWithSupertypes, Interface2OfBeanWithSupertypes {
}

View File

@@ -0,0 +1,5 @@
package org.test.supertypes;
public abstract class AbstractBeanWithSupertypes extends BaseClassOfAbstractBeanWithSupertypes implements InterfaceOfAbstractBean {
}

View File

@@ -0,0 +1,5 @@
package org.test.supertypes;
public class BaseClassOfAbstractBeanWithSupertypes implements Interface1OfBeanWithSupertypes {
}

View File

@@ -0,0 +1,5 @@
package org.test.supertypes;
public interface Interface1OfBeanWithSupertypes {
}

View File

@@ -0,0 +1,5 @@
package org.test.supertypes;
public interface Interface2OfBeanWithSupertypes {
}

View File

@@ -0,0 +1,5 @@
package org.test.supertypes;
public interface InterfaceOfAbstractBean {
}