Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
f8ed9e7a
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,发现更多精彩内容 >>
未验证
提交
f8ed9e7a
编写于
5月 15, 2020
作者:
C
CyrusNajmabadi
提交者:
GitHub
5月 15, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #44230 from CyrusNajmabadi/nullableMAS
Fix imports not being removed from MAS files.
上级
ead3faf7
31abe0c0
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
1108 addition
and
160 deletion
+1108
-160
src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs
...tructorFromMembers/GenerateConstructorFromMembersTests.cs
+1
-1
src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs
...res/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs
+0
-6
src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.VisualBasic.cs
...est/MetadataAsSource/MetadataAsSourceTests.VisualBasic.cs
+0
-3
src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs
...orFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs
+739
-20
src/Features/CSharp/Portable/MetadataAsSource/CSharpMetadataAsSourceService.cs
...ortable/MetadataAsSource/CSharpMetadataAsSourceService.cs
+154
-43
src/Features/CSharp/Portable/MetadataAsSource/FormattingRule.cs
...atures/CSharp/Portable/MetadataAsSource/FormattingRule.cs
+67
-0
src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs
...table/MetadataAsSource/AbstractMetadataAsSourceService.cs
+2
-23
src/Features/VisualBasic/Portable/MetadataAsSource/VisualBasicMetadataAsSourceService.vb
...le/MetadataAsSource/VisualBasicMetadataAsSourceService.vb
+6
-0
src/Workspaces/CSharp/Portable/CodeGeneration/AttributeGenerator.cs
...aces/CSharp/Portable/CodeGeneration/AttributeGenerator.cs
+51
-10
src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs
...rp/Portable/Simplification/CSharpSimplificationService.cs
+0
-1
src/Workspaces/Core/Portable/CodeGeneration/NullableSyntaxAnnotation.cs
.../Core/Portable/CodeGeneration/NullableSyntaxAnnotation.cs
+25
-0
src/Workspaces/Core/Portable/FindSymbols/SymbolFinder.cs
src/Workspaces/Core/Portable/FindSymbols/SymbolFinder.cs
+1
-1
src/Workspaces/Core/Portable/Remote/RemoteArguments.cs
src/Workspaces/Core/Portable/Remote/RemoteArguments.cs
+1
-1
src/Workspaces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs
...aces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs
+15
-25
src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs
src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs
+9
-14
src/Workspaces/Core/Portable/SymbolKey/SymbolKeyResolution.cs
...Workspaces/Core/Portable/SymbolKey/SymbolKeyResolution.cs
+4
-6
src/Workspaces/CoreTest/SymbolKeyTests.cs
src/Workspaces/CoreTest/SymbolKeyTests.cs
+4
-4
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs
...sions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs
+7
-1
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs
...ions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs
+22
-1
未找到文件。
src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs
浏览文件 @
f8ed9e7a
...
...
@@ -1069,7 +1069,7 @@ class Z<T> where T : class
string b;
T? c;
public Z(int a, string b, T c{|Navigation:)|}
public Z(int a, string b, T
?
c{|Navigation:)|}
{
this.a = a;
this.b = b ?? throw new ArgumentNullException(nameof(b));
...
...
src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs
浏览文件 @
f8ed9e7a
...
...
@@ -43,14 +43,10 @@ public async Task TestNativeInteger()
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
using System;
using System.Runtime.CompilerServices;
public class [|C|]
{{
[
NativeIntegerAttribute
]
public
nint
i
;
[
NativeIntegerAttribute
]
public
nuint
i2
;
public
C
();
...
...
@@ -88,8 +84,6 @@ public async Task TestValueTuple()
// System.ValueTuple.dll
#endregion
using
System
;
using
System
;
using
System.Collections
;
namespace
System
...
...
src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.VisualBasic.cs
浏览文件 @
f8ed9e7a
...
...
@@ -44,7 +44,6 @@ public async Task BracketedIdentifierSimplificationTest()
' mscorlib.v4_6_1038_0.dll
#End Region
Imports System
Imports System.Runtime.InteropServices
Namespace System
...
...
@@ -95,8 +94,6 @@ public async Task TestValueTuple()
'
System
.
ValueTuple
.
dll
#
End
Region
Imports
System
Imports
System
Imports
System
.
Collections
Namespace
System
...
...
src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs
浏览文件 @
f8ed9e7a
...
...
@@ -591,10 +591,7 @@ internal class AllowNullAttribute : System.Attribute { }
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
using System.Runtime.CompilerServices;
[NullableContextAttribute(1)]
public interface [|C|]<[NullableAttribute(2)] T>
public interface [|C|]<T>
{{
bool
Equals
([
AllowNullAttribute
]
T
other
);
}}
"
);
...
...
@@ -602,7 +599,6 @@ public interface [|C|]<[NullableAttribute(2)] T>
'
{
CodeAnalysisResources
.
InMemoryAssembly
}
#End Region
Imports System.Runtime.CompilerServices
<NullableContextAttribute(1)>
Public Interface [|C|](Of T)
...
...
@@ -1704,7 +1700,6 @@ public async Task TestReadOnlyStruct_ReadOnlyField()
'
{
CodeAnalysisResources
.
InMemoryAssembly
}
#End Region
Imports System.Runtime.CompilerServices
<IsReadOnlyAttribute>
Public Structure [|S|]
...
...
@@ -1766,7 +1761,6 @@ public async Task TestRefStruct()
#End Region
Imports System
Imports System.Runtime.CompilerServices
<IsByRefLikeAttribute> <Obsolete(""Types with embedded references are not supported in this version of your compiler."", True)>
Public Structure [|S|]
...
...
@@ -1797,7 +1791,6 @@ public async Task TestReadOnlyRefStruct()
#End Region
Imports System
Imports System.Runtime.CompilerServices
<IsByRefLikeAttribute> <IsReadOnlyAttribute> <Obsolete(""Types with embedded references are not supported in this version of your compiler."", True)>
Public Structure [|S|]
...
...
@@ -1832,7 +1825,6 @@ public struct S
'
{
CodeAnalysisResources
.
InMemoryAssembly
}
#End Region
Imports System.Runtime.CompilerServices
Public Structure S <IsReadOnlyAttribute>
Public Sub [|M|]()
...
...
@@ -1867,7 +1859,6 @@ public async Task TestReadOnlyMethod_InReadOnlyStruct()
'
{
CodeAnalysisResources
.
InMemoryAssembly
}
#End Region
Imports System.Runtime.CompilerServices
<IsReadOnlyAttribute>
Public Structure S
...
...
@@ -1998,7 +1989,6 @@ public async Task TestReadOnlyStructProperty_ReadOnlyGet()
'
{
CodeAnalysisResources
.
InMemoryAssembly
}
#End Region
Imports System.Runtime.CompilerServices
<IsReadOnlyAttribute>
Public Structure S
...
...
@@ -2244,7 +2234,6 @@ public async Task TestReadOnlyStruct_ReadOnlyEvent()
#End Region
Imports System
Imports System.Runtime.CompilerServices
<IsReadOnlyAttribute>
Public Structure S
...
...
@@ -2271,9 +2260,7 @@ void M()
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
using System.Runtime.CompilerServices;
public class [|TestType|]<[NullableAttribute(1)] T> where T : notnull
public class [|TestType|]<T> where T : notnull
{{
public
TestType
();
}}
"
;
...
...
@@ -2313,13 +2300,10 @@ void M()
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
using System.Runtime.CompilerServices;
public class TestType
{{
public
TestType
();
[
NullableContextAttribute
(
1
)]
public
void
[|
M
|]<
T
>()
where
T
:
notnull
;
}}
"
;
...
...
@@ -2352,9 +2336,744 @@ void M([|D|]<int> lambda)
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
using System.Runtime.CompilerServices;
public delegate void [|D|]<T>() where T : notnull;"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable1
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1(string s)
{
}
#nullable disable
public void M2(string s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
public class TestType
{{
public
TestType
();
public
void
[|
M1
|](
string
s
);
#
nullable
disable
public
void
M2
(
string
s
);
#
nullable
enable
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable2
()
{
var
metadata
=
@"
using System;
public class TestType
{
public void M1(string s)
{
}
#nullable enable
public void M2(string s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
public class TestType
{{
public
TestType
();
#
nullable
disable
public
void
[|
M1
|](
string
s
);
#
nullable
enable
public
void
M2
(
string
s
);
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable3
()
{
var
metadata
=
@"
#nullable enable
public delegate void [|D|]<[NullableAttribute(1)] T>() where T : notnull;"
;
using System;
public class TestType
{
public void M1(string s)
{
}
#nullable disable
public void M2(string s)
{
}
public void M3(string s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
public class TestType
{{
public
TestType
();
public
void
[|
M1
|](
string
s
);
#
nullable
disable
public
void
M2
(
string
s
);
public
void
M3
(
string
s
);
#
nullable
enable
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable4
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1(ICloneable s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
using System;
public class TestType
{{
public
TestType
();
public
void
[|
M1
|](
ICloneable
s
);
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable5
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1(ICloneable s)
{
#nullable disable
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
using System;
public class TestType
{{
public
TestType
();
public
void
[|
M1
|](
ICloneable
s
);
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable6
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1<T>(T? s) where T : class
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|]("""");
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
public class TestType
{{
public
TestType
();
public
void
[|
M1
|]<
T
>(
T
?
s
)
where
T
:
class
;
}}";
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable7
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1<T>(T s) where T : class
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|]("""");
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
public class TestType
{{
public
TestType
();
public
void
[|
M1
|]<
T
>(
T
s
)
where
T
:
class
;
}}";
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable8
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1<T>(T? s) where T : struct
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|]((int?)0);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
public class TestType
{{
public
TestType
();
public
void
[|
M1
|]<
T
>(
T
?
s
)
where
T
:
struct
;
}}";
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable9
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1<T>(T s) where T : struct
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](0);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
public class TestType
{{
public
TestType
();
public
void
[|
M1
|]<
T
>(
T
s
)
where
T
:
struct
;
}}";
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable10
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1<T>(T s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|]("""");
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
public class TestType
{{
public
TestType
();
public
void
[|
M1
|]<
T
>(
T
s
);
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable11
()
{
var
metadata
=
@"
using System;
public class TestType
{
public void M1<T>(T s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|]("""");
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
public class TestType
{{
public
TestType
();
public
void
[|
M1
|]<
T
>(
T
s
);
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable12
()
{
var
metadata
=
@"
#nullable enable
using System;
namespace N
{
public class TestType
{
public void M1(string s)
{
}
#nullable disable
public void M2(string s)
{
}
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new N.TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
namespace N
{{
public
class
TestType
{{
public
TestType
();
public
void
[|
M1
|](
string
s
);
#
nullable
disable
public
void
M2
(
string
s
);
#
nullable
enable
}}
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestNullableEnableDisable13
()
{
var
metadata
=
@"
#nullable enable
using System;
public class TestType
{
public void M1(string s)
{
}
#nullable disable
public class Nested
{
public void NestedM(string s)
{
}
}
#nullable enable
public void M2(string s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
#nullable enable
public class TestType
{{
public
TestType
();
public
void
[|
M1
|](
string
s
);
public
void
M2
(
string
s
);
public
class
Nested
{{
public
Nested
();
#
nullable
disable
public
void
NestedM
(
string
s
);
#
nullable
enable
}}
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
SpecializedCollections
.
SingletonEnumerable
(
metadata
),
includeXmlDocComments
:
false
,
languageVersion
:
"CSharp8"
,
sourceWithSymbolReference
:
sourceWithSymbolReference
,
metadataLanguageVersion
:
"CSharp8"
);
var
navigationSymbol
=
await
context
.
GetNavigationSymbolAsync
();
var
metadataAsSourceFile
=
await
context
.
GenerateSourceAsync
(
navigationSymbol
);
context
.
VerifyResult
(
metadataAsSourceFile
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
MetadataAsSource
)]
public
async
Task
TestDynamic1
()
{
var
metadata
=
@"
using System;
public class TestType
{
public void M1(dynamic s)
{
}
}"
;
var
sourceWithSymbolReference
=
@"
class C
{
void M()
{
var obj = new TestType().[|M1|](null);
}
}"
;
var
expected
=
$@"#region
{
FeaturesResources
.
Assembly
}
ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
//
{
CodeAnalysisResources
.
InMemoryAssembly
}
#endregion
public class TestType
{{
public
TestType
();
public
void
[|
M1
|](
dynamic
s
);
}}
"
;
using
var
context
=
TestContext
.
Create
(
LanguageNames
.
CSharp
,
...
...
src/Features/CSharp/Portable/MetadataAsSource/CSharpMetadataAsSourceService.cs
浏览文件 @
f8ed9e7a
...
...
@@ -7,19 +7,23 @@
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CodeGeneration
;
using
Microsoft.CodeAnalysis.CSharp.DocumentationComments
;
using
Microsoft.CodeAnalysis.CSharp.Simplification
;
using
Microsoft.CodeAnalysis.CSharp.
Utilities
;
using
Microsoft.CodeAnalysis.CSharp.
Syntax
;
using
Microsoft.CodeAnalysis.DocumentationComments
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Formatting.Rules
;
using
Microsoft.CodeAnalysis.MetadataAsSource
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.MetadataAsSource
{
internal
class
CSharpMetadataAsSourceService
:
AbstractMetadataAsSourceService
internal
partial
class
CSharpMetadataAsSourceService
:
AbstractMetadataAsSourceService
{
private
static
readonly
AbstractFormattingRule
s_memberSeparationRule
=
new
FormattingRule
();
public
static
readonly
CSharpMetadataAsSourceService
Instance
=
new
CSharpMetadataAsSourceService
();
...
...
@@ -37,16 +41,14 @@ protected override async Task<Document> AddAssemblyInfoRegionAsync(Document docu
.
WithTrailingTrivia
(
new
[]
{
SyntaxFactory
.
Space
,
SyntaxFactory
.
PreprocessingMessage
(
assemblyInfo
)
});
var
oldRoot
=
await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
newRoot
=
oldRoot
.
WithLeadingTrivia
(
new
[]
{
SyntaxFactory
.
Trivia
(
regionTrivia
),
SyntaxFactory
.
CarriageReturnLineFeed
,
SyntaxFactory
.
Comment
(
"// "
+
assemblyPath
),
SyntaxFactory
.
CarriageReturnLineFeed
,
SyntaxFactory
.
Trivia
(
SyntaxFactory
.
EndRegionDirectiveTrivia
(
true
)),
SyntaxFactory
.
CarriageReturnLineFeed
,
SyntaxFactory
.
CarriageReturnLineFeed
});
var
newRoot
=
oldRoot
.
WithPrependedLeadingTrivia
(
SyntaxFactory
.
Trivia
(
regionTrivia
),
SyntaxFactory
.
CarriageReturnLineFeed
,
SyntaxFactory
.
Comment
(
"// "
+
assemblyPath
),
SyntaxFactory
.
CarriageReturnLineFeed
,
SyntaxFactory
.
Trivia
(
SyntaxFactory
.
EndRegionDirectiveTrivia
(
true
)),
SyntaxFactory
.
CarriageReturnLineFeed
,
SyntaxFactory
.
CarriageReturnLineFeed
);
return
document
.
WithSyntaxRoot
(
newRoot
);
}
...
...
@@ -71,55 +73,164 @@ protected override ImmutableArray<AbstractReducer> GetReducers()
new
CSharpParenthesizedPatternReducer
(),
new
CSharpDefaultExpressionReducer
());
private
class
FormattingRule
:
AbstractMetadataFormattingRule
/// <summary>
/// Adds <c>#nullable enable</c> and <c>#nullable disable</c> annotations to the file as necessary. Note that
/// this does not try to be 100% accurate, but rather it handles the most common cases out there. Specifically,
/// if a file contains any nullable annotated/not-annotated types, then we prefix the file with <c>#nullable
/// enable</c>. Then if we hit any members that explicitly have *oblivious* types, but no annotated or
/// non-annotated types, then we switch to <c>#nullable disable</c> for those specific members.
/// <para/>
/// This is technically innacurate for possible, but very uncommon cases. For example, if the user's code
/// explicitly did something like this:
///
/// <code>
/// public void Goo(string goo,
/// #nullable disable
/// string bar
/// #nullable enable
/// string baz);
/// </code>
///
/// Then we would be unable to handle that. However, this is highly unlikely to happen, and so we accept the
/// inaccuracy for the purpose of simplicity and for handling the much more common cases of either the entire
/// file being annotated, or the user individually disabling annotations at the member level.
/// </summary>
protected
override
async
Task
<
Document
>
AddNullableRegionsAsync
(
Document
document
,
CancellationToken
cancellationToken
)
{
var
tree
=
await
document
.
GetSyntaxTreeAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
options
=
(
CSharpParseOptions
)
tree
.
Options
;
// Only valid for C# 8 and above.
if
(
options
.
LanguageVersion
<
LanguageVersion
.
CSharp8
)
return
document
;
var
root
=
await
tree
.
GetRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
(
_
,
annotatedOrNotAnnotated
)
=
GetNullableAnnotations
(
root
);
// If there are no annotated or not-annotated types, then no need to add `#nullable enable`.
if
(!
annotatedOrNotAnnotated
)
return
document
;
var
newRoot
=
AddNullableRegions
(
root
,
cancellationToken
);
newRoot
=
newRoot
.
WithPrependedLeadingTrivia
(
CreateNullableTrivia
(
enable
:
true
));
return
document
.
WithSyntaxRoot
(
newRoot
);
}
private
(
bool
oblivious
,
bool
annotatedOrNotAnnotated
)
GetNullableAnnotations
(
SyntaxNode
node
)
{
return
(
HasAnnotation
(
node
,
NullableSyntaxAnnotation
.
Oblivious
),
HasAnnotation
(
node
,
NullableSyntaxAnnotation
.
AnnotatedOrNotAnnotated
));
}
private
bool
HasAnnotation
(
SyntaxNode
node
,
SyntaxAnnotation
annotation
)
{
// see if any child nodes have this annotation. Ignore anything in attributes (like `[Obsolete]void Goo()`
// as these are not impacted by `#nullable` regions. Instead, we only care about signature types.
var
annotatedChildren
=
node
.
GetAnnotatedNodes
(
annotation
);
return
annotatedChildren
.
Any
(
n
=>
n
.
GetAncestorOrThis
<
AttributeSyntax
>()
==
null
);
}
private
static
SyntaxTrivia
[]
CreateNullableTrivia
(
bool
enable
)
{
var
keyword
=
enable
?
SyntaxKind
.
EnableKeyword
:
SyntaxKind
.
DisableKeyword
;
return
new
[]
{
SyntaxFactory
.
Trivia
(
SyntaxFactory
.
NullableDirectiveTrivia
(
SyntaxFactory
.
Token
(
keyword
),
isActive
:
enable
)),
SyntaxFactory
.
ElasticCarriageReturnLineFeed
,
SyntaxFactory
.
ElasticCarriageReturnLineFeed
,
};
}
private
TSyntax
AddNullableRegions
<
TSyntax
>(
TSyntax
node
,
CancellationToken
cancellationToken
)
where
TSyntax
:
SyntaxNode
{
protected
override
AdjustNewLinesOperation
GetAdjustNewLinesOperationBetweenMembersAndUsings
(
SyntaxToken
token1
,
SyntaxToken
token2
)
return
node
switch
{
var
previousToken
=
token1
;
var
currentToken
=
token2
;
CompilationUnitSyntax
compilationUnit
=>
(
TSyntax
)(
object
)
compilationUnit
.
WithMembers
(
AddNullableRegions
(
compilationUnit
.
Members
,
cancellationToken
)),
NamespaceDeclarationSyntax
ns
=>
(
TSyntax
)(
object
)
ns
.
WithMembers
(
AddNullableRegions
(
ns
.
Members
,
cancellationToken
)),
TypeDeclarationSyntax
type
=>
(
TSyntax
)(
object
)
AddNullableRegionsAroundTypeMembers
(
type
,
cancellationToken
),
_
=>
node
,
};
}
private
SyntaxList
<
MemberDeclarationSyntax
>
AddNullableRegions
(
SyntaxList
<
MemberDeclarationSyntax
>
members
,
CancellationToken
cancellationToken
)
{
using
var
_
=
ArrayBuilder
<
MemberDeclarationSyntax
>.
GetInstance
(
out
var
builder
);
foreach
(
var
member
in
members
)
builder
.
Add
(
AddNullableRegions
(
member
,
cancellationToken
));
return
SyntaxFactory
.
List
(
builder
);
}
private
TypeDeclarationSyntax
AddNullableRegionsAroundTypeMembers
(
TypeDeclarationSyntax
type
,
CancellationToken
cancellationToken
)
{
using
var
_
=
ArrayBuilder
<
MemberDeclarationSyntax
>.
GetInstance
(
out
var
builder
);
var
currentlyEnabled
=
true
;
foreach
(
var
member
in
type
.
Members
)
{
cancellationToken
.
ThrowIfCancellationRequested
();
// We are not between members or usings if the last token wasn't the end of a statement or if the current token
// is the end of a scope.
if
((
previousToken
.
Kind
()
!=
SyntaxKind
.
SemicolonToken
&&
previousToken
.
Kind
()
!=
SyntaxKind
.
CloseBraceToken
)
||
currentToken
.
Kind
()
==
SyntaxKind
.
CloseBraceToken
)
if
(
member
is
BaseTypeDeclarationSyntax
)
{
return
null
;
// if we hit a type, and we're currently disabled, then switch us back to enabled for that type.
// This ensures whenever we walk into a type-decl, we're always in the enabled-state.
builder
.
Add
(
TransitionTo
(
AddNullableRegions
(
member
,
cancellationToken
),
enabled
:
true
,
ref
currentlyEnabled
));
continue
;
}
SyntaxNode
previousMember
=
FormattingRangeHelper
.
GetEnclosingMember
(
previousToken
);
SyntaxNode
nextMember
=
FormattingRangeHelper
.
GetEnclosingMember
(
currentToken
);
// we hit a member. see what sort of types it contained.
var
(
oblivious
,
annotatedOrNotAnnotated
)
=
GetNullableAnnotations
(
member
);
// Is the previous statement an using directive? If so, treat it like a member to add
// the right number of lines.
if
(
previousToken
.
Kind
()
==
SyntaxKind
.
SemicolonToken
&&
previousToken
.
Parent
.
Kind
()
==
SyntaxKind
.
UsingDirective
)
// if we have null annotations, transition us back to the enabled state
if
(
annotatedOrNotAnnotated
)
{
previousMember
=
previousToken
.
Parent
;
builder
.
Add
(
TransitionTo
(
member
,
enabled
:
true
,
ref
currentlyEnabled
))
;
}
if
(
previousMember
==
null
||
nextMember
==
null
||
previousMember
==
nextMember
)
else
if
(
oblivious
)
{
return
null
;
// if we didn't have null annotations, and we had an explicit oblivious type,
// then definitely transition us to the disabled state
builder
.
Add
(
TransitionTo
(
member
,
enabled
:
false
,
ref
currentlyEnabled
));
}
// If we have two members of the same kind, we won't insert a blank line
if
(
previousMember
.
Kind
()
==
nextMember
.
Kind
())
else
{
return
FormattingOperations
.
CreateAdjustNewLinesOperation
(
1
,
AdjustNewLinesOption
.
ForceLines
);
// had no types at all. no need to change state.
builder
.
Add
(
member
);
}
// Force a blank line between the two nodes by counting the number of lines of
// trivia and adding one to it.
var
triviaList
=
token1
.
TrailingTrivia
.
Concat
(
token2
.
LeadingTrivia
);
return
FormattingOperations
.
CreateAdjustNewLinesOperation
(
GetNumberOfLines
(
triviaList
)
+
1
,
AdjustNewLinesOption
.
ForceLines
);
}
public
override
void
AddAnchorIndentationOperations
(
List
<
AnchorIndentationOperation
>
list
,
SyntaxNode
node
,
in
NextAnchorIndentationOperationAction
nextOperation
)
var
result
=
type
.
WithMembers
(
SyntaxFactory
.
List
(
builder
));
if
(!
currentlyEnabled
)
{
return
;
// switch us back to enabled as we leave the type.
result
=
result
.
WithCloseBraceToken
(
result
.
CloseBraceToken
.
WithPrependedLeadingTrivia
(
CreateNullableTrivia
(
enable
:
true
)));
}
protected
override
bool
IsNewLine
(
char
c
)
=>
SyntaxFacts
.
IsNewLine
(
c
);
return
result
;
}
private
MemberDeclarationSyntax
TransitionTo
(
MemberDeclarationSyntax
member
,
bool
enabled
,
ref
bool
currentlyEnabled
)
{
if
(
enabled
==
currentlyEnabled
)
{
// already in the right state. don't start a #nullable region
return
member
;
}
else
{
// switch to the desired state and add the right trivia to the node.
currentlyEnabled
=
enabled
;
return
member
.
WithPrependedLeadingTrivia
(
CreateNullableTrivia
(
currentlyEnabled
));
}
}
}
}
src/Features/CSharp/Portable/MetadataAsSource/FormattingRule.cs
0 → 100644
浏览文件 @
f8ed9e7a
// Licensed to the .NET Foundation under one or more agreements.
// 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.Linq
;
using
Microsoft.CodeAnalysis.CSharp.Utilities
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Formatting.Rules
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.MetadataAsSource
{
internal
partial
class
CSharpMetadataAsSourceService
{
private
class
FormattingRule
:
AbstractMetadataFormattingRule
{
protected
override
AdjustNewLinesOperation
GetAdjustNewLinesOperationBetweenMembersAndUsings
(
SyntaxToken
token1
,
SyntaxToken
token2
)
{
var
previousToken
=
token1
;
var
currentToken
=
token2
;
// We are not between members or usings if the last token wasn't the end of a statement or if the current token
// is the end of a scope.
if
((
previousToken
.
Kind
()
!=
SyntaxKind
.
SemicolonToken
&&
previousToken
.
Kind
()
!=
SyntaxKind
.
CloseBraceToken
)
||
currentToken
.
Kind
()
==
SyntaxKind
.
CloseBraceToken
)
{
return
null
;
}
SyntaxNode
previousMember
=
FormattingRangeHelper
.
GetEnclosingMember
(
previousToken
);
SyntaxNode
nextMember
=
FormattingRangeHelper
.
GetEnclosingMember
(
currentToken
);
// Is the previous statement an using directive? If so, treat it like a member to add
// the right number of lines.
if
(
previousToken
.
Kind
()
==
SyntaxKind
.
SemicolonToken
&&
previousToken
.
Parent
.
Kind
()
==
SyntaxKind
.
UsingDirective
)
{
previousMember
=
previousToken
.
Parent
;
}
if
(
previousMember
==
null
||
nextMember
==
null
||
previousMember
==
nextMember
)
{
return
null
;
}
// If we have two members of the same kind, we won't insert a blank line
if
(
previousMember
.
Kind
()
==
nextMember
.
Kind
())
{
return
FormattingOperations
.
CreateAdjustNewLinesOperation
(
1
,
AdjustNewLinesOption
.
ForceLines
);
}
// Force a blank line between the two nodes by counting the number of lines of
// trivia and adding one to it.
var
triviaList
=
token1
.
TrailingTrivia
.
Concat
(
token2
.
LeadingTrivia
);
return
FormattingOperations
.
CreateAdjustNewLinesOperation
(
GetNumberOfLines
(
triviaList
)
+
1
,
AdjustNewLinesOption
.
ForceLines
);
}
public
override
void
AddAnchorIndentationOperations
(
List
<
AnchorIndentationOperation
>
list
,
SyntaxNode
node
,
in
NextAnchorIndentationOperationAction
nextOperation
)
{
return
;
}
protected
override
bool
IsNewLine
(
char
c
)
=>
SyntaxFacts
.
IsNewLine
(
c
);
}
}
}
src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs
浏览文件 @
f8ed9e7a
...
...
@@ -5,12 +5,10 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CodeGeneration
;
using
Microsoft.CodeAnalysis.DocumentationComments
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Formatting.Rules
;
using
Microsoft.CodeAnalysis.LanguageServices
;
...
...
@@ -41,7 +39,7 @@ public async Task<Document> AddSourceToAsync(Document document, Compilation symb
CreateCodeGenerationOptions
(
newSemanticModel
.
SyntaxTree
.
GetLocation
(
new
TextSpan
())),
cancellationToken
).
ConfigureAwait
(
false
);
document
=
await
RemoveSimplifierAnnotationsFromImport
sAsync
(
document
,
cancellationToken
).
ConfigureAwait
(
false
);
document
=
await
AddNullableRegion
sAsync
(
document
,
cancellationToken
).
ConfigureAwait
(
false
);
var
docCommentFormattingService
=
document
.
GetLanguageService
<
IDocumentationCommentFormattingService
>();
var
docWithDocComments
=
await
ConvertDocCommentsToRegularCommentsAsync
(
document
,
docCommentFormattingService
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -55,26 +53,7 @@ public async Task<Document> AddSourceToAsync(Document document, Compilation symb
return
await
Simplifier
.
ReduceAsync
(
formattedDoc
,
reducers
,
null
,
cancellationToken
).
ConfigureAwait
(
false
);
}
/// <summary>
/// <see cref="ImportAdderService"/> adds <see cref="Simplifier.Annotation"/> to Import Directives it adds,
/// which causes the <see cref="Simplifier"/> to remove import directives when thety are only used by attributes.
/// Presumably this is because MetadataAsSource isn't actually semantically valid code.
///
/// To fix this we remove these annotations.
/// </summary>
private
static
async
Task
<
Document
>
RemoveSimplifierAnnotationsFromImportsAsync
(
Document
document
,
CancellationToken
cancellationToken
)
{
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
var
importDirectives
=
(
await
document
.
GetSyntaxRootAsync
().
ConfigureAwait
(
false
))
.
DescendantNodesAndSelf
()
.
Where
(
syntaxFacts
.
IsUsingOrExternOrImport
);
return
await
document
.
ReplaceNodesAsync
(
importDirectives
,
(
o
,
c
)
=>
c
.
WithoutAnnotations
(
Simplifier
.
Annotation
),
cancellationToken
).
ConfigureAwait
(
false
);
}
protected
abstract
Task
<
Document
>
AddNullableRegionsAsync
(
Document
document
,
CancellationToken
cancellationToken
);
/// <summary>
/// provide formatting rules to be used when formatting MAS file
...
...
src/Features/VisualBasic/Portable/MetadataAsSource/VisualBasicMetadataAsSourceService.vb
浏览文件 @
f8ed9e7a
...
...
@@ -4,6 +4,7 @@
Imports
System.Collections.Immutable
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.DocumentationComments
Imports
Microsoft.CodeAnalysis.Formatting
Imports
Microsoft.CodeAnalysis.Formatting.Rules
...
...
@@ -49,6 +50,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.MetadataAsSource
Return
document
.
WithSyntaxRoot
(
newRoot
)
End
Function
Protected
Overrides
Function
AddNullableRegionsAsync
(
document
As
Document
,
cancellationToken
As
CancellationToken
)
As
Task
(
Of
Document
)
' VB has no equivalent to #nullable enable
Return
Task
.
FromResult
(
document
)
End
Function
Protected
Overrides
Async
Function
ConvertDocCommentsToRegularCommentsAsync
(
document
As
Document
,
docCommentFormattingService
As
IDocumentationCommentFormattingService
,
cancellationToken
As
CancellationToken
)
As
Task
(
Of
Document
)
Dim
syntaxRoot
=
Await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
False
)
...
...
src/Workspaces/CSharp/Portable/CodeGeneration/AttributeGenerator.cs
浏览文件 @
f8ed9e7a
...
...
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
...
...
@@ -23,7 +25,10 @@ internal static class AttributeGenerator
{
if
(
options
.
MergeAttributes
)
{
var
attributeNodes
=
attributes
.
OrderBy
(
a
=>
a
.
AttributeClass
.
Name
).
Select
(
a
=>
GenerateAttribute
(
a
,
options
)).
WhereNotNull
().
ToList
();
var
attributeNodes
=
attributes
.
OrderBy
(
a
=>
a
.
AttributeClass
?.
Name
)
.
Select
(
a
=>
TryGenerateAttribute
(
a
,
options
))
.
WhereNotNull
().
ToList
();
return
attributeNodes
.
Count
==
0
?
default
:
SyntaxFactory
.
SingletonList
(
SyntaxFactory
.
AttributeList
(
...
...
@@ -32,26 +37,34 @@ internal static class AttributeGenerator
}
else
{
var
attributeDeclarations
=
attributes
.
OrderBy
(
a
=>
a
.
AttributeClass
.
Name
).
Select
(
a
=>
GenerateAttributeDeclaration
(
a
,
target
,
options
)).
WhereNotNull
().
ToList
();
var
attributeDeclarations
=
attributes
.
OrderBy
(
a
=>
a
.
AttributeClass
?.
Name
)
.
Select
(
a
=>
TryGenerateAttributeDeclaration
(
a
,
target
,
options
))
.
WhereNotNull
().
ToList
();
return
attributeDeclarations
.
Count
==
0
?
default
:
SyntaxFactory
.
List
<
AttributeListSyntax
>(
attributeDeclarations
);
}
}
private
static
AttributeListSyntax
GenerateAttributeDeclaration
(
private
static
AttributeListSyntax
?
Try
GenerateAttributeDeclaration
(
AttributeData
attribute
,
SyntaxToken
?
target
,
CodeGenerationOptions
options
)
{
var
attributeSyntax
=
GenerateAttribute
(
attribute
,
options
);
var
attributeSyntax
=
Try
GenerateAttribute
(
attribute
,
options
);
return
attributeSyntax
==
null
?
null
:
SyntaxFactory
.
AttributeList
(
target
.
HasValue
?
SyntaxFactory
.
AttributeTargetSpecifier
(
target
.
Value
)
:
null
,
target
.
HasValue
?
SyntaxFactory
.
AttributeTargetSpecifier
(
target
.
Value
)
:
null
,
SyntaxFactory
.
SingletonSeparatedList
(
attributeSyntax
));
}
private
static
AttributeSyntax
GenerateAttribute
(
AttributeData
attribute
,
CodeGenerationOptions
options
)
private
static
AttributeSyntax
?
Try
GenerateAttribute
(
AttributeData
attribute
,
CodeGenerationOptions
options
)
{
if
(
IsCompilerInternalAttribute
(
attribute
))
return
null
;
if
(!
options
.
MergeAttributes
)
{
var
reusableSyntax
=
GetReuseableSyntaxNodeForAttribute
<
AttributeSyntax
>(
attribute
,
options
);
...
...
@@ -61,17 +74,45 @@ private static AttributeSyntax GenerateAttribute(AttributeData attribute, CodeGe
}
}
if
(
attribute
.
AttributeClass
==
null
)
return
null
;
var
attributeArguments
=
GenerateAttributeArgumentList
(
attribute
);
return
!(
attribute
.
AttributeClass
.
GenerateTypeSyntax
()
is
NameSyntax
nameSyntax
)
?
null
:
SyntaxFactory
.
Attribute
(
nameSyntax
,
attributeArguments
);
return
attribute
.
AttributeClass
.
GenerateTypeSyntax
()
is
NameSyntax
nameSyntax
?
SyntaxFactory
.
Attribute
(
nameSyntax
,
attributeArguments
)
:
null
;
}
private
static
AttributeArgumentListSyntax
GenerateAttributeArgumentList
(
AttributeData
attribute
)
private
static
bool
IsCompilerInternalAttribute
(
AttributeData
attribute
)
{
if
(
attribute
.
ConstructorArguments
.
Length
==
0
&&
attribute
.
NamedArguments
.
Length
==
0
)
// from https://github.com/dotnet/roslyn/blob/master/docs/features/nullable-metadata.md
var
attrClass
=
attribute
.
AttributeClass
;
if
(
attrClass
==
null
)
return
false
;
var
name
=
attrClass
.
Name
;
if
(
name
!=
"NullableAttribute"
&&
name
!=
"NullableContextAttribute"
&&
name
!=
"NativeIntegerAttribute"
&&
name
!=
"DynamicAttribute"
)
{
return
null
;
return
false
;
}
var
ns
=
attrClass
.
ContainingNamespace
;
return
ns
?.
Name
==
nameof
(
System
.
Runtime
.
CompilerServices
)
&&
ns
.
ContainingNamespace
?.
Name
==
nameof
(
System
.
Runtime
)
&&
ns
.
ContainingNamespace
.
ContainingNamespace
?.
Name
==
nameof
(
System
)
&&
ns
.
ContainingNamespace
.
ContainingNamespace
.
ContainingNamespace
?.
IsGlobalNamespace
==
true
;
}
private
static
AttributeArgumentListSyntax
?
GenerateAttributeArgumentList
(
AttributeData
attribute
)
{
if
(
attribute
.
ConstructorArguments
.
Length
==
0
&&
attribute
.
NamedArguments
.
Length
==
0
)
return
null
;
var
arguments
=
new
List
<
AttributeArgumentSyntax
>();
arguments
.
AddRange
(
attribute
.
ConstructorArguments
.
Select
(
c
=>
SyntaxFactory
.
AttributeArgument
(
ExpressionGenerator
.
GenerateExpression
(
c
))));
...
...
src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs
浏览文件 @
f8ed9e7a
...
...
@@ -183,7 +183,6 @@ protected override void GetUnusedNamespaceImports(SemanticModel model, HashSet<S
{
if
(
diagnostic
.
Id
==
s_CS8019_UnusedUsingDirective
)
{
if
(
root
.
FindNode
(
diagnostic
.
Location
.
SourceSpan
)
is
UsingDirectiveSyntax
node
)
{
namespaceImports
.
Add
(
node
);
...
...
src/Workspaces/Core/Portable/CodeGeneration/NullableSyntaxAnnotation.cs
0 → 100644
浏览文件 @
f8ed9e7a
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
Microsoft.CodeAnalysis.Editing
;
namespace
Microsoft.CodeAnalysis.CodeGeneration
{
/// <summary>
/// Annotation placed on <see cref="ITypeSymbol"/>s that the <see cref="SyntaxGenerator"/> converts to a node. This
/// information tracks the original nullable state of the symbol and is used by metadata-as-source to determine if
/// it needs to add <c>#nullable</c> directives in the file.
/// </summary>
internal
sealed
class
NullableSyntaxAnnotation
{
/// <summary>
/// For <c>string~</c> types.
/// </summary>
public
static
readonly
SyntaxAnnotation
Oblivious
=
new
SyntaxAnnotation
(
$"
{
nameof
(
NullableSyntaxAnnotation
)}
.
{
Oblivious
}
"
);
/// <summary>
/// For <c>string!</c> or <c>string?</c> types.
/// </summary>
public
static
readonly
SyntaxAnnotation
AnnotatedOrNotAnnotated
=
new
SyntaxAnnotation
(
$"
{
nameof
(
NullableSyntaxAnnotation
)}
.
{
AnnotatedOrNotAnnotated
}
"
);
}
}
src/Workspaces/Core/Portable/FindSymbols/SymbolFinder.cs
浏览文件 @
f8ed9e7a
...
...
@@ -213,7 +213,7 @@ public static IEnumerable<TSymbol> FindSimilarSymbols<TSymbol>(TSymbol symbol, C
// We may be talking about different compilations. So do not try to resolve locations.
var
result
=
new
HashSet
<
TSymbol
>();
var
resolution
=
key
.
Resolve
(
compilation
,
resolveLocations
:
false
,
cancellationToken
:
cancellationToken
);
var
resolution
=
key
.
Resolve
(
compilation
,
cancellationToken
:
cancellationToken
);
foreach
(
var
current
in
resolution
.
OfType
<
TSymbol
>())
{
result
.
Add
(
current
);
...
...
src/Workspaces/Core/Portable/Remote/RemoteArguments.cs
浏览文件 @
f8ed9e7a
...
...
@@ -76,7 +76,7 @@ public static SerializableSymbolAndProjectId Create(ISymbol symbol, Project proj
// The server and client should both be talking about the same compilation. As such
// locations in symbols are save to resolve as we rehydrate the SymbolKey.
var
symbol
=
SymbolKey
.
ResolveString
(
SymbolKeyData
,
compilation
,
resolveLocations
:
true
,
cancellationToken
:
cancellationToken
).
GetAnySymbol
();
SymbolKeyData
,
compilation
,
cancellationToken
:
cancellationToken
).
GetAnySymbol
();
if
(
symbol
==
null
)
{
...
...
src/Workspaces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs
浏览文件 @
f8ed9e7a
...
...
@@ -275,7 +275,6 @@ private class SymbolKeyReader : Reader<string>
public
SymbolEquivalenceComparer
Comparer
{
get
;
private
set
;
}
private
readonly
List
<
IMethodSymbol
>
_methodSymbolStack
=
new
List
<
IMethodSymbol
>();
private
bool
_resolveLocations
;
public
SymbolKeyReader
()
{
...
...
@@ -289,7 +288,6 @@ public override void Dispose()
_idToResult
.
Clear
();
Compilation
=
null
;
IgnoreAssemblyKey
=
false
;
_resolveLocations
=
true
;
Comparer
=
null
;
_methodSymbolStack
.
Clear
();
...
...
@@ -299,11 +297,11 @@ public override void Dispose()
public
static
SymbolKeyReader
GetReader
(
string
data
,
Compilation
compilation
,
bool
ignoreAssemblyKey
,
bool
resolveLocations
,
bool
ignoreAssemblyKey
,
CancellationToken
cancellationToken
)
{
var
reader
=
s_readerPool
.
Allocate
();
reader
.
Initialize
(
data
,
compilation
,
ignoreAssemblyKey
,
resolveLocations
,
cancellationToken
);
reader
.
Initialize
(
data
,
compilation
,
ignoreAssemblyKey
,
cancellationToken
);
return
reader
;
}
...
...
@@ -311,13 +309,11 @@ public override void Dispose()
string
data
,
Compilation
compilation
,
bool
ignoreAssemblyKey
,
bool
resolveLocations
,
CancellationToken
cancellationToken
)
{
base
.
Initialize
(
data
,
cancellationToken
);
Compilation
=
compilation
;
IgnoreAssemblyKey
=
ignoreAssemblyKey
;
_resolveLocations
=
resolveLocations
;
Comparer
=
ignoreAssemblyKey
?
SymbolEquivalenceComparer
.
IgnoreAssembliesInstance
...
...
@@ -508,15 +504,12 @@ public Location ReadLocation()
var
start
=
ReadInteger
();
var
length
=
ReadInteger
();
if
(
_resolveLocations
)
// The syntax tree can be null if we're resolving this location in a compilation
// that does not contain this file. In this case, just map this location to None.
var
syntaxTree
=
GetSyntaxTree
(
filePath
);
if
(
syntaxTree
!=
null
)
{
// The syntax tree can be null if we're resolving this location in a compilation
// that does not contain this file. In this case, just map this location to None.
var
syntaxTree
=
GetSyntaxTree
(
filePath
);
if
(
syntaxTree
!=
null
)
{
return
Location
.
Create
(
syntaxTree
,
new
TextSpan
(
start
,
length
));
}
return
Location
.
Create
(
syntaxTree
,
new
TextSpan
(
start
,
length
));
}
}
else
if
(
kind
==
LocationKind
.
MetadataFile
)
...
...
@@ -524,20 +517,17 @@ public Location ReadLocation()
var
assemblyResolution
=
ReadSymbolKey
();
var
moduleName
=
ReadString
();
if
(
_resolveLocations
)
// We may be resolving in a compilation where we don't have a module
// with this name. In that case, just map this location to none.
if
(
assemblyResolution
.
GetAnySymbol
()
is
IAssemblySymbol
assembly
)
{
// We may be resolving in a compilation where we don't have a module
// with this name. In that case, just map this location to none.
if
(
assemblyResolution
.
GetAnySymbol
()
is
IAssemblySymbol
assembly
)
var
module
=
GetModule
(
assembly
.
Modules
,
moduleName
);
if
(
module
!=
null
)
{
var
module
=
GetModule
(
assembly
.
Modules
,
moduleName
);
if
(
module
!=
null
)
var
location
=
FirstOrDefault
(
module
.
Locations
);
if
(
location
!=
null
)
{
var
location
=
FirstOrDefault
(
module
.
Locations
);
if
(
location
!=
null
)
{
return
location
;
}
return
location
;
}
}
}
...
...
src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs
浏览文件 @
f8ed9e7a
...
...
@@ -77,11 +77,10 @@ namespace Microsoft.CodeAnalysis
/// The SymbolKey for both 'M' methods will be the same. The SymbolKey will then resolve to both methods.
/// </para>
/// <para>
/// <see cref="SymbolKey"/>s are not guaranteed to work across different versions of Roslyn.
/// They can be persisted in their <see cref="ToString()"/> form and used across sessions with
/// the same version of Roslyn. However, future versions may change the encoded format and may
/// no longer be able to <see cref="Resolve(Compilation, bool, bool, CancellationToken)"/> previous
/// keys. As such, only persist if using for a cache that can be regenerated if necessary.
/// <see cref="SymbolKey"/>s are not guaranteed to work across different versions of Roslyn. They can be persisted
/// in their <see cref="ToString()"/> form and used across sessions with the same version of Roslyn. However, future
/// versions may change the encoded format and may no longer be able to <see cref="Resolve"/> previous keys. As
/// such, only persist if using for a cache that can be regenerated if necessary.
/// </para>
/// </summary>
internal
partial
struct
SymbolKey
...
...
@@ -128,11 +127,10 @@ internal static IEqualityComparer<SymbolKey> GetComparer(bool ignoreCase = false
internal
static
SymbolKeyResolution
ResolveString
(
string
symbolKey
,
Compilation
compilation
,
bool
ignoreAssemblyKey
=
false
,
bool
resolveLocations
=
true
,
CancellationToken
cancellationToken
=
default
)
bool
ignoreAssemblyKey
=
false
,
CancellationToken
cancellationToken
=
default
)
{
using
var
reader
=
SymbolKeyReader
.
GetReader
(
symbolKey
,
compilation
,
ignoreAssemblyKey
,
resolveLocations
,
cancellationToken
);
symbolKey
,
compilation
,
ignoreAssemblyKey
,
cancellationToken
);
var
version
=
reader
.
ReadFormatVersion
();
if
(
version
!=
FormatVersion
)
{
...
...
@@ -158,15 +156,12 @@ internal static string CreateStringWorker(int version, ISymbol symbol, Cancellat
/// <summary>
/// Tries to resolve this <see cref="SymbolKey"/> in the given
/// <paramref name="compilation"/> to a matching symbol. <paramref name="resolveLocations"/>
/// should only be given <see langword="true"/> if the symbol was produced from a compilation
/// that has the exact same source as the compilation we're resolving against. Otherwise
/// the locations resolved may not actually be correct in the final compilation.
/// <paramref name="compilation"/> to a matching symbol.
/// </summary>
public
SymbolKeyResolution
Resolve
(
Compilation
compilation
,
bool
ignoreAssemblyKey
=
false
,
bool
resolveLocations
=
true
,
CancellationToken
cancellationToken
=
default
)
Compilation
compilation
,
bool
ignoreAssemblyKey
=
false
,
CancellationToken
cancellationToken
=
default
)
{
return
ResolveString
(
_symbolKeyData
,
compilation
,
ignoreAssemblyKey
,
resolveLocations
,
cancellationToken
);
return
ResolveString
(
_symbolKeyData
,
compilation
,
ignoreAssemblyKey
,
cancellationToken
);
}
/// <summary>
...
...
src/Workspaces/Core/Portable/SymbolKey/SymbolKeyResolution.cs
浏览文件 @
f8ed9e7a
...
...
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Immutable
;
using
System.Threading
;
#if DEBUG
using
System.Diagnostics
;
...
...
@@ -12,11 +11,10 @@
namespace
Microsoft.CodeAnalysis
{
/// <summary>
/// The result of <see cref="SymbolKey.Resolve(Compilation, bool, bool, CancellationToken)"/>.
/// If the <see cref="SymbolKey"/> could be uniquely mapped to a single <see cref="ISymbol"/>
/// then that will be returned in <see cref="Symbol"/>. Otherwise, if
/// the key resolves to multiple symbols (which can happen in error scenarios), then
/// <see cref="CandidateSymbols"/> and <see cref="CandidateReason"/> will be returned.
/// The result of <see cref="SymbolKey.Resolve"/>. If the <see cref="SymbolKey"/> could be uniquely mapped to a
/// single <see cref="ISymbol"/> then that will be returned in <see cref="Symbol"/>. Otherwise, if the key resolves
/// to multiple symbols (which can happen in error scenarios), then <see cref="CandidateSymbols"/> and <see
/// cref="CandidateReason"/> will be returned.
///
/// If no symbol can be found <see cref="Symbol"/> will be <c>null</c> and <see cref="CandidateSymbols"/>
/// will be empty.
...
...
src/Workspaces/CoreTest/SymbolKeyTests.cs
浏览文件 @
f8ed9e7a
...
...
@@ -223,7 +223,7 @@ public class C
public A GetA<A>(A a) { return a; }
public A GetA<A, B>(A a, B b) { return a; }
public B GetB<A, B>(A a, B b) { return b; }
publi C GetC() { return default(C); }
publi
c
C GetC() { return default(C); }
}
public class C<T>
...
...
@@ -699,7 +699,7 @@ object LocalFunction<T>()
Assert
.
NotNull
(
found
);
// note: we don't check that the symbols are equal. That's because the compiler
// doesn't guarantee that the TypeParameters will be
ht
e same across successive
// doesn't guarantee that the TypeParameters will be
th
e same across successive
// invocations.
Assert
.
Equal
(
symbol
.
OriginalDefinition
,
found
.
OriginalDefinition
);
...
...
@@ -736,7 +736,7 @@ void Method((C, int) t)
// Validate that if the client does ask to resolve locations that we
// do not crash if those locations cannot be found.
var
found
=
SymbolKey
.
ResolveString
(
id
,
compilation2
,
resolveLocations
:
true
).
GetAnySymbol
();
var
found
=
SymbolKey
.
ResolveString
(
id
,
compilation2
).
GetAnySymbol
();
Assert
.
NotNull
(
found
);
Assert
.
Equal
(
symbol
.
Name
,
found
.
Name
);
...
...
@@ -773,7 +773,7 @@ void Method((C a, int b) t)
// Validate that if the client does ask to resolve locations that we
// do not crash if those locations cannot be found.
var
found
=
SymbolKey
.
ResolveString
(
id
,
compilation2
,
resolveLocations
:
true
).
GetAnySymbol
();
var
found
=
SymbolKey
.
ResolveString
(
id
,
compilation2
).
GetAnySymbol
();
Assert
.
NotNull
(
found
);
Assert
.
Equal
(
symbol
.
Name
,
found
.
Name
);
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs
浏览文件 @
f8ed9e7a
...
...
@@ -304,7 +304,13 @@ public override TypeSyntax VisitPointerType(IPointerTypeSymbol symbol)
}
public
override
TypeSyntax
VisitTypeParameter
(
ITypeParameterSymbol
symbol
)
=>
AddInformationTo
(
symbol
.
Name
.
ToIdentifierName
(),
symbol
);
{
TypeSyntax
typeSyntax
=
AddInformationTo
(
symbol
.
Name
.
ToIdentifierName
(),
symbol
);
if
(
symbol
.
NullableAnnotation
==
NullableAnnotation
.
Annotated
)
typeSyntax
=
AddInformationTo
(
SyntaxFactory
.
NullableType
(
typeSyntax
),
symbol
);
return
typeSyntax
;
}
}
}
}
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs
浏览文件 @
f8ed9e7a
...
...
@@ -16,6 +16,10 @@
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
#if !CODE_STYLE
using
Microsoft.CodeAnalysis.CodeGeneration
;
#endif
namespace
Microsoft.CodeAnalysis.CSharp.Extensions
{
internal
static
partial
class
ITypeSymbolExtensions
...
...
@@ -41,7 +45,8 @@ internal static partial class ITypeSymbolExtensions
private
static
TypeSyntax
GenerateTypeSyntax
(
INamespaceOrTypeSymbol
symbol
,
bool
nameSyntax
,
bool
allowVar
=
true
)
{
if
(
symbol
is
ITypeSymbol
type
&&
type
.
ContainsAnonymousType
())
var
type
=
symbol
as
ITypeSymbol
;
if
(
type
!=
null
&&
type
.
ContainsAnonymousType
())
{
// something with an anonymous type can only be represented with 'var', regardless
// of what the user's preferences might be.
...
...
@@ -56,6 +61,22 @@ internal static partial class ITypeSymbolExtensions
syntax
=
syntax
.
WithAdditionalAnnotations
(
DoNotAllowVarAnnotation
.
Annotation
);
}
#if !CODE_STYLE
if
(
type
!=
null
&&
type
.
IsReferenceType
)
{
syntax
=
syntax
.
WithAdditionalAnnotations
(
type
.
NullableAnnotation
switch
{
NullableAnnotation
.
None
=>
NullableSyntaxAnnotation
.
Oblivious
,
NullableAnnotation
.
Annotated
=>
NullableSyntaxAnnotation
.
AnnotatedOrNotAnnotated
,
NullableAnnotation
.
NotAnnotated
=>
NullableSyntaxAnnotation
.
AnnotatedOrNotAnnotated
,
_
=>
throw
ExceptionUtilities
.
UnexpectedValue
(
type
.
NullableAnnotation
),
});
}
#endif
return
syntax
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录