Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
64bbbc41
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,发现更多精彩内容 >>
未验证
提交
64bbbc41
编写于
7月 29, 2020
作者:
J
Julien Couvreur
提交者:
GitHub
7月 29, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Use record keyword to display records (#46338)
上级
bccf2a17
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
169 addition
and
10 deletion
+169
-10
src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs
...harp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs
+61
-0
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs
...ble/Symbols/Synthesized/Records/SynthesizedRecordClone.cs
+2
-1
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+54
-9
src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs
...rs/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs
+21
-0
src/Compilers/Core/Portable/Symbols/SymbolEqualityComparer.cs
...Compilers/Core/Portable/Symbols/SymbolEqualityComparer.cs
+1
-0
src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs
...ures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs
+30
-0
未找到文件。
src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs
浏览文件 @
64bbbc41
...
...
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Linq
;
...
...
@@ -658,6 +659,11 @@ private void AddTypeKind(INamedTypeSymbol symbol)
{
switch
(
symbol
.
TypeKind
)
{
case
TypeKind
.
Class
when
FindValidCloneMethod
(
symbol
)
is
object
:
AddKeyword
(
SyntaxKind
.
RecordKeyword
);
AddSpace
();
break
;
case
TypeKind
.
Module
:
case
TypeKind
.
Class
:
AddKeyword
(
SyntaxKind
.
ClassKeyword
);
...
...
@@ -700,6 +706,61 @@ private void AddTypeKind(INamedTypeSymbol symbol)
}
}
/// <summary>
/// Copy of <see cref="SynthesizedRecordClone.FindValidCloneMethod(TypeSymbol, ref HashSet{DiagnosticInfo}?)"/>
/// </summary>
private
static
IMethodSymbol
FindValidCloneMethod
(
ITypeSymbol
containingType
)
{
IMethodSymbol
candidate
=
null
;
foreach
(
var
member
in
containingType
.
GetMembers
(
WellKnownMemberNames
.
CloneMethodName
))
{
if
(
member
is
IMethodSymbol
{
DeclaredAccessibility
:
Accessibility
.
Public
,
IsStatic
:
false
,
Parameters
:
{
Length
:
0
},
Arity
:
0
}
method
)
{
if
(
candidate
is
object
)
{
// An ambiguity case, can come from metadata, treat as an error for simplicity.
return
null
;
}
candidate
=
method
;
}
}
if
(
candidate
is
null
||
!(
containingType
.
IsSealed
||
candidate
.
IsOverride
||
candidate
.
IsVirtual
||
candidate
.
IsAbstract
)
||
!
isEqualToOrDerivedFrom
(
containingType
,
candidate
.
ReturnType
))
{
return
null
;
}
return
candidate
;
static
bool
isEqualToOrDerivedFrom
(
ITypeSymbol
one
,
ITypeSymbol
other
)
{
do
{
if
(
one
.
Equals
(
other
,
SymbolEqualityComparer
.
IgnoreAll
))
{
return
true
;
}
one
=
one
.
BaseType
;
}
while
(
one
!=
null
);
return
false
;
}
}
private
void
AddTypeParameterVarianceIfRequired
(
ITypeParameterSymbol
symbol
)
{
if
(
format
.
GenericsOptions
.
IncludesOption
(
SymbolDisplayGenericsOptions
.
IncludeVariance
))
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs
浏览文件 @
64bbbc41
...
...
@@ -139,6 +139,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
throw
ExceptionUtilities
.
Unreachable
;
}
// Note: this method was replicated in SymbolDisplayVisitor.FindValidCloneMethod
internal
static
MethodSymbol
?
FindValidCloneMethod
(
TypeSymbol
containingType
,
ref
HashSet
<
DiagnosticInfo
>?
useSiteDiagnostics
)
{
MethodSymbol
?
candidate
=
null
;
...
...
@@ -155,7 +156,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
{
if
(
candidate
is
object
)
{
// An am
m
biguity case, can come from metadata, treat as an error for simplicity.
// An ambiguity case, can come from metadata, treat as an error for simplicity.
return
null
;
}
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
浏览文件 @
64bbbc41
...
...
@@ -1730,6 +1730,9 @@ public void Clone_01()
Assert.True(clone.ContainingType.IsSealed);
Assert.True(clone.ContainingType.IsAbstract);
Assert.Equal("record C1", comp.GlobalNamespace.GetTypeMember("C1")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
...
...
@@ -1756,6 +1759,9 @@ public void Clone_02()
Assert.True(clone.ContainingType.IsSealed);
Assert.True(clone.ContainingType.IsAbstract);
Assert.Equal("record C1", comp.GlobalNamespace.GetTypeMember("C1")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
...
...
@@ -1810,10 +1816,13 @@ public void Clone_04()
Assert.True(clone.ContainingType.IsSealed);
Assert.True(clone.ContainingType.IsAbstract);
Assert.Equal("record C1", comp.GlobalNamespace.GetTypeMember("C1")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_05()
public void Clone_05
_IntReturnType_UsedAsBaseType
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -1904,10 +1913,13 @@ .maxstack 8
// public record B : A {
Diagnostic(ErrorCode.ERR_BadRecordBase, "A").WithLocation(2, 19)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_06()
public void Clone_06
_IntReturnType_UsedInWith
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -2004,10 +2016,13 @@ static void Main()
// A x = new A() with { };
Diagnostic(ErrorCode.ERR_NoSingleCloneMethod, "new A()").WithArguments("A").WithLocation(6, 15)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_07()
public void Clone_07
_Ambiguous_UsedAsBaseType
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -2108,10 +2123,13 @@ .maxstack 8
// public record B : A {
Diagnostic(ErrorCode.ERR_BadRecordBase, "A").WithLocation(2, 19)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_08()
public void Clone_08
_Ambiguous_UsedInWith
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -2218,16 +2236,18 @@ static void Main()
// A x = new A() with { };
Diagnostic(ErrorCode.ERR_NoSingleCloneMethod, "new A()").WithArguments("A").WithLocation(6, 15)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_09()
public void Clone_09
_AmbiguousReverseOrder_UsedAsBaseType
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
extends System.Object
{
// Methods
// Methods
.method public hidebysig specialname newslot virtual
instance class A '" + WellKnownMemberNames.CloneMethodName + @"' () cil managed
...
...
@@ -2322,10 +2342,13 @@ .maxstack 8
// public record B : A {
Diagnostic(ErrorCode.ERR_BadRecordBase, "A").WithLocation(2, 19)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_10()
public void Clone_10
_AmbiguousReverseOrder_UsedInWith
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -2432,6 +2455,9 @@ static void Main()
// A x = new A() with { };
Diagnostic(ErrorCode.ERR_NoSingleCloneMethod, "new A()").WithArguments("A").WithLocation(6, 15)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
...
...
@@ -2731,7 +2757,7 @@ public static void Main()
}
[Fact]
public void Clone_17()
public void Clone_17
_NonOverridable
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -2822,10 +2848,13 @@ .maxstack 8
// public record B : A {
Diagnostic(ErrorCode.ERR_BadRecordBase, "A").WithLocation(2, 19)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void Clone_18()
public void Clone_18
_NonOverridable
()
{
var ilSource = @"
.class public auto ansi beforefieldinit A
...
...
@@ -2916,6 +2945,9 @@ .maxstack 8
// public record B : A {
Diagnostic(ErrorCode.ERR_BadRecordBase, "A").WithLocation(2, 19)
);
Assert.Equal("class A", comp.GlobalNamespace.GetTypeMember("A")
.ToDisplayString(SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
...
...
@@ -19120,6 +19152,19 @@ public static void Main()
);
}
[Fact]
public void RecordLoadedInVisualBasicDisplaysAsRecord()
{
var src = @"
public record A;
";
var compRef = CreateCompilation(src).EmitToImageReference();
var vbComp = CreateVisualBasicCompilation("", referencedAssemblies: new[] { compRef });
var symbol = vbComp.GlobalNamespace.GetTypeMember("A");
Assert.Equal("record A",
SymbolDisplay.ToDisplayString(symbol, SymbolDisplayFormat.TestFormat.AddKindOptions(SymbolDisplayKindOptions.IncludeTypeKeyword)));
}
[Fact]
public void AnalyzerActions_01()
{
...
...
src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs
浏览文件 @
64bbbc41
...
...
@@ -7584,5 +7584,26 @@ class B
method
.
ToDisplayParts
(
formatWithoutOptions
),
"static void F4(nint[] x, A<nuint> y)"
);
}
[
Fact
]
public
void
RecordDeclaration
()
{
var
text
=
@"
record Person(string First, string Last);
"
;
Func
<
NamespaceSymbol
,
Symbol
>
findSymbol
=
global
=>
global
.
GetTypeMembers
(
"Person"
).
Single
();
var
format
=
new
SymbolDisplayFormat
(
memberOptions
:
SymbolDisplayMemberOptions
.
IncludeType
,
kindOptions
:
SymbolDisplayKindOptions
.
IncludeTypeKeyword
);
TestSymbolDescription
(
text
,
findSymbol
,
format
,
TestOptions
.
Regular
.
WithLanguageVersion
(
LanguageVersion
.
CSharp9
),
"record Person"
,
SymbolDisplayPartKind
.
Keyword
,
SymbolDisplayPartKind
.
Space
,
SymbolDisplayPartKind
.
ClassName
);
}
}
}
src/Compilers/Core/Portable/Symbols/SymbolEqualityComparer.cs
浏览文件 @
64bbbc41
...
...
@@ -27,6 +27,7 @@ public sealed class SymbolEqualityComparer : IEqualityComparer<ISymbol?>
// Internal only comparisons:
internal
readonly
static
SymbolEqualityComparer
ConsiderEverything
=
new
SymbolEqualityComparer
(
TypeCompareKind
.
ConsiderEverything
);
internal
readonly
static
SymbolEqualityComparer
IgnoreAll
=
new
SymbolEqualityComparer
(
TypeCompareKind
.
AllIgnoreOptions
);
internal
TypeCompareKind
CompareKind
{
get
;
}
...
...
src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs
浏览文件 @
64bbbc41
...
...
@@ -7036,5 +7036,35 @@ void Goo(object o)
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
QuickInfo
)]
public
async
Task
QuickInfoRecord
()
{
await
TestWithOptionsAsync
(
Options
.
Regular
.
WithLanguageVersion
(
LanguageVersion
.
CSharp9
),
@"record Person(string First, string Last)
{
void M($$Person p)
{
}
}"
,
MainDescription
(
"record Person"
));
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
QuickInfo
)]
public
async
Task
QuickInfoDerivedRecord
()
{
await
TestWithOptionsAsync
(
Options
.
Regular
.
WithLanguageVersion
(
LanguageVersion
.
CSharp9
),
@"record Person(string First, string Last)
{
}
record Student(string Id)
{
void M($$Student p)
{
}
}
"
,
MainDescription
(
"record Student"
));
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录