Detected candidate inner classes
This commit improves the indexer to also consider static inner classes on top of regular top level classes. Issue: SPR-16112
This commit is contained in:
@@ -19,6 +19,7 @@ package org.springframework.context.index;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -29,7 +30,9 @@ import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
/**
|
||||
@@ -42,6 +45,10 @@ import javax.lang.model.element.TypeElement;
|
||||
*/
|
||||
public class CandidateComponentsIndexer implements Processor {
|
||||
|
||||
private static final Set<ElementKind> TYPE_KINDS =
|
||||
Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
|
||||
ElementKind.INTERFACE));
|
||||
|
||||
private MetadataStore metadataStore;
|
||||
|
||||
private MetadataCollector metadataCollector;
|
||||
@@ -102,6 +109,11 @@ public class CandidateComponentsIndexer implements Processor {
|
||||
}
|
||||
|
||||
private void processElement(Element element) {
|
||||
addMetadataFor(element);
|
||||
staticTypesIn(element.getEnclosedElements()).forEach(this::processElement);
|
||||
}
|
||||
|
||||
private void addMetadataFor(Element element) {
|
||||
Set<String> stereotypes = new LinkedHashSet<>();
|
||||
this.stereotypesProviders.forEach(p -> stereotypes.addAll(p.getStereotypes(element)));
|
||||
if (!stereotypes.isEmpty()) {
|
||||
@@ -121,4 +133,14 @@ public class CandidateComponentsIndexer implements Processor {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<TypeElement> staticTypesIn(Iterable<? extends Element> elements) {
|
||||
List<TypeElement> list = new ArrayList<>();
|
||||
for (Element e : elements) {
|
||||
if (TYPE_KINDS.contains(e.getKind())
|
||||
&& e.getModifiers().contains(Modifier.STATIC))
|
||||
list.add(TypeElement.class.cast(e));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.context.index.sample.SampleComponent;
|
||||
import org.springframework.context.index.sample.SampleController;
|
||||
import org.springframework.context.index.sample.SampleMetaController;
|
||||
import org.springframework.context.index.sample.SampleMetaIndexedController;
|
||||
import org.springframework.context.index.sample.SampleNonStaticEmbedded;
|
||||
import org.springframework.context.index.sample.SampleNone;
|
||||
import org.springframework.context.index.sample.SampleRepository;
|
||||
import org.springframework.context.index.sample.SampleService;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.context.index.sample.cdi.SampleManagedBean;
|
||||
import org.springframework.context.index.sample.cdi.SampleNamed;
|
||||
import org.springframework.context.index.sample.jpa.SampleConverter;
|
||||
import org.springframework.context.index.sample.jpa.SampleEmbeddable;
|
||||
import org.springframework.context.index.sample.SampleEmbedded;
|
||||
import org.springframework.context.index.sample.jpa.SampleEntity;
|
||||
import org.springframework.context.index.sample.jpa.SampleMappedSuperClass;
|
||||
import org.springframework.context.index.sample.type.Repo;
|
||||
@@ -55,6 +57,7 @@ import org.springframework.context.index.sample.type.SmartRepo;
|
||||
import org.springframework.context.index.sample.type.SpecializedRepo;
|
||||
import org.springframework.context.index.test.TestCompiler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -198,6 +201,26 @@ public class CandidateComponentsIndexerTests {
|
||||
testSingleComponent(Repo.class, Repo.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void embeddedCandidatesAreDetected()
|
||||
throws IOException, ClassNotFoundException {
|
||||
// Validate nested type structure
|
||||
String nestedType = "org.springframework.context.index.sample.SampleEmbedded.Another$AnotherPublicCandidate";
|
||||
Class<?> type = ClassUtils.forName(nestedType, getClass().getClassLoader());
|
||||
assertThat(type, sameInstance(SampleEmbedded.Another.AnotherPublicCandidate.class));
|
||||
|
||||
CandidateComponentsMetadata metadata = compile(SampleEmbedded.class);
|
||||
assertThat(metadata, hasComponent(
|
||||
SampleEmbedded.PublicCandidate.class, Component.class));
|
||||
assertThat(metadata, hasComponent(nestedType, Component.class.getName()));
|
||||
assertThat(metadata.getItems(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void embeddedNonStaticCandidateAreIgnored() throws IOException {
|
||||
CandidateComponentsMetadata metadata = compile(SampleNonStaticEmbedded.class);
|
||||
assertThat(metadata.getItems(), hasSize(0));
|
||||
}
|
||||
|
||||
private void testComponent(Class<?>... classes) throws IOException {
|
||||
CandidateComponentsMetadata metadata = compile(classes);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.index.sample;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Test candidate for an embedded {@link Component}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class SampleEmbedded {
|
||||
|
||||
@Component
|
||||
public static class PublicCandidate {
|
||||
|
||||
}
|
||||
|
||||
public static class Another {
|
||||
|
||||
@Component
|
||||
public static class AnotherPublicCandidate {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.index.sample;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Candidate with a inner class that isn't static (and should therefore not be added).
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class SampleNonStaticEmbedded {
|
||||
|
||||
@Component
|
||||
public class InvalidCandidate {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user