From 9e1fd73d52aaa27a41b77fbb06b4bebf9c5cd1a7 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 19 Aug 2016 19:02:23 -0700 Subject: [PATCH 1/6] Extract method refactoring should handle tuples in VB --- .../Test/Emit/CodeGen/CodeGenTupleTest.cs | 11 +++++ .../Portable/Syntax/SyntaxFacts.vb | 2 + .../Test/Emit/CodeGen/CodeGenTuples.vb | 13 ++++++ .../ExtractMethod/ExtractMethodTests.vb | 41 +++++++++++++++++++ .../Extensions/TypeSyntaxGeneratorVisitor.vb | 18 ++++++++ 5 files changed, 85 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index df84a95efd910..d4cc8c6703196 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -5146,6 +5146,17 @@ public void CreateTupleTypeSymbol_ElementTypeIsError() Assert.Equal(SymbolKind.ErrorType, types[1].Kind); } + [Fact, WorkItem(13277, "https://github.com/dotnet/roslyn/issues/13277")] + public void CreateTupleTypeSymbol_UnderlyingTypeIsError() + { + var comp = CSharpCompilation.Create("test", references: new[] { MscorlibRef }); + + TypeSymbol intType = comp.GetSpecialType(SpecialType.System_Int32); + var vt2 = comp.CreateErrorTypeSymbol(null, "ValueTuple", 2).Construct(intType, intType); + + Assert.Throws(() => comp.CreateTupleTypeSymbol(vt2, default(ImmutableArray))); + } + [Fact] public void CreateTupleTypeSymbol_BadNames() { diff --git a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxFacts.vb b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxFacts.vb index 8796cf3af2ef4..5cab96e299d9c 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxFacts.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxFacts.vb @@ -107,6 +107,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Else Return parentQualName.Right Is node End If + Case SyntaxKind.TupleElement + Return DirectCast(parent, TupleElementSyntax).Type Is node End Select End If diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index 73c0a48c48b65..ebc538f6ecdb5 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -5896,6 +5896,19 @@ fourth]]>) End Sub + + Public Sub CreateTupleTypeSymbol_UnderlyingTypeIsError() + + Dim comp = VisualBasicCompilation.Create("test", references:={MscorlibRef}) + + Dim intType As TypeSymbol = comp.GetSpecialType(SpecialType.System_Int32) + Dim vt2 = comp.CreateErrorTypeSymbol(Nothing, "ValueTuple", 2).Construct(intType, intType) + + Dim tuple = comp.CreateTupleTypeSymbol(vt2, Nothing) + ' Crashes in IsTupleCompatible + + End Sub + End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb index f5f0fab07cdf1..49d91ebfbb1e3 100644 --- a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb +++ b/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb @@ -291,6 +291,47 @@ End Class End Sub End Class .Value.Replace(vbLf, vbCrLf), +compareTokens:=False) + End Function + + + Public Async Function TestTuples() As Task + + Await TestAsync( +Class Program + Sub Main(args As String()) + [|Dim x = (1, 2)|] + M(x) + End Sub + + Private Sub M(x As (Integer, Integer)) + End Sub +End Class + +Namespace System + Structure ValueTuple(Of T1, T2) + End Structure +End Namespace +.Value.Replace(vbLf, vbCrLf), +Class Program + Sub Main(args As String()) + Dim x As (Integer, Integer) = {|Rename:NewMethod|}() + M(x) + End Sub + + Private Shared Function NewMethod() As (Integer, Integer) + Return (1, 2) + End Function + + Private Sub M(x As (Integer, Integer)) + End Sub +End Class + +Namespace System + Structure ValueTuple(Of T1, T2) + End Structure +End Namespace +.Value.Replace(vbLf, vbCrLf), compareTokens:=False) End Function End Class diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb index 31b1a7b6d1e55..322d2ecc06319 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb @@ -102,6 +102,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("DateTime")) End Select + If symbol.IsTupleType Then + Return CreateTupleTypeSyntax(symbol) + End If + If symbol.Name = String.Empty OrElse symbol.IsAnonymousType Then Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Object")) End If @@ -119,6 +123,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(symbol.TypeArguments.[Select](Function(t) t.Accept(Me))))) End Function + Private Function CreateTupleTypeSyntax(symbol As INamedTypeSymbol) As TypeSyntax + Dim list = New SeparatedSyntaxList(Of TupleElementSyntax)() + Dim types = symbol.TupleElementTypes + Dim names = symbol.TupleElementNames + Dim hasNames = Not (names.IsDefault) + + For pos As Integer = 1 To types.Length + Dim name = If(hasNames, SyntaxFactory.IdentifierName(names(pos - 1)), Nothing) + list = list.Add(SyntaxFactory.TupleElement(name, GenerateTypeSyntax(types(pos - 1)))) + Next + + Return SyntaxFactory.TupleType(list) + End Function + Public Overrides Function VisitNamedType(symbol As INamedTypeSymbol) As TypeSyntax Dim typeSyntax = CreateSimpleTypeSyntax(symbol) If Not (TypeOf typeSyntax Is SimpleNameSyntax) Then From 502c8969d2d68d3b2c53aaa196c62ff9c507bc2a Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 22 Aug 2016 11:08:16 -0700 Subject: [PATCH 2/6] Add compiler test for GetSymbolInfo change on type in tuple --- .../Test/Emit/CodeGen/CodeGenTuples.vb | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index ebc538f6ecdb5..c444ef07c0ce7 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -5896,7 +5896,8 @@ fourth]]>) End Sub - + + Public Sub CreateTupleTypeSymbol_UnderlyingTypeIsError() Dim comp = VisualBasicCompilation.Create("test", references:={MscorlibRef}) @@ -5909,6 +5910,32 @@ fourth]]>) End Sub + + Public Sub GetSymbolInfoOnTupleType() + Dim verifier = CompileAndVerify( + + +Module C + Function M() As (System.Int32, String) + throw new System.Exception() + End Function +End Module + + + , additionalRefs:={ValueTupleRef, SystemRuntimeFacadeRef}) + + Dim comp = verifier.Compilation + Dim tree = comp.SyntaxTrees(0) + Dim model = comp.GetSemanticModel(tree, ignoreAccessibility:=False) + Dim nodes = tree.GetCompilationUnitRoot().DescendantNodes() + + Dim type = nodes.OfType(Of QualifiedNameSyntax)().First() + Assert.Equal("System.Int32", type.ToString()) + Assert.NotNull(model.GetSymbolInfo(type)) + Assert.NotNull(model.GetSymbolInfo(type).Symbol) + + End Sub + End Class End Namespace From 405ab3398d53f609f82b24c0c89ac96474dc5218 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 22 Aug 2016 11:24:33 -0700 Subject: [PATCH 3/6] PR feedback from Cyrus --- .../Test/Emit/CodeGen/CodeGenTuples.vb | 1 + .../ExtractMethod/ExtractMethodTests.vb | 43 ++++--------------- .../Extensions/TypeSyntaxGeneratorVisitor.vb | 9 ++-- 3 files changed, 13 insertions(+), 40 deletions(-) diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index c444ef07c0ce7..cfb3e56bae93b 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -5911,6 +5911,7 @@ fourth]]>) End Sub + Public Sub GetSymbolInfoOnTupleType() Dim verifier = CompileAndVerify( diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb index 49d91ebfbb1e3..c6dad64f49e94 100644 --- a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb +++ b/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb @@ -295,44 +295,19 @@ compareTokens:=False) End Function + Public Async Function TestTuples() As Task Await TestAsync( -Class Program - Sub Main(args As String()) - [|Dim x = (1, 2)|] - M(x) - End Sub - - Private Sub M(x As (Integer, Integer)) - End Sub -End Class +NewLines("Class Program \n Sub Main(args As String()) \n [|Dim x = (1, 2)|] \n M(x) \n End Sub +Private Sub M(x As (Integer, Integer)) \n End Sub \n End Class +Namespace System \n Structure ValueTuple(Of T1, T2) \n End Structure \n End Namespace"), +NewLines("Class Program \n Sub Main(args As String()) \n Dim x As (Integer, Integer) = {|Rename:NewMethod|}() \n M(x) \n End Sub +Private Shared Function NewMethod() As (Integer, Integer) \n Return (1, 2) \n End Function +Private Sub M(x As (Integer, Integer)) \n End Sub \n End Class +Namespace System \n Structure ValueTuple(Of T1, T2) \n End Structure \n End Namespace")) -Namespace System - Structure ValueTuple(Of T1, T2) - End Structure -End Namespace -.Value.Replace(vbLf, vbCrLf), -Class Program - Sub Main(args As String()) - Dim x As (Integer, Integer) = {|Rename:NewMethod|}() - M(x) - End Sub - - Private Shared Function NewMethod() As (Integer, Integer) - Return (1, 2) - End Function - - Private Sub M(x As (Integer, Integer)) - End Sub -End Class - -Namespace System - Structure ValueTuple(Of T1, T2) - End Structure -End Namespace -.Value.Replace(vbLf, vbCrLf), -compareTokens:=False) End Function + End Class End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb index 322d2ecc06319..6dd71f5d47ce5 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb @@ -127,14 +127,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Dim list = New SeparatedSyntaxList(Of TupleElementSyntax)() Dim types = symbol.TupleElementTypes Dim names = symbol.TupleElementNames - Dim hasNames = Not (names.IsDefault) + Dim hasNames = Not names.IsDefault - For pos As Integer = 1 To types.Length - Dim name = If(hasNames, SyntaxFactory.IdentifierName(names(pos - 1)), Nothing) - list = list.Add(SyntaxFactory.TupleElement(name, GenerateTypeSyntax(types(pos - 1)))) - Next + Return SyntaxFactory.TupleType(SyntaxFactory.SeparatedList( + types.Select(Function(t, i) SyntaxFactory.TupleElement(If(hasNames, SyntaxFactory.IdentifierName(names(i)), Nothing), GenerateTypeSyntax(t))))) - Return SyntaxFactory.TupleType(list) End Function Public Overrides Function VisitNamedType(symbol As INamedTypeSymbol) As TypeSyntax From 276c93ff6fe827016838971da218dc2c1adca8d7 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 22 Aug 2016 12:24:32 -0700 Subject: [PATCH 4/6] Using VB multiline literal --- .../ExtractMethod/ExtractMethodTests.vb | 34 +++++++++++++++---- .../Extensions/TypeSyntaxGeneratorVisitor.vb | 3 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb index c6dad64f49e94..08866747d6e5a 100644 --- a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb +++ b/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb @@ -299,13 +299,33 @@ compareTokens:=False) Public Async Function TestTuples() As Task Await TestAsync( -NewLines("Class Program \n Sub Main(args As String()) \n [|Dim x = (1, 2)|] \n M(x) \n End Sub -Private Sub M(x As (Integer, Integer)) \n End Sub \n End Class -Namespace System \n Structure ValueTuple(Of T1, T2) \n End Structure \n End Namespace"), -NewLines("Class Program \n Sub Main(args As String()) \n Dim x As (Integer, Integer) = {|Rename:NewMethod|}() \n M(x) \n End Sub -Private Shared Function NewMethod() As (Integer, Integer) \n Return (1, 2) \n End Function -Private Sub M(x As (Integer, Integer)) \n End Sub \n End Class -Namespace System \n Structure ValueTuple(Of T1, T2) \n End Structure \n End Namespace")) +"Class Program + Sub Main(args As String()) + [|Dim x = (1, 2)|] + M(x) + End Sub + Private Sub M(x As (Integer, Integer)) + End Sub +End Class +Namespace System + Structure ValueTuple(Of T1, T2) + End Structure +End Namespace", +"Class Program + Sub Main(args As String()) + Dim x As (Integer, Integer) = {|Rename:NewMethod|}() + M(x) + End Sub + Private Shared Function NewMethod() As (Integer, Integer) + Return (1, 2) + End Function + Private Sub M(x As (Integer, Integer)) + End Sub +End Class +Namespace System + Structure ValueTuple(Of T1, T2) + End Structure +End Namespace") End Function diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb index 6dd71f5d47ce5..0ae090c2301d2 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb @@ -130,7 +130,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Dim hasNames = Not names.IsDefault Return SyntaxFactory.TupleType(SyntaxFactory.SeparatedList( - types.Select(Function(t, i) SyntaxFactory.TupleElement(If(hasNames, SyntaxFactory.IdentifierName(names(i)), Nothing), GenerateTypeSyntax(t))))) + types.Select(Function(t, i) SyntaxFactory.TupleElement( + If(hasNames, SyntaxFactory.IdentifierName(names(i)), Nothing), GenerateTypeSyntax(t))))) End Function From 2164545c7269f6f22451a9a7b714846678221900 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 22 Aug 2016 15:28:02 -0700 Subject: [PATCH 5/6] Removing empty line --- .../Portable/Extensions/TypeSyntaxGeneratorVisitor.vb | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb index 0ae090c2301d2..993bbb5c7df27 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb @@ -132,7 +132,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Return SyntaxFactory.TupleType(SyntaxFactory.SeparatedList( types.Select(Function(t, i) SyntaxFactory.TupleElement( If(hasNames, SyntaxFactory.IdentifierName(names(i)), Nothing), GenerateTypeSyntax(t))))) - End Function Public Overrides Function VisitNamedType(symbol As INamedTypeSymbol) As TypeSyntax From 69d24f98b1ff2dcd7de9361dbeab1ed8fe52d83b Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Wed, 24 Aug 2016 10:56:55 -0700 Subject: [PATCH 6/6] PR feedback from Chuck --- src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs | 2 +- src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb | 2 +- .../Portable/Extensions/TypeSyntaxGeneratorVisitor.vb | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index d4cc8c6703196..47c3d16b97549 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -5154,7 +5154,7 @@ public void CreateTupleTypeSymbol_UnderlyingTypeIsError() TypeSymbol intType = comp.GetSpecialType(SpecialType.System_Int32); var vt2 = comp.CreateErrorTypeSymbol(null, "ValueTuple", 2).Construct(intType, intType); - Assert.Throws(() => comp.CreateTupleTypeSymbol(vt2, default(ImmutableArray))); + Assert.Throws(() => comp.CreateTupleTypeSymbol(underlyingType: vt2)); } [Fact] diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index cfb3e56bae93b..296aa89e087ca 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -5932,8 +5932,8 @@ End Module Dim type = nodes.OfType(Of QualifiedNameSyntax)().First() Assert.Equal("System.Int32", type.ToString()) - Assert.NotNull(model.GetSymbolInfo(type)) Assert.NotNull(model.GetSymbolInfo(type).Symbol) + Assert.Equal("System.Int32", model.GetSymbolInfo(type).Symbol.ToTestDisplayString()) End Sub diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb index 993bbb5c7df27..80d62d589d620 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/TypeSyntaxGeneratorVisitor.vb @@ -123,15 +123,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(symbol.TypeArguments.[Select](Function(t) t.Accept(Me))))) End Function - Private Function CreateTupleTypeSyntax(symbol As INamedTypeSymbol) As TypeSyntax - Dim list = New SeparatedSyntaxList(Of TupleElementSyntax)() + Private Shared Function CreateTupleTypeSyntax(symbol As INamedTypeSymbol) As TypeSyntax Dim types = symbol.TupleElementTypes Dim names = symbol.TupleElementNames Dim hasNames = Not names.IsDefault Return SyntaxFactory.TupleType(SyntaxFactory.SeparatedList( types.Select(Function(t, i) SyntaxFactory.TupleElement( - If(hasNames, SyntaxFactory.IdentifierName(names(i)), Nothing), GenerateTypeSyntax(t))))) + If(hasNames, SyntaxFactory.IdentifierName(names(i)), Nothing), t.GenerateTypeSyntax())))) End Function Public Overrides Function VisitNamedType(symbol As INamedTypeSymbol) As TypeSyntax