Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
89497254
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,发现更多精彩内容 >>
未验证
提交
89497254
编写于
8月 21, 2020
作者:
M
msftbot[bot]
提交者:
GitHub
8月 21, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #46999 from CyrusNajmabadi/extractMethodFix
Fix extract method crash with conditional access expressions.
上级
fa6725ee
e36304e0
变更
47
隐藏空白更改
内联
并排
Showing
47 changed file
with
995 addition
and
333 deletion
+995
-333
src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractObjectCreationExpressionAnalyzer.cs
...onInitializer/AbstractObjectCreationExpressionAnalyzer.cs
+2
-1
src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs
...SharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs
+231
-0
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs
...tion/CompletionProviders/SymbolCompletionProviderTests.cs
+43
-1
src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb
...BasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb
+254
-0
src/Features/CSharp/Portable/AddImport/CSharpAddImportFeatureService.cs
...Sharp/Portable/AddImport/CSharpAddImportFeatureService.cs
+2
-1
src/Features/CSharp/Portable/CodeRefactorings/SyncNamespace/CSharpChangeNamespaceService.cs
...efactorings/SyncNamespace/CSharpChangeNamespaceService.cs
+2
-1
src/Features/CSharp/Portable/Debugging/DataTipInfoGetter.cs
src/Features/CSharp/Portable/Debugging/DataTipInfoGetter.cs
+1
-12
src/Features/CSharp/Portable/DisambiguateSameVariable/CSharpDisambiguateSameVariableCodeFixProvider.cs
...Variable/CSharpDisambiguateSameVariableCodeFixProvider.cs
+2
-1
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs
...dExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs
+7
-29
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs
...or.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs
+7
-6
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs
...actor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs
+5
-5
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs
...xtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs
+20
-18
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.PostProcessor.cs
...able/ExtractMethod/CSharpMethodExtractor.PostProcessor.cs
+28
-28
src/Features/CSharp/Portable/ExtractMethod/CSharpSelectionResult.ExpressionResult.cs
...e/ExtractMethod/CSharpSelectionResult.ExpressionResult.cs
+7
-1
src/Features/CSharp/Portable/ImplementInterface/CSharpImplementExplicitlyCodeRefactoringProvider.cs
...rface/CSharpImplementExplicitlyCodeRefactoringProvider.cs
+1
-1
src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs
...Features/Core/Portable/AddImport/SymbolReferenceFinder.cs
+2
-1
src/Features/Core/Portable/ConvertAnonymousTypeToClass/AbstractConvertAnonymousTypeToClassCodeRefactoringProvider.cs
...ractConvertAnonymousTypeToClassCodeRefactoringProvider.cs
+2
-1
src/Features/Core/Portable/ExtractMethod/AbstractSyntaxTriviaService.Result.cs
...table/ExtractMethod/AbstractSyntaxTriviaService.Result.cs
+2
-8
src/Features/Core/Portable/ExtractMethod/MethodExtractor.Analyzer.cs
...s/Core/Portable/ExtractMethod/MethodExtractor.Analyzer.cs
+13
-11
src/Features/Core/Portable/ExtractMethod/MethodExtractor.AnalyzerResult.cs
.../Portable/ExtractMethod/MethodExtractor.AnalyzerResult.cs
+7
-6
src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs
...e/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs
+19
-30
src/Features/Core/Portable/ExtractMethod/MethodExtractor.VariableInfo.cs
...re/Portable/ExtractMethod/MethodExtractor.VariableInfo.cs
+3
-2
src/Features/Core/Portable/MakeMethodSynchronous/AbstractMakeMethodSynchronousCodeFixProvider.cs
...nchronous/AbstractMakeMethodSynchronousCodeFixProvider.cs
+2
-1
src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs
...yWithMethods/AbstractReplacePropertyWithMethodsService.cs
+2
-1
src/Features/VisualBasic/Portable/CodeRefactorings/SyncNamespace/VisualBasicChangeNamespaceService.vb
...orings/SyncNamespace/VisualBasicChangeNamespaceService.vb
+1
-1
src/Features/VisualBasic/Portable/Debugging/DataTipInfoGetter.vb
...tures/VisualBasic/Portable/Debugging/DataTipInfoGetter.vb
+1
-10
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.PostProcessor.vb
...ExtractMethod/VisualBasicMethodExtractor.PostProcessor.vb
+8
-7
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb
...actor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb
+10
-36
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb
...sualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb
+5
-4
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb
....VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb
+5
-4
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb
...od/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb
+9
-9
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicSelectionResult.vb
...asic/Portable/ExtractMethod/VisualBasicSelectionResult.vb
+13
-8
src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/SyntaxTokenClassifier.cs
...ssification/SyntaxClassification/SyntaxTokenClassifier.cs
+4
-3
src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.Expander.cs
...le/Simplification/CSharpSimplificationService.Expander.cs
+1
-1
src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs
...Symbols/FindReferences/Finders/AbstractReferenceFinder.cs
+3
-1
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs
.../Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs
+6
-6
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SimpleNameSyntaxExtensions.cs
.../Compiler/CSharp/Extensions/SimpleNameSyntaxExtensions.cs
+7
-11
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs
...nsions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs
+88
-8
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs
...Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs
+19
-2
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs
...nsions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs
+21
-2
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs
...piler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs
+20
-0
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ExpressionSyntaxExtensions.vb
...iler/VisualBasic/Extensions/ExpressionSyntaxExtensions.vb
+3
-4
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/MemberAccessExpressionSyntaxExtensions.vb
...asic/Extensions/MemberAccessExpressionSyntaxExtensions.vb
+1
-1
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/SyntaxNodeExtensions.vb
...s/Compiler/VisualBasic/Extensions/SyntaxNodeExtensions.vb
+81
-42
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb
...isualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb
+22
-4
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/SimpleNameSyntaxExtensions.vb
...pace/VisualBasic/Extensions/SimpleNameSyntaxExtensions.vb
+2
-2
src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.Expander.vb
...mplification/VisualBasicSimplificationService.Expander.vb
+1
-1
未找到文件。
src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractObjectCreationExpressionAnalyzer.cs
浏览文件 @
89497254
...
...
@@ -167,7 +167,8 @@ protected bool ExpressionContainsValuePatternOrReferencesInitializedSymbol(Synta
{
foreach
(
var
subExpression
in
expression
.
DescendantNodesAndSelf
().
OfType
<
TExpressionSyntax
>())
{
if
(!
_syntaxFacts
.
IsNameOfMemberAccessExpression
(
subExpression
))
if
(!
_syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
subExpression
)
&&
!
_syntaxFacts
.
IsNameOfMemberBindingExpression
(
subExpression
))
{
if
(
ValuePatternMatches
(
subExpression
))
{
...
...
src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs
浏览文件 @
89497254
...
...
@@ -3969,6 +3969,237 @@ private static Action<Context> NewMethod()
return context => context.ToString();
}
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess1
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?.[|ToString|]();
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static string NewMethod(List<int> b)
{
return b?.ToString();
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess2
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?.[|ToString|]().Length;
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static int? NewMethod(List<int> b)
{
return b?.ToString().Length;
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess3
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?.Count.[|ToString|]();
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static string NewMethod(List<int> b)
{
return b?.Count.ToString();
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess4
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?.[|Count|].ToString();
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static string NewMethod(List<int> b)
{
return b?.Count.ToString();
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess5
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?.[|ToString|]()?.ToString();
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static string NewMethod(List<int> b)
{
return b?.ToString()?.ToString();
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess6
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?.ToString()?.[|ToString|]();
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static string NewMethod(List<int> b)
{
return b?.ToString()?.ToString();
}
}"
);
}
[
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)]
public
async
Task
TestConditionalAccess7
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = b?[|[0]|];
}
}"
,
@"
using System;
using System.Collections.Generic;
class C
{
void Test()
{
List<int> b = null;
b?.Clear();
_ = {|Rename:NewMethod|}(b);
}
private static int? NewMethod(List<int> b)
{
return b?[0];
}
}"
);
}
}
...
...
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs
浏览文件 @
89497254
...
...
@@ -8074,7 +8074,7 @@ public void goo()
[
WorkItem
(
1109319
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
WithinChainOfConditionalAccesses
()
public
async
Task
WithinChainOfConditionalAccesses
1
()
{
var
markup
=
@"
class Program
...
...
@@ -8093,6 +8093,48 @@ class D { public int e; }";
await
VerifyItemExistsAsync
(
markup
,
"b"
);
}
[
WorkItem
(
1109319
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
WithinChainOfConditionalAccesses2
()
{
var
markup
=
@"
class Program
{
static void Main(string[] args)
{
A a;
var x = a?.b?.$$c?.d.e;
}
}
class A { public B b; }
class B { public C c; }
class C { public D d; }
class D { public int e; }"
;
await
VerifyItemExistsAsync
(
markup
,
"c"
);
}
[
WorkItem
(
1109319
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
WithinChainOfConditionalAccesses3
()
{
var
markup
=
@"
class Program
{
static void Main(string[] args)
{
A a;
var x = a?.b?.c?.$$d.e;
}
}
class A { public B b; }
class B { public C c; }
class C { public D d; }
class D { public int e; }"
;
await
VerifyItemExistsAsync
(
markup
,
"d"
);
}
[
WorkItem
(
843466
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/843466"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
NestedAttributeAccessibleOnSelf
()
...
...
src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb
浏览文件 @
89497254
...
...
@@ -834,5 +834,259 @@ End Class",
End Function
End Class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess1
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?.[|ToString|]()
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As String
Return b?.ToString()
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess2
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?.[|ToString|]().Length
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As Integer?
Return b?.ToString().Length
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess3
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?.Count.[|ToString|]()
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As String
Return b?.Count.ToString()
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess4
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?.[|Count|].ToString()
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As String
Return b?.Count.ToString()
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess5
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?.[|ToString|]()?.ToString()
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As String
Return b?.ToString()?.ToString()
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess6
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?.ToString()?.[|ToString|]()
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As String
Return b?.ToString()?.ToString()
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess7
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = b?[|(0)|]
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new List(of integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As List(Of Integer)) As Integer?
Return b?(0)
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess8
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new Dictionary(of string, integer)
dim x = b?![|a|]
end sub
end class"
,
"
imports System
imports System.Collections.Generic
class C
sub Test()
dim b as new Dictionary(of string, integer)
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As Dictionary(Of String, Integer)) As Integer?
Return b?!a
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess9
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
imports System.Xml.Linq
class C
sub Test()
dim b as XElement = nothing
dim x = b?.[|<e>|]
end sub
end class"
,
"
imports System
imports System.Collections.Generic
imports System.Xml.Linq
class C
sub Test()
dim b as XElement = nothing
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As XElement) As IEnumerable(Of XElement)
Return b?.<e>
End Function
end class"
)
End
Function
<
Fact
,
WorkItem
(
41895
,
"https://github.com/dotnet/roslyn/issues/41895"
)
>
Public
Async
Function
TestConditionalAccess10
()
As
Task
Await
TestInRegularAndScript1Async
(
"
imports System
imports System.Collections.Generic
imports System.Xml.Linq
class C
sub Test()
dim b as XElement = nothing
dim x = b?.[|@e|]
end sub
end class"
,
"
imports System
imports System.Collections.Generic
imports System.Xml.Linq
class C
sub Test()
dim b as XElement = nothing
dim x = {|Rename:GetX|}(b)
end sub
Private Shared Function GetX(b As XElement) As String
Return b?.@e
End Function
end class"
)
End
Function
End
Class
End
Namespace
src/Features/CSharp/Portable/AddImport/CSharpAddImportFeatureService.cs
浏览文件 @
89497254
...
...
@@ -129,7 +129,8 @@ protected override bool CanAddImport(SyntaxNode node, CancellationToken cancella
return
false
;
}
if
(!
syntaxFacts
.
IsNameOfMemberAccessExpression
(
node
))
if
(!
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
node
)
&&
!
syntaxFacts
.
IsNameOfMemberBindingExpression
(
node
))
{
return
false
;
}
...
...
src/Features/CSharp/Portable/CodeRefactorings/SyncNamespace/CSharpChangeNamespaceService.cs
浏览文件 @
89497254
...
...
@@ -159,7 +159,8 @@ protected override SyntaxList<MemberDeclarationSyntax> GetMemberDeclarationsInCo
newNode
=
newNode
.
WithTriviaFrom
(
oldNode
);
return
true
;
}
else
if
(
syntaxFacts
.
IsNameOfMemberAccessExpression
(
nameRef
))
else
if
(
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
nameRef
)
||
syntaxFacts
.
IsNameOfMemberBindingExpression
(
nameRef
))
{
RoslynDebug
.
Assert
(
nameRef
.
Parent
is
object
);
oldNode
=
nameRef
.
Parent
;
...
...
src/Features/CSharp/Portable/Debugging/DataTipInfoGetter.cs
浏览文件 @
89497254
...
...
@@ -51,18 +51,7 @@ internal static async Task<DebugDataTipInfo> GetInfoAsync(Document document, int
if
(
expression
.
IsRightSideOfDotOrArrow
())
{
var
curr
=
expression
;
while
(
true
)
{
var
conditionalAccess
=
curr
.
GetParentConditionalAccessExpression
();
if
(
conditionalAccess
==
null
)
{
break
;
}
curr
=
conditionalAccess
;
}
var
curr
=
expression
.
GetRootConditionalAccessExpression
()
??
expression
;
if
(
curr
==
expression
)
{
// NB: Parent.Span, not Span as below.
...
...
src/Features/CSharp/Portable/DisambiguateSameVariable/CSharpDisambiguateSameVariableCodeFixProvider.cs
浏览文件 @
89497254
...
...
@@ -161,7 +161,8 @@ where m.IsAccessibleWithin(enclosingType)
var
newNameNode
=
matchingMember
.
Name
.
ToIdentifierName
();
var
newExpr
=
(
ExpressionSyntax
)
newNameNode
;
if
(!
syntaxFacts
.
IsNameOfMemberAccessExpression
(
nameNode
))
if
(!
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
nameNode
)
&&
!
syntaxFacts
.
IsNameOfMemberBindingExpression
(
nameNode
))
{
newExpr
=
MemberAccessExpression
(
SyntaxKind
.
SimpleMemberAccessExpression
,
ThisExpression
(),
newNameNode
).
WithAdditionalAnnotations
(
Simplifier
.
Annotation
);
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs
浏览文件 @
89497254
...
...
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -91,7 +92,7 @@ private static string GetMethodNameBasedOnExpression(string methodName, SyntaxNo
return
methodName
;
}
protected
override
I
Enumerable
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
protected
override
I
mmutableArray
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
{
Contract
.
ThrowIfFalse
(
IsExtractMethodOnExpression
(
CSharpSelectionResult
));
...
...
@@ -113,13 +114,13 @@ protected override IEnumerable<StatementSyntax> GetInitialStatementsForMethodDef
if
(
AnalyzerResult
.
HasReturnType
)
{
return
SpecializedCollections
.
SingletonEnumerabl
e
<
StatementSyntax
>(
return
ImmutableArray
.
Creat
e
<
StatementSyntax
>(
SyntaxFactory
.
ReturnStatement
(
WrapInCheckedExpressionIfNeeded
(
expression
)));
}
else
{
return
SpecializedCollections
.
SingletonEnumerabl
e
<
StatementSyntax
>(
return
ImmutableArray
.
Creat
e
<
StatementSyntax
>(
SyntaxFactory
.
ExpressionStatement
(
WrapInCheckedExpressionIfNeeded
(
expression
)));
}
...
...
@@ -188,12 +189,11 @@ protected override SyntaxNode GetFirstStatementOrInitializerSelectedAtCallSite()
protected
override
SyntaxNode
GetLastStatementOrInitializerSelectedAtCallSite
()
=>
GetFirstStatementOrInitializerSelectedAtCallSite
();
protected
override
async
Task
<
SyntaxNode
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
SyntaxAnnotation
callSiteAnnotation
,
CancellationToken
cancellationToken
)
protected
override
async
Task
<
SyntaxNode
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
CancellationToken
cancellationToken
)
{
var
enclosingStatement
=
GetFirstStatementOrInitializerSelectedAtCallSite
();
var
callSignature
=
CreateCallSignature
().
WithAdditionalAnnotations
(
callSiteAnnotation
);
var
invocation
=
callSignature
.
IsKind
(
SyntaxKind
.
AwaitExpression
,
out
AwaitExpressionSyntax
awaitExpr
)
?
awaitExpr
.
Expression
:
callSignature
;
var
callSignature
=
CreateCallSignature
().
WithAdditionalAnnotations
(
CallSiteAnnotation
)
;
var
sourceNode
=
CSharpSelectionResult
.
GetContainingScope
();
Contract
.
ThrowIfTrue
(
...
...
@@ -220,28 +220,6 @@ protected override SyntaxNode GetLastStatementOrInitializerSelectedAtCallSite()
// however complexification of names is prepended, so the last annotation should be the original one.
sourceNode
=
updatedRoot
.
GetAnnotatedNodesAndTokens
(
sourceNodeAnnotation
).
Last
().
AsNode
();
// we want to replace the old identifier with a invocation expression, but because of MakeExplicit we might have
// a member access now instead of the identifier. So more syntax fiddling is needed.
if
(
sourceNode
.
Parent
.
Kind
()
==
SyntaxKind
.
SimpleMemberAccessExpression
&&
((
ExpressionSyntax
)
sourceNode
).
IsRightSideOfDot
())
{
var
explicitMemberAccess
=
(
MemberAccessExpressionSyntax
)
sourceNode
.
Parent
;
var
replacementMemberAccess
=
explicitMemberAccess
.
CopyAnnotationsTo
(
SyntaxFactory
.
MemberAccessExpression
(
sourceNode
.
Parent
.
Kind
(),
explicitMemberAccess
.
Expression
,
(
SimpleNameSyntax
)((
InvocationExpressionSyntax
)
invocation
).
Expression
));
var
newInvocation
=
SyntaxFactory
.
InvocationExpression
(
replacementMemberAccess
,
((
InvocationExpressionSyntax
)
invocation
).
ArgumentList
);
var
newCallSignature
=
callSignature
!=
invocation
?
callSignature
.
ReplaceNode
(
invocation
,
newInvocation
)
:
invocation
.
CopyAnnotationsTo
(
newInvocation
);
sourceNode
=
sourceNode
.
Parent
;
callSignature
=
newCallSignature
;
}
return
newEnclosingStatement
.
ReplaceNode
(
sourceNode
,
callSignature
);
}
}
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs
浏览文件 @
89497254
...
...
@@ -3,11 +3,13 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.ExtractMethod
...
...
@@ -47,13 +49,13 @@ public static bool IsExtractMethodOnMultipleStatements(SelectionResult code)
protected
override
SyntaxToken
CreateMethodName
()
=>
GenerateMethodNameForStatementGenerators
();
protected
override
I
Enumerable
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
protected
override
I
mmutableArray
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
{
var
firstSeen
=
false
;
var
firstStatementUnderContainer
=
CSharpSelectionResult
.
GetFirstStatementUnderContainer
();
var
lastStatementUnderContainer
=
CSharpSelectionResult
.
GetLastStatementUnderContainer
();
var
list
=
new
List
<
StatementSyntax
>(
);
using
var
_
=
ArrayBuilder
<
StatementSyntax
>.
GetInstance
(
out
var
list
);
foreach
(
var
statement
in
GetStatementsFromContainer
(
firstStatementUnderContainer
.
Parent
))
{
// reset first seen
...
...
@@ -77,7 +79,7 @@ protected override IEnumerable<StatementSyntax> GetInitialStatementsForMethodDef
}
}
return
list
;
return
list
.
ToImmutable
()
;
}
protected
override
SyntaxNode
GetOutermostCallSiteContainerToProcess
(
CancellationToken
cancellationToken
)
...
...
@@ -113,11 +115,10 @@ protected override SyntaxNode GetFirstStatementOrInitializerSelectedAtCallSite()
protected
override
SyntaxNode
GetLastStatementOrInitializerSelectedAtCallSite
()
=>
CSharpSelectionResult
.
GetLastStatementUnderContainer
();
protected
override
Task
<
SyntaxNode
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
SyntaxAnnotation
callSiteAnnotation
,
CancellationToken
cancellationToken
)
protected
override
Task
<
SyntaxNode
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
CancellationToken
cancellationToken
)
{
var
statement
=
GetStatementContainingInvocationToExtractedMethodWorker
();
return
Task
.
FromResult
<
SyntaxNode
>(
statement
.
WithAdditionalAnnotations
(
c
allSiteAnnotation
));
return
Task
.
FromResult
<
SyntaxNode
>(
statement
.
WithAdditionalAnnotations
(
C
allSiteAnnotation
));
}
}
}
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs
浏览文件 @
89497254
...
...
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
...
...
@@ -39,11 +40,11 @@ public static bool IsExtractMethodOnSingleStatement(SelectionResult code)
protected
override
SyntaxToken
CreateMethodName
()
=>
GenerateMethodNameForStatementGenerators
();
protected
override
I
Enumerable
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
protected
override
I
mmutableArray
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
{
Contract
.
ThrowIfFalse
(
IsExtractMethodOnSingleStatement
(
CSharpSelectionResult
));
return
SpecializedCollections
.
SingletonEnumerable
<
StatementSyntax
>
(
CSharpSelectionResult
.
GetFirstStatement
());
return
ImmutableArray
.
Create
(
CSharpSelectionResult
.
GetFirstStatement
());
}
protected
override
SyntaxNode
GetOutermostCallSiteContainerToProcess
(
CancellationToken
cancellationToken
)
...
...
@@ -70,11 +71,10 @@ protected override SyntaxNode GetLastStatementOrInitializerSelectedAtCallSite()
return
CSharpSelectionResult
.
GetFirstStatement
();
}
protected
override
Task
<
SyntaxNode
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
SyntaxAnnotation
callSiteAnnotation
,
CancellationToken
cancellationToken
)
protected
override
Task
<
SyntaxNode
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
CancellationToken
cancellationToken
)
{
var
statement
=
GetStatementContainingInvocationToExtractedMethodWorker
();
return
Task
.
FromResult
<
SyntaxNode
>(
statement
.
WithAdditionalAnnotations
(
c
allSiteAnnotation
));
return
Task
.
FromResult
<
SyntaxNode
>(
statement
.
WithAdditionalAnnotations
(
C
allSiteAnnotation
));
}
}
}
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs
浏览文件 @
89497254
...
...
@@ -20,6 +20,7 @@
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Operations
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
...
...
@@ -143,7 +144,7 @@ protected override async Task<SyntaxNode> GenerateBodyForCallSiteContainerAsync(
return
container
.
CopyAnnotationsTo
(
callSiteGenerator
.
Generate
()).
WithAdditionalAnnotations
(
Formatter
.
Annotation
);
}
private
async
Task
<
I
Enumerable
<
SyntaxNode
>>
CreateStatementsOrInitializerToInsertAtCallSiteAsync
(
CancellationToken
cancellationToken
)
private
async
Task
<
I
mmutableArray
<
SyntaxNode
>>
CreateStatementsOrInitializerToInsertAtCallSiteAsync
(
CancellationToken
cancellationToken
)
{
var
selectedNode
=
GetFirstStatementOrInitializerSelectedAtCallSite
();
...
...
@@ -153,8 +154,8 @@ private async Task<IEnumerable<SyntaxNode>> CreateStatementsOrInitializerToInser
IsExpressionBodiedMember
(
selectedNode
)
||
IsExpressionBodiedAccessor
(
selectedNode
))
{
var
statement
=
await
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
CallSiteAnnotation
,
cancellationToken
).
ConfigureAwait
(
false
);
return
SpecializedCollections
.
SingletonEnumerabl
e
(
statement
);
var
statement
=
await
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
return
ImmutableArray
.
Creat
e
(
statement
);
}
// regular case
...
...
@@ -168,7 +169,7 @@ private async Task<IEnumerable<SyntaxNode>> CreateStatementsOrInitializerToInser
statements
=
await
AddInvocationAtCallSiteAsync
(
statements
,
cancellationToken
).
ConfigureAwait
(
false
);
statements
=
AddReturnIfUnreachable
(
statements
);
return
statements
;
return
statements
.
CastArray
<
SyntaxNode
>()
;
}
private
static
bool
IsExpressionBodiedMember
(
SyntaxNode
node
)
...
...
@@ -279,7 +280,7 @@ private IEnumerable<StatementSyntax> WrapInCheckStatementIfNeeded(IEnumerable<St
return
SpecializedCollections
.
SingletonEnumerable
<
StatementSyntax
>(
SyntaxFactory
.
CheckedStatement
(
kind
,
SyntaxFactory
.
Block
(
statements
)));
}
private
static
I
Enumerable
<
StatementSyntax
>
CleanupCode
(
IEnumerable
<
StatementSyntax
>
statements
)
private
static
I
mmutableArray
<
StatementSyntax
>
CleanupCode
(
ImmutableArray
<
StatementSyntax
>
statements
)
{
statements
=
PostProcessor
.
RemoveRedundantBlock
(
statements
);
statements
=
PostProcessor
.
RemoveDeclarationAssignmentPattern
(
statements
);
...
...
@@ -324,20 +325,22 @@ private static OperationStatus CheckActiveStatements(IEnumerable<StatementSyntax
return
OperationStatus
.
NoActiveStatement
;
}
private
I
Enumerable
<
StatementSyntax
>
MoveDeclarationOutFromMethodDefinition
(
I
Enumerable
<
StatementSyntax
>
statements
,
CancellationToken
cancellationToken
)
private
I
mmutableArray
<
StatementSyntax
>
MoveDeclarationOutFromMethodDefinition
(
I
mmutableArray
<
StatementSyntax
>
statements
,
CancellationToken
cancellationToken
)
{
using
var
_
=
ArrayBuilder
<
StatementSyntax
>.
GetInstance
(
out
var
result
);
var
variableToRemoveMap
=
CreateVariableDeclarationToRemoveMap
(
AnalyzerResult
.
GetVariablesToMoveOutToCallSiteOrDelete
(
cancellationToken
),
cancellationToken
);
statements
=
statements
.
Select
(
s
=>
FixDeclarationExpressionsAndDeclarationPatterns
(
s
,
variableToRemoveMap
));
statements
=
statements
.
Select
AsArray
(
s
=>
FixDeclarationExpressionsAndDeclarationPatterns
(
s
,
variableToRemoveMap
));
foreach
(
var
statement
in
statements
)
{
if
(!(
statement
is
LocalDeclarationStatementSyntax
declarationStatement
)
||
declarationStatement
.
Declaration
.
Variables
.
FullSpan
.
IsEmpty
)
{
// if given statement is not decl statement.
yield
return
statement
;
result
.
Add
(
statement
)
;
continue
;
}
...
...
@@ -394,28 +397,27 @@ private static OperationStatus CheckActiveStatements(IEnumerable<StatementSyntax
// trivia to the statement
// TODO : think about a way to trivia attached to next token
yield
return
SyntaxFactory
.
EmptyStatement
(
SyntaxFactory
.
Token
(
SyntaxFactory
.
TriviaList
(
triviaList
),
SyntaxKind
.
SemicolonToken
,
SyntaxTriviaList
.
Create
(
SyntaxFactory
.
ElasticMarker
)));
result
.
Add
(
SyntaxFactory
.
EmptyStatement
(
SyntaxFactory
.
Token
(
SyntaxFactory
.
TriviaList
(
triviaList
),
SyntaxKind
.
SemicolonToken
,
SyntaxTriviaList
.
Create
(
SyntaxFactory
.
ElasticMarker
)
)));
triviaList
.
Clear
();
}
// return survived var decls
if
(
list
.
Count
>
0
)
{
yield
return
SyntaxFactory
.
LocalDeclarationStatement
(
result
.
Add
(
SyntaxFactory
.
LocalDeclarationStatement
(
declarationStatement
.
Modifiers
,
SyntaxFactory
.
VariableDeclaration
(
declarationStatement
.
Declaration
.
Type
,
SyntaxFactory
.
SeparatedList
(
list
)),
declarationStatement
.
SemicolonToken
.
WithPrependedLeadingTrivia
(
triviaList
));
declarationStatement
.
SemicolonToken
.
WithPrependedLeadingTrivia
(
triviaList
))
)
;
triviaList
.
Clear
();
}
// return any expression statement if there was any
foreach
(
var
expressionStatement
in
expressionStatements
)
{
yield
return
expressionStatement
;
}
result
.
AddRange
(
expressionStatements
);
}
return
result
.
ToImmutable
();
}
/// <summary>
...
...
@@ -512,8 +514,8 @@ private static SyntaxToken ApplyTriviaFromDeclarationToAssignmentIdentifier(Loca
return
identifier
;
}
private
I
Enumerable
<
StatementSyntax
>
SplitOrMoveDeclarationIntoMethodDefinition
(
I
Enumerable
<
StatementSyntax
>
statements
,
private
I
mmutableArray
<
StatementSyntax
>
SplitOrMoveDeclarationIntoMethodDefinition
(
I
mmutableArray
<
StatementSyntax
>
statements
,
CancellationToken
cancellationToken
)
{
var
semanticModel
=
SemanticDocument
.
SemanticModel
;
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.PostProcessor.cs
浏览文件 @
89497254
...
...
@@ -3,8 +3,10 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Roslyn.Utilities
;
...
...
@@ -25,7 +27,7 @@ public PostProcessor(SemanticModel semanticModel, int contextPosition)
_contextPosition
=
contextPosition
;
}
public
static
I
Enumerable
<
StatementSyntax
>
RemoveRedundantBlock
(
IEnumerable
<
StatementSyntax
>
statements
)
public
static
I
mmutableArray
<
StatementSyntax
>
RemoveRedundantBlock
(
ImmutableArray
<
StatementSyntax
>
statements
)
{
// it must have only one statement
if
(
statements
.
Count
()
!=
1
)
...
...
@@ -43,15 +45,16 @@ public static IEnumerable<StatementSyntax> RemoveRedundantBlock(IEnumerable<Stat
return
RemoveRedundantBlock
(
block
);
}
private
static
I
Enumerable
<
StatementSyntax
>
RemoveRedundantBlock
(
BlockSyntax
block
)
private
static
I
mmutableArray
<
StatementSyntax
>
RemoveRedundantBlock
(
BlockSyntax
block
)
{
// if block doesn't have any statement
if
(
block
.
Statements
.
Count
==
0
)
{
// either remove the block if it doesn't have any trivia, or return as it is if
// there are trivia attached to block
return
(
block
.
OpenBraceToken
.
GetAllTrivia
().
IsEmpty
()
&&
block
.
CloseBraceToken
.
GetAllTrivia
().
IsEmpty
())
?
SpecializedCollections
.
EmptyEnumerable
<
StatementSyntax
>()
:
SpecializedCollections
.
SingletonEnumerable
<
StatementSyntax
>(
block
);
return
(
block
.
OpenBraceToken
.
GetAllTrivia
().
IsEmpty
()
&&
block
.
CloseBraceToken
.
GetAllTrivia
().
IsEmpty
())
?
ImmutableArray
<
StatementSyntax
>.
Empty
:
ImmutableArray
.
Create
<
StatementSyntax
>(
block
);
}
// okay transfer asset attached to block to statements
...
...
@@ -67,10 +70,10 @@ private static IEnumerable<StatementSyntax> RemoveRedundantBlock(BlockSyntax blo
block
=
block
.
ReplaceTokens
(
new
[]
{
firstToken
,
lastToken
},
(
o
,
c
)
=>
(
o
==
firstToken
)
?
firstTokenWithAsset
:
lastTokenWithAsset
);
// return only statements without the wrapping block
return
block
.
Statements
;
return
ImmutableArray
.
CreateRange
(
block
.
Statements
)
;
}
public
I
Enumerable
<
StatementSyntax
>
MergeDeclarationStatements
(
IEnumerable
<
StatementSyntax
>
statements
)
public
I
mmutableArray
<
StatementSyntax
>
MergeDeclarationStatements
(
ImmutableArray
<
StatementSyntax
>
statements
)
{
if
(
statements
.
FirstOrDefault
()
==
null
)
{
...
...
@@ -80,19 +83,17 @@ public IEnumerable<StatementSyntax> MergeDeclarationStatements(IEnumerable<State
return
MergeDeclarationStatementsWorker
(
statements
);
}
private
I
Enumerable
<
StatementSyntax
>
MergeDeclarationStatementsWorker
(
IEnumerable
<
StatementSyntax
>
statements
)
private
I
mmutableArray
<
StatementSyntax
>
MergeDeclarationStatementsWorker
(
ImmutableArray
<
StatementSyntax
>
statements
)
{
using
var
_
=
ArrayBuilder
<
StatementSyntax
>.
GetInstance
(
out
var
result
);
var
map
=
new
Dictionary
<
ITypeSymbol
,
List
<
LocalDeclarationStatementSyntax
>>();
foreach
(
var
statement
in
statements
)
{
if
(!
IsDeclarationMergable
(
statement
))
{
foreach
(
var
declStatement
in
GetMergedDeclarationStatements
(
map
))
{
yield
return
declStatement
;
}
yield
return
statement
;
result
.
AddRange
(
GetMergedDeclarationStatements
(
map
));
result
.
Add
(
statement
);
continue
;
}
...
...
@@ -100,15 +101,10 @@ private IEnumerable<StatementSyntax> MergeDeclarationStatementsWorker(IEnumerabl
}
// merge leftover
if
(
map
.
Count
<=
0
)
{
yield
break
;
}
if
(
map
.
Count
>
0
)
result
.
AddRange
(
GetMergedDeclarationStatements
(
map
));
foreach
(
var
declStatement
in
GetMergedDeclarationStatements
(
map
))
{
yield
return
declStatement
;
}
return
result
.
ToImmutable
();
}
private
void
AppendDeclarationStatementToMap
(
...
...
@@ -223,7 +219,7 @@ private static bool ContainsOnlyWhitespaceTrivia(StatementSyntax statement)
return
true
;
}
public
static
I
Enumerable
<
StatementSyntax
>
RemoveInitializedDeclarationAndReturnPattern
(
IEnumerable
<
StatementSyntax
>
statements
)
public
static
I
mmutableArray
<
StatementSyntax
>
RemoveInitializedDeclarationAndReturnPattern
(
ImmutableArray
<
StatementSyntax
>
statements
)
{
// if we have inline temp variable as service, we could just use that service here.
// since it is not a service right now, do very simple clean up
...
...
@@ -258,10 +254,10 @@ public static IEnumerable<StatementSyntax> RemoveInitializedDeclarationAndReturn
return
statements
;
}
return
SpecializedCollections
.
SingletonEnumerabl
e
<
StatementSyntax
>(
SyntaxFactory
.
ReturnStatement
(
declaration
.
Declaration
.
Variables
[
0
].
Initializer
.
Value
));
return
ImmutableArray
.
Creat
e
<
StatementSyntax
>(
SyntaxFactory
.
ReturnStatement
(
declaration
.
Declaration
.
Variables
[
0
].
Initializer
.
Value
));
}
public
static
I
Enumerable
<
StatementSyntax
>
RemoveDeclarationAssignmentPattern
(
IEnumerable
<
StatementSyntax
>
statements
)
public
static
I
mmutableArray
<
StatementSyntax
>
RemoveDeclarationAssignmentPattern
(
ImmutableArray
<
StatementSyntax
>
statements
)
{
if
(!(
statements
.
ElementAtOrDefault
(
0
)
is
LocalDeclarationStatementSyntax
declaration
)
||
!(
statements
.
ElementAtOrDefault
(
1
)
is
ExpressionStatementSyntax
assignment
))
{
...
...
@@ -294,10 +290,14 @@ public static IEnumerable<StatementSyntax> RemoveDeclarationAssignmentPattern(IE
}
var
variable
=
declaration
.
Declaration
.
Variables
[
0
].
WithInitializer
(
SyntaxFactory
.
EqualsValueClause
(
assignmentExpression
.
Right
));
return
SpecializedCollections
.
SingletonEnumerable
<
StatementSyntax
>(
declaration
.
WithDeclaration
(
declaration
.
Declaration
.
WithVariables
(
SyntaxFactory
.
SingletonSeparatedList
(
variable
)))).
Concat
(
statements
.
Skip
(
2
));
using
var
_
=
ArrayBuilder
<
StatementSyntax
>.
GetInstance
(
out
var
result
);
result
.
Add
(
declaration
.
WithDeclaration
(
declaration
.
Declaration
.
WithVariables
(
SyntaxFactory
.
SingletonSeparatedList
(
variable
))));
result
.
AddRange
(
statements
.
Skip
(
2
));
return
result
.
ToImmutable
();
}
}
}
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpSelectionResult.ExpressionResult.cs
浏览文件 @
89497254
...
...
@@ -6,9 +6,11 @@
using
System.Linq
;
using
Microsoft.CodeAnalysis.CSharp.Extensions
;
using
Microsoft.CodeAnalysis.CSharp.LanguageServices
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Text
;
...
...
@@ -43,7 +45,11 @@ public override bool ContainingScopeHasAsyncKeyword()
var
firstToken
=
GetFirstTokenInSelection
();
var
lastToken
=
GetLastTokenInSelection
();
return
firstToken
.
GetCommonRoot
(
lastToken
).
GetAncestorOrThis
<
ExpressionSyntax
>();
var
scope
=
firstToken
.
GetCommonRoot
(
lastToken
).
GetAncestorOrThis
<
ExpressionSyntax
>();
if
(
scope
==
null
)
return
null
;
return
CSharpSyntaxFacts
.
Instance
.
GetRootStandaloneExpression
(
scope
);
}
public
override
ITypeSymbol
?
GetContainingScopeType
()
...
...
src/Features/CSharp/Portable/ImplementInterface/CSharpImplementExplicitlyCodeRefactoringProvider.cs
浏览文件 @
89497254
...
...
@@ -100,7 +100,7 @@ protected override bool CheckMemberCanBeConverted(ISymbol member)
if
(
identifierName
==
null
||
!
syntaxFacts
.
IsIdentifierName
(
identifierName
))
return
;
var
node
=
syntaxFacts
.
IsNameOf
MemberAccessExpression
(
identifierName
)
||
syntaxFacts
.
IsMemberBindingExpression
(
identifierName
.
Parent
)
var
node
=
syntaxFacts
.
IsNameOf
SimpleMemberAccessExpression
(
identifierName
)
||
syntaxFacts
.
IsNameOfMemberBindingExpression
(
identifierName
)
?
identifierName
.
Parent
:
identifierName
;
...
...
src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs
浏览文件 @
89497254
...
...
@@ -302,7 +302,8 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingType
// 'Black' did not bind. We want to find a type called 'Color' that will actually
// allow 'Black' to bind.
var
syntaxFacts
=
_document
.
GetLanguageService
<
ISyntaxFactsService
>();
if
(
syntaxFacts
.
IsNameOfMemberAccessExpression
(
nameNode
))
if
(
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
nameNode
)
||
syntaxFacts
.
IsNameOfMemberBindingExpression
(
nameNode
))
{
var
expression
=
syntaxFacts
.
GetExpressionOfMemberAccessExpression
(
nameNode
.
Parent
,
allowImplicitTarget
:
true
)
??
...
...
src/Features/Core/Portable/ConvertAnonymousTypeToClass/AbstractConvertAnonymousTypeToClassCodeRefactoringProvider.cs
浏览文件 @
89497254
...
...
@@ -170,7 +170,8 @@ private async Task<Document> ConvertToClassAsync(Document document, TextSpan spa
foreach
(
var
identifier
in
identifiers
)
{
if
(!
syntaxFacts
.
IsNameOfMemberAccessExpression
(
identifier
))
if
(!
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
identifier
)
&&
!
syntaxFacts
.
IsNameOfMemberBindingExpression
(
identifier
))
{
continue
;
}
...
...
src/Features/Core/Portable/ExtractMethod/AbstractSyntaxTriviaService.Result.cs
浏览文件 @
89497254
...
...
@@ -110,15 +110,9 @@ private int GetFirstEndOfLineIndex(List<SyntaxTrivia> list)
location
=>
location
,
location
=>
resolver
(
root
,
location
,
_annotations
[
location
]));
// check variable assumption. ordering of two pairs can't be changed
Contract
.
ThrowIfFalse
(
tokens
[
TriviaLocation
.
BeforeBeginningOfSpan
].
RawKind
==
0
/* && don't care */
||
/* don't care && */
tokens
[
TriviaLocation
.
AfterEndOfSpan
].
RawKind
==
0
||
tokens
[
TriviaLocation
.
BeforeBeginningOfSpan
].
Span
.
End
<=
tokens
[
TriviaLocation
.
AfterEndOfSpan
].
SpanStart
);
Contract
.
ThrowIfFalse
(
tokens
[
TriviaLocation
.
AfterBeginningOfSpan
].
RawKind
==
0
/* && don't care */
||
/* don't care && */
tokens
[
TriviaLocation
.
BeforeEndOfSpan
].
RawKind
==
0
||
tokens
[
TriviaLocation
.
AfterBeginningOfSpan
].
RawKind
==
0
/* don't care */
||
tokens
[
TriviaLocation
.
BeforeEndOfSpan
].
RawKind
==
0
/* don't care */
||
tokens
[
TriviaLocation
.
AfterBeginningOfSpan
]
==
tokens
[
TriviaLocation
.
BeforeEndOfSpan
]
||
tokens
[
TriviaLocation
.
AfterBeginningOfSpan
].
GetPreviousToken
(
includeZeroWidth
:
true
)
==
tokens
[
TriviaLocation
.
BeforeEndOfSpan
]
||
tokens
[
TriviaLocation
.
AfterBeginningOfSpan
].
Span
.
End
<=
tokens
[
TriviaLocation
.
BeforeEndOfSpan
].
SpanStart
);
...
...
src/Features/Core/Portable/ExtractMethod/MethodExtractor.Analyzer.cs
浏览文件 @
89497254
...
...
@@ -6,11 +6,13 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Roslyn.Utilities
;
...
...
@@ -229,7 +231,7 @@ private void WrapReturnTypeInTask(SemanticModel model, ref ITypeSymbol returnTyp
}
}
private
(
I
List
<
VariableInfo
>
parameters
,
ITypeSymbol
returnType
,
VariableInfo
?
variableToUseAsReturnValue
,
bool
unsafeAddressTakenUsed
)
private
(
I
mmutableArray
<
VariableInfo
>
parameters
,
ITypeSymbol
returnType
,
VariableInfo
?
variableToUseAsReturnValue
,
bool
unsafeAddressTakenUsed
)
GetSignatureInformation
(
DataFlowAnalysis
dataFlowAnalysisData
,
IDictionary
<
ISymbol
,
VariableInfo
>
variableInfoMap
,
...
...
@@ -384,22 +386,22 @@ private bool IsEndOfSelectionReachable(SemanticModel model)
return
analysis
.
EndPointIsReachable
;
}
private
I
List
<
VariableInfo
>
MarkVariableInfoToUseAsReturnValueIfPossible
(
IList
<
VariableInfo
>
variableInfo
)
private
I
mmutableArray
<
VariableInfo
>
MarkVariableInfoToUseAsReturnValueIfPossible
(
ImmutableArray
<
VariableInfo
>
variableInfo
)
{
var
variableToUseAsReturnValueIndex
=
GetIndexOfVariableInfoToUseAsReturnValue
(
variableInfo
);
if
(
variableToUseAsReturnValueIndex
>=
0
)
{
variableInfo
[
variableToUseAsReturnValueIndex
]
=
VariableInfo
.
CreateReturnValue
(
variableInfo
[
variableToUseAsReturnValueIndex
]);
}
var
index
=
GetIndexOfVariableInfoToUseAsReturnValue
(
variableInfo
);
if
(
index
<
0
)
return
variableInfo
;
return
variableInfo
;
return
variableInfo
.
SetItem
(
index
,
VariableInfo
.
CreateReturnValue
(
variableInfo
[
index
]))
;
}
private
I
List
<
VariableInfo
>
GetMethodParameters
(
ICollection
<
VariableInfo
>
variableInfo
)
private
I
mmutableArray
<
VariableInfo
>
GetMethodParameters
(
ICollection
<
VariableInfo
>
variableInfo
)
{
var
list
=
new
List
<
VariableInfo
>(
variableInfo
);
using
var
_
=
ArrayBuilder
<
VariableInfo
>.
GetInstance
(
variableInfo
.
Count
,
out
var
list
);
list
.
AddRange
(
variableInfo
);
VariableInfo
.
SortVariables
(
_semanticDocument
.
SemanticModel
.
Compilation
,
list
);
return
list
;
return
list
.
ToImmutable
()
;
}
/// <param name="bestEffort">When false, variables whose data flow is not understood
...
...
src/Features/Core/Portable/ExtractMethod/MethodExtractor.AnalyzerResult.cs
浏览文件 @
89497254
...
...
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Collections.ObjectModel
;
using
System.Linq
;
using
System.Threading
;
...
...
@@ -16,14 +17,14 @@ protected class AnalyzerResult
{
private
readonly
IList
<
ITypeParameterSymbol
>
_typeParametersInDeclaration
;
private
readonly
IList
<
ITypeParameterSymbol
>
_typeParametersInConstraintList
;
private
readonly
I
List
<
VariableInfo
>
_variables
;
private
readonly
I
mmutableArray
<
VariableInfo
>
_variables
;
private
readonly
VariableInfo
_variableToUseAsReturnValue
;
public
AnalyzerResult
(
SemanticDocument
document
,
IEnumerable
<
ITypeParameterSymbol
>
typeParametersInDeclaration
,
IEnumerable
<
ITypeParameterSymbol
>
typeParametersInConstraintList
,
I
List
<
VariableInfo
>
variables
,
I
mmutableArray
<
VariableInfo
>
variables
,
VariableInfo
variableToUseAsReturnValue
,
ITypeSymbol
returnType
,
bool
awaitTaskReturn
,
...
...
@@ -152,11 +153,11 @@ public IEnumerable<VariableInfo> MethodParameters
}
}
public
I
Enumerable
<
VariableInfo
>
GetVariablesToSplitOrMoveIntoMethodDefinition
(
CancellationToken
cancellationToken
)
public
I
mmutableArray
<
VariableInfo
>
GetVariablesToSplitOrMoveIntoMethodDefinition
(
CancellationToken
cancellationToken
)
{
return
_variables
.
Where
(
v
=>
v
.
GetDeclarationBehavior
(
cancellationToken
)
==
DeclarationBehavior
.
SplitIn
||
v
.
GetDeclarationBehavior
(
cancellationToken
)
==
DeclarationBehavior
.
MoveIn
);
return
_variables
.
WhereAsArray
(
v
=>
v
.
GetDeclarationBehavior
(
cancellationToken
)
==
DeclarationBehavior
.
SplitIn
||
v
.
GetDeclarationBehavior
(
cancellationToken
)
==
DeclarationBehavior
.
MoveIn
);
}
public
IEnumerable
<
VariableInfo
>
GetVariablesToMoveIntoMethodDefinition
(
CancellationToken
cancellationToken
)
...
...
src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs
浏览文件 @
89497254
...
...
@@ -68,14 +68,14 @@ protected CodeGenerator(InsertionPoint insertionPoint, SelectionResult selection
protected
abstract
TNodeUnderContainer
GetFirstStatementOrInitializerSelectedAtCallSite
();
protected
abstract
TNodeUnderContainer
GetLastStatementOrInitializerSelectedAtCallSite
();
protected
abstract
Task
<
TNodeUnderContainer
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
SyntaxAnnotation
callsiteAnnotation
,
CancellationToken
cancellationToken
);
protected
abstract
Task
<
TNodeUnderContainer
>
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
CancellationToken
cancellationToken
);
protected
abstract
TExpression
CreateCallSignature
();
protected
abstract
TStatement
CreateDeclarationStatement
(
VariableInfo
variable
,
TExpression
initialValue
,
CancellationToken
cancellationToken
);
protected
abstract
TStatement
CreateAssignmentExpressionStatement
(
SyntaxToken
identifier
,
TExpression
rvalue
);
protected
abstract
TStatement
CreateReturnStatement
(
string
identifierName
=
null
);
protected
abstract
I
Enumerable
<
TStatement
>
GetInitialStatementsForMethodDefinitions
();
protected
abstract
I
mmutableArray
<
TStatement
>
GetInitialStatementsForMethodDefinitions
();
#
endregion
public
async
Task
<
GeneratedCode
>
GenerateAsync
(
CancellationToken
cancellationToken
)
...
...
@@ -111,7 +111,8 @@ public async Task<GeneratedCode> GenerateAsync(CancellationToken cancellationTok
cancellationToken
);
}
var
newDocument
=
callSiteDocument
.
Document
.
WithSyntaxRoot
(
newCallSiteRoot
.
ReplaceNode
(
destination
,
newContainer
));
var
newSyntaxRoot
=
newCallSiteRoot
.
ReplaceNode
(
destination
,
newContainer
);
var
newDocument
=
callSiteDocument
.
Document
.
WithSyntaxRoot
(
newSyntaxRoot
);
newDocument
=
await
Simplifier
.
ReduceAsync
(
newDocument
,
Simplifier
.
Annotation
,
null
,
cancellationToken
).
ConfigureAwait
(
false
);
var
generatedDocument
=
await
SemanticDocument
.
CreateAsync
(
newDocument
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -165,17 +166,16 @@ protected virtual Task<GeneratedCode> CreateGeneratedCodeAsync(OperationStatus s
protected
VariableInfo
GetOutermostVariableToMoveIntoMethodDefinition
(
CancellationToken
cancellationToken
)
{
var
variables
=
new
List
<
VariableInfo
>(
AnalyzerResult
.
GetVariablesToMoveIntoMethodDefinition
(
cancellationToken
));
using
var
_
=
ArrayBuilder
<
VariableInfo
>.
GetInstance
(
out
var
variables
);
variables
.
AddRange
(
AnalyzerResult
.
GetVariablesToMoveIntoMethodDefinition
(
cancellationToken
));
if
(
variables
.
Count
<=
0
)
{
return
null
;
}
VariableInfo
.
SortVariables
(
SemanticDocument
.
SemanticModel
.
Compilation
,
variables
);
return
variables
[
0
];
}
protected
I
Enumerable
<
TStatement
>
AddReturnIfUnreachable
(
IEnumerable
<
TStatement
>
statements
)
protected
I
mmutableArray
<
TStatement
>
AddReturnIfUnreachable
(
ImmutableArray
<
TStatement
>
statements
)
{
if
(
AnalyzerResult
.
EndOfSelectionReachable
)
{
...
...
@@ -197,8 +197,8 @@ protected IEnumerable<TStatement> AddReturnIfUnreachable(IEnumerable<TStatement>
return
statements
.
Concat
(
CreateReturnStatement
());
}
protected
async
Task
<
I
Enumerable
<
TStatement
>>
AddInvocationAtCallSiteAsync
(
I
Enumerable
<
TStatement
>
statements
,
CancellationToken
cancellationToken
)
protected
async
Task
<
I
mmutableArray
<
TStatement
>>
AddInvocationAtCallSiteAsync
(
I
mmutableArray
<
TStatement
>
statements
,
CancellationToken
cancellationToken
)
{
if
(
AnalyzerResult
.
HasVariableToUseAsReturnValue
)
{
...
...
@@ -209,11 +209,11 @@ protected IEnumerable<TStatement> AddReturnIfUnreachable(IEnumerable<TStatement>
// add invocation expression
return
statements
.
Concat
(
(
TStatement
)(
SyntaxNode
)
await
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
CallSiteAnnotation
,
cancellationToken
).
ConfigureAwait
(
false
));
(
TStatement
)(
SyntaxNode
)
await
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
cancellationToken
).
ConfigureAwait
(
false
));
}
protected
I
Enumerable
<
TStatement
>
AddAssignmentStatementToCallSite
(
I
Enumerable
<
TStatement
>
statements
,
protected
I
mmutableArray
<
TStatement
>
AddAssignmentStatementToCallSite
(
I
mmutableArray
<
TStatement
>
statements
,
CancellationToken
cancellationToken
)
{
if
(!
AnalyzerResult
.
HasVariableToUseAsReturnValue
)
...
...
@@ -239,42 +239,31 @@ protected IEnumerable<TStatement> AddReturnIfUnreachable(IEnumerable<TStatement>
CreateAssignmentExpressionStatement
(
CreateIdentifier
(
variable
.
Name
),
CreateCallSignature
()).
WithAdditionalAnnotations
(
CallSiteAnnotation
));
}
protected
I
Enumerable
<
TStatement
>
CreateDeclarationStatements
(
I
Enumerable
<
VariableInfo
>
variables
,
CancellationToken
cancellationToken
)
protected
I
mmutableArray
<
TStatement
>
CreateDeclarationStatements
(
I
mmutableArray
<
VariableInfo
>
variables
,
CancellationToken
cancellationToken
)
{
var
list
=
new
List
<
TStatement
>();
foreach
(
var
variable
in
variables
)
{
var
declaration
=
CreateDeclarationStatement
(
variable
,
initialValue
:
null
,
cancellationToken
:
cancellationToken
);
list
.
Add
(
declaration
);
}
return
list
;
return
variables
.
SelectAsArray
(
v
=>
CreateDeclarationStatement
(
v
,
initialValue
:
null
,
cancellationToken
));
}
protected
I
Enumerable
<
TStatement
>
AddSplitOrMoveDeclarationOutStatementsToCallSite
(
protected
I
mmutableArray
<
TStatement
>
AddSplitOrMoveDeclarationOutStatementsToCallSite
(
CancellationToken
cancellationToken
)
{
var
list
=
new
List
<
TStatement
>(
);
using
var
_
=
ArrayBuilder
<
TStatement
>.
GetInstance
(
out
var
list
);
foreach
(
var
variable
in
AnalyzerResult
.
GetVariablesToSplitOrMoveOutToCallSite
(
cancellationToken
))
{
if
(
variable
.
UseAsReturnValue
)
{
continue
;
}
var
declaration
=
CreateDeclarationStatement
(
variable
,
initialValue
:
null
,
cancellationToken
:
cancellationToken
);
list
.
Add
(
declaration
);
}
return
list
;
return
list
.
ToImmutable
()
;
}
protected
I
Enumerable
<
TStatement
>
AppendReturnStatementIfNeeded
(
IEnumerable
<
TStatement
>
statements
)
protected
I
mmutableArray
<
TStatement
>
AppendReturnStatementIfNeeded
(
ImmutableArray
<
TStatement
>
statements
)
{
if
(!
AnalyzerResult
.
HasVariableToUseAsReturnValue
)
{
...
...
src/Features/Core/Portable/ExtractMethod/MethodExtractor.VariableInfo.cs
浏览文件 @
89497254
...
...
@@ -6,6 +6,7 @@
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.ExtractMethod
...
...
@@ -120,10 +121,10 @@ public SyntaxToken GetIdentifierTokenAtDeclaration(SemanticDocument document)
public
SyntaxToken
GetIdentifierTokenAtDeclaration
(
SyntaxNode
node
)
=>
node
.
GetAnnotatedTokens
(
_variableSymbol
.
IdentifierTokenAnnotation
).
SingleOrDefault
();
public
static
void
SortVariables
(
Compilation
compilation
,
List
<
VariableInfo
>
list
)
public
static
void
SortVariables
(
Compilation
compilation
,
ArrayBuilder
<
VariableInfo
>
variables
)
{
var
cancellationTokenType
=
compilation
.
GetTypeByMetadataName
(
typeof
(
CancellationToken
).
FullName
);
list
.
Sort
((
v1
,
v2
)
=>
Compare
(
v1
,
v2
,
cancellationTokenType
));
variables
.
Sort
((
v1
,
v2
)
=>
Compare
(
v1
,
v2
,
cancellationTokenType
));
}
private
static
int
Compare
(
VariableInfo
left
,
VariableInfo
right
,
INamedTypeSymbol
cancellationTokenType
)
...
...
src/Features/Core/Portable/MakeMethodSynchronous/AbstractMakeMethodSynchronousCodeFixProvider.cs
浏览文件 @
89497254
...
...
@@ -199,7 +199,8 @@ private async Task<Solution> RenameThenRemoveAsyncTokenAsync(Document document,
// await <expr>.M(...).ConfigureAwait(...)
var
expressionNode
=
nameNode
;
if
(
syntaxFacts
.
IsNameOfMemberAccessExpression
(
nameNode
))
if
(
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
nameNode
)
||
syntaxFacts
.
IsNameOfMemberBindingExpression
(
nameNode
))
{
expressionNode
=
nameNode
.
Parent
;
}
...
...
src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs
浏览文件 @
89497254
...
...
@@ -115,7 +115,8 @@ protected static SyntaxNode GetFieldReference(SyntaxGenerator generator, IFieldS
_expression
=
_identifierName
;
_cref
=
_service
.
TryGetCrefSyntax
(
_identifierName
);
if
(
_syntaxFacts
.
IsNameOfMemberAccessExpression
(
_expression
))
if
(
_syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
_expression
)
||
_syntaxFacts
.
IsNameOfMemberBindingExpression
(
_expression
))
{
_expression
=
(
TExpressionSyntax
)
_expression
.
Parent
!;
}
...
...
src/Features/VisualBasic/Portable/CodeRefactorings/SyncNamespace/VisualBasicChangeNamespaceService.vb
浏览文件 @
89497254
...
...
@@ -41,7 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ChangeNamespace
[
new
]
=
[
new
]
.
WithTriviaFrom
(
old
)
ElseIf
syntaxFacts
.
IsNameOfMemberAccessExpression
(
nameRef
)
Then
ElseIf
syntaxFacts
.
IsNameOf
simple
MemberAccessExpression
(
nameRef
)
Then
old
=
nameRef
.
Parent
If
IsGlobalNamespace
(
newNamespaceParts
)
Then
[
new
]
=
SyntaxFactory
.
SimpleMemberAccessExpression
(
SyntaxFactory
.
GlobalName
(),
nameRef
.
WithoutTrivia
())
...
...
src/Features/VisualBasic/Portable/Debugging/DataTipInfoGetter.vb
浏览文件 @
89497254
...
...
@@ -40,16 +40,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Debugging
Dim
conditionalAccess
As
ExpressionSyntax
=
Nothing
If
expression
.
IsRightSideOfDotOrBang
()
Then
expression
=
DirectCast
(
expression
.
Parent
,
ExpressionSyntax
)
Dim
curr
=
expression
While
True
curr
=
curr
.
GetCorrespondingConditionalAccessExpression
()
If
curr
Is
Nothing
Then
Exit
While
End
If
conditionalAccess
=
curr
End
While
conditionalAccess
=
If
(
expression
.
GetRootConditionalAccessExpression
(),
expression
)
End
If
If
expression
.
Parent
.
IsKind
(
SyntaxKind
.
InvocationExpression
)
Then
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.PostProcessor.vb
浏览文件 @
89497254
...
...
@@ -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.
Imports
System.Collections.Immutable
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.VisualBasic
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
...
...
@@ -19,7 +20,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Me
.
_contextPosition
=
contextPosition
End
Sub
Public
Function
MergeDeclarationStatements
(
statements
As
I
Enumerable
(
Of
StatementSyntax
))
As
IEnumerable
(
Of
StatementSyntax
)
Public
Function
MergeDeclarationStatements
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
))
As
ImmutableArray
(
Of
StatementSyntax
)
If
statements
.
FirstOrDefault
()
Is
Nothing
Then
Return
statements
End
If
...
...
@@ -27,7 +28,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
MergeDeclarationStatementsWorker
(
statements
)
End
Function
Private
Function
MergeDeclarationStatementsWorker
(
statements
As
I
Enumerable
(
Of
StatementSyntax
))
As
IEnumerable
(
Of
StatementSyntax
)
Private
Function
MergeDeclarationStatementsWorker
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
))
As
ImmutableArray
(
Of
StatementSyntax
)
Dim
declarationStatements
=
New
List
(
Of
StatementSyntax
)()
Dim
map
=
New
Dictionary
(
Of
ITypeSymbol
,
List
(
Of
LocalDeclarationStatementSyntax
))()
...
...
@@ -51,7 +52,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Next
declStatement
End
If
Return
declarationStatements
Return
declarationStatements
.
ToImmutableArray
()
End
Function
Private
Sub
AppendDeclarationStatementToMap
(
statement
As
LocalDeclarationStatementSyntax
,
map
As
Dictionary
(
Of
ITypeSymbol
,
List
(
Of
LocalDeclarationStatementSyntax
)))
...
...
@@ -171,7 +172,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
True
End
Function
Public
Shared
Function
RemoveDeclarationAssignmentPattern
(
statements
As
I
Enumerable
(
Of
StatementSyntax
))
As
IEnumerable
(
Of
StatementSyntax
)
Public
Shared
Function
RemoveDeclarationAssignmentPattern
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
))
As
ImmutableArray
(
Of
StatementSyntax
)
If
statements
.
Count
()
<
2
Then
Return
statements
End
If
...
...
@@ -207,10 +208,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Dim
variable
=
declaration
.
Declarators
(
0
).
WithoutTrailingTrivia
().
WithInitializer
(
SyntaxFactory
.
EqualsValue
(
assignment
.
Right
))
Dim
newDeclaration
=
declaration
.
WithDeclarators
(
SyntaxFactory
.
SingletonSeparatedList
(
variable
))
Return
SpecializedCollections
.
SingletonEnumerable
(
Of
StatementSyntax
)(
newDeclaration
).
Concat
(
statements
.
Skip
(
2
))
Return
SpecializedCollections
.
SingletonEnumerable
(
Of
StatementSyntax
)(
newDeclaration
).
Concat
(
statements
.
Skip
(
2
))
.
ToImmutableArray
()
End
Function
Public
Shared
Function
RemoveInitializedDeclarationAndReturnPattern
(
statements
As
I
Enumerable
(
Of
StatementSyntax
))
As
IEnumerable
(
Of
StatementSyntax
)
Public
Shared
Function
RemoveInitializedDeclarationAndReturnPattern
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
))
As
ImmutableArray
(
Of
StatementSyntax
)
' if we have inline temp variable as service, we could just use that service here.
' since it is not a service right now, do very simple clean up
If
statements
.
Count
()
<>
2
Then
...
...
@@ -241,7 +242,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
End
If
Return
SpecializedCollections
.
SingletonEnumerable
(
Of
StatementSyntax
)(
SyntaxFactory
.
ReturnStatement
(
declaration
.
Declarators
(
0
).
Initializer
.
Value
)).
Concat
(
statements
.
Skip
(
2
))
SyntaxFactory
.
ReturnStatement
(
declaration
.
Declarators
(
0
).
Initializer
.
Value
)).
Concat
(
statements
.
Skip
(
2
))
.
ToImmutableArray
()
End
Function
End
Class
End
Class
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb
浏览文件 @
89497254
...
...
@@ -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.
Imports
System.Collections.Immutable
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
...
...
@@ -24,11 +25,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Protected
Overrides
Function
CreateMethodName
()
As
SyntaxToken
Dim
methodName
=
"NewMethod"
Dim
containingScope
=
CType
(
VBSelectionResult
.
GetContainingScope
(),
SyntaxNode
)
Dim
containingScope
=
VBSelectionResult
.
GetContainingScope
(
)
methodName
=
GetMethodNameBasedOnExpression
(
methodName
,
containingScope
)
Dim
semanticModel
=
CType
(
SemanticDocument
.
SemanticModel
,
SemanticModel
)
Dim
semanticModel
=
SemanticDocument
.
SemanticModel
Dim
nameGenerator
=
New
UniqueNameGenerator
(
semanticModel
)
Return
SyntaxFactory
.
Identifier
(
nameGenerator
.
CreateUniqueMethodName
(
containingScope
,
methodName
))
...
...
@@ -65,7 +66,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
methodName
End
Function
Protected
Overrides
Function
GetInitialStatementsForMethodDefinitions
()
As
I
Enumerable
(
Of
StatementSyntax
)
Protected
Overrides
Function
GetInitialStatementsForMethodDefinitions
()
As
I
mmutableArray
(
Of
StatementSyntax
)
Contract
.
ThrowIfFalse
(
IsExtractMethodOnExpression
(
VBSelectionResult
))
Dim
expression
=
DirectCast
(
VBSelectionResult
.
GetContainingScope
(),
ExpressionSyntax
)
...
...
@@ -80,13 +81,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
' return error code
If
expression
.
Kind
<>
SyntaxKind
.
InvocationExpression
AndAlso
expression
.
Kind
<>
SyntaxKind
.
SimpleMemberAccessExpression
Then
Return
SpecializedCollections
.
EmptyEnumerable
(
Of
StatementSyntax
)()
Return
ImmutableArray
(
Of
StatementSyntax
).
Empty
End
If
statement
=
SyntaxFactory
.
ExpressionStatement
(
expression
:
=
expression
)
End
If
Return
SpecializedCollections
.
SingletonEnumerable
(
Of
StatementSyntax
)
(
statement
)
Return
ImmutableArray
.
Create
(
statement
)
End
Function
Protected
Overrides
Function
GetOutermostCallSiteContainerToProcess
(
cancellationToken
As
CancellationToken
)
As
SyntaxNode
...
...
@@ -113,13 +114,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
GetFirstStatementOrInitializerSelectedAtCallSite
()
End
Function
Protected
Overrides
Async
Function
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
ca
llSiteAnnotation
As
SyntaxAnnotation
,
ca
ncellationToken
As
CancellationToken
)
As
Task
(
Of
StatementSyntax
)
Protected
Overrides
Async
Function
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
cancellationToken
As
CancellationToken
)
As
Task
(
Of
StatementSyntax
)
Dim
enclosingStatement
=
GetFirstStatementOrInitializerSelectedAtCallSite
()
Dim
callSignature
=
CreateCallSignature
().
WithAdditionalAnnotations
(
callSiteAnnotation
)
Dim
invocation
=
If
(
TypeOf
callSignature
Is
AwaitExpressionSyntax
,
DirectCast
(
callSignature
,
AwaitExpressionSyntax
).
Expression
,
callSignature
)
Dim
callSignature
=
CreateCallSignature
().
WithAdditionalAnnotations
(
CallSiteAnnotation
)
Dim
sourceNode
=
DirectCast
(
VBSelectionResult
.
GetContainingScope
(),
SyntaxNode
)
Dim
sourceNode
=
VBSelectionResult
.
GetContainingScope
(
)
Contract
.
ThrowIfTrue
(
sourceNode
.
IsParentKind
(
SyntaxKind
.
SimpleMemberAccessExpression
)
AndAlso
DirectCast
(
sourceNode
.
Parent
,
MemberAccessExpressionSyntax
).
Name
Is
sourceNode
,
...
...
@@ -142,32 +141,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
' because of the complexification we cannot guarantee that there is only one annotation.
' however complexification of names is prepended, so the last annotation should be the original one.
sourceNode
=
DirectCast
(
updatedRoot
.
GetAnnotatedNodesAndTokens
(
sourceNodeAnnotation
).
Last
().
AsNode
(),
SyntaxNode
)
' we want to replace the old identifier with a invocation expression, but because of MakeExplicit we might have
' a member access now instead of the identifier. So more syntax fiddling is needed.
If
sourceNode
.
Parent
.
Kind
=
SyntaxKind
.
SimpleMemberAccessExpression
AndAlso
DirectCast
(
sourceNode
,
ExpressionSyntax
).
IsRightSideOfDot
()
Then
Dim
explicitMemberAccess
=
DirectCast
(
sourceNode
.
Parent
,
MemberAccessExpressionSyntax
)
Dim
replacementMemberAccess
=
SyntaxFactory
.
MemberAccessExpression
(
sourceNode
.
Parent
.
Kind
(),
explicitMemberAccess
.
Expression
,
SyntaxFactory
.
Token
(
SyntaxKind
.
DotToken
),
DirectCast
(
DirectCast
(
invocation
,
InvocationExpressionSyntax
).
Expression
,
SimpleNameSyntax
))
replacementMemberAccess
=
explicitMemberAccess
.
CopyAnnotationsTo
(
replacementMemberAccess
)
Dim
newInvocation
=
SyntaxFactory
.
InvocationExpression
(
replacementMemberAccess
,
DirectCast
(
invocation
,
InvocationExpressionSyntax
).
ArgumentList
)
_
.
WithTrailingTrivia
(
sourceNode
.
GetTrailingTrivia
())
Dim
newCallSignature
=
If
(
callSignature
IsNot
invocation
,
callSignature
.
ReplaceNode
(
invocation
,
newInvocation
),
invocation
.
CopyAnnotationsTo
(
newInvocation
))
sourceNode
=
sourceNode
.
Parent
callSignature
=
newCallSignature
End
If
sourceNode
=
updatedRoot
.
GetAnnotatedNodesAndTokens
(
sourceNodeAnnotation
).
Last
().
AsNode
()
Return
newEnclosingStatement
.
ReplaceNode
(
sourceNode
,
callSignature
)
End
Function
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb
浏览文件 @
89497254
...
...
@@ -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.
Imports
System.Collections.Immutable
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
...
...
@@ -39,7 +40,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
SyntaxFactory
.
Identifier
(
nameGenerator
.
CreateUniqueMethodName
(
containingScope
,
"NewMethod"
))
End
Function
Protected
Overrides
Function
GetInitialStatementsForMethodDefinitions
()
As
I
Enumerable
(
Of
StatementSyntax
)
Protected
Overrides
Function
GetInitialStatementsForMethodDefinitions
()
As
I
mmutableArray
(
Of
StatementSyntax
)
Dim
firstStatementUnderContainer
=
Me
.
VBSelectionResult
.
GetFirstStatementUnderContainer
()
Dim
lastStatementUnderContainer
=
Me
.
VBSelectionResult
.
GetLastStatementUnderContainer
()
...
...
@@ -55,7 +56,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Skip
(
firstStatementIndex
).
Take
(
lastStatementIndex
-
firstStatementIndex
+
1
)
Return
nodes
Return
nodes
.
ToImmutableArray
()
End
Function
Protected
Overrides
Function
GetOutermostCallSiteContainerToProcess
(
cancellationToken
As
CancellationToken
)
As
SyntaxNode
...
...
@@ -71,8 +72,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
Me
.
VBSelectionResult
.
GetLastStatementUnderContainer
()
End
Function
Protected
Overrides
Function
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
ca
llSiteAnnotation
As
SyntaxAnnotation
,
ca
ncellationToken
As
CancellationToken
)
As
Task
(
Of
StatementSyntax
)
Return
Task
.
FromResult
(
GetStatementContainingInvocationToExtractedMethodWorker
().
WithAdditionalAnnotations
(
c
allSiteAnnotation
))
Protected
Overrides
Function
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
cancellationToken
As
CancellationToken
)
As
Task
(
Of
StatementSyntax
)
Return
Task
.
FromResult
(
GetStatementContainingInvocationToExtractedMethodWorker
().
WithAdditionalAnnotations
(
C
allSiteAnnotation
))
End
Function
End
Class
End
Class
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb
浏览文件 @
89497254
...
...
@@ -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.
Imports
System.Collections.Immutable
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
...
...
@@ -34,10 +35,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
nameGenerator
.
CreateUniqueMethodName
(
containingScope
,
"NewMethod"
))
End
Function
Protected
Overrides
Function
GetInitialStatementsForMethodDefinitions
()
As
I
Enumerable
(
Of
StatementSyntax
)
Protected
Overrides
Function
GetInitialStatementsForMethodDefinitions
()
As
I
mmutableArray
(
Of
StatementSyntax
)
Contract
.
ThrowIfFalse
(
IsExtractMethodOnSingleStatement
(
VBSelectionResult
))
Return
SpecializedCollections
.
SingletonEnumerabl
e
(
Of
StatementSyntax
)(
VBSelectionResult
.
GetFirstStatement
())
Return
ImmutableArray
.
Creat
e
(
Of
StatementSyntax
)(
VBSelectionResult
.
GetFirstStatement
())
End
Function
Protected
Overrides
Function
GetOutermostCallSiteContainerToProcess
(
cancellationToken
As
CancellationToken
)
As
SyntaxNode
...
...
@@ -60,8 +61,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
VBSelectionResult
.
GetFirstStatement
()
End
Function
Protected
Overrides
Function
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
ca
llSiteAnnotation
As
SyntaxAnnotation
,
ca
ncellationToken
As
CancellationToken
)
As
Task
(
Of
StatementSyntax
)
Return
Task
.
FromResult
(
GetStatementContainingInvocationToExtractedMethodWorker
().
WithAdditionalAnnotations
(
c
allSiteAnnotation
))
Protected
Overrides
Function
GetStatementOrInitializerContainingInvocationToExtractedMethodAsync
(
cancellationToken
As
CancellationToken
)
As
Task
(
Of
StatementSyntax
)
Return
Task
.
FromResult
(
GetStatementContainingInvocationToExtractedMethodWorker
().
WithAdditionalAnnotations
(
C
allSiteAnnotation
))
End
Function
End
Class
End
Class
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb
浏览文件 @
89497254
...
...
@@ -161,27 +161,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
New
DeclarationModifiers
(
isStatic
:
=
isShared
,
isAsync
:
=
isAsync
)
End
Function
Private
Function
CreateMethodBody
(
cancellationToken
As
CancellationToken
)
As
OperationStatus
(
Of
I
Enumerable
(
Of
StatementSyntax
))
Private
Function
CreateMethodBody
(
cancellationToken
As
CancellationToken
)
As
OperationStatus
(
Of
I
mmutableArray
(
Of
StatementSyntax
))
Dim
statements
=
GetInitialStatementsForMethodDefinitions
()
statements
=
SplitOrMoveDeclarationIntoMethodDefinition
(
statements
,
cancellationToken
)
statements
=
MoveDeclarationOutFromMethodDefinition
(
statements
,
cancellationToken
)
Dim
emptyStatements
=
SpecializedCollections
.
EmptyEnumerable
(
Of
StatementSyntax
)()
Dim
emptyStatements
=
ImmutableArray
(
Of
StatementSyntax
).
Empty
Dim
returnStatements
=
AppendReturnStatementIfNeeded
(
emptyStatements
)
statements
=
statements
.
Concat
(
returnStatements
)
Dim
semanticModel
=
SemanticDocument
.
SemanticModel
Dim
context
=
Me
.
InsertionPoint
.
GetContext
()
Dim
postProcessor
=
New
PostProcessor
(
semanticModel
,
context
.
SpanStart
)
statements
=
p
ostProcessor
.
RemoveDeclarationAssignmentPattern
(
statements
)
statements
=
p
ostProcessor
.
RemoveInitializedDeclarationAndReturnPattern
(
statements
)
statements
=
P
ostProcessor
.
RemoveDeclarationAssignmentPattern
(
statements
)
statements
=
P
ostProcessor
.
RemoveInitializedDeclarationAndReturnPattern
(
statements
)
' assign before checking issues so that we can do negative preview
Return
CheckActiveStatements
(
statements
).
With
(
statements
)
End
Function
Private
Shared
Function
CheckActiveStatements
(
statements
As
I
Enumerable
(
Of
StatementSyntax
))
As
OperationStatus
Private
Shared
Function
CheckActiveStatements
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
))
As
OperationStatus
Dim
count
=
statements
.
Count
()
If
count
=
0
Then
Return
OperationStatus
.
NoActiveStatement
...
...
@@ -215,7 +215,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
OperationStatus
.
NoActiveStatement
End
Function
Private
Function
MoveDeclarationOutFromMethodDefinition
(
statements
As
I
Enumerable
(
Of
StatementSyntax
),
cancellationToken
As
CancellationToken
)
As
IEnumerable
(
Of
StatementSyntax
)
Private
Function
MoveDeclarationOutFromMethodDefinition
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
),
cancellationToken
As
CancellationToken
)
As
ImmutableArray
(
Of
StatementSyntax
)
Dim
variableToRemoveMap
=
CreateVariableDeclarationToRemoveMap
(
Me
.
AnalyzerResult
.
GetVariablesToMoveOutToCallSiteOrDelete
(
cancellationToken
),
cancellationToken
)
...
...
@@ -271,10 +271,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Next
expressionStatement
Next
Return
declarationStatements
Return
declarationStatements
.
ToImmutableArray
()
End
Function
Private
Function
SplitOrMoveDeclarationIntoMethodDefinition
(
statements
As
I
Enumerable
(
Of
StatementSyntax
),
cancellationToken
As
CancellationToken
)
As
IEnumerable
(
Of
StatementSyntax
)
Private
Function
SplitOrMoveDeclarationIntoMethodDefinition
(
statements
As
I
mmutableArray
(
Of
StatementSyntax
),
cancellationToken
As
CancellationToken
)
As
ImmutableArray
(
Of
StatementSyntax
)
Dim
semanticModel
=
CType
(
Me
.
SemanticDocument
.
SemanticModel
,
SemanticModel
)
Dim
context
=
Me
.
InsertionPoint
.
GetContext
()
Dim
postProcessor
=
New
PostProcessor
(
semanticModel
,
context
.
SpanStart
)
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicSelectionResult.vb
浏览文件 @
89497254
...
...
@@ -5,9 +5,11 @@
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
Imports
Microsoft.CodeAnalysis.LanguageServices
Imports
Microsoft.CodeAnalysis.Options
Imports
Microsoft.CodeAnalysis.Text
Imports
Microsoft.CodeAnalysis.VisualBasic
Imports
Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Imports
Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
...
...
@@ -94,7 +96,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
False
End
If
Dim
node
=
CType
(
Me
.
GetContainingScope
(),
SyntaxNode
)
Dim
node
=
Me
.
GetContainingScope
(
)
If
TypeOf
node
Is
MethodBlockBaseSyntax
Then
Dim
methodBlock
=
DirectCast
(
node
,
MethodBlockBaseSyntax
)
If
methodBlock
.
BlockStatement
IsNot
Nothing
Then
...
...
@@ -120,15 +122,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
If
SelectionInExpression
Then
Dim
last
=
GetLastTokenInSelection
()
Return
first
.
GetCommonRoot
(
last
).
GetAncestorOrThis
(
Of
ExpressionSyntax
)()
End
If
Dim
scope
=
first
.
GetCommonRoot
(
last
).
GetAncestorOrThis
(
Of
ExpressionSyntax
)()
Contract
.
ThrowIfNull
(
scope
,
"Should always find an expression given that SelectionInExpression was true"
)
' it contains statements
Return
first
.
GetAncestors
(
Of
SyntaxNode
).
FirstOrDefault
(
Function
(
n
)
TypeOf
n
Is
MethodBlockBaseSyntax
OrElse
TypeOf
n
Is
LambdaExpressionSyntax
)
Return
VisualBasicSyntaxFacts
.
Instance
.
GetRootStandaloneExpression
(
scope
)
Else
' it contains statements
Return
first
.
GetAncestors
(
Of
SyntaxNode
).
FirstOrDefault
(
Function
(
n
)
TypeOf
n
Is
MethodBlockBaseSyntax
OrElse
TypeOf
n
Is
LambdaExpressionSyntax
)
End
If
End
Function
Public
Overrides
Function
GetContainingScopeType
()
As
ITypeSymbol
Dim
node
=
CType
(
Me
.
GetContainingScope
(),
SyntaxNode
)
Dim
node
=
Me
.
GetContainingScope
(
)
Dim
semanticModel
=
Me
.
SemanticDocument
.
SemanticModel
' special case for collection initializer and explicit cast
...
...
@@ -286,11 +291,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
' Contract.ThrowIfFalse(last.IsParentKind(SyntaxKind.GlobalStatement))
' Contract.ThrowIfFalse(last.Parent.IsParentKind(SyntaxKind.CompilationUnit))
' Return last.Parent.Parent
t
hrow
ExceptionUtilities
.
Unreachable
T
hrow
ExceptionUtilities
.
Unreachable
End
Function
Public
Function
IsUnderModuleBlock
()
As
Boolean
Dim
currentScope
=
CType
(
GetContainingScope
(),
SyntaxNode
)
Dim
currentScope
=
GetContainingScope
(
)
Dim
types
=
currentScope
.
GetAncestors
(
Of
TypeBlockSyntax
)()
Return
types
.
Any
(
Function
(
t
)
t
.
BlockStatement
.
Kind
=
SyntaxKind
.
ModuleStatement
)
...
...
src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/SyntaxTokenClassifier.cs
浏览文件 @
89497254
...
...
@@ -72,10 +72,11 @@ private static bool CouldBeGenericType(SyntaxToken identifier)
}
// ?.X.Identifier or ?.X.Y.Identifier is never a generic type.
if
(
identifierName
.
Is
MemberAccessExpressionName
()
&&
identifier
.
Parent
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
))
if
(
identifierName
.
Is
SimpleMemberAccessExpressionName
()
||
identifier
Name
.
IsMemberBindingExpressionName
(
))
{
return
false
;
if
(
identifier
.
Parent
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
))
return
false
;
}
// Add more cases as necessary.
...
...
src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.Expander.cs
浏览文件 @
89497254
...
...
@@ -1067,7 +1067,7 @@ public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax
// Bail out on extension method invocations in conditional access expression.
// Note that this is a temporary workaround for https://github.com/dotnet/roslyn/issues/2593.
// Issue https://github.com/dotnet/roslyn/issues/3260 tracks fixing this workaround.
if
(
originalMemberAccess
.
Get
Paren
tConditionalAccessExpression
()
==
null
)
if
(
originalMemberAccess
.
Get
Roo
tConditionalAccessExpression
()
==
null
)
{
var
speculationPosition
=
originalNode
.
SpanStart
;
var
expression
=
RewriteExtensionMethodInvocation
(
speculationPosition
,
rewrittenNode
,
thisExpression
,
reducedExtensionMethod
);
...
...
src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs
浏览文件 @
89497254
...
...
@@ -793,7 +793,9 @@ private static bool IsNodeOrAnyAncestorLeftSideOfDot(SyntaxNode node, ISyntaxFac
return
true
;
}
if
(
syntaxFacts
.
IsRightSideOfQualifiedName
(
node
)
||
syntaxFacts
.
IsNameOfMemberAccessExpression
(
node
))
if
(
syntaxFacts
.
IsRightSideOfQualifiedName
(
node
)
||
syntaxFacts
.
IsNameOfSimpleMemberAccessExpression
(
node
)
||
syntaxFacts
.
IsNameOfMemberBindingExpression
(
node
))
{
return
syntaxFacts
.
IsLeftSideOfDot
(
node
.
Parent
);
}
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs
浏览文件 @
89497254
...
...
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using
System.Collections.Generic
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Linq
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
...
...
@@ -33,9 +34,8 @@ public static ExpressionSyntax WalkDownParentheses(this ExpressionSyntax express
public
static
bool
IsQualifiedCrefName
(
this
ExpressionSyntax
expression
)
=>
expression
.
IsParentKind
(
SyntaxKind
.
NameMemberCref
)
&&
expression
.
Parent
.
IsParentKind
(
SyntaxKind
.
QualifiedCref
);
public
static
bool
IsMemberAccessExpressionName
(
this
ExpressionSyntax
expression
)
=>
(
expression
.
IsParentKind
(
SyntaxKind
.
SimpleMemberAccessExpression
,
out
MemberAccessExpressionSyntax
memberAccess
)
&&
memberAccess
.
Name
==
expression
)
||
IsMemberBindingExpressionName
(
expression
);
public
static
bool
IsSimpleMemberAccessExpressionName
(
this
ExpressionSyntax
expression
)
=>
expression
.
IsParentKind
(
SyntaxKind
.
SimpleMemberAccessExpression
,
out
MemberAccessExpressionSyntax
memberAccess
)
&&
memberAccess
.
Name
==
expression
;
public
static
bool
IsAnyMemberAccessExpressionName
(
this
ExpressionSyntax
expression
)
{
...
...
@@ -48,7 +48,7 @@ public static bool IsAnyMemberAccessExpressionName(this ExpressionSyntax express
expression
.
IsMemberBindingExpressionName
();
}
p
rivate
static
bool
IsMemberBindingExpressionName
(
this
ExpressionSyntax
expression
)
p
ublic
static
bool
IsMemberBindingExpressionName
(
this
ExpressionSyntax
expression
)
=>
expression
.
IsParentKind
(
SyntaxKind
.
MemberBindingExpression
,
out
MemberBindingExpressionSyntax
memberBinding
)
&&
memberBinding
.
Name
==
expression
;
...
...
@@ -59,7 +59,7 @@ public static bool IsRightSideOfColonColon(this ExpressionSyntax expression)
=>
expression
.
IsParentKind
(
SyntaxKind
.
AliasQualifiedName
,
out
AliasQualifiedNameSyntax
aliasName
)
&&
aliasName
.
Name
==
expression
;
public
static
bool
IsRightSideOfDot
(
this
ExpressionSyntax
name
)
=>
Is
MemberAccess
ExpressionName
(
name
)
||
IsRightSideOfQualifiedName
(
name
)
||
IsQualifiedCrefName
(
name
);
=>
Is
SimpleMemberAccessExpressionName
(
name
)
||
IsMemberBinding
ExpressionName
(
name
)
||
IsRightSideOfQualifiedName
(
name
)
||
IsQualifiedCrefName
(
name
);
public
static
bool
IsRightSideOfDotOrArrow
(
this
ExpressionSyntax
name
)
=>
IsAnyMemberAccessExpressionName
(
name
)
||
IsRightSideOfQualifiedName
(
name
);
...
...
@@ -67,7 +67,7 @@ public static bool IsRightSideOfDotOrArrow(this ExpressionSyntax name)
public
static
bool
IsRightSideOfDotOrColonColon
(
this
ExpressionSyntax
name
)
=>
IsRightSideOfDot
(
name
)
||
IsRightSideOfColonColon
(
name
);
public
static
bool
IsRightSideOfDotOrArrowOrColonColon
(
this
ExpressionSyntax
name
)
public
static
bool
IsRightSideOfDotOrArrowOrColonColon
(
[
NotNullWhen
(
true
)]
this
ExpressionSyntax
name
)
=>
IsRightSideOfDotOrArrow
(
name
)
||
IsRightSideOfColonColon
(
name
);
public
static
bool
IsRightOfCloseParen
(
this
ExpressionSyntax
expression
)
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SimpleNameSyntaxExtensions.cs
浏览文件 @
89497254
...
...
@@ -11,18 +11,14 @@ internal static class SimpleNameSyntaxExtensions
{
public
static
ExpressionSyntax
GetLeftSideOfDot
(
this
SimpleNameSyntax
name
)
{
Debug
.
Assert
(
name
.
Is
MemberAccess
ExpressionName
()
||
name
.
IsRightSideOfQualifiedName
()
||
name
.
IsParentKind
(
SyntaxKind
.
NameMemberCref
));
if
(
name
.
IsMemberAccessExpressionName
())
Debug
.
Assert
(
name
.
Is
SimpleMemberAccessExpressionName
()
||
name
.
IsMemberBinding
ExpressionName
()
||
name
.
IsRightSideOfQualifiedName
()
||
name
.
IsParentKind
(
SyntaxKind
.
NameMemberCref
));
if
(
name
.
Is
Simple
MemberAccessExpressionName
())
{
var
conditionalAccess
=
name
.
GetParentConditionalAccessExpression
();
if
(
conditionalAccess
!=
null
)
{
return
conditionalAccess
.
Expression
;
}
else
{
return
((
MemberAccessExpressionSyntax
)
name
.
Parent
).
Expression
;
}
return
((
MemberAccessExpressionSyntax
)
name
.
Parent
).
Expression
;
}
else
if
(
name
.
IsMemberBindingExpressionName
())
{
return
name
.
GetParentConditionalAccessExpression
().
Expression
;
}
else
if
(
name
.
IsRightSideOfQualifiedName
())
{
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs
浏览文件 @
89497254
...
...
@@ -14,6 +14,7 @@
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CSharp.LanguageServices
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Utilities
;
...
...
@@ -271,21 +272,100 @@ public static SyntaxList<AttributeListSyntax> GetAttributeLists(this SyntaxNode
_
=>
default
,
};
public
static
ConditionalAccessExpressionSyntax
?
GetParentConditionalAccessExpression
(
this
SyntaxNode
node
)
public
static
ConditionalAccessExpressionSyntax
?
GetParentConditionalAccessExpression
(
this
SyntaxNode
?
node
)
{
// Walk upwards based on the grammar/parser rules around ?. expressions (can be seen in
// LanguageParser.ParseConsequenceSyntax).
// These are the parts of the expression that the ?... expression can end with. Specifically:
//
// 1. x?.y.M() // invocation
// 2. x?.y[...]; // element access
// 3. x?.y.z // member access
// 4. x?.y // member binding
// 5. x?[y] // element binding
var
current
=
node
;
while
(
current
?.
Parent
!=
null
)
if
((
current
.
IsParentKind
(
SyntaxKind
.
SimpleMemberAccessExpression
,
out
MemberAccessExpressionSyntax
?
memberAccess
)
&&
memberAccess
.
Name
==
current
)
||
(
current
.
IsParentKind
(
SyntaxKind
.
MemberBindingExpression
,
out
MemberBindingExpressionSyntax
?
memberBinding
)
&&
memberBinding
.
Name
==
current
))
{
if
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
ConditionalAccessExpressionSyntax
?
conditional
)
&&
conditional
.
WhenNotNull
==
current
)
{
return
conditional
;
}
current
=
current
.
Parent
;
}
// Effectively, if we're on the RHS of the ? we have to walk up the RHS spine first until we hit the first
// conditional access.
while
(
current
.
IsKind
(
SyntaxKind
.
InvocationExpression
,
SyntaxKind
.
ElementAccessExpression
,
SyntaxKind
.
SimpleMemberAccessExpression
,
SyntaxKind
.
MemberBindingExpression
,
SyntaxKind
.
ElementBindingExpression
)
&&
current
.
Parent
is
not
ConditionalAccessExpressionSyntax
)
{
current
=
current
.
Parent
;
}
return
null
;
// Two cases we have to care about:
//
// 1. a?.b.$$c.d and
// 2. a?.b.$$c.d?.e...
//
// Note that `a?.b.$$c.d?.e.f?.g.h.i` falls into the same bucket as two. i.e. the parts after `.e` are
// lower in the tree and are not seen as we walk upwards.
//
//
// To get the root ?. (the one after the `a`) we have to potentially consume the first ?. on the RHS of the
// right spine (i.e. the one after `d`). Once we do this, we then see if that itself is on the RHS of a
// another conditional, and if so we hten return the one on the left. i.e. for '2' this goes in this direction:
//
// a?.b.$$c.d?.e // it will do:
// ----->
// <---------
//
// Note that this only one CAE consumption on both sides. GetRootConditionalAccessExpression can be used to
// get the root parent in a case like:
//
// x?.y?.z?.a?.b.$$c.d?.e.f?.g.h.i // it will do:
// ----->
// <---------
// <---
// <---
// <---
if
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
ConditionalAccessExpressionSyntax
?
conditional
)
&&
conditional
.
Expression
==
current
)
{
current
=
conditional
;
}
if
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
conditional
)
&&
conditional
.
WhenNotNull
==
current
)
{
current
=
conditional
;
}
return
current
as
ConditionalAccessExpressionSyntax
;
}
/// <summary>
/// <inheritdoc cref="ISyntaxFacts.GetRootConditionalAccessExpression(SyntaxNode)"/>
/// </summary>>
public
static
ConditionalAccessExpressionSyntax
?
GetRootConditionalAccessExpression
(
this
SyntaxNode
?
node
)
{
// Once we've walked up the entire RHS, now we continually walk up the conditional accesses until we're at
// the root. For example, if we have `a?.b` and we're on the `.b`, this will give `a?.b`. Similarly with
// `a?.b?.c` if we're on either `.b` or `.c` this will result in `a?.b?.c` (i.e. the root of this CAE
// sequence).
var
current
=
node
.
GetParentConditionalAccessExpression
();
while
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
ConditionalAccessExpressionSyntax
?
conditional
)
&&
conditional
.
WhenNotNull
==
current
)
{
current
=
conditional
;
}
return
current
;
}
public
static
ConditionalAccessExpressionSyntax
?
GetInnerMostConditionalAccessExpression
(
this
SyntaxNode
node
)
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs
浏览文件 @
89497254
...
...
@@ -147,11 +147,28 @@ public bool IsRightSideOfQualifiedName(SyntaxNode node)
}
#
nullable
enable
public
bool
IsNameOfMemberAccessExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
)
public
bool
IsNameOfSimpleMemberAccessExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
)
{
var
name
=
node
as
SimpleNameSyntax
;
return
name
.
IsMemberAccessExpressionName
();
return
name
.
Is
Simple
MemberAccessExpressionName
();
}
public
bool
IsNameOfAnyMemberAccessExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
)
=>
node
?.
Parent
is
MemberAccessExpressionSyntax
memberAccess
&&
memberAccess
.
Name
==
node
;
public
bool
IsNameOfMemberBindingExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
)
{
var
name
=
node
as
SimpleNameSyntax
;
return
name
.
IsMemberBindingExpressionName
();
}
public
SyntaxNode
?
GetStandaloneExpression
(
SyntaxNode
?
node
)
=>
node
is
ExpressionSyntax
expression
?
SyntaxFactory
.
GetStandaloneExpression
(
expression
)
:
node
;
public
SyntaxNode
?
GetRootConditionalAccessExpression
(
SyntaxNode
?
node
)
=>
node
.
GetRootConditionalAccessExpression
();
#
nullable
restore
public
bool
IsObjectCreationExpressionType
(
SyntaxNode
node
)
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs
浏览文件 @
89497254
...
...
@@ -185,10 +185,29 @@ internal partial interface ISyntaxFacts
bool
IsLeftSideOfExplicitInterfaceSpecifier
(
SyntaxNode
node
);
#
nullable
enable
bool
IsNameOfMemberAccessExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
);
bool
IsNameOfSimpleMemberAccessExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
);
bool
IsNameOfAnyMemberAccessExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
);
bool
IsNameOfMemberBindingExpression
([
NotNullWhen
(
true
)]
SyntaxNode
?
node
);
#
nullable
restore
bool
IsExpressionOfMemberAccessExpression
(
SyntaxNode
node
);
/// <summary>
/// Gets the containing expression that is actually a language expression and not just typed
/// as an ExpressionSyntax for convenience. For example, NameSyntax nodes on the right side
/// of qualified names and member access expressions are not language expressions, yet the
/// containing qualified names or member access expressions are indeed expressions.
/// </summary>
SyntaxNode
GetStandaloneExpression
(
SyntaxNode
node
);
/// <summary>
/// Call on the `.y` part of a `x?.y` to get the entire `x?.y` conditional access expression. This also works
/// when there are multiple chained conditional accesses. For example, calling this on '.y' or '.z' in
/// `x?.y?.z` will both return the full `x?.y?.z` node. This can be used to effectively get 'out' of the RHS of
/// a conditional access, and commonly represents the full standalone expression that can be operated on
/// atomically.
/// </summary>
SyntaxNode
GetRootConditionalAccessExpression
(
SyntaxNode
node
);
bool
IsExpressionOfMemberAccessExpression
(
SyntaxNode
node
);
SyntaxNode
GetNameOfMemberAccessExpression
(
SyntaxNode
node
);
/// <summary>
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs
浏览文件 @
89497254
...
...
@@ -257,6 +257,26 @@ public static bool IsOnTypeHeader(this ISyntaxFacts syntaxFacts, SyntaxNode root
return
null
;
}
/// <summary>
/// Similar to <see cref="ISyntaxFacts.GetStandaloneExpression(SyntaxNode)"/>, this gets the containing
/// expression that is actually a language expression and not just typed as an ExpressionSyntax for convenience.
/// However, this goes beyond that that method in that if this expression is the RHS of a conditional access
/// (i.e. <c>a?.b()</c>) it will also return the root of the conditional access expression tree.
/// <para/> The intuition here is that this will give the topmost expression node that could realistically be
/// replaced with any other expression. For example, with <c>a?.b()</c> technically <c>.b()</c> is an
/// expression. But that cannot be replaced with something like <c>(1 + 1)</c> (as <c>a?.(1 + 1)</c> is not
/// legal). However, in <c>a?.b()</c>, then <c>a</c> itself could be replaced with <c>(1 + 1)?.b()</c> to form
/// a legal expression.
/// </summary>
public
static
SyntaxNode
GetRootStandaloneExpression
(
this
ISyntaxFacts
syntaxFacts
,
SyntaxNode
node
)
{
// First, make sure we're on a construct the language things is a standalone expression.
var
standalone
=
syntaxFacts
.
GetStandaloneExpression
(
node
);
// Then, if this is the RHS of a `?`, walk up to the top of that tree to get the final standalone expression.
return
syntaxFacts
.
GetRootConditionalAccessExpression
(
standalone
)
??
standalone
;
}
#
region
ISyntaxKinds
forwarding
methods
#
region
trivia
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ExpressionSyntaxExtensions.vb
浏览文件 @
89497254
...
...
@@ -53,15 +53,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
End
Function
<
Extension
()
>
Public
Function
IsMemberAccessExpressionName
(
expression
As
ExpressionSyntax
)
As
Boolean
Public
Function
Is
Simple
MemberAccessExpressionName
(
expression
As
ExpressionSyntax
)
As
Boolean
Return
expression
.
IsParentKind
(
SyntaxKind
.
SimpleMemberAccessExpression
)
AndAlso
DirectCast
(
expression
.
Parent
,
MemberAccessExpressionSyntax
).
Name
Is
expression
End
Function
<
Extension
()
>
Public
Function
IsAnyMemberAccessExpressionName
(
expression
As
ExpressionSyntax
)
As
Boolean
Return
expression
IsNot
Nothing
AndAlso
TypeOf
expression
.
Parent
Is
MemberAccessExpressionSyntax
AndAlso
Return
TypeOf
expression
?
.
Parent
Is
MemberAccessExpressionSyntax
AndAlso
DirectCast
(
expression
.
Parent
,
MemberAccessExpressionSyntax
).
Name
Is
expression
End
Function
...
...
@@ -72,7 +71,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
<
Extension
()
>
Public
Function
IsRightSideOfDot
(
expression
As
ExpressionSyntax
)
As
Boolean
Return
expression
.
IsMemberAccessExpressionName
()
OrElse
expression
.
IsRightSideOfQualifiedName
()
Return
expression
.
Is
Simple
MemberAccessExpressionName
()
OrElse
expression
.
IsRightSideOfQualifiedName
()
End
Function
<
Extension
()
>
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/MemberAccessExpressionSyntaxExtensions.vb
浏览文件 @
89497254
...
...
@@ -83,7 +83,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
' 3) new T() With { .a = 1, .b = .a <-- 'a refers to the T type
If
allowImplicitTarget
Then
Dim
conditional
=
memberAccessExpression
.
Get
Corresponding
ConditionalAccessExpression
()
Dim
conditional
=
memberAccessExpression
.
Get
Root
ConditionalAccessExpression
()
If
conditional
IsNot
Nothing
Then
If
conditional
.
Expression
Is
Nothing
Then
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/SyntaxNodeExtensions.vb
浏览文件 @
89497254
...
...
@@ -6,6 +6,7 @@ Imports System.Collections.Immutable
Imports
System.Runtime.CompilerServices
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.LanguageServices
Imports
Microsoft.CodeAnalysis.Text
Imports
Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
...
...
@@ -205,7 +206,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return
multiLineLambdaExpression
.
Statements
End
If
t
hrow
ExceptionUtilities
.
UnexpectedValue
(
node
)
T
hrow
ExceptionUtilities
.
UnexpectedValue
(
node
)
End
Function
<
Extension
()
>
...
...
@@ -997,58 +998,96 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Next
End
Function
''' <summary>
''' Given an expression within a tree of <see cref="ConditionalAccessExpressionSyntax"/>s,
''' finds the <see cref="ConditionalAccessExpressionSyntax"/> that it is part of.
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
<
Extension
>
Friend
Function
GetCorrespondingConditionalAccessExpression
(
node
As
ExpressionSyntax
)
As
ConditionalAccessExpressionSyntax
Dim
access
As
SyntaxNode
=
node
Dim
parent
As
SyntaxNode
=
access
.
Parent
While
parent
IsNot
Nothing
Select
Case
parent
.
Kind
Case
SyntaxKind
.
DictionaryAccessExpression
,
SyntaxKind
.
SimpleMemberAccessExpression
Friend
Function
GetParentConditionalAccessExpression
(
node
As
ExpressionSyntax
)
As
ConditionalAccessExpressionSyntax
' Walk upwards based on the grammar/parser rules around ?. expressions (can be seen in
' ParseExpression.vb (.ParsePostFixExpression).
'
' These are the parts of the expression that the ?... expression can end with. Specifically
'
' 1. x?.y.M() // invocation
' 2. x?.y and x?.y.z // member access (covered under MemberAccessExpressionSyntax below)
' 3. x?!y // dictionary access (covered under MemberAccessExpressionSyntax below)
' 4. x?.y<...> // xml access
If
node
.
IsAnyMemberAccessExpressionName
()
Then
node
=
DirectCast
(
node
.
Parent
,
ExpressionSyntax
)
End
If
If
DirectCast
(
parent
,
MemberAccessExpressionSyntax
).
Expression
IsNot
access
Then
Return
Nothing
End
If
' Effectively, if we're on the RHS of the ? we have to walk up the RHS spine first until we hit the first
' conditional access.
Case
SyntaxKind
.
XmlElementAccessExpression
,
SyntaxKind
.
XmlDescendantAccessExpression
,
SyntaxKind
.
XmlAttributeAccessExpression
While
(
TypeOf
node
Is
InvocationExpressionSyntax
OrElse
TypeOf
node
Is
MemberAccessExpressionSyntax
OrElse
TypeOf
node
Is
XmlMemberAccessExpressionSyntax
)
AndAlso
TypeOf
node
.
Parent
IsNot
ConditionalAccessExpressionSyntax
If
DirectCast
(
parent
,
XmlMemberAccessExpressionSyntax
).
Base
IsNot
access
Then
Return
Nothing
End
If
Case
SyntaxKind
.
InvocationExpression
node
=
TryCast
(
node
.
Parent
,
ExpressionSyntax
)
End
While
If
DirectCast
(
parent
,
InvocationExpressionSyntax
).
Expression
IsNot
access
Then
Return
Nothing
End
If
' Two cases we have to care about
'
' 1. a?.b.$$c.d And
' 2. a?.b.$$c.d?.e...
'
' Note that `a?.b.$$c.d?.e.f?.g.h.i` falls into the same bucket as two. i.e. the parts after `.e` are
' lower in the tree And are Not seen as we walk upwards.
'
'
' To get the root ?. (the one after the `a`) we have to potentially consume the first ?. on the RHS of the
' right spine (i.e. the one after `d`). Once we do this, we then see if that itself Is on the RHS of a
' another conditional, And if so we hten return the one on the left. i.e. for '2' this goes in this direction:
'
' a?.b.$$c.d?.e // it will do:
' ----->
' <---------
'
' Note that this only one CAE consumption on both sides. GetRootConditionalAccessExpression can be used to
' get the root parent in a case Like:
'
' x?.y?.z?.a?.b.$$c.d?.e.f?.g.h.i // It will do:
' ----->
' <---------
' <---
' <---
' <---
If
TypeOf
node
?
.
Parent
Is
ConditionalAccessExpressionSyntax
AndAlso
DirectCast
(
node
.
Parent
,
ConditionalAccessExpressionSyntax
).
Expression
Is
node
Then
node
=
DirectCast
(
node
.
Parent
,
ExpressionSyntax
)
End
If
Case
SyntaxKind
.
ConditionalAccessExpression
If
TypeOf
node
?
.
Parent
Is
ConditionalAccessExpressionSyntax
AndAlso
DirectCast
(
node
.
Parent
,
ConditionalAccessExpressionSyntax
).
WhenNotNull
Is
node
Then
Dim
conditional
=
DirectCast
(
parent
,
ConditionalAccessExpressionSyntax
)
If
conditional
.
WhenNotNull
Is
access
Then
Return
conditional
ElseIf
conditional
.
Expression
IsNot
access
Then
Return
Nothing
End
If
node
=
DirectCast
(
node
.
Parent
,
ExpressionSyntax
)
End
If
Case
Else
Return
Nothing
End
Select
Return
TryCast
(
node
,
ConditionalAccessExpressionSyntax
)
End
Function
access
=
parent
parent
=
access
.
Parent
''' <summary>
''' <see cref="ISyntaxFacts.GetRootConditionalAccessExpression"/>
''' </summary>
<
Extension
>
Friend
Function
GetRootConditionalAccessExpression
(
node
As
ExpressionSyntax
)
As
ConditionalAccessExpressionSyntax
' Once we've walked up the entire RHS, now we continually walk up the conditional accesses until we're at
' the root. For example, if we have `a?.b` And we're on the `.b`, this will give `a?.b`. Similarly with
' `a?.b?.c` if we're on either `.b` or `.c` this will result in `a?.b?.c` (i.e. the root of this CAE
' sequence).
node
=
node
.
GetParentConditionalAccessExpression
()
While
TypeOf
node
?
.
Parent
Is
ConditionalAccessExpressionSyntax
Dim
conditionalParent
=
DirectCast
(
node
.
Parent
,
ConditionalAccessExpressionSyntax
)
If
conditionalParent
.
WhenNotNull
Is
node
Then
node
=
conditionalParent
Else
Exit
While
End
If
End
While
Return
Nothing
Return
TryCast
(
node
,
ConditionalAccessExpressionSyntax
)
End
Function
<
Extension
>
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb
浏览文件 @
89497254
...
...
@@ -169,9 +169,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsRightSideOfQualifiedName
()
End
Function
Public
Function
IsNameOfMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFacts
.
IsNameOfMemberAccessExpression
Dim
vbNode
=
TryCast
(
node
,
SimpleNameSyntax
)
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsMemberAccessExpressionName
()
Public
Function
IsNameOfSimpleMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFacts
.
IsNameOfSimpleMemberAccessExpression
Dim
vbNode
=
TryCast
(
node
,
ExpressionSyntax
)
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsSimpleMemberAccessExpressionName
()
End
Function
Public
Function
IsNameOfAnyMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFacts
.
IsNameOfAnyMemberAccessExpression
Dim
memberAccess
=
TryCast
(
node
?
.
Parent
,
MemberAccessExpressionSyntax
)
Return
memberAccess
IsNot
Nothing
AndAlso
memberAccess
.
Name
Is
node
End
Function
Public
Function
GetStandaloneExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFacts
.
GetStandaloneExpression
Return
SyntaxFactory
.
GetStandaloneExpression
(
TryCast
(
node
,
ExpressionSyntax
))
End
Function
Public
Function
GetRootConditionalAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFacts
.
GetRootConditionalAccessExpression
Return
TryCast
(
node
,
ExpressionSyntax
).
GetRootConditionalAccessExpression
()
End
Function
Public
Sub
GetPartsOfConditionalAccessExpression
(
node
As
SyntaxNode
,
ByRef
expression
As
SyntaxNode
,
ByRef
operatorToken
As
SyntaxToken
,
ByRef
whenNotNull
As
SyntaxNode
)
Implements
ISyntaxFacts
.
GetPartsOfConditionalAccessExpression
...
...
@@ -1879,7 +1892,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices
End
Function
Public
Function
IsMemberBindingExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFacts
.
IsMemberBindingExpression
' Does not exist in VB.
' Does not exist in VB. VB represents a member binding as a MemberAccessExpression with null target.
Return
False
End
Function
Public
Function
IsNameOfMemberBindingExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFacts
.
IsNameOfMemberBindingExpression
' Does not exist in VB. VB represents a member binding as a MemberAccessExpression with null target.
Return
False
End
Function
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/SimpleNameSyntaxExtensions.vb
浏览文件 @
89497254
...
...
@@ -10,8 +10,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Friend
Module
SimpleNameSyntaxExtensions
<
Extension
()
>
Public
Function
GetLeftSideOfDot
(
name
As
SimpleNameSyntax
)
As
ExpressionSyntax
Debug
.
Assert
(
IsMemberAccessExpressionName
(
name
)
OrElse
IsRightSideOfQualifiedName
(
name
))
If
IsMemberAccessExpressionName
(
name
)
Then
Debug
.
Assert
(
Is
Simple
MemberAccessExpressionName
(
name
)
OrElse
IsRightSideOfQualifiedName
(
name
))
If
Is
Simple
MemberAccessExpressionName
(
name
)
Then
Return
DirectCast
(
name
.
Parent
,
MemberAccessExpressionSyntax
).
Expression
Else
Return
DirectCast
(
name
.
Parent
,
QualifiedNameSyntax
).
Left
...
...
src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.Expander.vb
浏览文件 @
89497254
...
...
@@ -224,7 +224,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification
reducedExtensionMethod
As
IMethodSymbol
)
As
InvocationExpressionSyntax
Dim
originalMemberAccess
=
DirectCast
(
originalNode
.
Expression
,
MemberAccessExpressionSyntax
)
If
originalMemberAccess
.
Get
CorrespondingConditionalAccessExpression
IsNot
Nothing
Then
If
originalMemberAccess
.
Get
RootConditionalAccessExpression
()
IsNot
Nothing
Then
' Bail out on extension method invocations in conditional access expression.
' Note that this is a temporary workaround for https://github.com/dotnet/roslyn/issues/2593.
' Issue https//github.com/dotnet/roslyn/issues/3260 tracks fixing this workaround.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录