diff --git a/CHANGELOG.md b/CHANGELOG.md index 155e0d00..bd475755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Changed - include new `Option.STANDARD_FORMATS` in `OptionPreset.PLAIN_JSON` by default +- extended parameters for creation of `FieldScope`/`MethodScope` through the `TypeContext` to include type for which a schema is being generated #### Fixed - when using `Option.FIELDS_DERIVED_FROM_ARGUMENTFREE_METHODS` on a method where the second character of the derived field name is in uppercase, don't capitalise the first character diff --git a/jsonschema-examples/src/main/java/com/github/victools/jsonschema/examples/InheritanceRefExample.java b/jsonschema-examples/src/main/java/com/github/victools/jsonschema/examples/InheritanceRefExample.java new file mode 100644 index 00000000..395dfab7 --- /dev/null +++ b/jsonschema-examples/src/main/java/com/github/victools/jsonschema/examples/InheritanceRefExample.java @@ -0,0 +1,96 @@ +/* + * Copyright 2023 VicTools. + * + * 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 com.github.victools.jsonschema.examples; + +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.victools.jsonschema.generator.CustomDefinition; +import com.github.victools.jsonschema.generator.CustomDefinitionProviderV2; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.OptionPreset; +import com.github.victools.jsonschema.generator.SchemaGenerationContext; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaKeyword; +import com.github.victools.jsonschema.generator.SchemaVersion; +import java.time.LocalDate; + +/** + * Example created in response to #407. + *
+ * Reference separate definitions for common super types. Show-casing capabilities; but not recommended due to risk of infinite loop. + */ +public class InheritanceRefExample implements SchemaGenerationExampleInterface { + + @Override + public ObjectNode generateSchema() { + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON) + .with(Option.DEFINITIONS_FOR_ALL_OBJECTS); + // ignore all fields declared in super types + configBuilder.forFields() + .withIgnoreCheck(field -> !field.getDeclaringType().equals(field.getDeclarationDetails().getSchemaTargetType())); + // reference super types explicitly + configBuilder.forTypesInGeneral() + // including SubtypeResolver would result in a StackOverflowError as the super reference is again replaced with it subtypes + //.withSubtypeResolver(new SubtypeLookUpExample.ClassGraphSubtypeResolver()) + .withCustomDefinitionProvider(new ParentReferenceDefinitionProvider()); + SchemaGeneratorConfig config = configBuilder.build(); + return new SchemaGenerator(config).generateSchema(TestType.class); + } + + static class ParentReferenceDefinitionProvider implements CustomDefinitionProviderV2 { + @Override + public CustomDefinition provideCustomSchemaDefinition(ResolvedType javaType, SchemaGenerationContext context) { + if (javaType.getErasedType().getSuperclass() == null || javaType.getErasedType().getSuperclass() == Object.class) { + return null; + } + ResolvedType superType = context.getTypeContext().resolve(javaType.getErasedType().getSuperclass()); + // two options here: + // 1. providing "null" as second parameter = multiple hierarchy levels are respected + // 2. providing "this" as second parameter = only one hierarchy level is respected + ObjectNode superTypeReference = context.createStandardDefinitionReference(superType, null); + ObjectNode definition = context.createStandardDefinition(javaType, this); + definition.withArray(context.getKeyword(SchemaKeyword.TAG_ALLOF)) + .add(superTypeReference); + return new CustomDefinition(definition, CustomDefinition.DefinitionType.STANDARD, CustomDefinition.AttributeInclusion.YES); + } + } + + static class TestType { + public Book favoriteBook; + public Poster favoritePoster; + } + + static class Book extends PrintPublication { + public int pageCount; + } + + static class Poster extends PrintPublication { + public boolean forMovie; + } + + static class PrintPublication extends Publication { + public String author; + public String publisher; + } + + static class Publication { + public LocalDate published; + public String title; + } +} diff --git a/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java b/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java index 92a4782f..ea49a003 100644 --- a/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java +++ b/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java @@ -36,6 +36,7 @@ public class ExampleTest { ExternalRefAnnotationExample.class, ExternalRefPackageExample.class, IfThenElseExample.class, + InheritanceRefExample.class, JacksonDescriptionAsTitleExample.class, JacksonSubtypeDefinitionExample.class, StrictTypeInfoExample.class, diff --git a/jsonschema-examples/src/test/resources/com/github/victools/jsonschema/examples/InheritanceRefExample-result.json b/jsonschema-examples/src/test/resources/com/github/victools/jsonschema/examples/InheritanceRefExample-result.json new file mode 100644 index 00000000..7a7dcb1d --- /dev/null +++ b/jsonschema-examples/src/test/resources/com/github/victools/jsonschema/examples/InheritanceRefExample-result.json @@ -0,0 +1,56 @@ +{ + "$schema" : "https://json-schema.org/draft/2020-12/schema", + "$defs" : { + "Book" : { + "type" : "object", + "properties" : { + "pageCount" : { + "type" : "integer" + } + }, + "$ref" : "#/$defs/PrintPublication" + }, + "Poster" : { + "type" : "object", + "properties" : { + "forMovie" : { + "type" : "boolean" + } + }, + "$ref" : "#/$defs/PrintPublication" + }, + "PrintPublication" : { + "type" : "object", + "properties" : { + "author" : { + "type" : "string" + }, + "publisher" : { + "type" : "string" + } + }, + "$ref" : "#/$defs/Publication" + }, + "Publication" : { + "type" : "object", + "properties" : { + "published" : { + "type" : "string", + "format" : "date" + }, + "title" : { + "type" : "string" + } + } + } + }, + "type" : "object", + "properties" : { + "favoriteBook" : { + "$ref" : "#/$defs/Book" + }, + "favoritePoster" : { + "$ref" : "#/$defs/Poster" + } + } +} \ No newline at end of file diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java index ff5aa88d..d67212f1 100644 --- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java +++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java @@ -40,38 +40,24 @@ public class FieldScope extends MemberScope { * Constructor. * * @param field targeted field - * @param declaringTypeMembers collection of the declaring type's (other) fields and methods + * @param declarationDetails basic details regarding the declaration context + * @param overrideDetails augmenting details (e.g., overridden type, name, or container item index) * @param context the overall type resolution context */ - protected FieldScope(ResolvedField field, ResolvedTypeWithMembers declaringTypeMembers, TypeContext context) { - this(field, null, null, declaringTypeMembers, null, context); - } - - /** - * Constructor. - * - * @param field targeted field - * @param overriddenType alternative type for this field - * @param overriddenName alternative name for this field - * @param declaringTypeMembers collection of the declaring type's (other) fields and methods - * @param fakeContainerItemIndex index of the container item on the generic field/method scope's declared type (e.g., in case of a List, it is 0) - * @param context the overall type resolution context - */ - protected FieldScope(ResolvedField field, ResolvedType overriddenType, String overriddenName, - ResolvedTypeWithMembers declaringTypeMembers, Integer fakeContainerItemIndex, TypeContext context) { - super(field, overriddenType, overriddenName, declaringTypeMembers, fakeContainerItemIndex, context); + protected FieldScope(ResolvedField field, DeclarationDetails declarationDetails, OverrideDetails overrideDetails, TypeContext context) { + super(field, declarationDetails, overrideDetails, context); } @Override public FieldScope withOverriddenType(ResolvedType overriddenType) { - return new FieldScope(this.getMember(), overriddenType, this.getOverriddenName(), this.getDeclaringTypeMembers(), - this.getFakeContainerItemIndex(), this.getContext()); + OverrideDetails overrideDetails = new OverrideDetails(overriddenType, this.getOverriddenName(), this.getFakeContainerItemIndex()); + return new FieldScope(this.getMember(), this.getDeclarationDetails(), overrideDetails, this.getContext()); } @Override public FieldScope withOverriddenName(String overriddenName) { - return new FieldScope(this.getMember(), this.getOverriddenType(), overriddenName, this.getDeclaringTypeMembers(), - this.getFakeContainerItemIndex(), this.getContext()); + OverrideDetails overrideDetails = new OverrideDetails(this.getOverriddenType(), overriddenName, this.getFakeContainerItemIndex()); + return new FieldScope(this.getMember(), this.getDeclarationDetails(), overrideDetails, this.getContext()); } @Override @@ -135,7 +121,7 @@ private MethodScope doFindGetter() { .filter(method -> method.isPublic() && method.getRawMember().getParameterCount() == 0) .filter(method -> possibleGetterNames.contains(method.getName())) .findFirst() - .map(method -> this.getContext().createMethodScope(method, this.getDeclaringTypeMembers())) + .map(method -> this.getContext().createMethodScope(method, this.getDeclarationDetails())) .orElse(null); } diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java index 77b80a02..6a037e55 100644 --- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java +++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java @@ -37,9 +37,9 @@ public abstract class MemberScope, T extends Member> extends TypeScope { private final M member; + private final DeclarationDetails declarationDetails; private final ResolvedType overriddenType; private final String overriddenName; - private final ResolvedTypeWithMembers declaringTypeMembers; private Integer fakeContainerItemIndex; private final LazyValue schemaPropertyName = new LazyValue<>(this::doGetSchemaPropertyName); @@ -47,20 +47,17 @@ public abstract class MemberScope, T extends Member> * Constructor. * * @param member targeted field or method - * @param overriddenType alternative type for this field or method's return value - * @param overriddenName alternative name for this field or method - * @param declaringTypeMembers collection of the declaring type's (other) fields and methods - * @param fakeContainerItemIndex index of the container item on the generic field/method scope's declared type (e.g., in case of a List, it is 0) + * @param declarationDetails basic details regarding the declaration context + * @param overrideDetails augmenting details (e.g., overridden type, name, or container item index) * @param context the overall type resolution context */ - protected MemberScope(M member, ResolvedType overriddenType, String overriddenName, - ResolvedTypeWithMembers declaringTypeMembers, Integer fakeContainerItemIndex, TypeContext context) { - super(Optional.ofNullable(overriddenType).orElseGet(member::getType), context); + protected MemberScope(M member, DeclarationDetails declarationDetails, OverrideDetails overrideDetails, TypeContext context) { + super(Optional.ofNullable(OverrideDetails.getOverriddenType(overrideDetails)).orElseGet(member::getType), context); this.member = member; - this.overriddenType = overriddenType; - this.overriddenName = overriddenName; - this.declaringTypeMembers = declaringTypeMembers; - this.fakeContainerItemIndex = fakeContainerItemIndex; + this.declarationDetails = declarationDetails; + this.overriddenType = OverrideDetails.getOverriddenType(overrideDetails); + this.overriddenName = OverrideDetails.getOverriddenName(overrideDetails); + this.fakeContainerItemIndex = OverrideDetails.getFakeContainerItemIndex(overrideDetails); } /** @@ -135,13 +132,22 @@ public M getMember() { return this.member; } + /** + * Getter for additional declaration context information. + * + * @return wrapper for the schema target type and declaring type's field and methods + */ + public DeclarationDetails getDeclarationDetails() { + return this.declarationDetails; + } + /** * Getter for the collection of the member's declaring type's (other) fields and methods. * * @return declaring type's fields and methods */ public ResolvedTypeWithMembers getDeclaringTypeMembers() { - return this.declaringTypeMembers; + return this.declarationDetails.getDeclaringTypeMembers(); } /** @@ -475,4 +481,64 @@ public String getSchemaPropertyName() { public String toString() { return this.getSimpleTypeDescription() + " " + this.getSchemaPropertyName(); } + + public static class DeclarationDetails { + private final ResolvedType schemaTargetType; + private final ResolvedTypeWithMembers declaringTypeMembers; + + public DeclarationDetails(ResolvedType schemaTargetType, ResolvedTypeWithMembers declaringTypeMembers) { + this.schemaTargetType = schemaTargetType; + this.declaringTypeMembers = declaringTypeMembers; + } + + /** + * Getter for the specific type for which a schema is being generated, that includes this field/method. This can differ from the wrapped + * member's declaring type, if that declaring type is an implemented interface or super type of the targeted one. + * + * @return target type for which a schema is being generated including this field/method + */ + public ResolvedType getSchemaTargetType() { + return this.schemaTargetType; + } + + /** + * Getter for the collection of the member's declaring type's (other) fields and methods. + * + * @return declaring type's fields and methods + */ + public ResolvedTypeWithMembers getDeclaringTypeMembers() { + return this.declaringTypeMembers; + } + } + + static class OverrideDetails { + private final ResolvedType overriddenType; + private final String overriddenName; + private final Integer fakeContainerItemIndex; + + /** + * Constructor. + * + * @param overriddenType alternative type for this field or method's return value + * @param overriddenName alternative name for this field or method + * @param fakeContainerItemIndex index of the container item on the generic field/method's declared type (e.g., in case of a List, it is 0) + */ + OverrideDetails(ResolvedType overriddenType, String overriddenName, Integer fakeContainerItemIndex) { + this.overriddenType = overriddenType; + this.overriddenName = overriddenName; + this.fakeContainerItemIndex = fakeContainerItemIndex; + } + + private static ResolvedType getOverriddenType(OverrideDetails details) { + return details == null ? null : details.overriddenType; + } + + private static String getOverriddenName(OverrideDetails details) { + return details == null ? null : details.overriddenName; + } + + private static Integer getFakeContainerItemIndex(OverrideDetails details) { + return details == null ? null : details.fakeContainerItemIndex; + } + } } diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java index 434f602b..2631daee 100644 --- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java +++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java @@ -17,7 +17,6 @@ package com.github.victools.jsonschema.generator; import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; import com.fasterxml.classmate.members.ResolvedMethod; import com.github.victools.jsonschema.generator.impl.LazyValue; import java.lang.annotation.Annotation; @@ -43,38 +42,24 @@ public class MethodScope extends MemberScope { * Constructor. * * @param method targeted method - * @param declaringTypeMembers collection of the declaring type's fields and (other) methods + * @param declarationDetails basic details regarding the declaration context + * @param overrideDetails augmenting details (e.g., overridden type, name, or container item index) * @param context the overall type resolution context */ - protected MethodScope(ResolvedMethod method, ResolvedTypeWithMembers declaringTypeMembers, TypeContext context) { - this(method, null, null, declaringTypeMembers, null, context); - } - - /** - * Constructor. - * - * @param method targeted method - * @param overriddenType alternative type for this method's return value - * @param overriddenName alternative name for this method - * @param declaringTypeMembers collection of the declaring type's fields and (other) methods - * @param fakeContainerItemIndex index of the container item on the generic field/method scope's declared type (e.g., in case of a List, it is 0) - * @param context the overall type resolution context - */ - protected MethodScope(ResolvedMethod method, ResolvedType overriddenType, String overriddenName, - ResolvedTypeWithMembers declaringTypeMembers, Integer fakeContainerItemIndex, TypeContext context) { - super(method, overriddenType, overriddenName, declaringTypeMembers, fakeContainerItemIndex, context); + protected MethodScope(ResolvedMethod method, DeclarationDetails declarationDetails, OverrideDetails overrideDetails, TypeContext context) { + super(method, declarationDetails, overrideDetails, context); } @Override public MethodScope withOverriddenType(ResolvedType overriddenType) { - return new MethodScope(this.getMember(), overriddenType, this.getOverriddenName(), this.getDeclaringTypeMembers(), - this.getFakeContainerItemIndex(), this.getContext()); + OverrideDetails overrideDetails = new OverrideDetails(overriddenType, this.getOverriddenName(), this.getFakeContainerItemIndex()); + return new MethodScope(this.getMember(), this.getDeclarationDetails(), overrideDetails, this.getContext()); } @Override public MethodScope withOverriddenName(String overriddenName) { - return new MethodScope(this.getMember(), this.getOverriddenType(), overriddenName, this.getDeclaringTypeMembers(), - this.getFakeContainerItemIndex(), this.getContext()); + OverrideDetails overrideDetails = new OverrideDetails(this.getOverriddenType(), overriddenName, this.getFakeContainerItemIndex()); + return new MethodScope(this.getMember(), this.getDeclarationDetails(), overrideDetails, this.getContext()); } @Override @@ -147,7 +132,7 @@ private FieldScope doFindGetterField() { return Stream.of(this.getDeclaringTypeMembers().getMemberFields()) .filter(memberField -> possibleFieldNames.contains(memberField.getName())) .findFirst() - .map(field -> this.getContext().createFieldScope(field, this.getDeclaringTypeMembers())) + .map(field -> this.getContext().createFieldScope(field, this.getDeclarationDetails())) .orElse(null); } diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/TypeContext.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/TypeContext.java index 291d66e9..5ffc95ca 100644 --- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/TypeContext.java +++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/TypeContext.java @@ -152,9 +152,24 @@ private ResolvedTypeWithMembers resolveWithMembersForCache(ResolvedType resolved * @param field targeted field * @param declaringTypeMembers collection of the declaring type's (other) fields and methods * @return created {@link FieldScope} instance + * @deprecated use {@link #createFieldScope(ResolvedField, MemberScope.DeclarationDetails)} instead */ + @Deprecated public FieldScope createFieldScope(ResolvedField field, ResolvedTypeWithMembers declaringTypeMembers) { - return new FieldScope(field, declaringTypeMembers, this); + return this.createFieldScope(field, new MemberScope.DeclarationDetails(field.getDeclaringType(), declaringTypeMembers)); + } + + /** + * Construct a {@link FieldScope} instance for the given field. + * + * @param field targeted field + * @param declarationDetails context of declaration + * @return created {@link FieldScope} instance + * + * @since 4.33.0 + */ + public FieldScope createFieldScope(ResolvedField field, MemberScope.DeclarationDetails declarationDetails) { + return new FieldScope(field, declarationDetails, null, this); } /** @@ -163,9 +178,24 @@ public FieldScope createFieldScope(ResolvedField field, ResolvedTypeWithMembers * @param method targeted method * @param declaringTypeMembers collection of the declaring type's fields and (other) methods * @return created {@link MethodScope} instance + * @deprecated use {@link #createMethodScope(ResolvedMethod, MemberScope.DeclarationDetails)} instead */ + @Deprecated public MethodScope createMethodScope(ResolvedMethod method, ResolvedTypeWithMembers declaringTypeMembers) { - return new MethodScope(method, declaringTypeMembers, this); + return this.createMethodScope(method, new MemberScope.DeclarationDetails(method.getDeclaringType(), declaringTypeMembers)); + } + + /** + * Construct a {@link MethodScope} instance for the given method. + * + * @param method targeted method + * @param declarationDetails context of declaration + * @return created {@link MethodScope} instance + * + * @since 4.33.0 + */ + public MethodScope createMethodScope(ResolvedMethod method, MemberScope.DeclarationDetails declarationDetails) { + return new MethodScope(method, declarationDetails, null, this); } /** diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/MemberCollectionContextImpl.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/MemberCollectionContextImpl.java index af404334..19fbfbbc 100644 --- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/MemberCollectionContextImpl.java +++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/MemberCollectionContextImpl.java @@ -91,9 +91,10 @@ public Set getRequiredPropertyNames() { public void collectProperties() { logger.debug("collecting non-static fields and methods from {}", this.schemaTargetType); ResolvedTypeWithMembers typeToCollectMembersFrom = this.typeContext.resolveWithMembers(this.schemaTargetType); + MemberScope.DeclarationDetails declarationDetails = new MemberScope.DeclarationDetails(this.schemaTargetType, typeToCollectMembersFrom); // member fields and methods are being collected from the targeted type as well as its super types - this.collectFields(typeToCollectMembersFrom.getMemberFields(), typeToCollectMembersFrom); - this.collectMethods(typeToCollectMembersFrom.getMemberMethods(), typeToCollectMembersFrom); + this.collectFields(typeToCollectMembersFrom.getMemberFields(), declarationDetails); + this.collectMethods(typeToCollectMembersFrom.getMemberMethods(), declarationDetails); if (this.generatorConfig.shouldIncludeStaticFields() || this.generatorConfig.shouldIncludeStaticMethods()) { // static fields and methods are being collected only for the targeted type itself, i.e. need to iterate over super types specifically @@ -108,23 +109,24 @@ private void collectStaticMembers(HierarchicType singleHierarchy) { logger.debug("collecting static fields and methods from {}", hierarchyType); // static members need to be looked up from the declaring type directly as they are not inherited as such ResolvedTypeWithMembers hierarchyTypeWithMembers = this.typeContext.resolveWithMembers(hierarchyType); + MemberScope.DeclarationDetails declarationDetails = new MemberScope.DeclarationDetails(this.schemaTargetType, hierarchyTypeWithMembers); if (this.generatorConfig.shouldIncludeStaticFields()) { - this.collectFields(hierarchyTypeWithMembers.getStaticFields(), hierarchyTypeWithMembers); + this.collectFields(hierarchyTypeWithMembers.getStaticFields(), declarationDetails); } if (this.generatorConfig.shouldIncludeStaticMethods()) { - this.collectMethods(hierarchyTypeWithMembers.getStaticMethods(), hierarchyTypeWithMembers); + this.collectMethods(hierarchyTypeWithMembers.getStaticMethods(), declarationDetails); } } /** * Preparation Step: collect the designated fields. * - * @param fields targeted fields from {@code typeToCollectMembersFrom} - * @param typeToCollectMembersFrom specific container of given fields (possibly a supertype or interface of the targeted type) + * @param fields targeted fields + * @param declarationDetails common declaration context for all given fields */ - private void collectFields(ResolvedField[] fields, ResolvedTypeWithMembers typeToCollectMembersFrom) { + private void collectFields(ResolvedField[] fields, MemberScope.DeclarationDetails declarationDetails) { Stream.of(fields) - .map(declaredField -> this.typeContext.createFieldScope(declaredField, typeToCollectMembersFrom)) + .map(declaredField -> this.typeContext.createFieldScope(declaredField, declarationDetails)) .filter(fieldScope -> !this.generatorConfig.shouldIgnore(fieldScope)) .forEach(this::collect); } @@ -132,12 +134,12 @@ private void collectFields(ResolvedField[] fields, ResolvedTypeWithMembers typeT /** * Preparation Step: collect the designated methods. * - * @param methods targeted methods from {@code typeToCollectMembersFrom} - * @param typeToCollectMembersFrom specific container of given fields (possibly a supertype or interface of the targeted type) + * @param methods targeted methods + * @param declarationDetails common declaration context for all given methods */ - private void collectMethods(ResolvedMethod[] methods, ResolvedTypeWithMembers typeToCollectMembersFrom) { + private void collectMethods(ResolvedMethod[] methods, MemberScope.DeclarationDetails declarationDetails) { Stream.of(methods) - .map(declaredMethod -> this.typeContext.createMethodScope(declaredMethod, typeToCollectMembersFrom)) + .map(declaredMethod -> this.typeContext.createMethodScope(declaredMethod, declarationDetails)) .filter(methodScope -> !this.generatorConfig.shouldIgnore(methodScope)) .forEach(this::collect); } diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/AbstractTypeAwareTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/AbstractTypeAwareTest.java index 71d9f18a..67662806 100644 --- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/AbstractTypeAwareTest.java +++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/AbstractTypeAwareTest.java @@ -33,7 +33,7 @@ public class AbstractTypeAwareTest { private final Class testClass; private SchemaGenerationContext context; - private ResolvedTypeWithMembers testClassMembers; + private MemberScope.DeclarationDetails declarationDetails; protected AbstractTypeAwareTest(Class testClass) { this.testClass = testClass; @@ -47,7 +47,7 @@ protected AbstractTypeAwareTest(Class testClass) { protected void prepareContextForVersion(SchemaVersion schemaVersion) { TypeContext typeContext = Mockito.spy(TypeContextFactory.createDefaultTypeContext()); ResolvedType resolvedTestClass = typeContext.resolve(this.testClass); - this.testClassMembers = typeContext.resolveWithMembers(resolvedTestClass); + this.declarationDetails = new MemberScope.DeclarationDetails(resolvedTestClass, typeContext.resolveWithMembers(resolvedTestClass)); this.context = Mockito.mock(SchemaGenerationContext.class, Mockito.RETURNS_DEEP_STUBS); Mockito.when(this.context.getTypeContext()).thenReturn(typeContext); ObjectMapper objectMapper = new ObjectMapper(); @@ -66,26 +66,26 @@ protected SchemaGenerationContext getContext() { } protected FieldScope getTestClassField(String fieldName) { - ResolvedField resolvedField = Stream.of(this.testClassMembers.getMemberFields()) + ResolvedField resolvedField = Stream.of(this.declarationDetails.getDeclaringTypeMembers().getMemberFields()) .filter(field -> fieldName.equals(field.getName())) .findAny() .orElseGet( - () -> Stream.of(this.testClassMembers.getStaticFields()) + () -> Stream.of(this.declarationDetails.getDeclaringTypeMembers().getStaticFields()) .filter(field -> fieldName.equals(field.getName())) .findAny() .get()); - return this.context.getTypeContext().createFieldScope(resolvedField, this.testClassMembers); + return this.context.getTypeContext().createFieldScope(resolvedField, this.declarationDetails); } protected MethodScope getTestClassMethod(String methodName) { - ResolvedMethod resolvedMethod = Stream.of(this.testClassMembers.getMemberMethods()) + ResolvedMethod resolvedMethod = Stream.of(this.declarationDetails.getDeclaringTypeMembers().getMemberMethods()) .filter(method -> methodName.equals(method.getName())) .findAny() .orElseGet( - () -> Stream.of(this.testClassMembers.getStaticMethods()) + () -> Stream.of(this.declarationDetails.getDeclaringTypeMembers().getStaticMethods()) .filter(method -> methodName.equals(method.getName())) .findAny() .get()); - return this.context.getTypeContext().createMethodScope(resolvedMethod, this.testClassMembers); + return this.context.getTypeContext().createMethodScope(resolvedMethod, this.declarationDetails); } } diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/AbstractTypeAwareTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/AbstractTypeAwareTest.java index 50ce687d..3ad0accb 100644 --- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/AbstractTypeAwareTest.java +++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/AbstractTypeAwareTest.java @@ -22,6 +22,7 @@ import com.fasterxml.classmate.members.ResolvedMethod; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.victools.jsonschema.generator.FieldScope; +import com.github.victools.jsonschema.generator.MemberScope; import com.github.victools.jsonschema.generator.MethodScope; import com.github.victools.jsonschema.generator.SchemaGenerationContext; import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; @@ -40,7 +41,7 @@ public class AbstractTypeAwareTest { private final Class testClass; private SchemaGenerationContext context; - private ResolvedTypeWithMembers testClassMembers; + private MemberScope.DeclarationDetails declarationDetails; protected AbstractTypeAwareTest(Class testClass) { this.testClass = testClass; @@ -54,7 +55,7 @@ protected AbstractTypeAwareTest(Class testClass) { protected void prepareContextForVersion(SchemaVersion schemaVersion) { TypeContext typeContext = TypeContextFactory.createDefaultTypeContext(); ResolvedType resolvedTestClass = typeContext.resolve(this.testClass); - this.testClassMembers = typeContext.resolveWithMembers(resolvedTestClass); + this.declarationDetails = new MemberScope.DeclarationDetails(resolvedTestClass, typeContext.resolveWithMembers(resolvedTestClass)); this.context = Mockito.mock(SchemaGenerationContext.class, Mockito.RETURNS_DEEP_STUBS); Mockito.when(this.context.getTypeContext()).thenReturn(typeContext); @@ -94,26 +95,26 @@ protected SchemaGenerationContext getContext() { } protected FieldScope getTestClassField(String fieldName) { - ResolvedField resolvedField = Stream.of(this.testClassMembers.getMemberFields()) + ResolvedField resolvedField = Stream.of(this.declarationDetails.getDeclaringTypeMembers().getMemberFields()) .filter(field -> fieldName.equals(field.getName())) .findAny() .orElseGet( - () -> Stream.of(this.testClassMembers.getStaticFields()) + () -> Stream.of(this.declarationDetails.getDeclaringTypeMembers().getStaticFields()) .filter(field -> fieldName.equals(field.getName())) .findAny() .get()); - return this.context.getTypeContext().createFieldScope(resolvedField, this.testClassMembers); + return this.context.getTypeContext().createFieldScope(resolvedField, this.declarationDetails); } protected MethodScope getTestClassMethod(String methodName) { - ResolvedMethod resolvedMethod = Stream.of(this.testClassMembers.getMemberMethods()) + ResolvedMethod resolvedMethod = Stream.of(this.declarationDetails.getDeclaringTypeMembers().getMemberMethods()) .filter(method -> methodName.equals(method.getName())) .findAny() .orElseGet( - () -> Stream.of(this.testClassMembers.getStaticMethods()) + () -> Stream.of(this.declarationDetails.getDeclaringTypeMembers().getStaticMethods()) .filter(method -> methodName.equals(method.getName())) .findAny() .get()); - return this.context.getTypeContext().createMethodScope(resolvedMethod, this.testClassMembers); + return this.context.getTypeContext().createMethodScope(resolvedMethod, this.declarationDetails); } } diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/TestType.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/TestType.java index 20175881..aee7067c 100644 --- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/TestType.java +++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/TestType.java @@ -21,6 +21,7 @@ import com.fasterxml.classmate.members.ResolvedField; import com.fasterxml.classmate.members.ResolvedMethod; import com.github.victools.jsonschema.generator.FieldScope; +import com.github.victools.jsonschema.generator.MemberScope; import com.github.victools.jsonschema.generator.MethodScope; import com.github.victools.jsonschema.generator.TypeContext; import com.github.victools.jsonschema.generator.impl.TypeContextFactory; @@ -32,44 +33,43 @@ public class TestType { private final TypeContext context; - private final ResolvedType resolvedTestClass; - private final ResolvedTypeWithMembers testClassMembers; + private final MemberScope.DeclarationDetails declarationDetails; public TestType(Class testClass) { this.context = TypeContextFactory.createDefaultTypeContext(); - this.resolvedTestClass = this.context.resolve(testClass); - this.testClassMembers = this.context.resolveWithMembers(this.resolvedTestClass); + ResolvedType resolvedTestClass = this.context.resolve(testClass); + this.declarationDetails = new MemberScope.DeclarationDetails(resolvedTestClass, this.context.resolveWithMembers(resolvedTestClass)); } public FieldScope getMemberField(String fieldName) { - return this.getField(this.testClassMembers.getMemberFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getMemberFields(), fieldName); } public FieldScope getStaticField(String fieldName) { - return this.getField(this.testClassMembers.getStaticFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getStaticFields(), fieldName); } private FieldScope getField(ResolvedField[] fields, String fieldName) { return Stream.of(fields) .filter(field -> fieldName.equals(field.getName())) .findAny() - .map(field -> this.context.createFieldScope(field, this.testClassMembers)) + .map(field -> this.context.createFieldScope(field, this.declarationDetails)) .get(); } public MethodScope getMemberMethod(String methodName) { - return this.getMethod(this.testClassMembers.getMemberMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getMemberMethods(), methodName); } public MethodScope getStaticMethod(String methodName) { - return this.getMethod(this.testClassMembers.getStaticMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getStaticMethods(), methodName); } private MethodScope getMethod(ResolvedMethod[] methods, String methodName) { return Stream.of(methods) .filter(method -> methodName.equals(method.getName())) .findAny() - .map(method -> this.context.createMethodScope(method, this.testClassMembers)) + .map(method -> this.context.createMethodScope(method, this.declarationDetails)) .get(); } } diff --git a/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/TestType.java b/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/TestType.java index 423c956a..d6426646 100644 --- a/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/TestType.java +++ b/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/TestType.java @@ -21,6 +21,7 @@ import com.fasterxml.classmate.members.ResolvedField; import com.fasterxml.classmate.members.ResolvedMethod; import com.github.victools.jsonschema.generator.FieldScope; +import com.github.victools.jsonschema.generator.MemberScope; import com.github.victools.jsonschema.generator.MethodScope; import com.github.victools.jsonschema.generator.TypeContext; import com.github.victools.jsonschema.generator.impl.TypeContextFactory; @@ -32,44 +33,43 @@ public class TestType { private final TypeContext context; - private final ResolvedType resolvedTestClass; - private final ResolvedTypeWithMembers testClassMembers; + private final MemberScope.DeclarationDetails declarationDetails; public TestType(Class testClass) { this.context = TypeContextFactory.createDefaultTypeContext(); - this.resolvedTestClass = this.context.resolve(testClass); - this.testClassMembers = this.context.resolveWithMembers(this.resolvedTestClass); + ResolvedType resolvedTestClass = this.context.resolve(testClass); + this.declarationDetails = new MemberScope.DeclarationDetails(resolvedTestClass, this.context.resolveWithMembers(resolvedTestClass)); } public FieldScope getMemberField(String fieldName) { - return this.getField(this.testClassMembers.getMemberFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getMemberFields(), fieldName); } public FieldScope getStaticField(String fieldName) { - return this.getField(this.testClassMembers.getStaticFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getStaticFields(), fieldName); } private FieldScope getField(ResolvedField[] fields, String fieldName) { return Stream.of(fields) .filter(field -> fieldName.equals(field.getName())) .findAny() - .map(field -> this.context.createFieldScope(field, this.testClassMembers)) + .map(field -> this.context.createFieldScope(field, this.declarationDetails)) .get(); } public MethodScope getMemberMethod(String methodName) { - return this.getMethod(this.testClassMembers.getMemberMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getMemberMethods(), methodName); } public MethodScope getStaticMethod(String methodName) { - return this.getMethod(this.testClassMembers.getStaticMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getStaticMethods(), methodName); } private MethodScope getMethod(ResolvedMethod[] methods, String methodName) { return Stream.of(methods) .filter(method -> methodName.equals(method.getName())) .findAny() - .map(method -> this.context.createMethodScope(method, this.testClassMembers)) + .map(method -> this.context.createMethodScope(method, this.declarationDetails)) .get(); } } diff --git a/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/TestType.java b/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/TestType.java index a2ef8a92..e55748de 100644 --- a/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/TestType.java +++ b/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/TestType.java @@ -21,6 +21,7 @@ import com.fasterxml.classmate.members.ResolvedField; import com.fasterxml.classmate.members.ResolvedMethod; import com.github.victools.jsonschema.generator.FieldScope; +import com.github.victools.jsonschema.generator.MemberScope; import com.github.victools.jsonschema.generator.MethodScope; import com.github.victools.jsonschema.generator.TypeContext; import com.github.victools.jsonschema.generator.impl.TypeContextFactory; @@ -32,44 +33,43 @@ public class TestType { private final TypeContext context; - private final ResolvedType resolvedTestClass; - private final ResolvedTypeWithMembers testClassMembers; + private final MemberScope.DeclarationDetails declarationDetails; public TestType(Class testClass) { this.context = TypeContextFactory.createDefaultTypeContext(); - this.resolvedTestClass = this.context.resolve(testClass); - this.testClassMembers = this.context.resolveWithMembers(this.resolvedTestClass); + ResolvedType resolvedTestClass = this.context.resolve(testClass); + this.declarationDetails = new MemberScope.DeclarationDetails(resolvedTestClass, this.context.resolveWithMembers(resolvedTestClass)); } public FieldScope getMemberField(String fieldName) { - return this.getField(this.testClassMembers.getMemberFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getMemberFields(), fieldName); } public FieldScope getStaticField(String fieldName) { - return this.getField(this.testClassMembers.getStaticFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getStaticFields(), fieldName); } private FieldScope getField(ResolvedField[] fields, String fieldName) { return Stream.of(fields) .filter(field -> fieldName.equals(field.getName())) .findAny() - .map(field -> this.context.createFieldScope(field, this.testClassMembers)) + .map(field -> this.context.createFieldScope(field, this.declarationDetails)) .get(); } public MethodScope getMemberMethod(String methodName) { - return this.getMethod(this.testClassMembers.getMemberMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getMemberMethods(), methodName); } public MethodScope getStaticMethod(String methodName) { - return this.getMethod(this.testClassMembers.getStaticMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getStaticMethods(), methodName); } private MethodScope getMethod(ResolvedMethod[] methods, String methodName) { return Stream.of(methods) .filter(method -> methodName.equals(method.getName())) .findAny() - .map(method -> this.context.createMethodScope(method, this.testClassMembers)) + .map(method -> this.context.createMethodScope(method, this.declarationDetails)) .get(); } } diff --git a/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/TestType.java b/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/TestType.java index 7bd47fc0..80cefa1f 100644 --- a/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/TestType.java +++ b/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/TestType.java @@ -21,6 +21,7 @@ import com.fasterxml.classmate.members.ResolvedField; import com.fasterxml.classmate.members.ResolvedMethod; import com.github.victools.jsonschema.generator.FieldScope; +import com.github.victools.jsonschema.generator.MemberScope; import com.github.victools.jsonschema.generator.MethodScope; import com.github.victools.jsonschema.generator.TypeContext; import com.github.victools.jsonschema.generator.impl.TypeContextFactory; @@ -32,44 +33,43 @@ public class TestType { private final TypeContext context; - private final ResolvedType resolvedTestClass; - private final ResolvedTypeWithMembers testClassMembers; + private final MemberScope.DeclarationDetails declarationDetails; public TestType(Class testClass) { this.context = TypeContextFactory.createDefaultTypeContext(); - this.resolvedTestClass = this.context.resolve(testClass); - this.testClassMembers = this.context.resolveWithMembers(this.resolvedTestClass); + ResolvedType resolvedTestClass = this.context.resolve(testClass); + this.declarationDetails = new MemberScope.DeclarationDetails(resolvedTestClass, this.context.resolveWithMembers(resolvedTestClass)); } public FieldScope getMemberField(String fieldName) { - return this.getField(this.testClassMembers.getMemberFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getMemberFields(), fieldName); } public FieldScope getStaticField(String fieldName) { - return this.getField(this.testClassMembers.getStaticFields(), fieldName); + return this.getField(this.declarationDetails.getDeclaringTypeMembers().getStaticFields(), fieldName); } private FieldScope getField(ResolvedField[] fields, String fieldName) { return Stream.of(fields) .filter(field -> fieldName.equals(field.getName())) .findAny() - .map(field -> this.context.createFieldScope(field, this.testClassMembers)) + .map(field -> this.context.createFieldScope(field, this.declarationDetails)) .get(); } public MethodScope getMemberMethod(String methodName) { - return this.getMethod(this.testClassMembers.getMemberMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getMemberMethods(), methodName); } public MethodScope getStaticMethod(String methodName) { - return this.getMethod(this.testClassMembers.getStaticMethods(), methodName); + return this.getMethod(this.declarationDetails.getDeclaringTypeMembers().getStaticMethods(), methodName); } private MethodScope getMethod(ResolvedMethod[] methods, String methodName) { return Stream.of(methods) .filter(method -> methodName.equals(method.getName())) .findAny() - .map(method -> this.context.createMethodScope(method, this.testClassMembers)) + .map(method -> this.context.createMethodScope(method, this.declarationDetails)) .get(); } }