Skip to content

Commit

Permalink
Limit casting to only basic types
Browse files Browse the repository at this point in the history
  • Loading branch information
heshanpadmasiri committed Jan 3, 2024
1 parent 44a5634 commit 3ae8778
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2468,7 +2468,7 @@ private void createSimpleVarDefStmt(BLangSimpleVariable simpleVariable, BLangBlo

@Override
public void visit(BLangAssignment assignNode) {
boolean isOptionalFieldAssignment = isOptionalFieldAssignment(assignNode);
boolean isOptionalFieldAssignment = isOptionalBasicTypeFieldAssignment(assignNode);
assignNode.varRef = rewriteExpr(assignNode.varRef);
assignNode.expr = rewriteExpr(assignNode.expr);
BType castingType = assignNode.varRef.getBType();
Expand All @@ -2479,7 +2479,7 @@ public void visit(BLangAssignment assignNode) {
result = assignNode;
}

private boolean isOptionalFieldAssignment(BLangAssignment assignNode) {
private boolean isOptionalBasicTypeFieldAssignment(BLangAssignment assignNode) {
if (assignNode.varRef.getKind() != NodeKind.FIELD_BASED_ACCESS_EXPR) {
return false;
}
Expand All @@ -2490,10 +2490,14 @@ private boolean isOptionalFieldAssignment(BLangAssignment assignNode) {
}
BRecordType recordType = (BRecordType) targetType;
BField field = recordType.fields.get(fieldAccessNode.field.value);
if (field == null) {
if (field == null || (field.symbol.flags & Flags.OPTIONAL) != Flags.OPTIONAL) {
return false;
}
return (field.symbol.flags & Flags.OPTIONAL) == Flags.OPTIONAL;
BType fieldType = field.getType();
return switch (fieldType.getKind()) {
case BOOLEAN, FLOAT, STRING, DECIMAL -> true;
default -> TypeTags.isIntegerTypeTag(fieldType.tag);
};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,21 @@ public void testOptionalFieldAccessOnMethodCall() {
BRunUtil.invoke(result, "testOptionalFieldAccessOnMethodCall");
}

@Test(dataProvider = "optionalFieldRemovalFunctions")
public void testOptionalFieldRemoval(String function) {
Object returns = BRunUtil.invoke(result, function);
Assert.assertFalse((Boolean) returns);
}

@DataProvider(name = "optionalFieldRemovalFunctions")
public Object[][] optionalFieldRemovalFunctions() {
return new Object[][]{
{"testOptionalFieldRemovalBasicType"},
{"testOptionalFieldRemovalIndirect"},
{"testOptionalFieldRemovalComplex"}
};
}

@Test
public void testNestedOptionalFieldAccessOnIntersectionTypes() {
BRunUtil.invoke(result, "testNestedOptionalFieldAccessOnIntersectionTypes");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,54 @@ type Bar record {
decimal c;
};

type R1 record {
int a?;
float b?;
string c?;
boolean d?;
decimal e?;
};

type R2 record {
int a;
R1 r1?;
};

function testOptionalFieldAccessOnRequiredRecordField() returns boolean {
string s = "Anne";
Employee e = { name: s, id: 100 };
string name = e?.name;
return name == s;
}

function testOptionalFieldRemovalBasicType() returns boolean {
R1 r = { a: 1, b: 2.0, c: "test", d: true, e: 3.0 };
r.a = ();
r.b = ();
r.c = ();
r.d = ();
r.e = ();
return r.hasKey("a") || r.hasKey("b") || r.hasKey("c") || r.hasKey("d") || r.hasKey("e");
}

function testOptionalFieldRemovalIndirect() returns boolean {
R2 r = { a: 1, r1: { a: 1, b: 2.0, c: "test" } };
r.r1.a = ();
r.r1.b = ();
r.r1.c = ();
R1? r1 = r.r1;
if r1 is () {
return true;
}
return r1.hasKey("a") || r1.hasKey("b") || r1.hasKey("c");
}

function testOptionalFieldRemovalComplex() returns boolean {
R2 r = { a: 1, r1: { a: 1, b: 2.0, c: "test" } };
r.r1 = ();
return r.hasKey("r1");
}

function testOptionalFieldAccessOnRequiredRecordFieldInRecordUnion() returns boolean {
Foo f = { a: 1, b: true };
Foo|Bar fb = f;
Expand Down

0 comments on commit 3ae8778

Please sign in to comment.