Skip to content

Commit bde4b5a

Browse files
Copilotxperiandri
andcommitted
Enforce input/output kind safety for ListOf/Nullable wrappers at compile time (#569)
Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Andrii Chebukin <XperiAndri@Outlook.com>
1 parent 239b68d commit bde4b5a

8 files changed

Lines changed: 75 additions & 51 deletions

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/ListOf.InputAsOutput.fsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let inputOnlyType =
9-
Define.InputObject<InputOnly> (name = "InputOnlyType", fields = [ Define.Input ("value", IntType) ])
9+
Define.InputObject<InputOnly>(
10+
name = "InputOnlyType",
11+
fields = [ Define.Input("value", IntType) ]
12+
)
1013

1114
// This should fail: InputDef cannot be assigned to OutputDef
1215
let _ : OutputDef<InputOnly list> = ListOf inputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/ListOf.OutputAsInput.fsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let outputOnlyType =
9-
Define.Object<OutputOnly> (name = "OutputOnlyType", fields = [ Define.Field ("value", IntType, fun _ x -> x.Value) ])
9+
Define.Object<OutputOnly>(
10+
name = "OutputOnlyType",
11+
fields = [ Define.Field("value", IntType, fun _ x -> x.Value) ]
12+
)
1013

1114
// This should fail: OutputDef cannot be assigned to InputDef
1215
let _ : InputDef<OutputOnly list> = ListOf outputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/Nullable.InputAsOutput.fsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let inputOnlyType =
9-
Define.InputObject<InputOnly> (name = "InputOnlyType", fields = [ Define.Input ("value", IntType) ])
9+
Define.InputObject<InputOnly>(
10+
name = "InputOnlyType",
11+
fields = [ Define.Input("value", IntType) ]
12+
)
1013

1114
// This should fail: InputDef cannot be assigned to OutputDef
1215
let _ : OutputDef<InputOnly option> = Nullable inputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/Nullable.OutputAsInput.fsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let outputOnlyType =
9-
Define.Object<OutputOnly> (name = "OutputOnlyType", fields = [ Define.Field ("value", IntType, fun _ x -> x.Value) ])
9+
Define.Object<OutputOnly>(
10+
name = "OutputOnlyType",
11+
fields = [ Define.Field("value", IntType, fun _ x -> x.Value) ]
12+
)
1013

1114
// This should fail: OutputDef cannot be assigned to InputDef
1215
let _ : InputDef<OutputOnly option> = Nullable outputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/StructNullable.InputAsOutput.fsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let inputOnlyType =
9-
Define.InputObject<InputOnly> (name = "InputOnlyType", fields = [ Define.Input ("value", IntType) ])
9+
Define.InputObject<InputOnly>(
10+
name = "InputOnlyType",
11+
fields = [ Define.Input("value", IntType) ]
12+
)
1013

1114
// This should fail: InputDef cannot be assigned to OutputDef
1215
let _ : OutputDef<InputOnly voption> = StructNullable inputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/StructNullable.OutputAsInput.fsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let outputOnlyType =
9-
Define.Object<OutputOnly> (name = "OutputOnlyType", fields = [ Define.Field ("value", IntType, fun _ x -> x.Value) ])
9+
Define.Object<OutputOnly>(
10+
name = "OutputOnlyType",
11+
fields = [ Define.Field("value", IntType, fun _ x -> x.Value) ]
12+
)
1013

1114
// This should fail: OutputDef cannot be assigned to InputDef
1215
let _ : InputDef<OutputOnly voption> = StructNullable outputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafety/Valid.fsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@ type InputOnly = { Value : int }
66
type OutputOnly = { Value : int }
77

88
let inputOnlyType =
9-
Define.InputObject<InputOnly> (name = "InputOnlyType", fields = [ Define.Input ("value", IntType) ])
9+
Define.InputObject<InputOnly>(
10+
name = "InputOnlyType",
11+
fields = [ Define.Input("value", IntType) ]
12+
)
1013

1114
let outputOnlyType =
12-
Define.Object<OutputOnly> (name = "OutputOnlyType", fields = [ Define.Field ("value", IntType, fun _ x -> x.Value) ])
15+
Define.Object<OutputOnly>(
16+
name = "OutputOnlyType",
17+
fields = [ Define.Field("value", IntType, fun _ x -> x.Value) ]
18+
)
1319

1420
// These are all valid assignments and must compile successfully
15-
let _inputList : InputDef<InputOnly list> = ListOf inputOnlyType
16-
let _outputList : OutputDef<OutputOnly list> = ListOf outputOnlyType
17-
let _inputNullable : InputDef<InputOnly option> = Nullable inputOnlyType
21+
let _inputList : InputDef<InputOnly list> = ListOf inputOnlyType
22+
let _outputList : OutputDef<OutputOnly list> = ListOf outputOnlyType
23+
let _inputNullable : InputDef<InputOnly option> = Nullable inputOnlyType
1824
let _outputNullable : OutputDef<OutputOnly option> = Nullable outputOnlyType
19-
let _inputStruct : InputDef<InputOnly voption> = StructNullable inputOnlyType
25+
let _inputStruct : InputDef<InputOnly voption> = StructNullable inputOnlyType
2026
let _outputStruct : OutputDef<OutputOnly voption> = StructNullable outputOnlyType

tests/FSharp.Data.GraphQL.Tests/TypeWrappersKindSafetyTests.fs

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ type TypeWrappersKindSafetyFixture () =
6262
interface IAsyncLifetime with
6363

6464
member this.InitializeAsync () : Task = task {
65-
IO.Directory.CreateDirectory (scriptsDir) |> ignore
66-
IO.Directory.CreateDirectory (sourceScriptsDir) |> ignore
65+
IO.Directory.CreateDirectory (scriptsDir) |> ignore
66+
IO.Directory.CreateDirectory (sourceScriptsDir) |> ignore
6767

68-
let content = this.ReferencesContent
68+
let content = this.ReferencesContent
6969

70-
do! ensureFileContentAsync referencesPath content
71-
do! ensureFileContentAsync sourceReferencesPath content
72-
}
70+
do! ensureFileContentAsync referencesPath content
71+
do! ensureFileContentAsync sourceReferencesPath content
72+
}
7373

