GH-1041: reconciler that finds non-registered aot processor beans updated to use spring index instead of symbols
This commit is contained in:
@@ -120,8 +120,8 @@ public class JdtConfig {
|
||||
return new BeanPostProcessingIgnoreInAotReconciler(server.getQuickfixRegistry());
|
||||
}
|
||||
|
||||
@Bean NotRegisteredBeansReconciler notRegisteredBeansReconciler(SimpleLanguageServer server) {
|
||||
return new NotRegisteredBeansReconciler(server.getQuickfixRegistry());
|
||||
@Bean NotRegisteredBeansReconciler notRegisteredBeansReconciler(SimpleLanguageServer server, SpringMetamodelIndex springIndex) {
|
||||
return new NotRegisteredBeansReconciler(server.getQuickfixRegistry(), springIndex);
|
||||
}
|
||||
|
||||
@Bean EntityIdForRepoReconciler entityIdForRepoReconciler(SimpleLanguageServer server) {
|
||||
|
||||
@@ -102,7 +102,18 @@ public class SpringMetamodelIndex {
|
||||
Bean[] allBeans = this.beansPerProject.get(project);
|
||||
|
||||
if (allBeans != null) {
|
||||
return Arrays.stream(allBeans).filter(bean -> bean.getName().equals(name)).collect(Collectors.toList()).toArray(new Bean[0]);
|
||||
return Arrays.stream(allBeans).filter(bean -> bean.getName().equals(name)).toArray(Bean[]::new);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Bean[] getBeansWithType(String project, String type) {
|
||||
Bean[] allBeans = this.beansPerProject.get(project);
|
||||
|
||||
if (allBeans != null) {
|
||||
return Arrays.stream(allBeans).filter(bean -> bean.getType().equals(type)).toArray(Bean[]::new);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2023, 2204 VMware, Inc.
|
||||
* Copyright (c) 2023, 2024 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
|
||||
@@ -27,23 +27,16 @@ import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.Modifier;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
|
||||
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.boot.java.beans.ConfigBeanSymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.DefineMethod;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
|
||||
@@ -52,19 +45,19 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class NotRegisteredBeansReconciler implements JdtAstReconciler, ApplicationContextAware {
|
||||
public class NotRegisteredBeansReconciler implements JdtAstReconciler {
|
||||
|
||||
private static final List<String> AOT_BEANS = List.of(
|
||||
"org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor",
|
||||
"org.springframework.beans.factory.aot.BeanRegistrationAotProcessor"
|
||||
);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private QuickfixRegistry registry;
|
||||
private SpringMetamodelIndex springIndex;
|
||||
|
||||
public NotRegisteredBeansReconciler(QuickfixRegistry registry) {
|
||||
this.registry = registry;
|
||||
public NotRegisteredBeansReconciler(QuickfixRegistry registry, SpringMetamodelIndex springIndex) {
|
||||
this.registry = registry;
|
||||
this.springIndex = springIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,11 +70,6 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
|
||||
return SpringAotJavaProblemType.JAVA_BEAN_NOT_REGISTERED_IN_AOT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
|
||||
|
||||
@@ -90,79 +78,81 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
|
||||
@Override
|
||||
public boolean visit(TypeDeclaration node) {
|
||||
if (!node.isInterface() && !Modifier.isAbstract(node.getModifiers())) {
|
||||
|
||||
ITypeBinding type = node.resolveBinding();
|
||||
if (type != null && ReconcileUtils.implementsAnyType(AOT_BEANS, type)) {
|
||||
String beanClassName =type.getQualifiedName();
|
||||
SpringSymbolIndex index = applicationContext.getBean(SpringSymbolIndex.class);
|
||||
List<WorkspaceSymbol> beanSymbols = index.getSymbols(data -> {
|
||||
SymbolAddOnInformation[] additionalInformation = data.getAdditionalInformation();
|
||||
if (additionalInformation != null) {
|
||||
for (SymbolAddOnInformation info : additionalInformation) {
|
||||
if (info instanceof BeansSymbolAddOnInformation) {
|
||||
BeansSymbolAddOnInformation info2 = (BeansSymbolAddOnInformation) info;
|
||||
return beanClassName.equals(info2.getBeanType());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}).limit(1).collect(Collectors.toList());
|
||||
String beanClassName = type.getQualifiedName();
|
||||
|
||||
if (beanSymbols.isEmpty()) {
|
||||
Builder<FixDescriptor> fixListBuilder = ImmutableList.builder();
|
||||
for (EnhancedSymbolInformation s : index.getEnhancedSymbols(project)) {
|
||||
if (s.getAdditionalInformation() != null) {
|
||||
ConfigBeanSymbolAddOnInformation configInfo = Arrays.stream(s.getAdditionalInformation()).filter(ConfigBeanSymbolAddOnInformation.class::isInstance).map(ConfigBeanSymbolAddOnInformation.class::cast).findFirst().orElse(null);
|
||||
if (configInfo != null) {
|
||||
for (IMethodBinding constructor : type.getDeclaredMethods()) {
|
||||
if (constructor.isConstructor()) {
|
||||
String constructorParamsSignature = "(" + Arrays.stream(constructor.getParameterTypes()).map(pt -> typePattern(pt)).collect(Collectors.joining(",")) + ")";
|
||||
String beanMethodName = "get" + type.getName();
|
||||
String pattern = beanMethodName + constructorParamsSignature;
|
||||
String contructorParamsLabel = "(" + Arrays.stream(constructor.getParameterTypes()).map(NotRegisteredBeansReconciler::typeStr).collect(Collectors.joining(", ")) + ")";
|
||||
|
||||
Builder<String> paramBuilder = ImmutableList.builder();
|
||||
for (int i = 0; i < constructor.getParameterNames().length && i < constructor.getParameterTypes().length; i++) {
|
||||
ITypeBinding paramType = constructor.getParameterTypes()[i];
|
||||
String paramName = constructor.getParameterNames()[i];
|
||||
paramBuilder.add(typeStr(paramType) + ' ' + paramName);
|
||||
}
|
||||
String paramsStr = String.join(", ", paramBuilder.build().toArray(String[]::new));
|
||||
|
||||
final Set<String> allFqTypes = new HashSet<>();
|
||||
allFqTypes.add(Annotations.BEAN);
|
||||
allFqTypes.addAll(allFQTypes(constructor));
|
||||
fixListBuilder.add(new FixDescriptor(DefineMethod.class.getName(), List.of(s.getSymbol().getLocation().getLeft().getUri()), "Define bean in config '" + configInfo.getBeanID() + "' with constructor " + contructorParamsLabel)
|
||||
.withRecipeScope(RecipeScope.FILE)
|
||||
.withParameters(Map.of(
|
||||
"targetFqName", configInfo.getBeanType(),
|
||||
"signature", pattern,
|
||||
"template", "@Bean\n"
|
||||
+ type.getName() + " " + beanMethodName + "(" + paramsStr + ") {\n"
|
||||
+ "return new " + type.getName() + "(" + Arrays.stream(constructor.getParameterNames()).collect(Collectors.joining(", ")) + ");\n"
|
||||
+ "}\n",
|
||||
"imports", allFqTypes.toArray(String[]::new),
|
||||
"typeStubs", new String[0]/*new String[] { source.printAll() }*/,
|
||||
"classpath", IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath().toString()).toArray(String[]::new)
|
||||
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), getProblemType().getLabel(), node.getName().getStartPosition(), node.getName().getLength());
|
||||
ReconcileUtils.setRewriteFixes(registry, problem, fixListBuilder.build());
|
||||
problemCollector.accept(problem);
|
||||
Bean[] registeredBeans = springIndex.getBeansWithType(project.getElementName(), beanClassName);
|
||||
|
||||
if (registeredBeans == null || registeredBeans.length == 0) {
|
||||
createProblemAndQuickFixes(project, problemCollector, node, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
protected void createProblemAndQuickFixes(IJavaProject project, IProblemCollector problemCollector, TypeDeclaration node, ITypeBinding type) {
|
||||
Builder<FixDescriptor> fixListBuilder = ImmutableList.builder();
|
||||
|
||||
Bean[] configBeans = getConfigurationBeans(project);
|
||||
|
||||
for (Bean configBean : configBeans) {
|
||||
for (IMethodBinding constructor : type.getDeclaredMethods()) {
|
||||
if (constructor.isConstructor()) {
|
||||
String constructorParamsSignature = "(" + Arrays.stream(constructor.getParameterTypes()).map(pt -> typePattern(pt)).collect(Collectors.joining(",")) + ")";
|
||||
String beanMethodName = "get" + type.getName();
|
||||
String pattern = beanMethodName + constructorParamsSignature;
|
||||
String contructorParamsLabel = "(" + Arrays.stream(constructor.getParameterTypes()).map(NotRegisteredBeansReconciler::typeStr).collect(Collectors.joining(", ")) + ")";
|
||||
|
||||
Builder<String> paramBuilder = ImmutableList.builder();
|
||||
for (int i = 0; i < constructor.getParameterNames().length && i < constructor.getParameterTypes().length; i++) {
|
||||
ITypeBinding paramType = constructor.getParameterTypes()[i];
|
||||
String paramName = constructor.getParameterNames()[i];
|
||||
paramBuilder.add(typeStr(paramType) + ' ' + paramName);
|
||||
}
|
||||
String paramsStr = String.join(", ", paramBuilder.build().toArray(String[]::new));
|
||||
|
||||
final Set<String> allFqTypes = new HashSet<>();
|
||||
allFqTypes.add(Annotations.BEAN);
|
||||
allFqTypes.addAll(allFQTypes(constructor));
|
||||
fixListBuilder.add(new FixDescriptor(DefineMethod.class.getName(), List.of(configBean.getLocation().getUri()), "Define bean in config '" + configBean.getName() + "' with constructor " + contructorParamsLabel)
|
||||
.withRecipeScope(RecipeScope.FILE)
|
||||
.withParameters(Map.of(
|
||||
"targetFqName", configBean.getType(),
|
||||
"signature", pattern,
|
||||
"template", "@Bean\n"
|
||||
+ type.getName() + " " + beanMethodName + "(" + paramsStr + ") {\n"
|
||||
+ "return new " + type.getName() + "(" + Arrays.stream(constructor.getParameterNames()).collect(Collectors.joining(", ")) + ");\n"
|
||||
+ "}\n",
|
||||
"imports", allFqTypes.toArray(String[]::new),
|
||||
"typeStubs", new String[0]/*new String[] { source.printAll() }*/,
|
||||
"classpath", IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath().toString()).toArray(String[]::new)
|
||||
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), getProblemType().getLabel(), node.getName().getStartPosition(), node.getName().getLength());
|
||||
ReconcileUtils.setRewriteFixes(registry, problem, fixListBuilder.build());
|
||||
problemCollector.accept(problem);
|
||||
}
|
||||
|
||||
private Bean[] getConfigurationBeans(IJavaProject project) {
|
||||
Bean[] beans = springIndex.getBeansOfProject(project.getElementName());
|
||||
if (beans != null) {
|
||||
return Arrays.stream(beans).filter(bean -> bean.isConfiguration()).toArray(Bean[]::new);
|
||||
}
|
||||
else {
|
||||
return new Bean[0];
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> allFQTypes(IBinding binding) {
|
||||
ImmutableSet.Builder<String> b = ImmutableSet.builder();
|
||||
if (binding instanceof IMethodBinding) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2023 VMware, Inc.
|
||||
* Copyright (c) 2023, 2024 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
|
||||
@@ -11,36 +11,21 @@
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolKind;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
|
||||
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
|
||||
import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.beans.ConfigBeanSymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JdtAstReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.NotRegisteredBeansReconciler;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
|
||||
public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
|
||||
@@ -53,33 +38,14 @@ public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
protected String getProjectName() {
|
||||
return "test-spring-validations";
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@Override
|
||||
protected JdtAstReconciler getReconciler() {
|
||||
NotRegisteredBeansReconciler reconciler = new NotRegisteredBeansReconciler(new QuickfixRegistry());
|
||||
SpringSymbolIndex mockSymbolIndex = mock(SpringSymbolIndex.class);
|
||||
when(mockSymbolIndex.getSymbols(any(Predicate.class))).thenReturn(Stream.empty());
|
||||
|
||||
ApplicationContext context = mock(ApplicationContext.class);
|
||||
when(context.getBean(SpringSymbolIndex.class)).thenReturn(mockSymbolIndex);
|
||||
|
||||
reconciler.setApplicationContext(context);
|
||||
return reconciler;
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private NotRegisteredBeansReconciler createReconciler(EnhancedSymbolInformation... beanSymbols) {
|
||||
NotRegisteredBeansReconciler reconciler = new NotRegisteredBeansReconciler(new QuickfixRegistry());
|
||||
SpringSymbolIndex mockSymbolIndex = mock(SpringSymbolIndex.class);
|
||||
when(mockSymbolIndex.getSymbols(any(Predicate.class))).thenReturn(Stream.empty());
|
||||
when(mockSymbolIndex.getEnhancedSymbols(any(IJavaProject.class))).thenReturn(Arrays.asList(beanSymbols));
|
||||
|
||||
ApplicationContext context = mock(ApplicationContext.class);
|
||||
when(context.getBean(SpringSymbolIndex.class)).thenReturn(mockSymbolIndex);
|
||||
|
||||
reconciler.setApplicationContext(context);
|
||||
return reconciler;
|
||||
private NotRegisteredBeansReconciler createReconciler(SpringMetamodelIndex springIndex) {
|
||||
return new NotRegisteredBeansReconciler(new QuickfixRegistry(), springIndex);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@@ -93,7 +59,7 @@ public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void sanityTest() throws Exception {
|
||||
void sanityTestAotProcessorIsRegisteredAsBean() throws Exception {
|
||||
String source = """
|
||||
package example.demo;
|
||||
|
||||
@@ -104,7 +70,30 @@ public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
public A(String k) {}
|
||||
}
|
||||
""";
|
||||
List<ReconcileProblem> problems = reconcile(() -> createReconciler(), "A.java", source, true);
|
||||
|
||||
SpringMetamodelIndex springIndex = new SpringMetamodelIndex();
|
||||
Bean aotBean = new Bean("a", "example.demo.A", new Location("docURI", new Range()), null, null, null, true);
|
||||
springIndex.updateBeans(getProjectName(), new Bean[] {aotBean});
|
||||
|
||||
List<ReconcileProblem> problems = reconcile(() -> createReconciler(springIndex), "A.java", source, true);
|
||||
assertEquals(0, problems.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void sanityTestAotProcessorIsNotRegisteredAsBean() throws Exception {
|
||||
String source = """
|
||||
package example.demo;
|
||||
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
|
||||
|
||||
class A implements BeanRegistrationAotProcessor {
|
||||
|
||||
public A(String k) {}
|
||||
}
|
||||
""";
|
||||
|
||||
SpringMetamodelIndex emptySpringIndex = new SpringMetamodelIndex();
|
||||
List<ReconcileProblem> problems = reconcile(() -> createReconciler(emptySpringIndex), "A.java", source, true);
|
||||
|
||||
assertEquals(1, problems.size());
|
||||
|
||||
@@ -120,17 +109,7 @@ public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void sanityTestWithQuickFixes() throws Exception {
|
||||
Path configClassPath = createFile("TestConfig.java", """
|
||||
package example.demo;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
class TestConfig {
|
||||
}
|
||||
""");
|
||||
|
||||
void sanityTestAotProcessorIsNotRegisteredAsBeanWithQuickFixes() throws Exception {
|
||||
String source = """
|
||||
package example.demo;
|
||||
|
||||
@@ -142,10 +121,11 @@ public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
}
|
||||
""";
|
||||
|
||||
WorkspaceSymbol workspaceSymbol = new WorkspaceSymbol("testConfig", SymbolKind.Class, Either.forLeft(new Location(configClassPath.toUri().toASCIIString(), new Range())));
|
||||
ConfigBeanSymbolAddOnInformation configBeanAddOn = new ConfigBeanSymbolAddOnInformation("testConfig", "example.demo.TestConfig");
|
||||
|
||||
List<ReconcileProblem> problems = reconcile(() -> createReconciler(new EnhancedSymbolInformation(workspaceSymbol, new SymbolAddOnInformation[] { configBeanAddOn })), "A.java", source, true);
|
||||
SpringMetamodelIndex springIndex = new SpringMetamodelIndex();
|
||||
Bean configBean = new Bean("testConfig", "example.demo.TestConfig", new Location("docURI", new Range()), null, null, null, true);
|
||||
springIndex.updateBeans(getProjectName(), new Bean[] {configBean});
|
||||
|
||||
List<ReconcileProblem> problems = reconcile(() -> createReconciler(springIndex), "A.java", source, true);
|
||||
|
||||
assertEquals(1, problems.size());
|
||||
|
||||
@@ -159,5 +139,4 @@ public class NotRegisteredBeansReconcilerTest extends BaseReconcilerTest {
|
||||
assertEquals(1, problem.getQuickfixes().size());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user