Skip to content

Commit d985039

Browse files
committed
#16 - add CalculateDifference method to ObjectType and integrate with SemanticChecker; update unit tests to include CalculateDifference and refactor IsSubsetOf tests
1 parent 6ed6301 commit d985039

File tree

6 files changed

+298
-182
lines changed

6 files changed

+298
-182
lines changed

src/Application/HydraScript.Application.StaticAnalysis/Visitors/SemanticChecker.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ public ObjectType Visit(WithExpression visitable)
415415
left: supersetObjectType,
416416
right: subsetObjectType);
417417

418+
visitable.ComputedCopiedProperties = supersetObjectType.CalculateDifference(subsetObjectType);
419+
418420
return supersetObjectType;
419421
}
420422

src/Domain/HydraScript.Domain.FrontEnd/Parser/Impl/Ast/Nodes/Expressions/WithExpression.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ public partial class WithExpression : Expression
1010
public Expression Expression { get; }
1111
public ObjectLiteral ObjectLiteral { get; }
1212

13+
public IReadOnlyList<string> ComputedCopiedProperties { get; set; } = [];
14+
1315
public WithExpression(Expression expression, ObjectLiteral objectLiteral)
1416
{
1517
Expression = expression;

src/Domain/HydraScript.Domain.IR/Types/ObjectType.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ public bool IsSubsetOf(ObjectType that)
4646
return true;
4747
}
4848

