提交 fb22e0f2 编写于 作者: A AlekseyTs 提交者: GitHub

Merge pull request #14105 from AlekseyTs/Issue7659

Properly calculate OverridenProperty for synthesized WithEvents overrides.
...@@ -26590,7 +26590,7 @@ public static void TakeOutParam(out int x, long y) ...@@ -26590,7 +26590,7 @@ public static void TakeOutParam(out int x, long y)
"; ";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script);
compilation.VerifyDiagnostics( compilation.GetDeclarationDiagnostics().Verify(
// (3,24): error CS7019: Type of 'x1' cannot be inferred since its initializer directly or indirectly refers to the definition. // (3,24): error CS7019: Type of 'x1' cannot be inferred since its initializer directly or indirectly refers to the definition.
// H.TakeOutParam(out var x1, x1); // H.TakeOutParam(out var x1, x1);
Diagnostic(ErrorCode.ERR_RecursivelyTypedVariable, "x1").WithArguments("x1").WithLocation(3, 24) Diagnostic(ErrorCode.ERR_RecursivelyTypedVariable, "x1").WithArguments("x1").WithLocation(3, 24)
...@@ -365,6 +365,10 @@ Friend Class MockNamedTypeSymbol ...@@ -365,6 +365,10 @@ Friend Class MockNamedTypeSymbol
Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken) Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken)
Throw New InvalidOperationException() Throw New InvalidOperationException()
End Sub End Sub
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
Friend Class MockMethodSymbol Friend Class MockMethodSymbol
......
...@@ -295,7 +295,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -295,7 +295,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get End Get
End Property End Property
Friend Overrides Sub AddSynthesizedAttributes(compilationState as ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData)) Friend Overrides Sub AddSynthesizedAttributes(compilationState As ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedAttributes(compilationState, attributes) MyBase.AddSynthesizedAttributes(compilationState, attributes)
Dim compilation = Me.DeclaringCompilation Dim compilation = Me.DeclaringCompilation
...@@ -308,5 +308,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -308,5 +308,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)) WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor))
End Sub End Sub
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Namespace End Namespace
...@@ -300,6 +300,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -300,6 +300,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Throw ExceptionUtilities.Unreachable Throw ExceptionUtilities.Unreachable
End Function End Function
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Class End Class
......
...@@ -355,6 +355,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -355,6 +355,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Throw ExceptionUtilities.Unreachable Throw ExceptionUtilities.Unreachable
End Sub End Sub
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Class End Class
......
...@@ -396,6 +396,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -396,6 +396,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Throw ExceptionUtilities.Unreachable Throw ExceptionUtilities.Unreachable
End Sub End Sub
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
#Region "IErrorTypeSymbol members" #Region "IErrorTypeSymbol members"
Public ReadOnly Property IErrorTypeSymbol_CandidateSymbols As ImmutableArray(Of ISymbol) Implements IErrorTypeSymbol.CandidateSymbols Public ReadOnly Property IErrorTypeSymbol_CandidateSymbols As ImmutableArray(Of ISymbol) Implements IErrorTypeSymbol.CandidateSymbols
......
...@@ -1475,6 +1475,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ...@@ -1475,6 +1475,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Next Next
End Function End Function
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Namespace End Namespace
...@@ -1080,6 +1080,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -1080,6 +1080,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' <returns>True if this Is an interface type.</returns> ''' <returns>True if this Is an interface type.</returns>
Friend MustOverride ReadOnly Property IsInterface As Boolean Friend MustOverride ReadOnly Property IsInterface As Boolean
''' <summary>
''' Get synthesized WithEvents overrides that aren't returned by <see cref="GetMembers"/>
''' </summary>
Friend MustOverride Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
#Region "INamedTypeSymbol" #Region "INamedTypeSymbol"
Private ReadOnly Property INamedTypeSymbol_Arity As Integer Implements INamedTypeSymbol.Arity Private ReadOnly Property INamedTypeSymbol_Arity As Integer Implements INamedTypeSymbol.Arity
......
...@@ -522,5 +522,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting ...@@ -522,5 +522,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
Public Overrides Function GetDocumentationCommentXml(Optional preferredCulture As CultureInfo = Nothing, Optional expandIncludes As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As String Public Overrides Function GetDocumentationCommentXml(Optional preferredCulture As CultureInfo = Nothing, Optional expandIncludes As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As String
Return _underlyingType.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken) Return _underlyingType.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken)
End Function End Function
Friend Overrides Iterator Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
For Each underlying As PropertySymbol In _underlyingType.GetSynthesizedWithEventsOverrides()
Yield RetargetingTranslator.Retarget(underlying)
Next
End Function
End Class End Class
End Namespace End Namespace
...@@ -191,5 +191,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -191,5 +191,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Next Next
End Sub End Sub
Friend Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
' All infrastructure for proper WithEvents handling is in SourceNamedTypeSymbol,
' but this type derives directly from SourceMemberContainerTypeSymbol, which is a base class of
' SourceNamedTypeSymbol.
' Tracked by https://github.com/dotnet/roslyn/issues/14073.
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Namespace End Namespace
...@@ -697,6 +697,53 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -697,6 +697,53 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim overriddenInThisType As ArrayBuilder(Of TSymbol) = ArrayBuilder(Of TSymbol).GetInstance() Dim overriddenInThisType As ArrayBuilder(Of TSymbol) = ArrayBuilder(Of TSymbol).GetInstance()
For Each sym In currType.GetMembers(overridingSym.Name) For Each sym In currType.GetMembers(overridingSym.Name)
ProcessMemberWithMatchingName(sym, overridingSym, overridingIsFromSomeCompilation, overridingContainingType, inexactOverriddenMembers,
inaccessibleBuilder, overriddenInThisType, stopLookup, haveExactMatch)
Next
If overridingSym.Kind = SymbolKind.Property Then
Dim prop = DirectCast(DirectCast(overridingSym, Object), PropertySymbol)
If prop.IsImplicitlyDeclared AndAlso prop.IsWithEvents Then
For Each sym In currType.GetSynthesizedWithEventsOverrides()
If sym.Name.Equals(prop.Name) Then
ProcessMemberWithMatchingName(sym, overridingSym, overridingIsFromSomeCompilation, overridingContainingType, inexactOverriddenMembers,
inaccessibleBuilder, overriddenInThisType, stopLookup, haveExactMatch)
End If
Next
End If
End If
If overriddenInThisType.Count > 1 Then
RemoveMembersWithConflictingAccessibility(overriddenInThisType)
End If
If overriddenInThisType.Count > 0 Then
If haveExactMatch Then
Debug.Assert(stopLookup)
overriddenBuilder.Clear()
End If
If overriddenBuilder.Count = 0 Then
overriddenBuilder.AddRange(overriddenInThisType)
End If
End If
overriddenInThisType.Free()
Return stopLookup
End Function
Private Shared Sub ProcessMemberWithMatchingName(
sym As Symbol,
overridingSym As TSymbol,
overridingIsFromSomeCompilation As Boolean,
overridingContainingType As NamedTypeSymbol,
inexactOverriddenMembers As ArrayBuilder(Of TSymbol),
inaccessibleBuilder As ArrayBuilder(Of TSymbol),
overriddenInThisType As ArrayBuilder(Of TSymbol),
ByRef stopLookup As Boolean,
ByRef haveExactMatch As Boolean
)
' Use original definition for accessibility check, because substitutions can cause ' Use original definition for accessibility check, because substitutions can cause
' reductions in accessibility that aren't appropriate (see bug #12038 for example). ' reductions in accessibility that aren't appropriate (see bug #12038 for example).
Dim accessible = AccessCheck.IsSymbolAccessible(sym.OriginalDefinition, overridingContainingType.OriginalDefinition, Nothing, useSiteDiagnostics:=Nothing) Dim accessible = AccessCheck.IsSymbolAccessible(sym.OriginalDefinition, overridingContainingType.OriginalDefinition, Nothing, useSiteDiagnostics:=Nothing)
...@@ -744,26 +791,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -744,26 +791,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
' Any accessible symbol of different kind stops further lookup ' Any accessible symbol of different kind stops further lookup
stopLookup = True stopLookup = True
End If End If
Next End Sub
If overriddenInThisType.Count > 1 Then
RemoveMembersWithConflictingAccessibility(overriddenInThisType)
End If
If overriddenInThisType.Count > 0 Then
If haveExactMatch Then
Debug.Assert(stopLookup)
overriddenBuilder.Clear()
End If
If overriddenBuilder.Count = 0 Then
overriddenBuilder.AddRange(overriddenInThisType)
End If
End If
overriddenInThisType.Free()
Return stopLookup
End Function
Private Shared Sub AddMemberToABuilder(member As TSymbol, Private Shared Sub AddMemberToABuilder(member As TSymbol,
builder As ArrayBuilder(Of TSymbol)) builder As ArrayBuilder(Of TSymbol))
......
...@@ -35,6 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -35,6 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
' Overriding properties are created when a methods "Handles" is bound and can happen concurrently. ' Overriding properties are created when a methods "Handles" is bound and can happen concurrently.
' We need this table to ensure that we create each override just once. ' We need this table to ensure that we create each override just once.
Private _lazyWithEventsOverrides As ConcurrentDictionary(Of PropertySymbol, SynthesizedOverridingWithEventsProperty) Private _lazyWithEventsOverrides As ConcurrentDictionary(Of PropertySymbol, SynthesizedOverridingWithEventsProperty)
Private _withEventsOverridesAreFrozen As Boolean
' method flags for the synthesized delegate methods ' method flags for the synthesized delegate methods
Friend Const DelegateConstructorMethodFlags As SourceMemberFlags = SourceMemberFlags.MethodKindConstructor Friend Const DelegateConstructorMethodFlags As SourceMemberFlags = SourceMemberFlags.MethodKindConstructor
...@@ -99,7 +100,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -99,7 +100,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
#Region "Completion" #Region "Completion"
Protected Overrides Sub GenerateAllDeclarationErrorsImpl(cancellationToken As CancellationToken) Protected Overrides Sub GenerateAllDeclarationErrorsImpl(cancellationToken As CancellationToken)
#If DEBUG Then
EnsureAllHandlesAreBound()
#End If
MyBase.GenerateAllDeclarationErrorsImpl(cancellationToken) MyBase.GenerateAllDeclarationErrorsImpl(cancellationToken)
_withEventsOverridesAreFrozen = True
cancellationToken.ThrowIfCancellationRequested() cancellationToken.ThrowIfCancellationRequested()
PerformComClassAnalysis() PerformComClassAnalysis()
...@@ -144,7 +150,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -144,7 +150,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
' for cases where constraint checking may result in a recursive binding attempt. ' for cases where constraint checking may result in a recursive binding attempt.
Private Function CreateLocationSpecificBinderForType(tree As SyntaxTree, location As BindingLocation) As Binder Private Function CreateLocationSpecificBinderForType(tree As SyntaxTree, location As BindingLocation) As Binder
Debug.Assert(location <> BindingLocation.None) Debug.Assert(location <> BindingLocation.None)
Dim binder As binder = BinderBuilder.CreateBinderForType(ContainingSourceModule, tree, Me) Dim binder As Binder = BinderBuilder.CreateBinderForType(ContainingSourceModule, tree, Me)
Return New LocationSpecificBinder(location, binder) Return New LocationSpecificBinder(location, binder)
End Function End Function
#End Region #End Region
...@@ -164,7 +170,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -164,7 +170,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim node = syntaxRef.GetVisualBasicSyntax() Dim node = syntaxRef.GetVisualBasicSyntax()
' Set up a binder for this part of the type. ' Set up a binder for this part of the type.
Dim binder As binder = BinderBuilder.CreateBinderForType(ContainingSourceModule, syntaxRef.SyntaxTree, Me) Dim binder As Binder = BinderBuilder.CreateBinderForType(ContainingSourceModule, syntaxRef.SyntaxTree, Me)
' Script and implicit classes are syntactically represented by CompilationUnitSyntax or NamespaceBlockSyntax nodes. ' Script and implicit classes are syntactically represented by CompilationUnitSyntax or NamespaceBlockSyntax nodes.
Dim staticInitializers As ArrayBuilder(Of FieldOrPropertyInitializer) = Nothing Dim staticInitializers As ArrayBuilder(Of FieldOrPropertyInitializer) = Nothing
...@@ -2472,10 +2478,36 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -2472,10 +2478,36 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Else Else
' we need to create a lambda here since we need to close over baseProperty ' we need to create a lambda here since we need to close over baseProperty
' we will however create a lambda only on a cache miss, hopefully not very often. ' we will however create a lambda only on a cache miss, hopefully not very often.
Return overridesDict.GetOrAdd(baseProperty, Function() New SynthesizedOverridingWithEventsProperty(baseProperty, Me)) Return overridesDict.GetOrAdd(baseProperty, Function()
Debug.Assert(Not _withEventsOverridesAreFrozen)
Return New SynthesizedOverridingWithEventsProperty(baseProperty, Me)
End Function)
End If End If
End Function End Function
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
EnsureAllHandlesAreBound()
Dim overridesDict = Me._lazyWithEventsOverrides
If overridesDict IsNot Nothing Then
Return overridesDict.Values
End If
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
Private Sub EnsureAllHandlesAreBound()
If Not _withEventsOverridesAreFrozen Then
For Each member In Me.GetMembersUnordered()
If member.Kind = SymbolKind.Method Then
Dim notUsed = DirectCast(member, MethodSymbol).HandledEvents
End If
Next
_withEventsOverridesAreFrozen = True
End If
End Sub
Protected Overrides Sub AddEntryPointIfNeeded(membersBuilder As MembersAndInitializersBuilder) Protected Overrides Sub AddEntryPointIfNeeded(membersBuilder As MembersAndInitializersBuilder)
If Me.TypeKind = TypeKind.Class AndAlso Not Me.IsGenericType Then If Me.TypeKind = TypeKind.Class AndAlso Not Me.IsGenericType Then
Dim mainTypeName As String = DeclaringCompilation.Options.MainTypeName Dim mainTypeName As String = DeclaringCompilation.Options.MainTypeName
......
...@@ -1009,6 +1009,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -1009,6 +1009,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend Overrides Function GetUnificationUseSiteDiagnosticRecursive(owner As Symbol, ByRef checkedTypes As HashSet(Of TypeSymbol)) As DiagnosticInfo Friend Overrides Function GetUnificationUseSiteDiagnosticRecursive(owner As Symbol, ByRef checkedTypes As HashSet(Of TypeSymbol)) As DiagnosticInfo
Return Nothing Return Nothing
End Function End Function
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
Private Class SynthesizedComMethod Private Class SynthesizedComMethod
......
...@@ -536,6 +536,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -536,6 +536,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return OriginalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken) Return OriginalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken)
End Function End Function
Friend NotOverridable Overrides Iterator Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
For Each definition In OriginalDefinition.GetSynthesizedWithEventsOverrides()
Yield SubstituteTypeParametersForMemberProperty(definition)
Next
End Function
''' <summary> ''' <summary>
''' Base class for symbols representing non-generic or open generic types contained within constructed generic type. ''' Base class for symbols representing non-generic or open generic types contained within constructed generic type.
''' For example: A(Of Integer).B, A(Of Integer).B.C or A(Of Integer).B.C(Of ). ''' For example: A(Of Integer).B, A(Of Integer).B.C or A(Of Integer).B.C(Of ).
......
...@@ -431,6 +431,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -431,6 +431,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return Nothing Return Nothing
End Get End Get
End Property End Property
Friend Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Namespace End Namespace
...@@ -999,5 +999,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -999,5 +999,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken) Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken)
Me._underlyingType.GenerateDeclarationErrors(cancellationToken) Me._underlyingType.GenerateDeclarationErrors(cancellationToken)
End Sub End Sub
Friend Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
' We might need to have a real implementation here, depending on the resolution
' of https://github.com/dotnet/roslyn/issues/14104
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Namespace End Namespace
...@@ -317,6 +317,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -317,6 +317,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Throw ExceptionUtilities.Unreachable Throw ExceptionUtilities.Unreachable
End Function End Function
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
Private NotInheritable Class ConstructedSymbol Private NotInheritable Class ConstructedSymbol
Inherits UnboundGenericType Inherits UnboundGenericType
......
...@@ -356,6 +356,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator ...@@ -356,6 +356,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Next Next
End Sub End Sub
Friend Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function
End Class End Class
End Namespace End Namespace
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册