Skip to content

Commit

Permalink
Fix cyclic reference detection
Browse files Browse the repository at this point in the history
  • Loading branch information
TharmiganK committed Feb 20, 2025
1 parent ec4c33b commit 6b548e1
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,12 @@
import java.util.Optional;
import java.util.Set;

import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getConstantValues;
import static io.ballerina.openapi.service.mapper.Constants.JSON_DATA;
import static io.ballerina.openapi.service.mapper.Constants.NAME_CONFIG;
import static io.ballerina.openapi.service.mapper.Constants.VALUE;
import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getConstantValues;
import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getNameFromAnnotation;
import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getRecordFieldTypeDescription;
import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getTypeName;

/**
* This {@link RecordTypeMapper} class represents the record type mapper.
Expand Down Expand Up @@ -121,20 +120,7 @@ static List<Schema> mapIncludedRecords(RecordTypeSymbol typeSymbol, Components c
// Type inclusion in a record is a TypeReferenceType and the referred type is a RecordType
if (typeInclusion.typeKind() == TypeDescKind.TYPE_REFERENCE &&
((TypeReferenceTypeSymbol) typeInclusion).typeDescriptor().typeKind() == TypeDescKind.RECORD) {
Schema includedRecordSchema;
if (additionalData.enableExpansion()) {
if (additionalData.visitedTypes().contains(MapperCommonUtils.getTypeName(typeInclusion))) {
ExceptionDiagnostic error = new ExceptionDiagnostic(DiagnosticMessages.OAS_CONVERTOR_140);
additionalData.diagnostics().add(error);
continue;
}
includedRecordSchema = TypeMapperImpl.getTypeSchema(typeInclusion, components, additionalData);
} else {
includedRecordSchema = new Schema();
includedRecordSchema.set$ref(getTypeName(typeInclusion));
TypeMapperImpl.createComponentMapping((TypeReferenceTypeSymbol) typeInclusion,
components, additionalData);
}
Schema includedRecordSchema = TypeMapperImpl.getTypeSchema(typeInclusion, components, additionalData);
allOfSchemaList.add(includedRecordSchema);

RecordTypeSymbol includedRecordTypeSymbol = (RecordTypeSymbol) ((TypeReferenceTypeSymbol) typeInclusion)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import io.ballerina.compiler.api.symbols.TypeDescKind;
import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol;
import io.ballerina.compiler.api.symbols.TypeSymbol;
import io.ballerina.openapi.service.mapper.diagnostic.DiagnosticMessages;
import io.ballerina.openapi.service.mapper.diagnostic.ExceptionDiagnostic;
import io.ballerina.openapi.service.mapper.model.AdditionalData;
import io.ballerina.openapi.service.mapper.utils.MapperCommonUtils;
import io.swagger.v3.oas.models.Components;
Expand Down Expand Up @@ -60,15 +58,6 @@ public static Schema getSchema(TypeReferenceTypeSymbol typeSymbol, Components co
if (isBuiltInSubTypes(typeSymbol)) {
return SimpleTypeMapper.getTypeSchema(typeSymbol.typeDescriptor(), additionalData);
}
if (additionalData.enableExpansion()) {
if (additionalData.visitedTypes().contains(MapperCommonUtils.getTypeName(typeSymbol))) {
ExceptionDiagnostic error = new ExceptionDiagnostic(DiagnosticMessages.OAS_CONVERTOR_140);
additionalData.diagnostics().add(error);
return null;
}
additionalData.visitedTypes().add(MapperCommonUtils.getTypeName(typeSymbol));
return TypeMapperImpl.getTypeSchema(getReferredType(typeSymbol), components, additionalData);
}
if (!AbstractTypeMapper.hasMapping(components, typeSymbol)) {
createComponentMapping(typeSymbol, components, additionalData);
if (!AbstractTypeMapper.hasFullMapping(components, typeSymbol)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@
import io.ballerina.compiler.api.symbols.RecordTypeSymbol;
import io.ballerina.compiler.api.symbols.TableTypeSymbol;
import io.ballerina.compiler.api.symbols.TupleTypeSymbol;
import io.ballerina.compiler.api.symbols.TypeDescKind;
import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol;
import io.ballerina.compiler.api.symbols.TypeSymbol;
import io.ballerina.compiler.api.symbols.UnionTypeSymbol;
import io.ballerina.openapi.service.mapper.diagnostic.DiagnosticMessages;
import io.ballerina.openapi.service.mapper.diagnostic.ExceptionDiagnostic;
import io.ballerina.openapi.service.mapper.model.AdditionalData;
import io.ballerina.openapi.service.mapper.model.ModuleMemberVisitor;
import io.ballerina.openapi.service.mapper.type.extension.BallerinaTypeExtensioner;
import io.ballerina.openapi.service.mapper.utils.MapperCommonUtils;
import io.ballerina.projects.Project;
import io.ballerina.projects.plugins.SyntaxNodeAnalysisContext;
import io.swagger.v3.core.util.Json;
Expand Down Expand Up @@ -88,7 +92,6 @@ public String getJsonSchemaString(TypeSymbol typeSymbol, boolean enableExpansion
if (!isAnydata(typeSymbol)) {
throw new UnsupportedOperationException("Only 'anydata' type is supported for JSON schema generation.");
}
typeSymbol = getReferredType(typeSymbol);
Components components = new Components().schemas(new HashMap<>());
AdditionalData componentMapperData = cloneComponentMapperData(enableExpansion);
Schema schema = getTypeSchema(typeSymbol, components, componentMapperData);
Expand Down Expand Up @@ -150,13 +153,23 @@ public static Schema getTypeSchema(TypeSymbol typeSymbol, Components components,

public static Schema getTypeSchema(TypeSymbol typeSymbol, Components components, AdditionalData componentMapperData,
boolean skipNilType) {
String typeName = typeSymbol.typeKind().equals(TypeDescKind.TYPE_REFERENCE) ?
MapperCommonUtils.getTypeName(typeSymbol) : "";
if (componentMapperData.enableExpansion()) {
if (componentMapperData.visitedTypes().contains(MapperCommonUtils.getTypeName(typeSymbol))) {
ExceptionDiagnostic error = new ExceptionDiagnostic(DiagnosticMessages.OAS_CONVERTOR_140);
componentMapperData.diagnostics().add(error);
return null;
}
if (!typeName.isEmpty()) {
componentMapperData.visitedTypes().add(typeName);
}
TypeSymbol referredType = ReferenceTypeMapper.getReferredType(typeSymbol);
if (Objects.nonNull(referredType)) {
typeSymbol = referredType;
}
}
return switch (typeSymbol.typeKind()) {
Schema schema = switch (typeSymbol.typeKind()) {
case MAP -> MapTypeMapper.getSchema((MapTypeSymbol) typeSymbol, components, componentMapperData);
case ARRAY ->
ArrayTypeMapper.getSchema((ArrayTypeSymbol) typeSymbol, components, componentMapperData);
Expand All @@ -177,6 +190,10 @@ public static Schema getTypeSchema(TypeSymbol typeSymbol, Components components,
ErrorTypeMapper.getSchema((ErrorTypeSymbol) typeSymbol, components, componentMapperData);
default -> SimpleTypeMapper.getTypeSchema(typeSymbol, componentMapperData);
};
if (componentMapperData.enableExpansion() && !typeName.isEmpty()) {
componentMapperData.visitedTypes().remove(typeName);
}
return schema;
}

protected static void createComponentMapping(TypeReferenceTypeSymbol typeSymbol, Components components,
Expand Down

0 comments on commit 6b548e1

Please sign in to comment.