Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
cc1186ba
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,发现更多精彩内容 >>
提交
cc1186ba
编写于
5月 24, 2017
作者:
C
CyrusNajmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix crash with using 'replce property with method' with interfaces in VB.
上级
732a69f1
变更
9
显示空白变更内容
内联
并排
Showing
9 changed file
with
165 addition
and
29 deletion
+165
-29
src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb
...acePropertyWithMethods/ReplacePropertyWithMethodsTests.vb
+32
-0
src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs
...yWithMethods/AbstractReplacePropertyWithMethodsService.cs
+14
-9
src/Features/Core/Portable/ReplacePropertyWithMethods/IReplacePropertyWithMethodsService.cs
...PropertyWithMethods/IReplacePropertyWithMethodsService.cs
+1
-1
src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs
...hods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs
+27
-11
src/Features/VisualBasic/Portable/ReplacePropertyWithMethods/VisualBasicReplacePropertyWithMethods.vb
...pertyWithMethods/VisualBasicReplacePropertyWithMethods.vb
+41
-6
src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs
...s/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs
+15
-0
src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs
...re/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs
+4
-2
src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs
src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs
+7
-0
src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb
...sic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb
+24
-0
未找到文件。
src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb
浏览文件 @
cc1186ba
...
...
@@ -576,5 +576,37 @@ Structure AStruct
Private X As Integer
End Structure"
,
ignoreTrivia
:
=
False
)
End
Function
<
WorkItem
(
440371
,
"https://devdiv.visualstudio.com/DevDiv/_workitems/edit/440371"
)
>
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsReplacePropertyWithMethods
)
>
Public
Async
Function
TestInterfaceReplacement1
()
As
Task
Await
TestInRegularAndScriptAsync
(
"Interface IFoo
Property [||]Foo As Integer
End Interface
Class C
Implements IFoo
Public Property Foo As Integer Implements IFoo.Foo
End Class"
,
"Interface IFoo
Property Foo As Integer
End Interface
Class C
Implements IFoo
Private _Foo As Integer
Public Function GetFoo() As Integer Implements IFoo.GetFoo
Return _Foo
End Function
Public Sub SetFoo(AutoPropertyValue As Integer) Implements IFoo.SetFoo
_Foo = AutoPropertyValue
End Sub
End Class"
)
End
Function
End
Class
End
Namespace
\ No newline at end of file
src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs
浏览文件 @
cc1186ba
...
...
@@ -45,7 +45,7 @@ protected static SyntaxNode GetFieldReference(SyntaxGenerator generator, IFieldS
public
async
Task
ReplaceReferenceAsync
(
Document
document
,
SyntaxEditor
editor
,
Syntax
Token
nameToken
,
SyntaxEditor
editor
,
Syntax
Node
identifierName
,
IPropertySymbol
property
,
IFieldSymbol
propertyBackingField
,
string
desiredGetMethodName
,
string
desiredSetMethodName
,
CancellationToken
cancellationToken
)
...
...
@@ -55,10 +55,9 @@ protected static SyntaxNode GetFieldReference(SyntaxGenerator generator, IFieldS
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
var
referenceReplacer
=
new
ReferenceReplacer
(
this
,
semanticModel
,
syntaxFacts
,
semanticFacts
,
editor
,
nameToken
,
property
,
propertyBackingField
,
desiredGetMethodName
,
desiredSetMethodName
,
cancellationToken
);
this
,
semanticModel
,
syntaxFacts
,
semanticFacts
,
editor
,
(
TIdentifierNameSyntax
)
identifierName
,
property
,
propertyBackingField
,
desiredGetMethodName
,
desiredSetMethodName
,
cancellationToken
);
referenceReplacer
.
Do
();
}
...
...
@@ -71,7 +70,6 @@ private struct ReferenceReplacer
private
readonly
ISyntaxFactsService
_syntaxFacts
;
private
readonly
ISemanticFactsService
_semanticFacts
;
private
readonly
SyntaxEditor
_editor
;
private
readonly
SyntaxToken
_nameToken
;
private
readonly
IPropertySymbol
_property
;
private
readonly
IFieldSymbol
_propertyBackingField
;
private
readonly
string
_desiredGetMethodName
;
...
...
@@ -87,7 +85,8 @@ private struct ReferenceReplacer
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
ISemanticFactsService
semanticFacts
,
SyntaxEditor
editor
,
SyntaxToken
nameToken
,
SyntaxEditor
editor
,
TIdentifierNameSyntax
identifierName
,
IPropertySymbol
property
,
IFieldSymbol
propertyBackingField
,
string
desiredGetMethodName
,
string
desiredSetMethodName
,
...
...
@@ -98,14 +97,13 @@ private struct ReferenceReplacer
_syntaxFacts
=
syntaxFacts
;
_semanticFacts
=
semanticFacts
;
_editor
=
editor
;
_
nameToken
=
nameToken
;
_
identifierName
=
identifierName
;
_property
=
property
;
_propertyBackingField
=
propertyBackingField
;
_desiredGetMethodName
=
desiredGetMethodName
;
_desiredSetMethodName
=
desiredSetMethodName
;
_cancellationToken
=
cancellationToken
;
_identifierName
=
(
TIdentifierNameSyntax
)
nameToken
.
Parent
;
_expression
=
_identifierName
;
_cref
=
_service
.
TryGetCrefSyntax
(
_identifierName
);
if
(
_syntaxFacts
.
IsNameOfMemberAccessExpression
(
_expression
))
...
...
@@ -252,6 +250,13 @@ public void Do()
_editor
.
ReplaceNode
(
declarator
,
newDeclarator
);
}
else
if
(
_syntaxFacts
.
IsRightSideOfQualifiedName
(
_identifierName
))
{
// Found a reference in a qualified name. This happens for VB explicit interface
// names. We don't want to update this. (The "Implement IFoo.Bar" clause will be
// updated when we generate the actual Get/Set methods.
return
;
}
else
{
// No writes. Replace this with an appropriate read.
...
...
src/Features/Core/Portable/ReplacePropertyWithMethods/IReplacePropertyWithMethodsService.cs
浏览文件 @
cc1186ba
...
...
@@ -14,7 +14,7 @@ internal interface IReplacePropertyWithMethodsService : ILanguageService
Task
ReplaceReferenceAsync
(
Document
document
,
SyntaxEditor
editor
,
Syntax
Token
nameToken
,
SyntaxEditor
editor
,
Syntax
Node
identifierName
,
IPropertySymbol
property
,
IFieldSymbol
propertyBackingField
,
string
desiredGetMethodName
,
string
desiredSetMethodName
,
CancellationToken
cancellationToken
);
...
...
src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs
浏览文件 @
cc1186ba
...
...
@@ -13,6 +13,7 @@
using
Microsoft.CodeAnalysis.CodeRefactorings
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Shared.Utilities
;
using
Roslyn.Utilities
;
...
...
@@ -91,12 +92,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
// Get the warnings we'd like to put at the definition site.
var
definitionWarning
=
GetDefinitionIssues
(
propertyReferences
);
var
equalityComparer
=
(
IEqualityComparer
<
IPropertySymbol
>)
SymbolEquivalenceComparer
.
Instance
;
var
definitionToBackingField
=
propertyReferences
.
Select
(
r
=>
r
.
Definition
)
.
OfType
<
IPropertySymbol
>()
.
ToDictionary
(
d
=>
d
,
GetBackingField
,
equalityComparer
);
var
definitionToBackingField
=
CreateDefinitionToBackingFieldMap
(
propertyReferences
);
var
q
=
from
r
in
propertyReferences
where
r
.
Definition
is
IPropertySymbol
...
...
@@ -122,6 +118,22 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return
updatedSolution
;
}
private
static
Dictionary
<
IPropertySymbol
,
IFieldSymbol
>
CreateDefinitionToBackingFieldMap
(
IEnumerable
<
ReferencedSymbol
>
propertyReferences
)
{
var
definitionToBackingField
=
new
Dictionary
<
IPropertySymbol
,
IFieldSymbol
>(
SymbolEquivalenceComparer
.
Instance
);
foreach
(
var
reference
in
propertyReferences
)
{
if
(
reference
.
Definition
is
IPropertySymbol
property
)
{
var
backingField
=
GetBackingField
(
property
);
definitionToBackingField
[
property
]
=
backingField
;
}
}
return
definitionToBackingField
;
}
private
bool
HasAnyMatchingGetOrSetMethods
(
IPropertySymbol
property
,
string
name
)
{
return
HasAnyMatchingGetMethods
(
property
,
name
)
||
...
...
@@ -238,6 +250,8 @@ private string GetDefinitionIssues(IEnumerable<ReferencedSymbol> getMethodRefere
{
if
(
references
!=
null
)
{
var
syntaxFacts
=
originalDocument
.
GetLanguageService
<
ISyntaxFactsService
>();
foreach
(
var
tuple
in
references
)
{
cancellationToken
.
ThrowIfCancellationRequested
();
...
...
@@ -247,17 +261,19 @@ private string GetDefinitionIssues(IEnumerable<ReferencedSymbol> getMethodRefere
var
location
=
referenceLocation
.
Location
;
var
nameToken
=
root
.
FindToken
(
location
.
SourceSpan
.
Start
,
findInsideTrivia
:
true
);
if
(
referenceLocation
.
IsImplicit
)
var
parent
=
nameToken
.
Parent
;
if
(
referenceLocation
.
IsImplicit
||
!
syntaxFacts
.
IsIdentifierName
(
parent
))
{
// Warn the user that we can't properly replace this property with a method.
editor
.
ReplaceNode
(
nameToken
.
P
arent
,
nameToken
.
Parent
.
WithAdditionalAnnotations
(
editor
.
ReplaceNode
(
p
arent
,
nameToken
.
Parent
.
WithAdditionalAnnotations
(
ConflictAnnotation
.
Create
(
FeaturesResources
.
Property_referenced_implicitly
)));
}
else
{
var
fieldSymbol
=
propertyToBackingField
.
GetValueOrDefault
(
tuple
.
property
);
await
service
.
ReplaceReferenceAsync
(
originalDocument
,
editor
,
nameToken
,
originalDocument
,
editor
,
parent
,
property
,
fieldSymbol
,
desiredGetMethodName
,
desiredSetMethodName
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
src/Features/VisualBasic/Portable/ReplacePropertyWithMethods/VisualBasicReplacePropertyWithMethods.vb
浏览文件 @
cc1186ba
...
...
@@ -2,6 +2,7 @@
Imports
System.Composition
Imports
System.Threading
Imports
Microsoft.CodeAnalysis.CodeGeneration
Imports
Microsoft.CodeAnalysis.Editing
Imports
Microsoft.CodeAnalysis.Formatting
Imports
Microsoft.CodeAnalysis.Host.Mef
...
...
@@ -82,17 +83,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP
Dim
getMethod
=
[
property
]
.
GetMethod
If
getMethod
IsNot
Nothing
Then
result
.
Add
(
GetGetMethod
(
generator
,
propertyStatement
,
propertyBackingField
,
getMethod
,
desiredGetMethodName
,
cancellationToken
:
=
cancellationToken
))
generator
,
[
property
]
,
propertyStatement
,
propertyBackingField
,
getMethod
,
desiredGetMethodName
,
cancellationToken
:
=
cancellationToken
))
End
If
Dim
setMethod
=
[
property
]
.
SetMethod
If
setMethod
IsNot
Nothing
Then
result
.
Add
(
GetSetMethod
(
generator
,
propertyStatement
,
propertyBackingField
,
setMethod
,
desiredSetMethodName
,
cancellationToken
:
=
cancellationToken
))
generator
,
[
property
]
,
propertyStatement
,
propertyBackingField
,
setMethod
,
desiredSetMethodName
,
cancellationToken
:
=
cancellationToken
))
End
If
Return
result
...
...
@@ -100,6 +99,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP
Private
Function
GetGetMethod
(
generator
As
SyntaxGenerator
,
[
property
]
As
IPropertySymbol
,
propertyStatement
As
PropertyStatementSyntax
,
propertyBackingField
As
IFieldSymbol
,
getMethod
As
IMethodSymbol
,
...
...
@@ -119,7 +119,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP
statements
.
Add
(
generator
.
ReturnStatement
(
fieldReference
))
End
If
getMethod
=
UpdateExplicitInterfaceImplementations
(
[
property
]
,
getMethod
,
desiredGetMethodName
)
Dim
methodDeclaration
=
generator
.
MethodDeclaration
(
getMethod
,
desiredGetMethodName
,
statements
)
methodDeclaration
=
CopyLeadingTriviaOver
(
propertyStatement
,
methodDeclaration
,
ConvertValueToReturnsRewriter
.
instance
)
Return
methodDeclaration
End
Function
...
...
@@ -130,6 +132,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP
Private
Function
GetSetMethod
(
generator
As
SyntaxGenerator
,
[
property
]
As
IPropertySymbol
,
propertyStatement
As
PropertyStatementSyntax
,
propertyBackingField
As
IFieldSymbol
,
setMethod
As
IMethodSymbol
,
...
...
@@ -150,11 +153,43 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP
fieldReference
,
generator
.
IdentifierName
(
setMethod
.
Parameters
(
0
).
Name
)))
End
If
setMethod
=
UpdateExplicitInterfaceImplementations
(
[
property
]
,
setMethod
,
desiredSetMethodName
)
Dim
methodDeclaration
=
generator
.
MethodDeclaration
(
setMethod
,
desiredSetMethodName
,
statements
)
methodDeclaration
=
CopyLeadingTriviaOver
(
propertyStatement
,
methodDeclaration
,
ConvertValueToParamRewriter
.
instance
)
Return
methodDeclaration
End
Function
Private
Function
UpdateExplicitInterfaceImplementations
(
[
property
]
As
IPropertySymbol
,
method
As
IMethodSymbol
,
desiredName
As
String
)
As
IMethodSymbol
Dim
updatedExplicitImpl
=
UpdateExplicitInterfaceImplementation
(
[
property
]
,
method
.
ExplicitInterfaceImplementations
.
FirstOrDefault
(),
desiredName
)
Return
If
(
updatedExplicitImpl
Is
method
.
ExplicitInterfaceImplementations
.
FirstOrDefault
(),
method
,
CodeGenerationSymbolFactory
.
CreateMethodSymbol
(
method
,
explicitInterfaceSymbol
:
=
updatedExplicitImpl
))
End
Function
Private
Function
UpdateExplicitInterfaceImplementation
(
[
property
]
As
IPropertySymbol
,
methodSymbol
As
IMethodSymbol
,
desiredName
As
String
)
As
IMethodSymbol
If
methodSymbol
IsNot
Nothing
Then
If
methodSymbol
.
Name
=
"get_"
+
[
property
]
.
Name
OrElse
methodSymbol
.
Name
=
"set_"
+
[
property
]
.
Name
Then
Return
CodeGenerationSymbolFactory
.
CreateMethodSymbol
(
methodSymbol
,
name
:
=
desiredName
,
containingType
:
=
methodSymbol
.
ContainingType
)
End
If
End
If
Return
methodSymbol
End
Function
Private
Function
CopyLeadingTriviaOver
(
propertyStatement
As
PropertyStatementSyntax
,
methodDeclaration
As
SyntaxNode
,
documentationCommentRewriter
As
VisualBasicSyntaxRewriter
)
As
SyntaxNode
...
...
src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs
浏览文件 @
cc1186ba
...
...
@@ -1903,6 +1903,21 @@ public override SyntaxNode WithTypeParameters(SyntaxNode declaration, IEnumerabl
}
}
internal
override
SyntaxNode
WithExplicitInterfaceImplementations
(
SyntaxNode
declaration
,
ImmutableArray
<
IMethodSymbol
>
explicitInterfaceImplementations
)
{
switch
(
declaration
)
{
case
MethodDeclarationSyntax
methodDeclaration
:
return
methodDeclaration
.
WithExplicitInterfaceSpecifier
(
CreateExplicitInterfaceSpecifier
(
explicitInterfaceImplementations
));
}
return
declaration
;
}
private
ExplicitInterfaceSpecifierSyntax
CreateExplicitInterfaceSpecifier
(
ImmutableArray
<
IMethodSymbol
>
explicitInterfaceImplementations
)
=>
SyntaxFactory
.
ExplicitInterfaceSpecifier
(
explicitInterfaceImplementations
[
0
].
ContainingType
.
GenerateNameSyntax
());
public
override
SyntaxNode
WithTypeConstraint
(
SyntaxNode
declaration
,
string
typeParameterName
,
SpecialTypeConstraintKind
kinds
,
IEnumerable
<
SyntaxNode
>
types
)
{
switch
(
declaration
.
Kind
())
...
...
src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs
浏览文件 @
cc1186ba
...
...
@@ -414,9 +414,11 @@ public static INamespaceSymbol CreateNamespaceSymbol(string name, IList<ISymbol>
DeclarationModifiers
?
modifiers
=
null
,
IMethodSymbol
explicitInterfaceSymbol
=
null
,
string
name
=
null
,
ImmutableArray
<
SyntaxNode
>
statements
=
default
(
ImmutableArray
<
SyntaxNode
>))
ImmutableArray
<
SyntaxNode
>
statements
=
default
(
ImmutableArray
<
SyntaxNode
>),
INamedTypeSymbol
containingType
=
null
)
{
return
CodeGenerationSymbolFactory
.
CreateMethodSymbol
(
return
CreateMethodSymbol
(
containingType
,
attributes
,
accessibility
??
method
.
DeclaredAccessibility
,
modifiers
??
method
.
GetSymbolModifiers
(),
...
...
src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs
浏览文件 @
cc1186ba
...
...
@@ -172,6 +172,11 @@ internal SyntaxNode MethodDeclaration(IMethodSymbol method, string name, IEnumer
decl
=
this
.
WithTypeParametersAndConstraints
(
decl
,
method
.
TypeParameters
);
}
if
(
method
.
ExplicitInterfaceImplementations
.
Length
>
0
)
{
decl
=
this
.
WithExplicitInterfaceImplementations
(
decl
,
method
.
ExplicitInterfaceImplementations
);
}
return
decl
;
}
...
...
@@ -665,6 +670,8 @@ private SyntaxNode WithTypeParametersAndConstraints(SyntaxNode declaration, Immu
return
declaration
;
}
internal
abstract
SyntaxNode
WithExplicitInterfaceImplementations
(
SyntaxNode
declaration
,
ImmutableArray
<
IMethodSymbol
>
explicitInterfaceImplementations
);
/// <summary>
/// Converts a declaration (method, class, etc) into a declaration with type parameters.
/// </summary>
...
...
src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb
浏览文件 @
cc1186ba
...
...
@@ -2863,6 +2863,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return
declaration
End
Function
Friend
Overrides
Function
WithExplicitInterfaceImplementations
(
declaration
As
SyntaxNode
,
explicitInterfaceImplementations
As
ImmutableArray
(
Of
IMethodSymbol
))
As
SyntaxNode
If
TypeOf
declaration
Is
MethodStatementSyntax
Then
Dim
methodStatement
=
DirectCast
(
declaration
,
MethodStatementSyntax
)
Dim
interfaceMembers
=
explicitInterfaceImplementations
.
Select
(
AddressOf
GenerateInterfaceMember
)
Return
methodStatement
.
WithImplementsClause
(
SyntaxFactory
.
ImplementsClause
(
SyntaxFactory
.
SeparatedList
(
interfaceMembers
)))
ElseIf
TypeOf
declaration
Is
MethodBlockSyntax
Then
Dim
methodBlock
=
DirectCast
(
declaration
,
MethodBlockSyntax
)
Return
methodBlock
.
WithSubOrFunctionStatement
(
DirectCast
(
WithExplicitInterfaceImplementations
(
methodBlock
.
SubOrFunctionStatement
,
explicitInterfaceImplementations
),
MethodStatementSyntax
))
End
If
Return
declaration
End
Function
Private
Function
GenerateInterfaceMember
(
method
As
IMethodSymbol
)
As
QualifiedNameSyntax
Dim
interfaceName
=
method
.
ContainingType
.
GenerateTypeSyntax
()
Return
SyntaxFactory
.
QualifiedName
(
DirectCast
(
interfaceName
,
NameSyntax
),
SyntaxFactory
.
IdentifierName
(
method
.
Name
))
End
Function
Public
Overrides
Function
WithTypeConstraint
(
declaration
As
SyntaxNode
,
typeParameterName
As
String
,
kinds
As
SpecialTypeConstraintKind
,
Optional
types
As
IEnumerable
(
Of
SyntaxNode
)
=
Nothing
)
As
SyntaxNode
Dim
constraints
=
SyntaxFactory
.
SeparatedList
(
Of
ConstraintSyntax
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录