49+
public IReadOnlyList<string> CalculateDifference(ObjectType that)
50+
{
51+
return _properties.Keys
52+
.Where(key => !that._properties.ContainsKey(key))
53+
.ToList();
54+
}
55+
4956
public override void ResolveReference(
5057
Type reference,
5158
string refId,
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
using HydraScript.Domain.IR.Types;
2+
3+
namespace HydraScript.UnitTests.Domain.IR;
4+
5+
public sealed class CalculateDifferenceData :
6+
TheoryData<ObjectType, ObjectType, IReadOnlyList<string>>
7+
{
8+
public CalculateDifferenceData()
9+
{
10+
Type number = "number";
11+
Type stringType = "string";
12+
13+
// Current has extra properties
14+
Add(
15+
new ObjectType(new Dictionary<string, Type>
16+
{
17+
["x"] = number,
18+
["y"] = number,
19+
["z"] = number
20+
}),
21+
new ObjectType(new Dictionary<string, Type>
22+
{
23+
["x"] = number,
24+
["y"] = number
25+
}),
26+
new List<string> { "z" }
27+
);
28+
29+
// Same properties
30+
Add(
31+
new ObjectType(new Dictionary<string, Type>
32+
{
33+
["x"] = number,
34+
["y"] = number
35+
}),
36+
new ObjectType(new Dictionary<string, Type>
37+
{
38+
["x"] = number,
39+
["y"] = number
40+
}),
41+
new List<string>()
42+
);
43+
44+
// Current is subset
45+
Add(
46+
new ObjectType(new Dictionary<string, Type>
47+
{
48+
["x"] = number,
49+
["y"] = number
50+
}),
51+
new ObjectType(new Dictionary<string, Type>
52+
{
53+
["x"] = number,
54+
["y"] = number,
55+
["z"] = number
56+
}),
57+
new List<string>()
58+
);
59+
60+
// That is empty
61+
Add(
62+
new ObjectType(new Dictionary<string, Type>
63+
{
64+
["x"] = number,
65+
["y"] = number,
66+
["z"] = number
67+
}),
68+
new ObjectType(new Dictionary<string, Type>()),
69+
new List<string> { "x", "y", "z" }
70+
);
71+
72+
// Current is empty
73+
Add(
74+
new ObjectType(new Dictionary<string, Type>()),
75+
new ObjectType(new Dictionary<string, Type>
76+
{
77+
["x"] = number,
78+
["y"] = number
79+
}),
80+
new List<string>()
81+
);
82+
83+
// Multiple different properties
84+
Add(
85+
new ObjectType(new Dictionary<string, Type>
86+
{
87+
["a"] = number,
88+
["b"] = stringType,
89+
["x"] = number,
90+
["y"] = number,
91+
["z"] = stringType
92+
}),
93+
new ObjectType(new Dictionary<string, Type>
94+
{
95+
["x"] = number,
96+
["y"] = number
97+
}),
98+
new List<string> { "a", "b", "z" }
99+
);
100+
101+
// Completely different properties
102+
Add(
103+
new ObjectType(new Dictionary<string, Type>
104+
{
105+
["a"] = number,
106+
["b"] = number
107+
}),
108+
new ObjectType(new Dictionary<string, Type>
109+
{
110+
["x"] = number,
111+
["y"] = number
112+
}),
113+
new List<string> { "a", "b" }
114+
);
115+
116+
// Same object reference
117+
var objectType = new ObjectType(new Dictionary<string, Type>
118+
{
119+
["x"] = number,
120+
["y"] = number
121+
});
122+
Add(
123+
objectType,
124+
objectType,
125+
new List<string>()
126+
);
127+
}
128+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
using HydraScript.Domain.IR.Types;
2+
3+
namespace HydraScript.UnitTests.Domain.IR;
4+
5+
public sealed class IsSubsetOfData : TheoryData<ObjectType, ObjectType, bool>
6+
{
7+
public IsSubsetOfData()
8+
{
9+
Type number = "number";
10+
Type stringType = "string";
11+
12+
// Subset has fewer properties
13+
Add(
14+
new ObjectType(new Dictionary<string, Type>
15+
{
16+
["x"] = number,
17+
["y"] = number,
18+
["z"] = number
19+
}),
20+
new ObjectType(new Dictionary<string, Type>
21+
{
22+
["x"] = number,
23+
["y"] = number
24+
}),
25+
true
26+
);
27+
28+
// Subset has same properties
29+
Add(
30+
new ObjectType(new Dictionary<string, Type>
31+
{
32+
["x"] = number,
33+
["y"] = number
34+
}),
35+
new ObjectType(new Dictionary<string, Type>
36+
{
37+
["x"] = number,
38+
["y"] = number
39+
}),
40+
true
41+
);
42+
43+
// Subset has extra properties
44+
Add(
45+
new ObjectType(new Dictionary<string, Type>
46+
{
47+
["x"] = number,
48+
["y"] = number
49+
}),
50+
new ObjectType(new Dictionary<string, Type>
51+
{
52+
["x"] = number,
53+
["y"] = number,
54+
["z"] = number
55+
}),
56+
false
57+
);
58+
59+
// Property types mismatch
60+
Add(
61+
new ObjectType(new Dictionary<string, Type>
62+
{
63+
["x"] = number,
64+
["y"] = number
65+
}),
66+
new ObjectType(new Dictionary<string, Type>
67+
{
68+
["x"] = number,
69+
["y"] = stringType
70+
}),
71+
false
72+
);
73+
74+
// Empty subset
75+
Add(
76+
new ObjectType(new Dictionary<string, Type>
77+
{
78+
["x"] = number,
79+
["y"] = number
80+
}),
81+
new ObjectType(new Dictionary<string, Type>()),
82+
true
83+
);
84+
85+
// Same object reference
86+
var objectType = new ObjectType(new Dictionary<string, Type>
87+
{
88+
["x"] = number,
89+
["y"] = number
90+
});
91+
Add(
92+
objectType,
93+
objectType,
94+
true
95+
);
96+
97+
// Complex nested types
98+
var nestedObject = new ObjectType(new Dictionary<string, Type>
99+
{
100+
["a"] = number,
101+
["b"] = number
102+
});
103+
var arrayType = new ArrayType(number);
104+
Add(
105+
new ObjectType(new Dictionary<string, Type>
106+
{
107+
["nested"] = nestedObject,
108+
["array"] = arrayType,
109+
["simple"] = number
110+
}),
111+
new ObjectType(new Dictionary<string, Type>
112+
{
113+
["nested"] = nestedObject,
114+
["array"] = arrayType
115+
}),
116+
true
117+
);
118+
119+
// Complex nested types mismatch
120+
var nestedObject1 = new ObjectType(new Dictionary<string, Type>
121+
{
122+
["a"] = number,
123+
["b"] = number
124+
});
125+
var nestedObject2 = new ObjectType(new Dictionary<string, Type>
126+
{
127+
["a"] = number,
128+
["c"] = number
129+
});
130+
Add(
131+
new ObjectType(new Dictionary<string, Type>
132+
{
133+
["nested"] = nestedObject1
134+
}),
135+
new ObjectType(new Dictionary<string, Type>
136+
{
137+
["nested"] = nestedObject2
138+
}),
139+
false
140+
);
141+
}
142+
}

0 commit comments

Comments
 (0)