Skip to content

Commit

Permalink
Merge pull request #41 from SasinduDilshara/fix_7008
Browse files Browse the repository at this point in the history
Handle recursive types in the `data.jsondata` compiler plugin
  • Loading branch information
SasinduDilshara authored Sep 23, 2024
2 parents 4a8ec18 + 7b928b0 commit b55778b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ public void testDuplicateField1() {
List<Diagnostic> errorDiagnosticsList = diagnosticResult.diagnostics().stream()
.filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR))
.collect(Collectors.toList());
Assert.assertEquals(errorDiagnosticsList.size(), 1);
Assert.assertEquals(errorDiagnosticsList.size(), 2);
Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(),
"invalid field: duplicate field found");
Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(),
"invalid field: duplicate field found");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,14 @@ type Data record {
string A;
string B;
};

type Data2 record {
@jsondata:Name {
value: "C"
}
string A;
@jsondata:Name {
value: "C"
}
string B;
};
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -155,22 +156,31 @@ private void processFunctionDefinitionNode(FunctionDefinitionNode functionDefini
}

private void checkTypeAndDetectDuplicateFields(TypeSymbol typeSymbol, SyntaxNodeAnalysisContext ctx) {
checkTypeAndDetectDuplicateFields(typeSymbol, ctx, new HashSet<>());
}

private void checkTypeAndDetectDuplicateFields(TypeSymbol typeSymbol,
SyntaxNodeAnalysisContext ctx, HashSet<TypeSymbol> visited) {
if (!visited.add(typeSymbol)) {
return;
}
switch (typeSymbol.typeKind()) {
case RECORD -> detectDuplicateFields((RecordTypeSymbol) typeSymbol, ctx);
case ARRAY -> checkTypeAndDetectDuplicateFields(((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(), ctx);
case ARRAY -> checkTypeAndDetectDuplicateFields(((ArrayTypeSymbol) typeSymbol)
.memberTypeDescriptor(), ctx, visited);
case TUPLE -> {
for (TypeSymbol memberType : ((TupleTypeSymbol) typeSymbol).memberTypeDescriptors()) {
checkTypeAndDetectDuplicateFields(memberType, ctx);
checkTypeAndDetectDuplicateFields(memberType, ctx, visited);
}
}
case UNION -> {
for (TypeSymbol memberType : ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors()) {
checkTypeAndDetectDuplicateFields(memberType, ctx);
checkTypeAndDetectDuplicateFields(memberType, ctx, visited);
}
}
case TYPE_REFERENCE -> checkTypeAndDetectDuplicateFields(
((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor(), ctx);
case INTERSECTION -> checkTypeAndDetectDuplicateFields(getRawType(typeSymbol), ctx);
((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor(), ctx, visited);
case INTERSECTION -> checkTypeAndDetectDuplicateFields(getRawType(typeSymbol), ctx, visited);
}
}

Expand All @@ -196,32 +206,43 @@ private boolean isParseFunctionOfStringSource(ExpressionNode expressionNode) {
}

private void validateExpectedType(TypeSymbol typeSymbol, SyntaxNodeAnalysisContext ctx) {
validateExpectedType(typeSymbol, ctx, new HashSet<>());
}

private void validateExpectedType(TypeSymbol typeSymbol,
SyntaxNodeAnalysisContext ctx, HashSet<TypeSymbol> visited) {
if (!visited.add(typeSymbol)) {
return;
}
typeSymbol.getLocation().ifPresent(location -> currentLocation = location);
switch (typeSymbol.typeKind()) {
case UNION -> validateUnionType((UnionTypeSymbol) typeSymbol, typeSymbol.getLocation(), ctx);
case RECORD -> validateRecordType((RecordTypeSymbol) typeSymbol, ctx);
case ARRAY -> validateExpectedType(((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(), ctx);
case TUPLE -> validateTupleType((TupleTypeSymbol) typeSymbol, ctx);
case RECORD -> validateRecordType((RecordTypeSymbol) typeSymbol, ctx, visited);
case ARRAY -> validateExpectedType(((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(), ctx, visited);
case TUPLE -> validateTupleType((TupleTypeSymbol) typeSymbol, ctx, visited);
case TABLE, XML -> reportDiagnosticInfo(ctx, typeSymbol.getLocation(),
JsondataDiagnosticCodes.UNSUPPORTED_TYPE);
case TYPE_REFERENCE -> validateExpectedType(((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor(), ctx);
case INTERSECTION -> validateExpectedType(getRawType(typeSymbol), ctx);
case TYPE_REFERENCE -> validateExpectedType(((TypeReferenceTypeSymbol) typeSymbol)
.typeDescriptor(), ctx, visited);
case INTERSECTION -> validateExpectedType(getRawType(typeSymbol), ctx, visited);
}
}

private void validateTupleType(TupleTypeSymbol tupleTypeSymbol, SyntaxNodeAnalysisContext ctx) {
private void validateTupleType(TupleTypeSymbol tupleTypeSymbol,
SyntaxNodeAnalysisContext ctx, HashSet<TypeSymbol> visited) {
for (TypeSymbol memberType : tupleTypeSymbol.memberTypeDescriptors()) {
validateExpectedType(memberType, ctx);
validateExpectedType(memberType, ctx, visited);
}
}

private void validateRecordType(RecordTypeSymbol recordTypeSymbol, SyntaxNodeAnalysisContext ctx) {
private void validateRecordType(RecordTypeSymbol recordTypeSymbol,
SyntaxNodeAnalysisContext ctx, HashSet<TypeSymbol> visited) {
detectDuplicateFields(recordTypeSymbol, ctx);

for (Map.Entry<String, RecordFieldSymbol> entry : recordTypeSymbol.fieldDescriptors().entrySet()) {
RecordFieldSymbol fieldSymbol = entry.getValue();
currentLocation = fieldSymbol.getLocation().orElseGet(() -> currentLocation);
validateExpectedType(fieldSymbol.typeDescriptor(), ctx);
validateExpectedType(fieldSymbol.typeDescriptor(), ctx, visited);
}
}

Expand Down
1 change: 1 addition & 0 deletions native/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
requires junit;
requires org.apache.commons.lang3;
exports io.ballerina.lib.data.jsondata.json;
exports io.ballerina.lib.data;
}

0 comments on commit b55778b

Please sign in to comment.