Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
5abfbeeb
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5abfbeeb
编写于
7月 22, 2015
作者:
W
Wonseok Chae
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
VS crash during EnC around active statements
It updates earlier C# implementation and ports to VB (#3894)
上级
3c027a4c
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
261 addition
and
27 deletion
+261
-27
src/Compilers/VisualBasic/Portable/Syntax/SyntaxEquivalence.vb
...ompilers/VisualBasic/Portable/Syntax/SyntaxEquivalence.vb
+26
-0
src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
...atures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
+29
-2
src/EditorFeatures/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb
...s/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb
+151
-5
src/EditorFeatures/VisualBasicTest/EditAndContinue/Helpers/RudeEditTestBase.vb
...sualBasicTest/EditAndContinue/Helpers/RudeEditTestBase.vb
+1
-1
src/EditorFeatures/VisualBasicTest/EditAndContinue/RudeEditTopLevelTests.vb
.../VisualBasicTest/EditAndContinue/RudeEditTopLevelTests.vb
+18
-2
src/Features/CSharp/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
...s/CSharp/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
+2
-13
src/Features/Core/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
...s/Core/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
+8
-2
src/Features/VisualBasic/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb
...sic/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb
+26
-2
未找到文件。
src/Compilers/VisualBasic/Portable/Syntax/SyntaxEquivalence.vb
浏览文件 @
5abfbeeb
...
...
@@ -78,6 +78,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
Dim
kind
=
CType
(
before
.
RawKind
,
SyntaxKind
)
If
Not
AreModifiersEquivalent
(
before
,
after
,
kind
)
Then
Return
False
End
If
If
topLevel
Then
Select
Case
kind
Case
SyntaxKind
.
SubBlock
,
...
...
@@ -173,5 +177,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
Return
True
End
If
End
Function
Private
Function
AreModifiersEquivalent
(
before
As
GreenNode
,
after
As
GreenNode
,
kind
As
SyntaxKind
)
As
Boolean
Select
Case
kind
Case
SyntaxKind
.
SubBlock
,
SyntaxKind
.
FunctionBlock
Dim
beforeModifiers
=
DirectCast
(
before
,
Green
.
MethodBlockBaseSyntax
).
Begin
.
Modifiers
Dim
afterModifiers
=
DirectCast
(
after
,
Green
.
MethodBlockBaseSyntax
).
Begin
.
Modifiers
If
beforeModifiers
.
Count
<>
afterModifiers
.
Count
Then
Return
False
End
If
For
i
=
0
To
beforeModifiers
.
Count
-
1
If
Not
beforeModifiers
.
Any
(
afterModifiers
(
i
).
Kind
)
Then
Return
False
End
If
Next
End
Select
Return
True
End
Function
End
Module
End
Namespace
src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
浏览文件 @
5abfbeeb
...
...
@@ -7437,8 +7437,7 @@ static async Task<int> F()
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
InsertAroundActiveStatement
,
"await"
,
CSharpFeaturesResources
.
AwaitExpression
),
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"static async Task<int> F()"
));
Diagnostic
(
RudeEditKind
.
InsertAroundActiveStatement
,
"await"
,
CSharpFeaturesResources
.
AwaitExpression
));
}
[
Fact
]
...
...
@@ -7557,6 +7556,34 @@ static async void F()
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"static async void F()"
));
}
[
Fact
]
public
void
MethodToAsyncMethod_WithActiveStatementInLambda_3
()
{
string
src1
=
@"
class C
{
static void F()
{
var f = new Action(() => { <AS:0>Console.WriteLine(1);</AS:0> });
}
}
"
;
string
src2
=
@"
class C
{
static async void F()
{
var f = new Action(async () => { <AS:0>Console.WriteLine(1);</AS:0> });
}
}
"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"()"
));
}
[
Fact
]
public
void
MethodToAsyncMethod_WithLambda
()
{
...
...
src/EditorFeatures/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb
浏览文件 @
5abfbeeb
...
...
@@ -4738,7 +4738,7 @@ End Class
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithActiveStatement
()
Public
Sub
MethodToAsyncMethod_WithActiveStatement
1
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
...
...
@@ -4767,14 +4767,71 @@ End Class
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithActiveStatementInLambda
()
Public
Sub
MethodToAsyncMethod_WithActiveStatement2
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
Class C
<AS:0>Function F() As Task(Of Integer)</AS:0>
Console.WriteLine(1)
Return Task.FromResult(1)
End Function
End Class
"
Dim
src2
=
"
Imports System
Imports System.Threading.Tasks
Class C
<AS:0>Async Function F() As Task(Of Integer)</AS:0>
Console.WriteLine(1)
Return 1
End Function
End Class
"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
Dim
active
=
GetActiveStatements
(
src1
,
src2
)
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"Async Function F()"
))
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithActiveStatement3
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
Class C
Function F() As Task(Of Integer)
<AS:0>Console.WriteLine(1)</AS:0>
Return Task.FromResult(1)
End Function
End Class
"
Dim
src2
=
"
Imports System
Imports System.Threading.Tasks
Class C
Async Function F() As Task(Of Integer)
<AS:0>Console.WriteLine(1)</AS:0>
Return 1
End Function
End Class
"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
Dim
active
=
GetActiveStatements
(
src1
,
src2
)
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"Async Function F()"
))
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithActiveStatementInLambda1
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
Class C
Function F() As Task(Of Integer)
Dim a = Sub() <AS:0>Console.WriteLine(1)</AS:0>
a()
Return Task.FromResult(1)
End Function
End Class
...
...
@@ -4785,7 +4842,6 @@ Imports System.Threading.Tasks
Class C
Async Function F() As Task(Of Integer)
Dim a = Sub() <AS:0>Console.WriteLine(1)</AS:0>
a()
Return Await Task.FromResult(1)
End Function
End Class
...
...
@@ -4797,7 +4853,69 @@ End Class
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithoutActiveStatement
()
Public
Sub
MethodToAsyncMethod_WithActiveStatementInLambda2
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
Class C
Function F() As Task(Of Integer)
Dim a = Sub() <AS:1>Console.WriteLine(1)</AS:1>
<AS:0>a()</AS:0>
Return Task.FromResult(1)
End Function
End Class
"
Dim
src2
=
"
Imports System
Imports System.Threading.Tasks
Class C
Async Function F() As Task(Of Integer)
Dim a = Sub() <AS:1>Console.WriteLine(1)</AS:1>
<AS:0>a()</AS:0>
Return 1
End Function
End Class
"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
Dim
active
=
GetActiveStatements
(
src1
,
src2
)
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"Async Function F()"
))
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithActiveStatementInLambda3
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
Class C
Sub F()
Dim a = Sub() <AS:1>Console.WriteLine(1)</AS:1>
<AS:0>a()</AS:0>
Return
End Sub
End Class
"
Dim
src2
=
"
Imports System
Imports System.Threading.Tasks
Class C
Async Sub F()
Dim a = Sub() <AS:1>Console.WriteLine(1)</AS:1>
<AS:0>a()</AS:0>
Return
End Sub
End Class
"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
Dim
active
=
GetActiveStatements
(
src1
,
src2
)
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
"Async Sub F()"
))
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithoutActiveStatement1
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
...
...
@@ -4823,6 +4941,34 @@ End Class
edits
.
VerifyRudeDiagnostics
(
active
)
End
Sub
<
Fact
>
Public
Sub
MethodToAsyncMethod_WithoutActiveStatement2
()
Dim
src1
=
"
Imports System
Imports System.Threading.Tasks
Class C
Sub F()
Console.WriteLine(1)
Return
End Sub
End Class
"
Dim
src2
=
"
Imports System
Imports System.Threading.Tasks
Class C
Async Sub F()
Console.WriteLine(1)
Return
End Sub
End Class
"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
Dim
active
=
GetActiveStatements
(
src1
,
src2
)
edits
.
VerifyRudeDiagnostics
(
active
)
End
Sub
#End Region
#Region "On Error"
...
...
src/EditorFeatures/VisualBasicTest/EditAndContinue/Helpers/RudeEditTestBase.vb
浏览文件 @
5abfbeeb
...
...
@@ -60,7 +60,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests
Dim
diagnostics
=
New
List
(
Of
RudeEditDiagnostic
)()
Dim
needsSyntaxMap
As
Boolean
Dim
match
=
Analyzer
.
ComputeBodyMatch
(
m1
,
m2
,
{
New
AbstractEditAndContinueAnalyzer
.
ActiveNode
}
,
diagnostics
,
needsSyntaxMap
)
Dim
match
=
Analyzer
.
ComputeBodyMatch
(
m1
,
m2
,
Array
.
Empty
(
Of
AbstractEditAndContinueAnalyzer
.
ActiveNode
)()
,
diagnostics
,
needsSyntaxMap
)
Assert
.
Equal
(
stateMachine
<>
StateMachineKind
.
None
,
needsSyntaxMap
)
...
...
src/EditorFeatures/VisualBasicTest/EditAndContinue/RudeEditTopLevelTests.vb
浏览文件 @
5abfbeeb
...
...
@@ -1898,16 +1898,32 @@ End Class
End
Sub
<
Fact
>
Public
Sub
MethodUpdate_AsyncModifier
()
Public
Sub
MethodUpdate_AsyncModifier1
()
Dim
src1
=
"Class C : "
&
vbLf
&
"Function F() As Task(Of String) : End Function : End Class"
Dim
src2
=
"Class C : "
&
vbLf
&
"Async Function F() As Task(Of String) : End Function : End Class"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
edits
.
VerifyEdits
(
"Update [Function F() As Task(Of String) : End Function]@11 -> [Async Function F() As Task(Of String) : End Function]@11"
,
"Update [Function F() As Task(Of String)]@11 -> [Async Function F() As Task(Of String)]@11"
)
edits
.
VerifyRudeDiagnostics
()
End
Sub
<
Fact
>
Public
Sub
MethodUpdate_AsyncModifier2
()
Dim
src1
=
"Class C : "
&
vbLf
&
"Async Function F() As Task(Of String) : End Function : End Class"
Dim
src2
=
"Class C : "
&
vbLf
&
"Function F() As Task(Of String) : End Function : End Class"
Dim
edits
=
GetTopEdits
(
src1
,
src2
)
edits
.
VerifyEdits
(
"Update [Async Function F() As Task(Of String) : End Function]@11 -> [Function F() As Task(Of String) : End Function]@11"
,
"Update [Async Function F() As Task(Of String)]@11 -> [Function F() As Task(Of String)]@11"
)
edits
.
VerifyRudeDiagnostics
()
edits
.
VerifyRudeDiagnostics
(
Diagnostic
(
RudeEditKind
.
ModifiersUpdate
,
"Function F()"
,
FeaturesResources
.
Method
))
End
Sub
<
Fact
>
...
...
src/Features/CSharp/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
浏览文件 @
5abfbeeb
...
...
@@ -3011,15 +3011,12 @@ private static bool IsSimpleAwaitAssignment(SyntaxNode node, SyntaxNode awaitExp
internal
override
void
ReportOtherRudeEditsAroundActiveStatement
(
List
<
RudeEditDiagnostic
>
diagnostics
,
Match
<
SyntaxNode
>
match
,
SyntaxNode
oldBody
,
SyntaxNode
newBody
,
SyntaxNode
oldActiveStatement
,
SyntaxNode
newActiveStatement
,
bool
isLeaf
)
{
ReportRudeEditsForAncestorsDeclaringInterStatementTemps
(
diagnostics
,
match
,
oldActiveStatement
,
newActiveStatement
,
isLeaf
);
ReportRudeEditsForCheckedStatements
(
diagnostics
,
oldActiveStatement
,
newActiveStatement
,
isLeaf
);
ReportRudeEditsForStateMachineMethod
(
diagnostics
,
oldBody
,
newBody
,
oldActiveStatement
,
newActiveStatement
);
}
private
void
ReportRudeEditsForCheckedStatements
(
...
...
@@ -3132,19 +3129,11 @@ private static bool DeclareSameIdentifiers(SeparatedSyntaxList<VariableDeclarato
return
true
;
}
privat
e
void
ReportRudeEditsForStateMachineMethod
(
internal
overrid
e
void
ReportRudeEditsForStateMachineMethod
(
List
<
RudeEditDiagnostic
>
diagnostics
,
SyntaxNode
oldBody
,
SyntaxNode
newBody
,
SyntaxNode
oldActiveStatement
,
SyntaxNode
newActiveStatement
)
SyntaxNode
newBody
)
{
var
isInLambdaBody
=
FindEnclosingLambdaBody
(
oldBody
,
oldActiveStatement
);
if
(
isInLambdaBody
!=
null
)
{
return
;
}
// It is allow to update a regular method to an async method or an iterator.
// The only restriction is a presence of an active statement in the method body
// since the debugger does not support remapping active statements to a different method.
...
...
src/Features/Core/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
浏览文件 @
5abfbeeb
...
...
@@ -234,7 +234,8 @@ private SyntaxNode FindStatement(SyntaxNode declarationBody, int position, out i
internal
abstract
void
ReportSyntacticRudeEdits
(
List
<
RudeEditDiagnostic
>
diagnostics
,
Match
<
SyntaxNode
>
match
,
Edit
<
SyntaxNode
>
edit
,
Dictionary
<
SyntaxNode
,
EditKind
>
editMap
);
internal
abstract
void
ReportEnclosingExceptionHandlingRudeEdits
(
List
<
RudeEditDiagnostic
>
diagnostics
,
IEnumerable
<
Edit
<
SyntaxNode
>>
exceptionHandlingEdits
,
SyntaxNode
oldStatement
,
SyntaxNode
newStatement
);
internal
abstract
void
ReportOtherRudeEditsAroundActiveStatement
(
List
<
RudeEditDiagnostic
>
diagnostics
,
Match
<
SyntaxNode
>
match
,
SyntaxNode
oldBody
,
SyntaxNode
newBody
,
SyntaxNode
oldStatement
,
SyntaxNode
newStatement
,
bool
isLeaf
);
internal
abstract
void
ReportOtherRudeEditsAroundActiveStatement
(
List
<
RudeEditDiagnostic
>
diagnostics
,
Match
<
SyntaxNode
>
match
,
SyntaxNode
oldStatement
,
SyntaxNode
newStatement
,
bool
isLeaf
);
internal
abstract
void
ReportRudeEditsForStateMachineMethod
(
List
<
RudeEditDiagnostic
>
diagnostics
,
SyntaxNode
oldBody
,
SyntaxNode
newBody
);
internal
abstract
void
ReportMemberUpdateRudeEdits
(
List
<
RudeEditDiagnostic
>
diagnostics
,
SyntaxNode
newMember
,
TextSpan
?
span
);
internal
abstract
void
ReportInsertedMemberSymbolRudeEdits
(
List
<
RudeEditDiagnostic
>
diagnostics
,
ISymbol
newSymbol
);
internal
abstract
void
ReportStateMachineSuspensionPointRudeEdits
(
List
<
RudeEditDiagnostic
>
diagnostics
,
SyntaxNode
oldNode
,
SyntaxNode
newNode
);
...
...
@@ -1062,7 +1063,7 @@ internal struct UpdatedMemberInfo
}
// other statements around active statement:
ReportOtherRudeEditsAroundActiveStatement
(
diagnostics
,
match
,
old
Body
,
newBody
,
old
StatementSyntax
,
newStatementSyntax
,
isLeaf
);
ReportOtherRudeEditsAroundActiveStatement
(
diagnostics
,
match
,
oldStatementSyntax
,
newStatementSyntax
,
isLeaf
);
}
else
if
(
match
==
null
)
{
...
...
@@ -1305,6 +1306,11 @@ internal struct UpdatedMemberInfo
ReportStateMachineSuspensionPointRudeEdits
(
diagnostics
,
oldStateMachineSuspensionPoints
[
i
],
newStateMachineSuspensionPoints
[
i
]);
}
}
else
if
(
activeNodes
.
Length
>
0
)
{
// other state machine related issue around active statement:
ReportRudeEditsForStateMachineMethod
(
diagnostics
,
oldBody
,
newBody
);
}
return
match
;
}
...
...
src/Features/VisualBasic/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb
浏览文件 @
5abfbeeb
...
...
@@ -2594,6 +2594,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue
newModifiers
=
newModifiers
.
RemoveAt
(
newAsyncIndex
)
End
If
' 'async' keyword is allowed to add, but not to remove
If
oldAsyncIndex
>=
0
AndAlso
newAsyncIndex
<
0
Then
Return
False
End
If
Dim
oldIteratorIndex
=
oldModifiers
.
IndexOf
(
SyntaxKind
.
IteratorKeyword
)
Dim
newIteratorIndex
=
newModifiers
.
IndexOf
(
SyntaxKind
.
IteratorKeyword
)
...
...
@@ -2605,6 +2610,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue
newModifiers
=
newModifiers
.
RemoveAt
(
newIteratorIndex
)
End
If
' 'iterator' keyword is allowed to add, but not to remove
If
oldIteratorIndex
>=
0
AndAlso
newIteratorIndex
<
0
Then
Return
False
End
If
Return
SyntaxFactory
.
AreEquivalent
(
oldModifiers
,
newModifiers
)
End
Function
...
...
@@ -3091,8 +3101,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue
Friend
Overrides
Sub
ReportOtherRudeEditsAroundActiveStatement
(
diagnostics
As
List
(
Of
RudeEditDiagnostic
),
match
As
Match
(
Of
SyntaxNode
),
oldBody
As
SyntaxNode
,
newBody
As
SyntaxNode
,
oldActiveStatement
As
SyntaxNode
,
newActiveStatement
As
SyntaxNode
,
isLeaf
As
Boolean
)
...
...
@@ -3154,6 +3162,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue
areSimilar
:
=
Function
(
n1
,
n2
)
AreEquivalentIgnoringLambdaBodies
(
DirectCast
(
n1
.
ForOrForEachStatement
,
ForEachStatementSyntax
).
ControlVariable
,
DirectCast
(
n2
.
ForOrForEachStatement
,
ForEachStatementSyntax
).
ControlVariable
))
End
Sub
Friend
Overrides
Sub
ReportRudeEditsForStateMachineMethod
(
diagnostics
As
List
(
Of
RudeEditDiagnostic
),
oldBody
As
SyntaxNode
,
newBody
As
SyntaxNode
)
' It Is allow to update a regular method to an async method Or an iterator.
' The only restriction Is a presence of an active statement in the method body
' since the debugger does Not support remapping active statements to a different method.
Dim
IsAsyncAdded
=
Not
SyntaxUtilities
.
IsAsyncMethodOrLambda
(
oldBody
)
AndAlso
SyntaxUtilities
.
IsAsyncMethodOrLambda
(
newBody
)
Dim
IsIteratorAdded
=
Not
SyntaxUtilities
.
IsIteratorMethodOrLambda
(
oldBody
)
AndAlso
SyntaxUtilities
.
IsIteratorMethodOrLambda
(
newBody
)
If
IsAsyncAdded
OrElse
IsIteratorAdded
Then
diagnostics
.
Add
(
New
RudeEditDiagnostic
(
RudeEditKind
.
UpdatingStateMachineMethodAroundActiveStatement
,
GetDiagnosticSpan
(
newBody
,
EditKind
.
Update
)))
End
If
End
Sub
#End Region
End
Class
End
Namespace
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录