From d3ba651656e57028647245d6c398007efe6d5a20 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 21 Aug 2024 16:42:26 +0530 Subject: [PATCH] Add support for union types and disable compiler tests --- .github/CODEOWNERS | 2 +- .../xmldata/compiler/CompilerPluginTest.java | 168 +++++------------- .../compiler/XmldataRecordFieldValidator.java | 54 +++--- .../xmldata/utils/DiagnosticErrorCode.java | 4 +- .../lib/data/xmldata/xml/XmlParser.java | 2 +- .../lib/data/xmldata/xml/XmlTraversal.java | 84 +++++++-- native/src/main/resources/error.properties | 6 + 7 files changed, 157 insertions(+), 163 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c5ebbcf..8d17e9c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ # See: https://help.github.com/articles/about-codeowners/ # These owners will be the default owners for everything in the repo. -* @hasithaa @prakanth97 +* @hasithaa @prakanth97 @SasinduDilshara diff --git a/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java b/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java index 81c1040..e4c0aca 100644 --- a/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java +++ b/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java @@ -55,78 +55,6 @@ public void testDuplicateFieldNegative2() { "invalid field: duplicate field found"); } - @Test - public void testUnsupportedUnionTypeNegative1() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_3").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 2); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - - @Test - public void testUnsupportedUnionTypeNegative2() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_4").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 2); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - - @Test - public void testUnsupportedTypeNegative1() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_5").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 4); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - - @Test - public void testUnsupportedTypeNegative2() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_7").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 8); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(6).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(7).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - @Test public void testChildRecordWithNameAnnotNegative() { DiagnosticResult diagnosticResult = @@ -157,27 +85,27 @@ public void testDuplicateFieldInInlineRecordsNegative() { "invalid field: duplicate field found"); } - @Test - public void testUnionTypeNegative() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_9").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 6); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - } +// @Test +// public void testUnionTypeNegative() { +// DiagnosticResult diagnosticResult = +// CompilerPluginTestUtils.loadPackage("sample_package_9").getCompilation().diagnosticResult(); +// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() +// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) +// .collect(Collectors.toList()); +// Assert.assertEquals(errorDiagnosticsList.size(), 6); +// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// } @Test public void testCompilerPluginWithAProjectWithSubModule() { @@ -198,31 +126,31 @@ public void testCompilerPluginWithAProjectWithSubModule() { "invalid annotation attachment: child record does not allow name annotation"); } - @Test - public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_11").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 1); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - } - - @Test - public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix2() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_12").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 3); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - } +// @Test +// public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix() { +// DiagnosticResult diagnosticResult = +// CompilerPluginTestUtils.loadPackage("sample_package_11").getCompilation().diagnosticResult(); +// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() +// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) +// .collect(Collectors.toList()); +// Assert.assertEquals(errorDiagnosticsList.size(), 1); +// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// } + +// @Test +// public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix2() { +// DiagnosticResult diagnosticResult = +// CompilerPluginTestUtils.loadPackage("sample_package_12").getCompilation().diagnosticResult(); +// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() +// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) +// .collect(Collectors.toList()); +// Assert.assertEquals(errorDiagnosticsList.size(), 3); +// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// } } diff --git a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java index 170ed26..07150eb 100644 --- a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java +++ b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java @@ -179,15 +179,17 @@ private void validateExpectedType(TypeSymbol typeSymbol, Optional loca case TYPE_REFERENCE -> validateExpectedType(((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor(), location, ctx); case UNION -> { - int nonErrorTypeCount = 0; + int recordCount = 0; for (TypeSymbol memberTSymbol : ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors()) { if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.ERROR) { continue; } - nonErrorTypeCount++; - validateExpectedType(memberTSymbol, location, ctx); + if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.RECORD) { + validateExpectedType(memberTSymbol, location, ctx); + recordCount++; + } } - if (nonErrorTypeCount > 1) { + if (recordCount == 0) { reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.EXPECTED_RECORD_TYPE); } } @@ -215,7 +217,7 @@ private boolean isNotValidExpectedType(TypeSymbol typeSymbol) { continue; } - if (isNotValidExpectedType(memberTSymbol)) { + if (!(getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.RECORD)) { return true; } } @@ -323,7 +325,7 @@ private void processRecordFieldsType(RecordTypeSymbol recordTypeSymbol, SyntaxNo private void validateRecordFieldType(TypeSymbol typeSymbol, Optional location, SyntaxNodeAnalysisContext ctx) { switch (typeSymbol.typeKind()) { - case UNION -> validateUnionType((UnionTypeSymbol) typeSymbol, location, ctx); +// case UNION -> validateUnionType((UnionTypeSymbol) typeSymbol, location, ctx); case NIL, TUPLE -> reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_TYPE); case ARRAY -> validateRecordFieldType(((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(), location, ctx); case TYPE_REFERENCE -> @@ -331,26 +333,26 @@ private void validateRecordFieldType(TypeSymbol typeSymbol, Optional l } } - private void validateUnionType(UnionTypeSymbol unionTypeSymbol, Optional location, - SyntaxNodeAnalysisContext ctx) { - int nonPrimitiveMemberCount = 0; - boolean isNilPresent = false; - List memberTypeSymbols = unionTypeSymbol.memberTypeDescriptors(); - for (TypeSymbol memberTypeSymbol : memberTypeSymbols) { - if (isPrimitiveType(memberTypeSymbol)) { - continue; - } - - if (memberTypeSymbol.typeKind() == TypeDescKind.NIL) { - isNilPresent = true; - } - nonPrimitiveMemberCount++; - } - - if (nonPrimitiveMemberCount > 1 || (memberTypeSymbols.size() > 1 && isNilPresent)) { - reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_UNION_TYPE); - } - } +// private void validateUnionType(UnionTypeSymbol unionTypeSymbol, Optional location, +// SyntaxNodeAnalysisContext ctx) { +// int nonPrimitiveMemberCount = 0; +// boolean isNilPresent = false; +// List memberTypeSymbols = unionTypeSymbol.memberTypeDescriptors(); +// for (TypeSymbol memberTypeSymbol : memberTypeSymbols) { +// if (isPrimitiveType(memberTypeSymbol)) { +// continue; +// } +// +// if (memberTypeSymbol.typeKind() == TypeDescKind.NIL) { +// isNilPresent = true; +// } +// nonPrimitiveMemberCount++; +// } +// +// if (nonPrimitiveMemberCount > 1 || (memberTypeSymbols.size() > 1 && isNilPresent)) { +// reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_UNION_TYPE); +// } +// } private boolean isPrimitiveType(TypeSymbol typeSymbol) { TypeDescKind kind = typeSymbol.typeKind(); diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java index 0d90190..7f09304 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java @@ -41,7 +41,9 @@ public enum DiagnosticErrorCode { UNSUPPORTED_TYPE("XML_ERROR_014", "unsupported.type"), STREAM_BROKEN("XML_ERROR_015", "stream.broken"), XML_PARSE_ERROR("XML_ERROR_016", "xml.parse.error"), - UNDEFINED_FIELD("XML_ERROR_0017", "undefined.field"); + UNDEFINED_FIELD("XML_ERROR_0017", "undefined.field"), + CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE("XML_ERROR_0018", "cannot.convert.source.into.expected.type"), + FIELD_CANNOT_CAST_INTO_TYPE("XML_ERROR_0019", "field.cannot.convert.into.type"); String diagnosticId; String messageKey; diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java index 98a5a72..ddbffcf 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java @@ -113,7 +113,7 @@ public static Object parse(Reader reader, BMap options, Type ty } catch (BError e) { return e; } catch (Throwable e) { - return DiagnosticLog.error(DiagnosticErrorCode.XML_PARSE_ERROR, e.getMessage()); + throw DiagnosticLog.error(DiagnosticErrorCode.XML_PARSE_ERROR, e.getMessage()); } } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index 21a0f0e..cda93cd 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -33,6 +33,7 @@ import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.types.XmlNodeType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; @@ -83,30 +84,60 @@ static class XmlTree { private Object currentNode; public Object traverseXml(BXml xml, BMap options, Type type) { + XmlAnalyzerData analyzerData = new XmlAnalyzerData(); + DataUtils.updateOptions(options, analyzerData); + return traverseXml(xml, analyzerData, type); + } + + public Object traverseXml(BXml xml, XmlAnalyzerData analyzerData, Type type) { Type referredType = TypeUtils.getReferredType(type); switch (referredType.getTag()) { case TypeTags.RECORD_TYPE_TAG -> { - XmlAnalyzerData analyzerData = new XmlAnalyzerData(); - DataUtils.updateOptions(options, analyzerData); - RecordType recordType = (RecordType) referredType; - currentNode = ValueCreator.createRecordValue(recordType.getPackage(), recordType.getName()); - BXml nextXml = validateRootElement(xml, recordType, analyzerData); - Object resultRecordValue = traverseXml(nextXml, recordType, analyzerData); - DataUtils.validateRequiredFields(analyzerData); - return resultRecordValue; + return traverseXmlWithRecordAsExpectedType(xml, analyzerData, referredType); } case TypeTags.MAP_TAG -> { - MapType mapType = (MapType) referredType; - RecordType anonRecType = TypeCreator.createRecordType(Constants.ANON_TYPE, mapType.getPackage(), 0, - new HashMap<>(), mapType.getConstrainedType(), false, 0); - return traverseXml(xml, options, anonRecType); + return traverseXmlWithMapAsExpectedType(xml, referredType, analyzerData); + } + case TypeTags.UNION_TAG -> { + return traverseXmlToUnion(xml, analyzerData, type); } default -> { - return DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, - type.getName()); + throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, type); } } } + + private Object traverseXmlWithRecordAsExpectedType(BXml xml, + XmlAnalyzerData analyzerData, Type referredType) { + RecordType recordType = (RecordType) referredType; + currentNode = ValueCreator.createRecordValue(recordType.getPackage(), recordType.getName()); + BXml nextXml = validateRootElement(xml, recordType, analyzerData); + Object resultRecordValue = traverseXml(nextXml, recordType, analyzerData); + DataUtils.validateRequiredFields(analyzerData); + return resultRecordValue; + } + + private Object traverseXmlWithMapAsExpectedType(BXml xml, Type referredType, XmlAnalyzerData analyzerData) { + MapType mapType = (MapType) referredType; + RecordType anonRecType = TypeCreator.createRecordType(Constants.ANON_TYPE, mapType.getPackage(), 0, + new HashMap<>(), mapType.getConstrainedType(), false, 0); + return traverseXml(xml, analyzerData, anonRecType); + } + + private Object traverseXmlToUnion(BXml xml, XmlAnalyzerData options, Type type) { + UnionType unionType = (UnionType) type; + for (Type memberType: unionType.getMemberTypes()) { + try { + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + return traverseXml(xml, options, memberType); + } catch (Exception ex) { + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE, type); + } private Object traverseXml(BXml xml, Type type, XmlAnalyzerData analyzerData) { switch (xml.getNodeType()) { @@ -235,10 +266,16 @@ private void convertToFieldType(BXmlItem xmlItem, Field currentField, String fie case TypeTags.TYPE_REFERENCED_TYPE_TAG -> convertToFieldType(xmlItem, currentField, fieldName, TypeUtils.getReferredType(currentFieldType), mapValue, analyzerData); + case TypeTags.UNION_TAG -> traverseXml(xmlItem, analyzerData, currentFieldType); default -> traverseXml(xmlItem.getChildrenSeq(), currentFieldType, analyzerData); } } + private void convertFieldTypeToUnionType(BXmlItem xmlItem, Field currentField, String fieldName, + Type currentFieldType, BMap mapValue, XmlAnalyzerData analyzerData) { + + } + private void convertToArrayType(BXmlItem xmlItem, Field field, BMap mapValue, BString bCurrentFieldName, ArrayType arrayType, XmlAnalyzerData analyzerData) { Object temp = mapValue.get(bCurrentFieldName); @@ -276,10 +313,28 @@ private void convertToArrayMemberType(BXmlItem xmlItem, String fieldName, ArrayT case TypeTags.TYPE_REFERENCED_TYPE_TAG -> convertToArrayMemberType(xmlItem, fieldName, fieldType, TypeUtils.getReferredType(elementType), mapValue, analyzerData); + case TypeTags.UNION_TAG -> convertToUnionMemberType(xmlItem, fieldName, fieldType, + elementType, mapValue, analyzerData); default -> traverseXml(xmlItem.getChildrenSeq(), fieldType, analyzerData); } } + private void convertToUnionMemberType(BXmlItem xmlItem, String fieldName, ArrayType fieldType, + Type elementType, BMap mapValue, XmlAnalyzerData analyzerData) { + for (Type memberType: ((UnionType) elementType).getMemberTypes()) { + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + try { + convertToArrayMemberType(xmlItem, fieldName, fieldType, memberType, mapValue, analyzerData); + return; + } catch (Exception ex) { + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldName, fieldType); + } + private void convertToRecordType(BXmlItem xmlItem, Type currentFieldType, String fieldName, RecordType elementType, BMap mapValue, XmlAnalyzerData analyzerData) { @@ -386,6 +441,7 @@ private void checkRestTypeAndConvert(BXmlItem xmlItem, String elemName, Type res checkRestTypeAndConvert(xmlItem, elemName, restType, ((ArrayType) restType).getElementType(), mapValue, analyzerData); } + case TypeTags.UNION_TAG -> traverseXml(xmlItem, analyzerData, elementType); default -> { BString bElementName = StringUtils.fromString(elemName); if (mapValue.containsKey(bElementName) && mapValue.get(bElementName) != null) { diff --git a/native/src/main/resources/error.properties b/native/src/main/resources/error.properties index bcb5cf9..1c4fe88 100644 --- a/native/src/main/resources/error.properties +++ b/native/src/main/resources/error.properties @@ -70,3 +70,9 @@ error.xml.parse.error=\ error.undefined.field=\ undefined field ''{0}'' in record ''{1}'' + +error.cannot.convert.source.into.expected.type=\ + source value cannot convert into ''{0}'' + +field.cannot.convert.into.type=\ + field ''{0}'' cannot convert into the type ''{1}''