7474
member _.DisposeAsync () = Task.CompletedTask
7575

@@ -78,63 +78,63 @@ type TypeWrappersKindSafetyTests (fixture : TypeWrappersKindSafetyFixture) =
7878

7979
[<Fact>]
8080
member _.``ListOf keeps input-output direction`` () : Task = task {
81-
let inputList : InputDef<InputOnly list> = ListOf InputOnlyType
82-
let outputList : OutputDef<OutputOnly list> = ListOf OutputOnlyType
83-
Assert.Equal ("[InputOnlyType!]!", inputList.ToString ())
84-
Assert.Equal ("[OutputOnlyType!]!", outputList.ToString ())
85-
}
81+
let inputList : InputDef<InputOnly list> = ListOf InputOnlyType
82+
let outputList : OutputDef<OutputOnly list> = ListOf OutputOnlyType
83+
Assert.Equal ("[InputOnlyType!]!", inputList.ToString ())
84+
Assert.Equal ("[OutputOnlyType!]!", outputList.ToString ())
85+
}
8686

8787
[<Fact>]
8888
member _.``Nullable keeps input-output direction`` () : Task = task {
89-
let nullableInput : InputDef<InputOnly option> = Nullable InputOnlyType
90-
let nullableOutput : OutputDef<OutputOnly option> = Nullable OutputOnlyType
91-
Assert.Equal ("InputOnlyType", nullableInput.ToString ())
92-
Assert.Equal ("OutputOnlyType", nullableOutput.ToString ())
93-
}
89+
let nullableInput : InputDef<InputOnly option> = Nullable InputOnlyType
90+
let nullableOutput : OutputDef<OutputOnly option> = Nullable OutputOnlyType
91+
Assert.Equal ("InputOnlyType", nullableInput.ToString ())
92+
Assert.Equal ("OutputOnlyType", nullableOutput.ToString ())
93+
}
9494

9595
[<Fact>]
9696
member _.``StructNullable keeps input-output direction`` () : Task = task {
97-
let nullableInput : InputDef<InputOnly voption> = StructNullable InputOnlyType
98-
let nullableOutput : OutputDef<OutputOnly voption> = StructNullable OutputOnlyType
99-
Assert.Equal ("InputOnlyType", nullableInput.ToString ())
100-
Assert.Equal ("OutputOnlyType", nullableOutput.ToString ())
101-
}
97+
let nullableInput : InputDef<InputOnly voption> = StructNullable InputOnlyType
98+
let nullableOutput : OutputDef<OutputOnly voption> = StructNullable OutputOnlyType
99+
Assert.Equal ("InputOnlyType", nullableInput.ToString ())
100+
Assert.Equal ("OutputOnlyType", nullableOutput.ToString ())
101+
}
102102

103103
[<Fact>]
104104
member _.``Valid script compiles successfully`` () : Task = task {
105-
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("Valid.fsx"))
106-
Assert.Equal (0, exitCode)
107-
}
105+
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("Valid.fsx"))
106+
Assert.Equal (0, exitCode)
107+
}
108108

109109
[<Fact>]
110110
member _.``ListOf rejects output type as input at compile time`` () : Task = task {
111-
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("ListOf.OutputAsInput.fsx"))
112-
Assert.NotEqual (0, exitCode)
113-
}
111+
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("ListOf.OutputAsInput.fsx"))
112+
Assert.NotEqual (0, exitCode)
113+
}
114114

115115
[<Fact>]
116116
member _.``ListOf rejects input type as output at compile time`` () : Task = task {
117-
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("ListOf.InputAsOutput.fsx"))
118-
Assert.NotEqual (0, exitCode)
119-
}
117+
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("ListOf.InputAsOutput.fsx"))
118+
Assert.NotEqual (0, exitCode)
119+
}
120120

121121
[<Fact>]
122122
member _.``Nullable rejects output type as input at compile time`` () : Task = task {
123-
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("Nullable.OutputAsInput.fsx"))
124-
Assert.NotEqual (0, exitCode)
125-
}
123+
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("Nullable.OutputAsInput.fsx"))
124+
Assert.NotEqual (0, exitCode)
125+
}
126126

127127
[<Fact>]
128128
member _.``Nullable rejects input type as output at compile time`` () : Task = task {
129-
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("Nullable.InputAsOutput.fsx"))
130-
Assert.NotEqual (0, exitCode)
131-
}
129+
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("Nullable.InputAsOutput.fsx"))
130+
Assert.NotEqual (0, exitCode)
131+
}
132132

133133
[<Fact>]
134134
member _.``StructNullable rejects output type as input at compile time`` () : Task = task {
135-
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("StructNullable.OutputAsInput.fsx"))
136-
Assert.NotEqual (0, exitCode)
137-
}
135+
let! exitCode = fixture.RunFsiCheckAsync (fixture.ScriptPath ("StructNullable.OutputAsInput.fsx"))
136+
Assert.NotEqual (0, exitCode)
137+
}
138138

139139
[<Fact>]
140140
member _.``StructNullable rejects input type as output at compile time`` () : Task = task {

0 commit comments

Comments
 (0)