提交 0d972cf9 编写于 作者: T Tanner Gooding

Merge remote-tracking branch 'origin/stabilization'

......@@ -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
<Fact(), Trait(Traits.Feature, Traits.Features.CodeActionsInsertMissingCast)>
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
......@@ -2363,7 +2363,7 @@ End Class
<WorkItem(544655)>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
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 =
<File>
......@@ -2396,7 +2396,7 @@ End Class
<WorkItem(545926)>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
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 =
<File>
......@@ -2427,7 +2427,7 @@ End Class
<WorkItem(529937)>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
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 =
<File>
......@@ -2456,7 +2456,7 @@ End Module
<WorkItem(529897)>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
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 =
<File>
......@@ -2691,6 +2691,84 @@ Class Program
End If
End Sub
End Class
</File>
TestMissing(markup)
End Sub
<WorkItem(3163, "https://github.com/dotnet/roslyn/issues/3163")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
Public Sub DoNotRemoveCastInUserDefinedNarrowingConverionStrictOn()
Dim markup =
<File>
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
</File>
TestMissing(markup)
End Sub
<WorkItem(3163, "https://github.com/dotnet/roslyn/issues/3163")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
Public Sub DoNotRemoveCastInUserDefinedNarrowingConverionStrictOff()
Dim markup =
<File>
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
</File>
TestMissing(markup)
End Sub
......
......@@ -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
......
......@@ -482,6 +482,9 @@ public override string AssemblyAttributeString
}
}
/// <summary>
/// Do not use this method directly! Instead, go through <see cref="FileCodeModel.CreateCodeElement{T}(SyntaxNode)"/>
/// </summary>
public override EnvDTE.CodeElement CreateInternalCodeElement(
CodeModelState state,
FileCodeModel fileCodeModel,
......
......@@ -266,6 +266,9 @@ public EnvDTE.CodeElement CreateExternalCodeElement(CodeModelState state, Projec
}
}
/// <summary>
/// Do not use this method directly! Instead, go through <see cref="FileCodeModel.CreateCodeElement{T}(SyntaxNode)"/>
/// </summary>
public abstract EnvDTE.CodeElement CreateInternalCodeElement(
CodeModelState state,
FileCodeModel fileCodeModel,
......@@ -350,15 +353,16 @@ public ISymbol ResolveSymbol(Workspace workspace, ProjectId projectId, SymbolKey
protected EnvDTE.CodeFunction CreateInternalCodeAccessorFunction(CodeModelState state, FileCodeModel fileCodeModel, SyntaxNode node)
{
SyntaxNode parentNode = node.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
SyntaxNode parentNode = node
.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
if (parentNode == null)
{
throw new InvalidOperationException();
}
var parent = CreateInternalCodeElement(state, fileCodeModel, parentNode);
var parent = fileCodeModel.CreateCodeElement<EnvDTE.CodeElement>(parentNode);
var parentObj = ComAggregate.GetManagedObject<AbstractCodeMember>(parent);
var accessorKind = GetAccessorKind(node);
......@@ -373,7 +377,7 @@ protected EnvDTE.CodeAttribute CreateInternalCodeAttribute(CodeModelState state,
if (IsParameterNode(parentNode))
{
var parentElement = CreateInternalCodeParameter(state, fileCodeModel, parentNode);
var parentElement = fileCodeModel.CreateCodeElement<EnvDTE.CodeElement>(parentNode);
parentObject = ComAggregate.GetManagedObject<AbstractCodeElement>(parentElement);
}
else
......@@ -415,7 +419,7 @@ protected EnvDTE80.CodeImport CreateInternalCodeImport(CodeModelState state, Fil
AbstractCodeElement parentObj = null;
if (parentNode != null)
{
var parent = CreateInternalCodeElement(state, fileCodeModel, parentNode);
var parent = fileCodeModel.CreateCodeElement<EnvDTE.CodeElement>(parentNode);
parentObj = ComAggregate.GetManagedObject<AbstractCodeElement>(parent);
}
......@@ -424,8 +428,9 @@ protected EnvDTE80.CodeImport CreateInternalCodeImport(CodeModelState state, Fil
protected EnvDTE.CodeParameter CreateInternalCodeParameter(CodeModelState state, FileCodeModel fileCodeModel, SyntaxNode node)
{
SyntaxNode parentNode = node.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
SyntaxNode parentNode = node
.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
if (parentNode == null)
{
......@@ -434,7 +439,7 @@ protected EnvDTE.CodeParameter CreateInternalCodeParameter(CodeModelState state,
string name = GetParameterName(node);
var parent = CreateInternalCodeElement(state, fileCodeModel, parentNode);
var parent = fileCodeModel.CreateCodeElement<EnvDTE.CodeElement>(parentNode);
var parentObj = ComAggregate.GetManagedObject<AbstractCodeMember>(parent);
return CodeParameter.Create(state, parentObj, name);
......@@ -451,8 +456,9 @@ protected EnvDTE80.CodeElement2 CreateInternalCodeOptionStatement(CodeModelState
protected EnvDTE80.CodeElement2 CreateInternalCodeInheritsStatement(CodeModelState state, FileCodeModel fileCodeModel, SyntaxNode node)
{
SyntaxNode parentNode = node.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
SyntaxNode parentNode = node
.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
if (parentNode == null)
{
......@@ -463,7 +469,7 @@ protected EnvDTE80.CodeElement2 CreateInternalCodeInheritsStatement(CodeModelSta
int ordinal;
GetInheritsNamespaceAndOrdinal(parentNode, node, out namespaceName, out ordinal);
var parent = CreateInternalCodeElement(state, fileCodeModel, parentNode);
var parent = fileCodeModel.CreateCodeElement<EnvDTE.CodeElement>(parentNode);
var parentObj = ComAggregate.GetManagedObject<AbstractCodeMember>(parent);
return CodeInheritsStatement.Create(state, parentObj, namespaceName, ordinal);
......@@ -471,8 +477,9 @@ protected EnvDTE80.CodeElement2 CreateInternalCodeInheritsStatement(CodeModelSta
protected EnvDTE80.CodeElement2 CreateInternalCodeImplementsStatement(CodeModelState state, FileCodeModel fileCodeModel, SyntaxNode node)
{
SyntaxNode parentNode = node.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
SyntaxNode parentNode = node
.Ancestors()
.FirstOrDefault(n => TryGetNodeKey(n) != SyntaxNodeKey.Empty);
if (parentNode == null)
{
......@@ -483,7 +490,7 @@ protected EnvDTE80.CodeElement2 CreateInternalCodeImplementsStatement(CodeModelS
int ordinal;
GetImplementsNamespaceAndOrdinal(parentNode, node, out namespaceName, out ordinal);
var parent = CreateInternalCodeElement(state, fileCodeModel, parentNode);
var parent = fileCodeModel.CreateCodeElement<EnvDTE.CodeElement>(parentNode);
var parentObj = ComAggregate.GetManagedObject<AbstractCodeMember>(parent);
return CodeImplementsStatement.Create(state, parentObj, namespaceName, ordinal);
......
......@@ -73,6 +73,9 @@ internal interface ICodeModelService : ICodeModelNavigationPointService
string Language { get; }
string AssemblyAttributeString { get; }
/// <summary>
/// Do not use this method directly! Instead, go through <see cref="FileCodeModel.CreateCodeElement{T}(SyntaxNode)"/>
/// </summary>
EnvDTE.CodeElement CreateInternalCodeElement(CodeModelState state, FileCodeModel fileCodeModel, SyntaxNode node);
EnvDTE.CodeElement CreateExternalCodeElement(CodeModelState state, ProjectId projectId, ISymbol symbol);
EnvDTE.CodeElement CreateUnknownCodeElement(CodeModelState state, FileCodeModel fileCodeModel, SyntaxNode node);
......
......@@ -3,6 +3,8 @@
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.InternalElements
Imports Microsoft.VisualStudio.LanguageServices.Implementation.Interop
Imports Roslyn.Test.Utilities
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.CSharp
......@@ -1021,6 +1023,113 @@ class C
End Sub)
End Sub
<WorkItem(858153)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestCodeElements_PropertyAccessor()
Dim code =
<code>
class C
{
int P
{
get { return 0; }
}
}
</code>
TestOperation(code,
Sub(fileCodeModel)
Dim classC = TryCast(fileCodeModel.CodeElements.Item(1), EnvDTE.CodeClass)
Assert.NotNull(classC)
Assert.Equal("C", classC.Name)
Dim propertyP = TryCast(classC.Members.Item(1), EnvDTE.CodeProperty)
Assert.NotNull(propertyP)
Assert.Equal("P", propertyP.Name)
Dim getter = propertyP.Getter
Assert.NotNull(getter)
Dim searchedGetter = fileCodeModel.CodeElementFromPoint(getter.StartPoint, EnvDTE.vsCMElement.vsCMElementFunction)
Dim parent = TryCast(getter.Collection.Parent, EnvDTE.CodeProperty)
Assert.NotNull(parent)
Assert.Equal("P", parent.Name)
' This assert is very important!
'
' We are testing that we don't regress a bug where a property accessor creates its
' parent incorrectly such that *existing* Code Model objects for its parent ("P") get a different
' NodeKey that makes the existing objects invalid. If the bug regresses, the line below will
' fail with an ArguementException when trying to use propertyP's NodeKey to lookup its node.
' (Essentially, its NodeKey will be {C.P,2} rather than {C.P,1}).
Assert.Equal("P", propertyP.Name)
' Sanity: ensure that the NodeKeys are correct
Dim member1 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(parent)
Dim member2 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(propertyP)
Assert.Equal("C.P", member1.NodeKey.Name)
Assert.Equal(1, member1.NodeKey.Ordinal)
Assert.Equal("C.P", member2.NodeKey.Name)
Assert.Equal(1, member2.NodeKey.Ordinal)
End Sub)
End Sub
<WorkItem(858153)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestCodeElements_EventAccessor()
Dim code =
<code>
class C
{
event System.EventHandler E
{
add { }
remove { }
}
}
</code>
TestOperation(code,
Sub(fileCodeModel)
Dim classC = TryCast(fileCodeModel.CodeElements.Item(1), EnvDTE.CodeClass)
Assert.NotNull(classC)
Assert.Equal("C", classC.Name)
Dim eventE = TryCast(classC.Members.Item(1), EnvDTE80.CodeEvent)
Assert.NotNull(eventE)
Assert.Equal("E", eventE.Name)
Dim adder = eventE.Adder
Assert.NotNull(adder)
Dim searchedAdder = fileCodeModel.CodeElementFromPoint(adder.StartPoint, EnvDTE.vsCMElement.vsCMElementFunction)
Dim parent = TryCast(adder.Collection.Parent, EnvDTE80.CodeEvent)
Assert.NotNull(parent)
Assert.Equal("E", parent.Name)
' This assert is very important!
'
' We are testing that we don't regress a bug where an event accessor creates its
' parent incorrectly such that *existing* Code Model objects for its parent ("P") get a different
' NodeKey that makes the existing objects invalid. If the bug regresses, the line below will
' fail with an ArguementException when trying to use propertyP's NodeKey to lookup its node.
' (Essentially, its NodeKey will be {C.E,2} rather than {C.E,1}).
Assert.Equal("E", eventE.Name)
' Sanity: ensure that the NodeKeys are correct
Dim member1 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(parent)
Dim member2 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(eventE)
Assert.Equal("C.E", member1.NodeKey.Name)
Assert.Equal(1, member1.NodeKey.Ordinal)
Assert.Equal("C.E", member2.NodeKey.Name)
Assert.Equal(1, member2.NodeKey.Ordinal)
End Sub)
End Sub
Protected Overrides ReadOnly Property LanguageName As String
Get
Return LanguageNames.CSharp
......
......@@ -4,6 +4,8 @@ Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.InternalElements
Imports Microsoft.VisualStudio.LanguageServices.Implementation.Interop
Imports Roslyn.Test.Utilities
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
......@@ -1021,6 +1023,209 @@ End Class
End Using
End Sub
<WorkItem(858153)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestCodeElements_InheritsStatements()
Dim code =
<code>
Class A
End Class
Class C
Inherits A
End Class
</code>
TestOperation(code,
Sub(fileCodeModel)
Dim classC = TryCast(fileCodeModel.CodeElements.Item(2), EnvDTE.CodeClass)
Assert.NotNull(classC)
Assert.Equal("C", classC.Name)
Dim inheritsA = TryCast(classC.Children.Item(1), EnvDTE80.CodeElement2)
Assert.NotNull(inheritsA)
Dim parent = TryCast(inheritsA.Collection.Parent, EnvDTE.CodeClass)
Assert.NotNull(parent)
Assert.Equal("C", parent.Name)
' This assert is very important!
'
' We are testing that we don't regress a bug where the VB Inherits statement creates its
' parent incorrectly such that *existing* Code Model objects for its parent ("C") get a different
' NodeKey that makes the existing objects invalid. If the bug regresses, the line below will
' fail with an ArguementException when trying to use classC's NodeKey to lookup its node.
' (Essentially, its NodeKey will be {C,2} rather than {C,1}).
Assert.Equal("C", classC.Name)
' Sanity: ensure that the NodeKeys are correct
Dim member1 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(parent)
Dim member2 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(classC)
Assert.Equal("C", member1.NodeKey.Name)
Assert.Equal(1, member1.NodeKey.Ordinal)
Assert.Equal("C", member2.NodeKey.Name)
Assert.Equal(1, member2.NodeKey.Ordinal)
End Sub)
End Sub
<WorkItem(858153)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestCodeElements_ImplementsStatements()
Dim code =
<code>
Interface I
End Interface
Class C
Implements I
End Class
</code>
TestOperation(code,
Sub(fileCodeModel)
Dim classC = TryCast(fileCodeModel.CodeElements.Item(2), EnvDTE.CodeClass)
Assert.NotNull(classC)
Assert.Equal("C", classC.Name)
Dim implementsI = TryCast(classC.Children.Item(1), EnvDTE80.CodeElement2)
Assert.NotNull(implementsI)
Dim parent = TryCast(implementsI.Collection.Parent, EnvDTE.CodeClass)
Assert.NotNull(parent)
Assert.Equal("C", parent.Name)
' This assert is very important!
'
' We are testing that we don't regress a bug where the VB Implements statement creates its
' parent incorrectly such that *existing* Code Model objects for its parent ("C") get a different
' NodeKey that makes the existing objects invalid. If the bug regresses, the line below will
' fail with an ArguementException when trying to use classC's NodeKey to lookup its node.
' (Essentially, its NodeKey will be {C,2} rather than {C,1}).
Assert.Equal("C", classC.Name)
' Sanity: ensure that the NodeKeys are correct
Dim member1 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(parent)
Dim member2 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(classC)
Assert.Equal("C", member1.NodeKey.Name)
Assert.Equal(1, member1.NodeKey.Ordinal)
Assert.Equal("C", member2.NodeKey.Name)
Assert.Equal(1, member2.NodeKey.Ordinal)
End Sub)
End Sub
<WorkItem(858153)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestCodeElements_PropertyAccessor()
Dim code =
<code>
Class C
ReadOnly Property P As Integer
Get
End Get
End Property
End Class
</code>
TestOperation(code,
Sub(fileCodeModel)
Dim classC = TryCast(fileCodeModel.CodeElements.Item(1), EnvDTE.CodeClass)
Assert.NotNull(classC)
Assert.Equal("C", classC.Name)
Dim propertyP = TryCast(classC.Members.Item(1), EnvDTE.CodeProperty)
Assert.NotNull(propertyP)
Assert.Equal("P", propertyP.Name)
Dim getter = propertyP.Getter
Assert.NotNull(getter)
Dim searchedGetter = fileCodeModel.CodeElementFromPoint(getter.StartPoint, EnvDTE.vsCMElement.vsCMElementFunction)
Dim parent = TryCast(getter.Collection.Parent, EnvDTE.CodeProperty)
Assert.NotNull(parent)
Assert.Equal("P", parent.Name)
' This assert is very important!
'
' We are testing that we don't regress a bug where a property accessor creates its
' parent incorrectly such that *existing* Code Model objects for its parent ("P") get a different
' NodeKey that makes the existing objects invalid. If the bug regresses, the line below will
' fail with an ArguementException when trying to use propertyP's NodeKey to lookup its node.
' (Essentially, its NodeKey will be {C.P As Integer,2} rather than {C.P As Integer,1}).
Assert.Equal("P", propertyP.Name)
' Sanity: ensure that the NodeKeys are correct
Dim member1 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(parent)
Dim member2 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(propertyP)
Assert.Equal("C.P As Integer", member1.NodeKey.Name)
Assert.Equal(1, member1.NodeKey.Ordinal)
Assert.Equal("C.P As Integer", member2.NodeKey.Name)
Assert.Equal(1, member2.NodeKey.Ordinal)
End Sub)
End Sub
<WorkItem(858153)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
Public Sub TestCodeElements_EventAccessor()
Dim code =
<code>
Class C
Custom Event E As System.EventHandler
AddHandler(value As System.EventHandler)
End AddHandler
RemoveHandler(value As System.EventHandler)
End RemoveHandler
RaiseEvent(sender As Object, e As System.EventArgs)
End RaiseEvent
End Event
End Class
</code>
TestOperation(code,
Sub(fileCodeModel)
Dim classC = TryCast(fileCodeModel.CodeElements.Item(1), EnvDTE.CodeClass)
Assert.NotNull(classC)
Assert.Equal("C", classC.Name)
Dim eventE = TryCast(classC.Members.Item(1), EnvDTE80.CodeEvent)
Assert.NotNull(eventE)
Assert.Equal("E", eventE.Name)
Dim adder = eventE.Adder
Assert.NotNull(adder)
Dim searchedAdder = fileCodeModel.CodeElementFromPoint(adder.StartPoint, EnvDTE.vsCMElement.vsCMElementFunction)
Dim parent = TryCast(adder.Collection.Parent, EnvDTE80.CodeEvent)
Assert.NotNull(parent)
Assert.Equal("E", parent.Name)
' This assert is very important!
'
' We are testing that we don't regress a bug where an event accessor creates its
' parent incorrectly such that *existing* Code Model objects for its parent ("E") get a different
' NodeKey that makes the existing objects invalid. If the bug regresses, the line below will
' fail with an ArguementException when trying to use propertyP's NodeKey to lookup its node.
' (Essentially, its NodeKey will be {C.E As System.EventHandler,2} rather than {C.E As System.EventHandler,1}).
Assert.Equal("E", eventE.Name)
' Sanity: ensure that the NodeKeys are correct
Dim member1 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(parent)
Dim member2 = ComAggregate.GetManagedObject(Of AbstractCodeMember)(eventE)
Assert.Equal("C.E As System.EventHandler", member1.NodeKey.Name)
Assert.Equal(1, member1.NodeKey.Ordinal)
Assert.Equal("C.E As System.EventHandler", member2.NodeKey.Name)
Assert.Equal(1, member2.NodeKey.Ordinal)
End Sub)
End Sub
Protected Overrides ReadOnly Property LanguageName As String
Get
Return LanguageNames.VisualBasic
......
......@@ -520,6 +520,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
End Get
End Property
''' <summary>
''' Do not use this method directly! Instead, go through <see cref="FileCodeModel.CreateCodeElement(Of T)(SyntaxNode)"/>
''' </summary>
Public Overloads Overrides Function CreateInternalCodeElement(
state As CodeModelState,
fileCodeModel As FileCodeModel,
......
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.CodeCleanup.Providers;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -1376,6 +1377,72 @@ End Module
Verify(code, expected);
}
[Fact]
[WorkItem(1085887)]
[Trait(Traits.Feature, Traits.Features.RemoveUnnecessaryLineContinuation)]
public void DontRemoveLineContinuationInVisualBasic9()
{
var code = @"[|
Module Program
Function Add( _
i As Integer, _
j As Integer, _
) As Integer
Return i + j
End Function
End Module
|]";
var expected = @"
Module Program
Function Add( _
i As Integer, _
j As Integer, _
) As Integer
Return i + j
End Function
End Module
";
Verify(code, expected, langVersion: LanguageVersion.VisualBasic9);
}
[Fact]
[WorkItem(1085887)]
[Trait(Traits.Feature, Traits.Features.RemoveUnnecessaryLineContinuation)]
public void RemoveLineContinuationInVisualBasic10_11_12_And_14()
{
var code = @"[|
Module Program
Function Add( _
i As Integer, _
j As Integer, _
) As Integer
Return i + j
End Function
End Module
|]";
var expected = @"
Module Program
Function Add(
i As Integer,
j As Integer,
) As Integer
Return i + j
End Function
End Module
";
Verify(code, expected, langVersion: LanguageVersion.VisualBasic10);
Verify(code, expected, langVersion: LanguageVersion.VisualBasic11);
Verify(code, expected, langVersion: LanguageVersion.VisualBasic12);
Verify(code, expected);
}
private string CreateMethod(string body)
{
return @"Imports System
......@@ -1385,13 +1452,13 @@ End Sub
End Class";
}
private void Verify(string codeWithMarker, string expectedResult)
private void Verify(string codeWithMarker, string expectedResult, LanguageVersion langVersion = LanguageVersion.VisualBasic14)
{
var codeWithoutMarker = default(string);
var textSpans = (IList<TextSpan>)new List<TextSpan>();
MarkupTestFile.GetSpans(codeWithMarker, out codeWithoutMarker, out textSpans);
var document = CreateDocument(codeWithoutMarker, LanguageNames.VisualBasic);
var document = CreateDocument(codeWithoutMarker, LanguageNames.VisualBasic, langVersion);
var codeCleanups = CodeCleaner.GetDefaultProviders(document).Where(p => p.Name == PredefinedCodeCleanupProviderNames.RemoveUnnecessaryLineContinuation || p.Name == PredefinedCodeCleanupProviderNames.Format);
var cleanDocument = CodeCleaner.CleanupAsync(document, textSpans[0], codeCleanups).Result;
......@@ -1399,11 +1466,17 @@ private void Verify(string codeWithMarker, string expectedResult)
Assert.Equal(expectedResult, cleanDocument.GetSyntaxRootAsync().Result.ToFullString());
}
private static Document CreateDocument(string code, string language)
private static Document CreateDocument(string code, string language, LanguageVersion langVersion)
{
var solution = new AdhocWorkspace().CurrentSolution;
var projectId = ProjectId.CreateNewId();
var project = solution.AddProject(projectId, "Project", "Project.dll", language).GetProject(projectId);
var project = solution
.AddProject(projectId, "Project", "Project.dll", language)
.GetProject(projectId);
var parseOptions = (VisualBasicParseOptions)project.ParseOptions;
parseOptions = parseOptions.WithLanguageVersion(langVersion);
project = project.WithParseOptions(parseOptions);
return project.AddDocument("Document", SourceText.From(code));
}
......
......@@ -20,6 +20,12 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers
End Property
Public Async Function CleanupAsync(document As Document, spans As IEnumerable(Of TextSpan), Optional cancellationToken As CancellationToken = Nothing) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync
' Is this VB 9? If so, we shouldn't remove line continuations because implicit line continuation was introduced in VB 10.
Dim parseOptions = TryCast(document.Project.ParseOptions, VisualBasicParseOptions)
If parseOptions?.LanguageVersion <= LanguageVersion.VisualBasic9 Then
Return document
End If
Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False)
Dim newRoot = Cleanup(root, spans, document.Project.Solution.Workspace, cancellationToken)
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册