Skip to content

Commit

Permalink
Fix introspection for abstract classes (micronaut-projects#10889)
Browse files Browse the repository at this point in the history
Ignore constructors for abstract classes, so the introspection is
written as not buildable and the instantiation methods in the
introspection are not overridden, trying to call a constructor for an
abstract class.
  • Loading branch information
rorueda committed Oct 22, 2024
1 parent f8a2e5a commit a8f9599
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ default Optional<MethodElement> getDefaultConstructor() {
// only static inner classes can be constructed
return Optional.empty();
}
if (isAbstract()) {
// abstract classes constructors are accessible only from their subtypes
return Optional.empty();
}
List<ConstructorElement> constructors = getAccessibleConstructors()
.stream()
.filter(ctor -> ctor.getParameters().length == 0).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2216,6 +2216,14 @@ abstract class Test {
expect:
beanIntrospection != null
beanIntrospection.getBeanProperties().size() == 2
!beanIntrospection.isBuildable()

when:
beanIntrospection.instantiate()

then:
def e = thrown(InstantiationException)
e.message == 'No default constructor exists'
}

void "test targeting abstract class with @Introspected(classes = "() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4561,6 +4561,14 @@ abstract class Test {
expect:
beanIntrospection != null
beanIntrospection.getBeanProperties().size() == 2
!beanIntrospection.isBuildable()

when:
beanIntrospection.instantiate()

then:
def e = thrown(InstantiationException)
e.message == 'No default constructor exists'
}

void "test introspection on abstract class with custom getter"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,19 @@ internal open class KotlinClassElement(
if (defaultConstructor.isPresent) {
defaultConstructor
} else {
Optional.ofNullable(declaration.primaryConstructor)
.filter { !it.isPrivate() && it.parameters.isEmpty() }
.map {
visitorContext.elementFactory.newConstructorElement(
this,
it,
elementAnnotationMetadataFactory
)
}
if (isAbstract) {
Optional.empty()
} else {
Optional.ofNullable(declaration.primaryConstructor)
.filter { !it.isPrivate() && it.parameters.isEmpty() }
.map {
visitorContext.elementFactory.newConstructorElement(
this,
it,
elementAnnotationMetadataFactory
)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,14 @@ abstract class Test {
expect:
beanIntrospection != null
beanIntrospection.getBeanProperties().size() == 2
!beanIntrospection.isBuildable()

when:
beanIntrospection.instantiate()

then:
def e = thrown(InstantiationException)
e.message == 'No default constructor exists'
}

void "test targeting abstract class with @Introspected(classes = "() {
Expand Down

0 comments on commit a8f9599

Please sign in to comment.