diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/InsertMissingCast/InsertMissingCastTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/InsertMissingCast/InsertMissingCastTests.vb index 9cc3d5f7f7d3a5644ed9f536efd19a25a3d1ecc2..137cc15cd848838d5f83d22853b741cd068c82c9 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/InsertMissingCast/InsertMissingCastTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/InsertMissingCast/InsertMissingCastTests.vb @@ -87,5 +87,12 @@ NewLines("Option Strict On \n Module Program \n Sub Main(args As String()) \n Di TestMissing( NewLines("Option Strict On \n Class A \n End Class \n Class B \n End Class \n Module Program[||] \n Sub Main(args As String()) \n Dim x As A = New B() \n End Sub \n End Module")) End Sub + + + Public Sub TestOptionStrictOn() + Test( +NewLines("Option Strict On \n Module Module1 \n Sub Main() \n Dim red = ColorF.FromArgb(255, 255, 0, 0) \n Dim c As Color = [|red|] \n End Sub \n End Module \n Public Structure ColorF \n Public A, R, G, B As Single \n Public Shared Function FromArgb(a As Double, r As Double, g As Double, b As Double) As ColorF \n Return New ColorF With {.A = CSng(a), .R = CSng(r), .G = CSng(g), .B = CSng(b)} \n End Function \n Public Shared Widening Operator CType(x As Color) As ColorF \n Return ColorF.FromArgb(x.A / 255, x.R / 255, x.G / 255, x.B / 255) \n End Operator \n Public Shared Narrowing Operator CType(x As ColorF) As Color \n Return Color.FromArgb(CByte(x.A * 255), CByte(x.R * 255), CByte(x.G * 255), CByte(x.B * 255)) \n End Operator \n End Structure \n Public Structure Color \n Public A, R, G, B As Byte \n Public Shared Function FromArgb(a As Byte, r As Byte, g As Byte, b As Byte) As Color \n Return New Color With {.A = a, .R = r, .G = g, .B = b} \n End Function \n End Structure"), +NewLines("Option Strict On \n Module Module1 \n Sub Main() \n Dim red = ColorF.FromArgb(255, 255, 0, 0) \n Dim c As Color = CType(red, Color) \n End Sub \n End Module \n Public Structure ColorF \n Public A, R, G, B As Single \n Public Shared Function FromArgb(a As Double, r As Double, g As Double, b As Double) As ColorF \n Return New ColorF With {.A = CSng(a), .R = CSng(r), .G = CSng(g), .B = CSng(b)} \n End Function \n Public Shared Widening Operator CType(x As Color) As ColorF \n Return ColorF.FromArgb(x.A / 255, x.R / 255, x.G / 255, x.B / 255) \n End Operator \n Public Shared Narrowing Operator CType(x As ColorF) As Color \n Return Color.FromArgb(CByte(x.A * 255), CByte(x.R * 255), CByte(x.G * 255), CByte(x.B * 255)) \n End Operator \n End Structure \n Public Structure Color \n Public A, R, G, B As Byte \n Public Shared Function FromArgb(a As Byte, r As Byte, g As Byte, b As Byte) As Color \n Return New Color With {.A = a, .R = r, .G = g, .B = b} \n End Function \n End Structure")) + End Sub End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb index fe788a93de4fca458aab80e52557d60623a263ae..a89d717acf431e64492f201c20566eee82061018 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb @@ -2363,7 +2363,7 @@ End Class Public Sub RemoveCastToICloneableForDelegate() - ' Note: The cast below can be removed because delegates are implictly sealed. + ' Note: The cast below can be removed because delegates are implicitly sealed. Dim markup = @@ -2396,7 +2396,7 @@ End Class Public Sub RemoveCastToICloneableForArray() - ' Note: The cast below can be removed because arrays are implictly sealed. + ' Note: The cast below can be removed because arrays are implicitly sealed. Dim markup = @@ -2427,7 +2427,7 @@ End Class Public Sub RemoveCastToICloneableForArray2() - ' Note: The cast below can be removed because arrays are implictly sealed. + ' Note: The cast below can be removed because arrays are implicitly sealed. Dim markup = @@ -2456,7 +2456,7 @@ End Module Public Sub RemoveCastToIConvertibleForEnum() - ' Note: The cast below can be removed because enums are implictly sealed. + ' Note: The cast below can be removed because enums are implicitly sealed. Dim markup = @@ -2691,6 +2691,84 @@ Class Program End If End Sub End Class + + TestMissing(markup) + End Sub + + + + Public Sub DoNotRemoveCastInUserDefinedNarrowingConverionStrictOn() + Dim markup = + +Option Strict On + +Module Module1 + + Sub Main() + Dim red = ColorF.FromArgb(255, 255, 0, 0) + Dim c As Color = [|CType(red, Color)|] + End Sub + +End Module + +Public Structure ColorF + Public A, R, G, B As Single + Public Shared Function FromArgb(a As Double, r As Double, g As Double, b As Double) As ColorF + Return New ColorF With {.A = CSng(a), .R = CSng(r), .G = CSng(g), .B = CSng(b)} + End Function + Public Shared Widening Operator CType(x As Color) As ColorF + Return ColorF.FromArgb(x.A / 255, x.R / 255, x.G / 255, x.B / 255) + End Operator + Public Shared Narrowing Operator CType(x As ColorF) As Color + Return Color.FromArgb(CByte(x.A * 255), CByte(x.R * 255), CByte(x.G * 255), CByte(x.B * 255)) + End Operator +End Structure + +Public Structure Color + Public A, R, G, B As Byte + Public Shared Function FromArgb(a As Byte, r As Byte, g As Byte, b As Byte) As Color + Return New Color With {.A = a, .R = r, .G = g, .B = b} + End Function +End Structure + + TestMissing(markup) + End Sub + + + + Public Sub DoNotRemoveCastInUserDefinedNarrowingConverionStrictOff() + Dim markup = + +Option Strict Off + +Module Module1 + + Sub Main() + Dim red = ColorF.FromArgb(255, 255, 0, 0) + Dim c As Color = [|CType(red, Color)|] + End Sub + +End Module + +Public Structure ColorF + Public A, R, G, B As Single + Public Shared Function FromArgb(a As Double, r As Double, g As Double, b As Double) As ColorF + Return New ColorF With {.A = CSng(a), .R = CSng(r), .G = CSng(g), .B = CSng(b)} + End Function + Public Shared Widening Operator CType(x As Color) As ColorF + Return ColorF.FromArgb(x.A / 255, x.R / 255, x.G / 255, x.B / 255) + End Operator + Public Shared Narrowing Operator CType(x As ColorF) As Color + Return Color.FromArgb(CByte(x.A * 255), CByte(x.R * 255), CByte(x.G * 255), CByte(x.B * 255)) + End Operator +End Structure + +Public Structure Color + Public A, R, G, B As Byte + Public Shared Function FromArgb(a As Byte, r As Byte, g As Byte, b As Byte) As Color + Return New Color With {.A = a, .R = r, .G = g, .B = b} + End Function +End Structure TestMissing(markup) End Sub diff --git a/src/Features/VisualBasic/CodeFixes/InsertMissingCast/InsertMissingCastCodeFixProvider.vb b/src/Features/VisualBasic/CodeFixes/InsertMissingCast/InsertMissingCastCodeFixProvider.vb index 0804811bccbad4509bb6892ddee42e7e9ca76b1e..df0bad79f94a9256f8dc9e0dd72e1c441eb1c201 100644 --- a/src/Features/VisualBasic/CodeFixes/InsertMissingCast/InsertMissingCastCodeFixProvider.vb +++ b/src/Features/VisualBasic/CodeFixes/InsertMissingCast/InsertMissingCastCodeFixProvider.vb @@ -12,10 +12,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.InsertMissingCast Inherits CodeFixProvider Friend Const BC30512 As String = "BC30512" ' Option Strict On disallows implicit conversions from '{0}' to '{1}'. + Friend Const BC42016 As String = "BC42016" ' Implicit conversions from '{0}' to '{1}'. Public NotOverridable Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String) Get - Return ImmutableArray.Create(BC30512) + Return ImmutableArray.Create(BC30512, BC42016) End Get End Property diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/CastAnalyzer.vb b/src/Workspaces/VisualBasic/Portable/Extensions/CastAnalyzer.vb index b6edbc3c8b655394d880af48797434f8c6c579f5..82660eb29b180caff5bbf15a985d7ae2c5ba2703 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/CastAnalyzer.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/CastAnalyzer.vb @@ -253,7 +253,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions If castToOuterType.IsUserDefined OrElse expressionToCastType.IsUserDefined Then Return (HaveSameUserDefinedConversion(expressionToCastType, expressionToOuterType) OrElse HaveSameUserDefinedConversion(castToOuterType, expressionToOuterType)) AndAlso - UserDefinedConversionIsAllowed(_castNode, _semanticModel) + (UserDefinedConversionIsAllowed(_castNode, _semanticModel) AndAlso + Not expressionToCastType.IsNarrowing) ElseIf expressionToOuterType.IsUserDefined Then Return False End If