Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle recursive types in the data.jsondata compiler plugin #41

Merged
merged 4 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
SasinduDilshara marked this conversation as resolved.
Show resolved Hide resolved
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;
}
Loading