diff --git a/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs b/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs new file mode 100644 index 00000000000..557aa81a4d4 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs @@ -0,0 +1,208 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Warn Expression`` = + + [] + let ``Warn If Expression Result Unused``() = + CompilerAssert.TypeCheckSingleError + """ +1 + 2 +printfn "%d" 3 + """ + FSharpErrorSeverity.Warning + 20 + (2, 1, 2, 6) + "The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + + [] + let ``Warn If Possible Assignment``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = "hello" + +let changeX() = + x = 20 + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 11) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'." + + [] + let ``Warn If Possible Assignment To Mutable``() = + CompilerAssert.TypeCheckSingleError + """ +let mutable x = 10 +let y = "hello" + +let changeX() = + x = 20 + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 11) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'." + + [] + let ``Warn If Possible dotnet Property Setter``() = + CompilerAssert.TypeCheckWithErrors + """ +open System + +let z = System.Timers.Timer() +let y = "hello" + +let changeProperty() = + z.Enabled = true + y = "test" + """ + [| + FSharpErrorSeverity.Warning, 760, (4, 9, 4, 30), "It is recommended that objects supporting the IDisposable interface are created using the syntax 'new Type(args)', rather than 'Type(args)' or 'Type' as a function value representing the constructor, to indicate that resources may be owned by the generated value" + FSharpErrorSeverity.Warning, 20, (8, 5, 8, 21), "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression'." + |] + + [] + let ``Don't Warn If Property Without Setter``() = + CompilerAssert.TypeCheckSingleError + """ +type MyClass(property1 : int) = + member val Property2 = "" with get + +let x = MyClass(1) +let y = "hello" + +let changeProperty() = + x.Property2 = "22" + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (9, 5, 9, 23) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." + + [] + let ``Warn If Implicitly Discarded``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = 20 + +let changeX() = + y * x = 20 + y = 30 + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 15) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." + + [] + let ``Warn If Discarded In List``() = + CompilerAssert.TypeCheckSingleError + """ +let div _ _ = 1 +let subView _ _ = [1; 2] + +// elmish view +let view model dispatch = + [ + yield! subView model dispatch + div [] [] + ] + """ + FSharpErrorSeverity.Warning + 3221 + (9, 8, 9, 17) + "This expression returns a value of type 'int' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'." + + [] + let ``Warn If Discarded In List 2``() = + CompilerAssert.TypeCheckSingleError + """ +// stupid things to make the sample compile +let div _ _ = 1 +let subView _ _ = [1; 2] +let y = 1 + +// elmish view +let view model dispatch = + [ + div [] [ + match y with + | 1 -> yield! subView model dispatch + | _ -> subView model dispatch + ] + ] + """ + FSharpErrorSeverity.Warning + 3222 + (13, 19, 13, 41) + "This expression returns a value of type 'int list' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'." + + [] + let ``Warn If Discarded In List 3``() = + CompilerAssert.TypeCheckSingleError + """ +// stupid things to make the sample compile +let div _ _ = 1 +let subView _ _ = true +let y = 1 + +// elmish view +let view model dispatch = + [ + div [] [ + match y with + | 1 -> () + | _ -> subView model dispatch + ] + ] + """ + FSharpErrorSeverity.Warning + 20 + (13, 19, 13, 41) + "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + + [] + let ``Warn Only On Last Expression``() = + CompilerAssert.TypeCheckSingleError + """ +let mutable x = 0 +while x < 1 do + printfn "unneeded" + x <- x + 1 + true + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 9) + "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + + [] + let ``Warn If Possible Property Setter``() = + CompilerAssert.TypeCheckSingleError + """ +type MyClass(property1 : int) = + member val Property1 = property1 + member val Property2 = "" with get, set + +let x = MyClass(1) +let y = "hello" + +let changeProperty() = + x.Property2 = "20" + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (10, 5, 10, 23) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression'." diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index ec2a852b131..43bda95f1c2 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -37,6 +37,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs b/tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs deleted file mode 100644 index 4492e6338c6..00000000000 --- a/tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -//The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. - -type MyClass(property1 : int) = - member val Property2 = "" with get - -let x = MyClass(1) -let y = "hello" - -let changeProperty() = - x.Property2 = "22" - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs b/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs deleted file mode 100644 index d47a4c13769..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -// - -let div _ _ = 1 -let subView _ _ = [1; 2] - -// elmish view -let view model dispatch = - [ - yield! subView model dispatch - div [] [] - ] - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs b/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs deleted file mode 100644 index d360da4d666..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs +++ /dev/null @@ -1,19 +0,0 @@ -// #Warnings -// - -// stupid things to make the sample compile -let div _ _ = 1 -let subView _ _ = [1; 2] -let y = 1 - -// elmish view -let view model dispatch = - [ - div [] [ - match y with - | 1 -> yield! subView model dispatch - | _ -> subView model dispatch - ] - ] - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs b/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs deleted file mode 100644 index 238d4388f9e..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs +++ /dev/null @@ -1,19 +0,0 @@ -// #Warnings -// - -// stupid things to make the sample compile -let div _ _ = 1 -let subView _ _ = true -let y = 1 - -// elmish view -let view model dispatch = - [ - div [] [ - match y with - | 1 -> () - | _ -> subView model dispatch - ] - ] - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs b/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs deleted file mode 100644 index 9480f35b6b6..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs +++ /dev/null @@ -1,5 +0,0 @@ -// #Warnings -//The result of this expression has type 'int' and is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ - -1 + 2 -printfn "%d" 3 diff --git a/tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs b/tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs deleted file mode 100644 index ad7f9deacdd..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. - -let x = 10 -let y = 20 - -let changeX() = - y * x = 20 - y = 30 - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs deleted file mode 100644 index b3fca3a0b92..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'. - -let x = 10 -let y = "hello" - -let changeX() = - x = 20 - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs deleted file mode 100644 index bd827ec4adc..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'. - -let mutable x = 10 -let y = "hello" - -let changeX() = - x = 20 - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs deleted file mode 100644 index 7c461349ec2..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression' - -open System - -let z = System.Timers.Timer() -let y = "hello" - -let changeProperty() = - z.Enabled = true - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs deleted file mode 100644 index 7548d204685..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs +++ /dev/null @@ -1,15 +0,0 @@ -// #Warnings -//If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression' - -type MyClass(property1 : int) = - member val Property1 = property1 - member val Property2 = "" with get, set - -let x = MyClass(1) -let y = "hello" - -let changeProperty() = - x.Property2 = "20" - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs b/tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs deleted file mode 100644 index 7b0b968c23b..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//The result of this expression has type 'bool' and is implicitly ignored - -let mutable x = 0 -while x < 1 do - printfn "unneeded" - x <- x + 1 - true - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 3a31070e079..9b5fbffaeba 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -40,19 +40,8 @@ SOURCE=RefCellInsteadOfNot2.fs # RefCellInsteadOfNot2.fs SOURCE=RuntimeTypeTestInPattern.fs # RuntimeTypeTestInPattern.fs SOURCE=RuntimeTypeTestInPattern2.fs # RuntimeTypeTestInPattern2.fs - SOURCE=WarnIfExpressionResultUnused.fs # WarnIfExpressionResultUnused.fs SOURCE=MemberHasMultiplePossibleDispatchSlots.fs # MemberHasMultiplePossibleDispatchSlots.fs SOURCE=Repro1548.fs SCFLAGS="-r:Repro1548.dll" # Repro1548.fs - SOURCE=WarnIfPossibleAssignment.fs - SOURCE=WarnIfPossibleAssignmentToMutable.fs - SOURCE=WarnIfPossibleDotNetPropertySetter.fs - SOURCE=DontWarnIfPropertyWithoutSetter.fs - SOURCE=WarnIfImplicitlyDiscarded.fs - SOURCE=WarnIfDiscardedInList.fs - SOURCE=WarnIfDiscardedInList2.fs - SOURCE=WarnIfDiscardedInList3.fs - SOURCE=WarnOnlyOnLastExpression.fs - SOURCE=WarnIfPossiblePropertySetter.fs SOURCE=DoCannotHaveVisibilityDeclarations.fs SOURCE=ModuleAbbreviationsArePrivate.fs SOURCE=DontSuggestIntentionallyUnusedVariables.fs SCFLAGS="--vserrors" # DontSuggestIntentionallyUnusedVariables.fs