Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4278a17b
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,发现更多精彩内容 >>
未验证
提交
4278a17b
编写于
12月 23, 2019
作者:
A
Allison Chou
提交者:
GitHub
12月 23, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #40284 from allisonchou/ExtractLocalFunctionNamingConvention
Fix extract local function bugs
上级
bc98ebc0
cf9bc9e8
变更
18
显示空白变更内容
内联
并排
Showing
18 changed file
with
829 addition
and
97 deletion
+829
-97
src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs
...st/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs
+463
-3
src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs
...SharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs
+205
-1
src/Features/CSharp/Portable/CodeRefactorings/ConvertLocalFunctionToMethod/CSharpConvertLocalFunctionToMethodCodeRefactoringProvider.cs
...arpConvertLocalFunctionToMethodCodeRefactoringProvider.cs
+3
-3
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs
...dExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs
+14
-6
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs
...or.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs
+4
-2
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs
...actor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs
+4
-2
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs
...xtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs
+53
-9
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs
...es/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs
+3
-2
src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs
...e/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs
+7
-4
src/Features/Core/Portable/ExtractMethod/MethodExtractor.cs
src/Features/Core/Portable/ExtractMethod/MethodExtractor.cs
+10
-2
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb
...actor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb
+4
-3
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb
...sualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb
+2
-1
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb
....VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb
+2
-1
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb
...od/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb
+1
-1
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb
...asic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb
+1
-1
src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs
...rp/Portable/CodeGeneration/CSharpCodeGenerationService.cs
+15
-10
src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
...kspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
+30
-46
src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOptions.cs
...ces/Core/Portable/CodeGeneration/CodeGenerationOptions.cs
+8
-0
未找到文件。
src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs
浏览文件 @
4278a17b
...
...
@@ -8,6 +8,7 @@
using
Microsoft.CodeAnalysis.CSharp.CodeStyle
;
using
Microsoft.CodeAnalysis.CSharp.Test.Utilities
;
using
Microsoft.CodeAnalysis.Test.Utilities
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
namespace
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.ExtractMethod
...
...
@@ -21,6 +22,39 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
private
int
CodeActionIndex
=>
1
;
private
const
string
EditorConfigNaming_CamelCase
=
@"[*]
# Naming rules
dotnet_naming_rule.local_functions_should_be_camel_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_camel_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_camel_case.style = camel_case
# Symbol specifications
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
# Naming styles
dotnet_naming_style.camel_case.capitalization = camel_case"
;
private
const
string
EditorConfigNaming_PascalCase
=
@"[*]
# Naming rules
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
dotnet_naming_symbols.local_functions.required_modifiers =
# Naming styles
dotnet_naming_style.pascal_case.capitalization = pascal_case"
;
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestPartialSelection_StaticOptionTrue
()
{
...
...
@@ -1538,7 +1572,7 @@ static void NewMethod()
}"
,
CodeActionIndex
);
}
[
Fact
(
Skip
=
"https://github.com/dotnet/roslyn/issues/39946"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
[
Fact
,
WorkItem
(
39946
,
"https://github.com/dotnet/roslyn/issues/39946"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
ExtractLocalFunctionCall_3
()
{
await
TestInRegularAndScriptAsync
(
@"
...
...
@@ -1551,7 +1585,6 @@ static void LocalParent()
[|void Local() { }
Local();|]
}
}
}"
,
@"
class C
...
...
@@ -1572,7 +1605,7 @@ static void NewMethod()
}"
,
CodeActionIndex
);
}
[
Fact
(
Skip
=
"https://github.com/dotnet/roslyn/issues/39946"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
[
Fact
,
WorkItem
(
39946
,
"https://github.com/dotnet/roslyn/issues/39946"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
ExtractFunctionUnderLocalFunctionCall
()
{
await
TestInRegularAndScriptAsync
(
@"
...
...
@@ -3790,6 +3823,433 @@ static int NewMethod()
}"
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40188
,
"https://github.com/dotnet/roslyn/issues/40188"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestEditorconfigSetting_StaticLocalFunction_True
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool test = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_prefer_static_local_function = true:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
{|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
static void NewMethod()
{
bool test = true;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_prefer_static_local_function = true:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40188
,
"https://github.com/dotnet/roslyn/issues/40188"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestEditorconfigSetting_StaticLocalFunction_False
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool test = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_prefer_static_local_function = false:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
{|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
void NewMethod()
{
bool test = true;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_prefer_static_local_function = false:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40188
,
"https://github.com/dotnet/roslyn/issues/40188"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestEditorconfigSetting_ExpressionBodiedLocalFunction_True
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_local_functions = true:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
static bool NewMethod() => true;
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_local_functions = true:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40188
,
"https://github.com/dotnet/roslyn/issues/40188"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestEditorconfigSetting_ExpressionBodiedLocalFunction_False
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_local_functions = false:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
static bool NewMethod()
{
return true;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_local_functions = false:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_CamelCase
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:newMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
static bool newMethod()
{
return true;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_CamelCase_GetName
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class MethodExtraction
{
void TestMethod()
{
int a = [|1 + 1|];
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class MethodExtraction
{
void TestMethod()
{
int a = {|Rename:getA|}();
static int getA()
{
return 1 + 1;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_PascalCase
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_PascalCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
static bool NewMethod()
{
return true;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_PascalCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_PascalCase_GetName
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class MethodExtraction
{
void TestMethod()
{
int a = [|1 + 1|];
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_PascalCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class MethodExtraction
{
void TestMethod()
{
int a = {|Rename:GetA|}();
static int GetA()
{
return 1 + 1;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_PascalCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_CamelCase_DoesntApply
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_CamelCase
+
@"
dotnet_naming_symbols.local_functions.required_modifiers = static
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
bool NewMethod()
{
return true;
}
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_CamelCase
+
@"
dotnet_naming_symbols.local_functions.required_modifiers = static
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
,
CodeActionIndex
,
options
:
Option
(
CSharpCodeStyleOptions
.
PreferStaticLocalFunction
,
CodeStyleOptions
.
FalseWithSilentEnforcement
));
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestMissingInLocalFunctionDeclaration_ExpressionBody
()
{
...
...
src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs
浏览文件 @
4278a17b
...
...
@@ -17,6 +17,23 @@ public class ExtractMethodTests : AbstractCSharpCodeActionTest
protected
override
CodeRefactoringProvider
CreateCodeRefactoringProvider
(
Workspace
workspace
,
TestParameters
parameters
)
=>
new
ExtractMethodCodeRefactoringProvider
();
private
const
string
EditorConfigNaming_LocalFunctions_CamelCase
=
@"[*]
# Naming rules
dotnet_naming_rule.local_functions_should_be_camel_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_camel_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_camel_case.style = camel_case
# Symbol specifications
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
dotnet_naming_symbols.local_functions.required_modifiers =
# Naming styles
dotnet_naming_style.camel_case.capitalization = camel_case"
;
[
Fact
]
[
WorkItem
(
39946
,
"https://github.com/dotnet/roslyn/issues/39946"
)]
public
async
Task
LocalFuncExtract
()
...
...
@@ -3205,7 +3222,7 @@ private static bool NewMethod(bool b)
}"
,
options
:
Option
(
CSharpCodeStyleOptions
.
PreferStaticLocalFunction
,
CodeStyleOptions
.
FalseWithSuggestionEnforcement
));
}
[
Fact
(
Skip
=
"https://github.com/dotnet/roslyn/issues/39946"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractMethod
)]
[
Fact
,
WorkItem
(
39946
,
"https://github.com/dotnet/roslyn/issues/39946"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractMethod
)]
public
async
Task
ExtractLocalFunctionCallAndDeclaration
()
{
await
TestInRegularAndScriptAsync
(
@"
...
...
@@ -3638,5 +3655,192 @@ private static async Task NewMethod(TimeSpan duration)
}
}"
);
}
[
Fact
,
WorkItem
(
40188
,
"https://github.com/dotnet/roslyn/issues/40188"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractMethod
)]
public
async
Task
TestEditorconfigSetting_ExpressionBodiedLocalFunction_True
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_methods = true:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
}
private static bool NewMethod() => true;
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_methods = true:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
);
}
[
Fact
,
WorkItem
(
40188
,
"https://github.com/dotnet/roslyn/issues/40188"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractMethod
)]
public
async
Task
TestEditorconfigSetting_ExpressionBodiedLocalFunction_False
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_methods = false:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
}
private static bool NewMethod()
{
return true;
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">[*.cs]
csharp_style_expression_bodied_methods = false:silent
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_CamelCase_VerifyLocalFunctionSettingsDontApply
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class Program1
{
static void Main()
{
[|bool b = true;|]
System.Console.WriteLine(b != true ? b = true : b = false);
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_LocalFunctions_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class Program1
{
static void Main()
{
bool b = {|Rename:NewMethod|}();
System.Console.WriteLine(b != true ? b = true : b = false);
}
private static bool NewMethod()
{
return true;
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_LocalFunctions_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
);
}
[
Fact
,
WorkItem
(
40209
,
"https://github.com/dotnet/roslyn/issues/40209"
),
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsExtractLocalFunction
)]
public
async
Task
TestNaming_CamelCase_VerifyLocalFunctionSettingsDontApply_GetName
()
{
var
input
=
@"
<Workspace>
<Project Language = ""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath = ""z:\\file.cs"">
class MethodExtraction
{
void TestMethod()
{
int a = [|1 + 1|];
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_LocalFunctions_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
var
expected
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""z:\\file.cs"">
class MethodExtraction
{
void TestMethod()
{
int a = {|Rename:GetA|}();
}
private static int GetA()
{
return 1 + 1;
}
}
</Document>
<AnalyzerConfigDocument FilePath = ""z:\\.editorconfig"">"
+
EditorConfigNaming_LocalFunctions_CamelCase
+
@"
</AnalyzerConfigDocument>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
input
,
expected
);
}
}
}
src/Features/CSharp/Portable/CodeRefactorings/ConvertLocalFunctionToMethod/CSharpConvertLocalFunctionToMethodCodeRefactoringProvider.cs
浏览文件 @
4278a17b
...
...
@@ -115,9 +115,9 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
typeParameters
:
typeParameters
.
ToImmutableArray
(),
parameters
:
parameters
.
AddRange
(
capturesAsParameters
));
var
defaultOptions
=
CodeGenerationOptions
.
Default
;
var
method
=
MethodGenerator
.
GenerateMethodDeclaration
(
methodSymbol
,
CodeGenerationDestination
.
Unspecified
,
document
.
Project
.
Solution
.
Workspace
,
defaultOptions
,
root
.
SyntaxTree
.
Options
);
var
options
=
await
document
.
GetOptionsAsync
(
cancellationToken
).
ConfigureAwait
(
false
)
;
var
defaultOptions
=
new
CodeGenerationOptions
(
options
:
options
);
var
method
=
MethodGenerator
.
GenerateMethodDeclaration
(
methodSymbol
,
CodeGenerationDestination
.
Unspecified
,
defaultOptions
,
root
.
SyntaxTree
.
Options
);
var
generator
=
s_generator
;
var
editor
=
new
SyntaxEditor
(
root
,
generator
);
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs
浏览文件 @
4278a17b
...
...
@@ -6,9 +6,14 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CSharp.Extensions
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
using
static
Microsoft
.
CodeAnalysis
.
Diagnostics
.
Analyzers
.
NamingStyles
.
SymbolSpecification
;
namespace
Microsoft.CodeAnalysis.CSharp.ExtractMethod
{
...
...
@@ -22,8 +27,9 @@ private class ExpressionCodeGenerator : CSharpCodeGenerator
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
,
bool
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
)
{
}
...
...
@@ -32,9 +38,10 @@ public static bool IsExtractMethodOnExpression(SelectionResult code)
return
code
.
SelectionInExpression
;
}
protected
override
SyntaxToken
CreateMethodName
(
bool
localFunction
)
protected
override
SyntaxToken
CreateMethodName
()
{
var
methodName
=
"NewMethod"
;
var
methodName
=
GenerateMethodNameFromUserPreference
();
var
containingScope
=
this
.
CSharpSelectionResult
.
GetContainingScope
();
methodName
=
GetMethodNameBasedOnExpression
(
methodName
,
containingScope
);
...
...
@@ -44,7 +51,7 @@ protected override SyntaxToken CreateMethodName(bool localFunction)
return
SyntaxFactory
.
Identifier
(
nameGenerator
.
CreateUniqueMethodName
(
containingScope
,
methodName
));
}
private
st
atic
st
ring
GetMethodNameBasedOnExpression
(
string
methodName
,
SyntaxNode
expression
)
private
string
GetMethodNameBasedOnExpression
(
string
methodName
,
SyntaxNode
expression
)
{
if
(
expression
.
Parent
!=
null
&&
expression
.
Parent
.
Kind
()
==
SyntaxKind
.
EqualsValueClause
&&
...
...
@@ -52,7 +59,7 @@ private static string GetMethodNameBasedOnExpression(string methodName, SyntaxNo
expression
.
Parent
.
Parent
.
Kind
()
==
SyntaxKind
.
VariableDeclarator
)
{
var
name
=
((
VariableDeclaratorSyntax
)
expression
.
Parent
.
Parent
).
Identifier
.
ValueText
;
return
(
name
!=
null
&&
name
.
Length
>
0
)
?
MakeMethodName
(
"Get"
,
name
)
:
methodName
;
return
(
name
!=
null
&&
name
.
Length
>
0
)
?
MakeMethodName
(
"Get"
,
name
,
methodName
.
Equals
(
NewMethodCamelCaseStr
)
)
:
methodName
;
}
if
(
expression
is
MemberAccessExpressionSyntax
memberAccess
)
...
...
@@ -81,7 +88,8 @@ private static string GetMethodNameBasedOnExpression(string methodName, SyntaxNo
}
var
unqualifiedNameIdentifierValueText
=
unqualifiedName
.
Identifier
.
ValueText
;
return
(
unqualifiedNameIdentifierValueText
!=
null
&&
unqualifiedNameIdentifierValueText
.
Length
>
0
)
?
MakeMethodName
(
"Get"
,
unqualifiedNameIdentifierValueText
)
:
methodName
;
return
(
unqualifiedNameIdentifierValueText
!=
null
&&
unqualifiedNameIdentifierValueText
.
Length
>
0
)
?
MakeMethodName
(
"Get"
,
unqualifiedNameIdentifierValueText
,
methodName
.
Equals
(
NewMethodCamelCaseStr
))
:
methodName
;
}
return
methodName
;
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs
浏览文件 @
4278a17b
...
...
@@ -5,6 +5,7 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.Options
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.ExtractMethod
...
...
@@ -19,8 +20,9 @@ public class MultipleStatementsCodeGenerator : CSharpCodeGenerator
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
,
bool
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
)
{
}
...
...
@@ -41,7 +43,7 @@ public static bool IsExtractMethodOnMultipleStatements(SelectionResult code)
return
false
;
}
protected
override
SyntaxToken
CreateMethodName
(
bool
localFunction
)
=>
CreateMethodNameForStatementGenerators
(
localFunction
);
protected
override
SyntaxToken
CreateMethodName
(
)
=>
GenerateMethodNameForStatementGenerators
(
);
protected
override
IEnumerable
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
{
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs
浏览文件 @
4278a17b
...
...
@@ -5,6 +5,7 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.Options
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.ExtractMethod
...
...
@@ -19,8 +20,9 @@ public class SingleStatementCodeGenerator : CSharpCodeGenerator
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
,
bool
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
)
{
}
...
...
@@ -33,7 +35,7 @@ public static bool IsExtractMethodOnSingleStatement(SelectionResult code)
return
firstStatement
==
lastStatement
||
firstStatement
.
Span
.
Contains
(
lastStatement
.
Span
);
}
protected
override
SyntaxToken
CreateMethodName
(
bool
localFunction
)
=>
CreateMethodNameForStatementGenerators
(
localFunction
);
protected
override
SyntaxToken
CreateMethodName
(
)
=>
GenerateMethodNameForStatementGenerators
(
);
protected
override
IEnumerable
<
StatementSyntax
>
GetInitialStatementsForMethodDefinitions
()
{
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs
浏览文件 @
4278a17b
...
...
@@ -9,15 +9,19 @@
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeGeneration
;
using
Microsoft.CodeAnalysis.CSharp.CodeStyle
;
using
Microsoft.CodeAnalysis.CSharp.Extensions
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Operations
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
using
static
Microsoft
.
CodeAnalysis
.
Diagnostics
.
Analyzers
.
NamingStyles
.
SymbolSpecification
;
namespace
Microsoft.CodeAnalysis.CSharp.ExtractMethod
{
...
...
@@ -27,14 +31,18 @@ private abstract partial class CSharpCodeGenerator : CodeGenerator<StatementSynt
{
private
readonly
SyntaxToken
_methodName
;
private
const
string
NewMethodPascalCaseStr
=
"NewMethod"
;
private
const
string
NewMethodCamelCaseStr
=
"newMethod"
;
public
static
Task
<
GeneratedCode
>
GenerateAsync
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
,
bool
localFunction
,
CancellationToken
cancellationToken
)
{
var
codeGenerator
=
Create
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
);
var
codeGenerator
=
Create
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
);
return
codeGenerator
.
GenerateAsync
(
cancellationToken
);
}
...
...
@@ -42,21 +50,22 @@ private abstract partial class CSharpCodeGenerator : CodeGenerator<StatementSynt
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
,
bool
localFunction
)
{
if
(
ExpressionCodeGenerator
.
IsExtractMethodOnExpression
(
selectionResult
))
{
return
new
ExpressionCodeGenerator
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
);
return
new
ExpressionCodeGenerator
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
);
}
if
(
SingleStatementCodeGenerator
.
IsExtractMethodOnSingleStatement
(
selectionResult
))
{
return
new
SingleStatementCodeGenerator
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
);
return
new
SingleStatementCodeGenerator
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
);
}
if
(
MultipleStatementsCodeGenerator
.
IsExtractMethodOnMultipleStatements
(
selectionResult
))
{
return
new
MultipleStatementsCodeGenerator
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
);
return
new
MultipleStatementsCodeGenerator
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
);
}
return
Contract
.
FailWithReturn
<
CSharpCodeGenerator
>(
"Unknown selection"
);
...
...
@@ -66,12 +75,13 @@ private abstract partial class CSharpCodeGenerator : CodeGenerator<StatementSynt
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
,
bool
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
localFunction
)
:
base
(
insertionPoint
,
selectionResult
,
analyzerResult
,
options
,
localFunction
)
{
Contract
.
ThrowIfFalse
(
this
.
SemanticDocument
==
selectionResult
.
SemanticDocument
);
var
nameToken
=
CreateMethodName
(
localFunction
);
var
nameToken
=
CreateMethodName
();
_methodName
=
nameToken
.
WithAdditionalAnnotations
(
this
.
MethodNameAnnotation
);
}
...
...
@@ -210,6 +220,14 @@ private DeclarationModifiers CreateMethodModifiers()
var
isStatic
=
!
this
.
AnalyzerResult
.
UseInstanceMember
;
var
isReadOnly
=
this
.
AnalyzerResult
.
ShouldBeReadOnly
;
// Static local functions are only supported in C# 8.0 and later
var
languageVersion
=
((
CSharpParseOptions
)
this
.
SemanticDocument
.
SyntaxTree
.
Options
).
LanguageVersion
;
if
(
LocalFunction
&&
(!
this
.
Options
.
GetOption
(
CSharpCodeStyleOptions
.
PreferStaticLocalFunction
).
Value
||
languageVersion
<
LanguageVersion
.
CSharp8
))
{
isStatic
=
false
;
}
return
new
DeclarationModifiers
(
isUnsafe
:
isUnsafe
,
isAsync
:
isAsync
,
...
...
@@ -777,19 +795,45 @@ static bool ReturnOperationBelongsToMethod(SyntaxNode returnOperationSyntax, Syn
}
}
protected
SyntaxToken
CreateMethodNameForStatementGenerators
(
bool
localFunction
)
protected
SyntaxToken
GenerateMethodNameForStatementGenerators
(
)
{
var
semanticModel
=
this
.
SemanticDocument
.
SemanticModel
;
var
nameGenerator
=
new
UniqueNameGenerator
(
semanticModel
);
var
scope
=
this
.
CSharpSelectionResult
.
GetContainingScope
();
// If extracting a local function, we want to ensure all local variables are considered when generating a unique name.
if
(
l
ocalFunction
)
if
(
L
ocalFunction
)
{
scope
=
this
.
CSharpSelectionResult
.
GetFirstTokenInSelection
().
Parent
;
}
return
SyntaxFactory
.
Identifier
(
nameGenerator
.
CreateUniqueMethodName
(
scope
,
"NewMethod"
));
return
SyntaxFactory
.
Identifier
(
nameGenerator
.
CreateUniqueMethodName
(
scope
,
GenerateMethodNameFromUserPreference
()));
}
protected
string
GenerateMethodNameFromUserPreference
()
{
var
methodName
=
NewMethodPascalCaseStr
;
if
(!
LocalFunction
)
{
return
methodName
;
}
// For local functions, pascal case and camel case should be the most common and therefore we only consider those cases.
var
namingPreferences
=
this
.
Options
.
GetOption
(
SimplificationOptions
.
NamingPreferences
,
LanguageNames
.
CSharp
);
var
localFunctionPreferences
=
namingPreferences
.
SymbolSpecifications
.
Where
(
symbol
=>
symbol
.
AppliesTo
(
new
SymbolKindOrTypeKind
(
MethodKind
.
LocalFunction
),
CreateMethodModifiers
(),
null
));
var
namingRules
=
namingPreferences
.
Rules
.
NamingRules
;
var
localFunctionKind
=
new
SymbolKindOrTypeKind
(
MethodKind
.
LocalFunction
);
if
(
LocalFunction
)
{
if
(
namingRules
.
Any
(
rule
=>
rule
.
NamingStyle
.
CapitalizationScheme
.
Equals
(
Capitalization
.
CamelCase
)
&&
rule
.
SymbolSpecification
.
AppliesTo
(
localFunctionKind
,
CreateMethodModifiers
(),
null
)))
{
methodName
=
NewMethodCamelCaseStr
;
}
}
// We default to pascal case.
return
methodName
;
}
}
}
...
...
src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs
浏览文件 @
4278a17b
...
...
@@ -9,6 +9,7 @@
using
Microsoft.CodeAnalysis.ExtractMethod
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Formatting.Rules
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
...
...
@@ -87,9 +88,9 @@ protected override async Task<SemanticDocument> ExpandAsync(SelectionResult sele
return
await
selection
.
SemanticDocument
.
WithSyntaxRootAsync
(
selection
.
SemanticDocument
.
Root
.
ReplaceNode
(
lastExpression
,
newExpression
),
cancellationToken
).
ConfigureAwait
(
false
);
}
protected
override
Task
<
GeneratedCode
>
GenerateCodeAsync
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzeResult
,
CancellationToken
cancellationToken
)
protected
override
Task
<
GeneratedCode
>
GenerateCodeAsync
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzeResult
,
OptionSet
options
,
CancellationToken
cancellationToken
)
{
return
CSharpCodeGenerator
.
GenerateAsync
(
insertionPoint
,
selectionResult
,
analyzeResult
,
LocalFunction
,
cancellationToken
);
return
CSharpCodeGenerator
.
GenerateAsync
(
insertionPoint
,
selectionResult
,
analyzeResult
,
options
,
LocalFunction
,
cancellationToken
);
}
protected
override
IEnumerable
<
AbstractFormattingRule
>
GetFormattingRules
(
Document
document
)
...
...
src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs
浏览文件 @
4278a17b
...
...
@@ -8,6 +8,7 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CodeGeneration
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Simplification
;
...
...
@@ -31,9 +32,10 @@ protected abstract partial class CodeGenerator<TStatement, TExpression, TNodeUnd
protected
readonly
SelectionResult
SelectionResult
;
protected
readonly
AnalyzerResult
AnalyzerResult
;
protected
readonly
OptionSet
Options
;
protected
readonly
bool
LocalFunction
;
protected
CodeGenerator
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
bool
localFunction
=
false
)
protected
CodeGenerator
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzerResult
,
OptionSet
options
=
null
,
bool
localFunction
=
false
)
{
Contract
.
ThrowIfFalse
(
insertionPoint
.
SemanticDocument
==
analyzerResult
.
SemanticDocument
);
...
...
@@ -43,6 +45,7 @@ protected CodeGenerator(InsertionPoint insertionPoint, SelectionResult selection
SelectionResult
=
selectionResult
;
AnalyzerResult
=
analyzerResult
;
Options
=
options
;
LocalFunction
=
localFunction
;
MethodNameAnnotation
=
new
SyntaxAnnotation
();
...
...
@@ -58,7 +61,7 @@ protected CodeGenerator(InsertionPoint insertionPoint, SelectionResult selection
protected
abstract
OperationStatus
<
IMethodSymbol
>
GenerateMethodDefinition
(
bool
localFunction
,
CancellationToken
cancellationToken
);
protected
abstract
SyntaxToken
CreateIdentifier
(
string
name
);
protected
abstract
SyntaxToken
CreateMethodName
(
bool
localFunction
);
protected
abstract
SyntaxToken
CreateMethodName
();
protected
abstract
bool
LastStatementOrHasReturnStatementInReturnableConstruct
();
protected
abstract
TNodeUnderContainer
GetFirstStatementOrInitializerSelectedAtCallSite
();
...
...
@@ -91,7 +94,7 @@ public async Task<GeneratedCode> GenerateAsync(CancellationToken cancellationTok
destination
=
InsertionPoint
.
With
(
callSiteDocument
).
GetContext
();
var
localMethod
=
codeGenerationService
.
CreateMethodDeclaration
(
method
:
result
.
Data
,
options
:
new
CodeGenerationOptions
(
generateDefaultAccessibility
:
false
,
generateMethodBodies
:
true
,
parseOptions
:
destination
?.
SyntaxTree
.
Options
));
options
:
new
CodeGenerationOptions
(
generateDefaultAccessibility
:
false
,
generateMethodBodies
:
true
,
options
:
this
.
Options
,
parseOptions
:
destination
?.
SyntaxTree
.
Options
));
newContainer
=
codeGenerationService
.
AddStatements
(
destination
,
new
[]
{
localMethod
},
cancellationToken
:
cancellationToken
);
}
else
...
...
@@ -102,7 +105,7 @@ public async Task<GeneratedCode> GenerateAsync(CancellationToken cancellationTok
destination
=
previousMemberNode
.
Parent
??
previousMemberNode
;
newContainer
=
codeGenerationService
.
AddMethod
(
destination
,
result
.
Data
,
new
CodeGenerationOptions
(
afterThisLocation
:
previousMemberNode
.
GetLocation
(),
generateDefaultAccessibility
:
true
,
generateMethodBodies
:
true
),
new
CodeGenerationOptions
(
afterThisLocation
:
previousMemberNode
.
GetLocation
(),
generateDefaultAccessibility
:
true
,
generateMethodBodies
:
true
,
options
:
this
.
Options
),
cancellationToken
);
}
...
...
src/Features/Core/Portable/ExtractMethod/MethodExtractor.cs
浏览文件 @
4278a17b
...
...
@@ -7,6 +7,7 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Formatting.Rules
;
using
Microsoft.CodeAnalysis.Options
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.ExtractMethod
...
...
@@ -28,7 +29,7 @@ public MethodExtractor(SelectionResult selectionResult, bool localFunction)
protected
abstract
Task
<
TriviaResult
>
PreserveTriviaAsync
(
SelectionResult
selectionResult
,
CancellationToken
cancellationToken
);
protected
abstract
Task
<
SemanticDocument
>
ExpandAsync
(
SelectionResult
selection
,
CancellationToken
cancellationToken
);
protected
abstract
Task
<
GeneratedCode
>
GenerateCodeAsync
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzeResult
,
CancellationToken
cancellationToken
);
protected
abstract
Task
<
GeneratedCode
>
GenerateCodeAsync
(
InsertionPoint
insertionPoint
,
SelectionResult
selectionResult
,
AnalyzerResult
analyzeResult
,
OptionSet
options
,
CancellationToken
cancellationToken
);
protected
abstract
SyntaxToken
GetMethodNameAtInvocation
(
IEnumerable
<
SyntaxNodeOrToken
>
methodNames
);
protected
abstract
IEnumerable
<
AbstractFormattingRule
>
GetFormattingRules
(
Document
document
);
...
...
@@ -57,11 +58,13 @@ public async Task<ExtractMethodResult> ExtractMethodAsync(CancellationToken canc
cancellationToken
.
ThrowIfCancellationRequested
();
var
expandedDocument
=
await
ExpandAsync
(
OriginalSelectionResult
.
With
(
triviaResult
.
SemanticDocument
),
cancellationToken
).
ConfigureAwait
(
false
);
var
options
=
await
analyzeResult
.
SemanticDocument
.
Document
.
GetOptionsAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
generatedCode
=
await
GenerateCodeAsync
(
insertionPoint
.
With
(
expandedDocument
),
OriginalSelectionResult
.
With
(
expandedDocument
),
analyzeResult
.
With
(
expandedDocument
),
options
,
cancellationToken
).
ConfigureAwait
(
false
);
var
applied
=
await
triviaResult
.
ApplyAsync
(
generatedCode
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -173,11 +176,16 @@ public async Task<ExtractMethodResult> ExtractMethodAsync(CancellationToken canc
return
Tuple
.
Create
(
true
,
status
);
}
internal
static
string
MakeMethodName
(
string
prefix
,
string
originalName
)
internal
static
string
MakeMethodName
(
string
prefix
,
string
originalName
,
bool
camelCase
)
{
var
startingWithLetter
=
originalName
.
ToCharArray
().
SkipWhile
(
c
=>
!
char
.
IsLetter
(
c
)).
ToArray
();
var
name
=
startingWithLetter
.
Length
==
0
?
originalName
:
new
string
(
startingWithLetter
);
if
(
camelCase
&&
!
prefix
.
IsEmpty
())
{
prefix
=
char
.
ToLowerInvariant
(
prefix
[
0
])
+
prefix
.
Substring
(
1
);
}
return
char
.
IsUpper
(
name
[
0
])
?
prefix
+
name
:
prefix
+
char
.
ToUpper
(
name
[
0
]).
ToString
()
+
name
.
Substring
(
1
);
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb
浏览文件 @
4278a17b
...
...
@@ -3,6 +3,7 @@
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
Imports
Microsoft.CodeAnalysis.Options
Imports
Microsoft.CodeAnalysis.VisualBasic
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
...
...
@@ -20,7 +21,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
code
.
SelectionInExpression
End
Function
Protected
Overrides
Function
CreateMethodName
(
localFunction
As
Boolean
)
As
SyntaxToken
Protected
Overrides
Function
CreateMethodName
()
As
SyntaxToken
Dim
methodName
=
"NewMethod"
Dim
containingScope
=
CType
(
VBSelectionResult
.
GetContainingScope
(),
SyntaxNode
)
...
...
@@ -47,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
End
If
Dim
name
=
identifierNode
.
Identifier
.
ValueText
Return
If
(
name
IsNot
Nothing
AndAlso
name
.
Length
>
0
,
MakeMethodName
(
"Get"
,
name
),
methodName
)
Return
If
(
name
IsNot
Nothing
AndAlso
name
.
Length
>
0
,
MakeMethodName
(
"Get"
,
name
,
camelCase
:
=
False
),
methodName
)
End
If
If
TypeOf
expression
Is
MemberAccessExpressionSyntax
Then
...
...
@@ -57,7 +58,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
If
TypeOf
expression
Is
NameSyntax
Then
Dim
lastDottedName
=
CType
(
expression
,
NameSyntax
).
GetLastDottedName
()
Dim
plainName
=
CType
(
lastDottedName
,
SimpleNameSyntax
).
Identifier
.
ValueText
Return
If
(
plainName
IsNot
Nothing
AndAlso
plainName
.
Length
>
0
,
MakeMethodName
(
"Get"
,
plainName
),
methodName
)
Return
If
(
plainName
IsNot
Nothing
AndAlso
plainName
.
Length
>
0
,
MakeMethodName
(
"Get"
,
plainName
,
camelCase
:
=
False
),
methodName
)
End
If
Return
methodName
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb
浏览文件 @
4278a17b
...
...
@@ -3,6 +3,7 @@
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
Imports
Microsoft.CodeAnalysis.Options
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace
Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
...
...
@@ -29,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
False
End
Function
Protected
Overrides
Function
CreateMethodName
(
localFunction
As
Boolean
)
As
SyntaxToken
Protected
Overrides
Function
CreateMethodName
()
As
SyntaxToken
' change this to more smarter one.
Dim
semanticModel
=
SemanticDocument
.
SemanticModel
Dim
nameGenerator
=
New
UniqueNameGenerator
(
semanticModel
)
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb
浏览文件 @
4278a17b
...
...
@@ -3,6 +3,7 @@
Imports
System.Threading
Imports
Microsoft.CodeAnalysis
Imports
Microsoft.CodeAnalysis.ExtractMethod
Imports
Microsoft.CodeAnalysis.Options
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace
Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
...
...
@@ -23,7 +24,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
firstStatement
Is
lastStatement
OrElse
firstStatement
.
Span
.
Contains
(
lastStatement
.
Span
)
End
Function
Protected
Overrides
Function
CreateMethodName
(
localFunction
As
Boolean
)
As
SyntaxToken
Protected
Overrides
Function
CreateMethodName
()
As
SyntaxToken
' change this to more smarter one.
Dim
semanticModel
=
CType
(
SemanticDocument
.
SemanticModel
,
SemanticModel
)
Dim
nameGenerator
=
New
UniqueNameGenerator
(
semanticModel
)
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb
浏览文件 @
4278a17b
...
...
@@ -45,7 +45,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
MyBase
.
New
(
insertionPoint
,
selectionResult
,
analyzerResult
)
Contract
.
ThrowIfFalse
(
Me
.
SemanticDocument
Is
selectionResult
.
SemanticDocument
)
Me
.
_methodName
=
CreateMethodName
(
localFunction
:
=
False
).
WithAdditionalAnnotations
(
MethodNameAnnotation
)
Me
.
_methodName
=
CreateMethodName
().
WithAdditionalAnnotations
(
MethodNameAnnotation
)
End
Sub
Private
ReadOnly
Property
VBSelectionResult
()
As
VisualBasicSelectionResult
...
...
src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb
浏览文件 @
4278a17b
...
...
@@ -63,7 +63,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return
Await
selection
.
SemanticDocument
.
WithSyntaxRootAsync
(
selection
.
SemanticDocument
.
Root
.
ReplaceNode
(
lastExpression
,
newStatement
),
cancellationToken
).
ConfigureAwait
(
False
)
End
Function
Protected
Overrides
Function
GenerateCodeAsync
(
insertionPoint
As
InsertionPoint
,
selectionResult
As
SelectionResult
,
analyzeResult
As
AnalyzerResult
,
cancellationToken
As
CancellationToken
)
As
Task
(
Of
GeneratedCode
)
Protected
Overrides
Function
GenerateCodeAsync
(
insertionPoint
As
InsertionPoint
,
selectionResult
As
SelectionResult
,
analyzeResult
As
AnalyzerResult
,
options
As
OptionSet
,
cancellationToken
As
CancellationToken
)
As
Task
(
Of
GeneratedCode
)
Return
VisualBasicCodeGenerator
.
GenerateResultAsync
(
insertionPoint
,
selectionResult
,
analyzeResult
,
cancellationToken
)
End
Function
...
...
src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs
浏览文件 @
4278a17b
...
...
@@ -113,6 +113,8 @@ protected override TDeclarationNode AddMethod<TDeclarationNode>(TDeclarationNode
{
CheckDeclarationNode
<
TypeDeclarationSyntax
,
CompilationUnitSyntax
,
NamespaceDeclarationSyntax
>(
destination
);
options
=
options
.
With
(
options
:
options
.
Options
??
Workspace
.
Options
);
// Synthesized methods for properties/events are not things we actually generate
// declarations for.
if
(
method
.
AssociatedSymbol
is
IEventSymbol
)
...
...
@@ -155,7 +157,7 @@ protected override TDeclarationNode AddMethod<TDeclarationNode>(TDeclarationNode
}
return
Cast
<
TDeclarationNode
>(
MethodGenerator
.
AddMethodTo
(
typeDeclaration
,
method
,
Workspace
,
options
,
availableIndices
));
typeDeclaration
,
method
,
options
,
availableIndices
));
}
if
(
method
.
IsConstructor
()
||
...
...
@@ -167,12 +169,12 @@ protected override TDeclarationNode AddMethod<TDeclarationNode>(TDeclarationNode
if
(
destination
is
CompilationUnitSyntax
compilationUnit
)
{
return
Cast
<
TDeclarationNode
>(
MethodGenerator
.
AddMethodTo
(
compilationUnit
,
method
,
Workspace
,
options
,
availableIndices
));
MethodGenerator
.
AddMethodTo
(
compilationUnit
,
method
,
options
,
availableIndices
));
}
var
ns
=
Cast
<
NamespaceDeclarationSyntax
>(
destination
);
return
Cast
<
TDeclarationNode
>(
MethodGenerator
.
AddMethodTo
(
ns
,
method
,
Workspace
,
options
,
availableIndices
));
MethodGenerator
.
AddMethodTo
(
ns
,
method
,
options
,
availableIndices
));
}
protected
override
TDeclarationNode
AddProperty
<
TDeclarationNode
>(
TDeclarationNode
destination
,
IPropertySymbol
property
,
CodeGenerationOptions
options
,
IList
<
bool
>
availableIndices
)
...
...
@@ -573,15 +575,18 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera
}
}
if
(
method
.
IsDestructor
())
{
return
DestructorGenerator
.
GenerateDestructorDeclaration
(
method
,
destination
,
options
);
}
options
=
options
.
With
(
options
:
options
.
Options
??
Workspace
.
Options
);
if
(
method
.
IsConstructor
())
{
return
ConstructorGenerator
.
GenerateConstructorDeclaration
(
method
,
destination
,
Workspace
,
options
,
options
.
ParseOptions
);
}
else
if
(
method
.
IsDestructor
())
{
return
DestructorGenerator
.
GenerateDestructorDeclaration
(
method
,
destination
,
options
);
}
else
if
(
method
.
IsUserDefinedOperator
())
{
return
OperatorGenerator
.
GenerateOperatorDeclaration
(
...
...
@@ -594,13 +599,13 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera
}
else
if
(
method
.
IsLocalFunction
())
{
return
MethodGenerator
.
GenerateLocal
Method
Declaration
(
method
,
destination
,
Workspace
,
options
,
options
.
ParseOptions
);
return
MethodGenerator
.
GenerateLocal
Function
Declaration
(
method
,
destination
,
options
,
options
.
ParseOptions
);
}
else
{
return
MethodGenerator
.
GenerateMethodDeclaration
(
method
,
destination
,
Workspace
,
options
,
options
.
ParseOptions
);
method
,
destination
,
options
,
options
.
ParseOptions
);
}
}
...
...
src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
浏览文件 @
4278a17b
...
...
@@ -18,12 +18,11 @@ internal static class MethodGenerator
internal
static
NamespaceDeclarationSyntax
AddMethodTo
(
NamespaceDeclarationSyntax
destination
,
IMethodSymbol
method
,
Workspace
workspace
,
CodeGenerationOptions
options
,
IList
<
bool
>
availableIndices
)
{
var
declaration
=
GenerateMethodDeclaration
(
method
,
CodeGenerationDestination
.
Namespace
,
workspace
,
options
,
method
,
CodeGenerationDestination
.
Namespace
,
options
,
destination
?.
SyntaxTree
.
Options
??
options
.
ParseOptions
);
var
members
=
Insert
(
destination
.
Members
,
declaration
,
options
,
availableIndices
,
after
:
LastMethod
);
return
destination
.
WithMembers
(
members
.
ToSyntaxList
());
...
...
@@ -32,12 +31,11 @@ internal static class MethodGenerator
internal
static
CompilationUnitSyntax
AddMethodTo
(
CompilationUnitSyntax
destination
,
IMethodSymbol
method
,
Workspace
workspace
,
CodeGenerationOptions
options
,
IList
<
bool
>
availableIndices
)
{
var
declaration
=
GenerateMethodDeclaration
(
method
,
CodeGenerationDestination
.
CompilationUnit
,
workspace
,
options
,
method
,
CodeGenerationDestination
.
CompilationUnit
,
options
,
destination
?.
SyntaxTree
.
Options
??
options
.
ParseOptions
);
var
members
=
Insert
(
destination
.
Members
,
declaration
,
options
,
availableIndices
,
after
:
LastMethod
);
return
destination
.
WithMembers
(
members
.
ToSyntaxList
());
...
...
@@ -46,12 +44,11 @@ internal static class MethodGenerator
internal
static
TypeDeclarationSyntax
AddMethodTo
(
TypeDeclarationSyntax
destination
,
IMethodSymbol
method
,
Workspace
workspace
,
CodeGenerationOptions
options
,
IList
<
bool
>
availableIndices
)
{
var
methodDeclaration
=
GenerateMethodDeclaration
(
method
,
GetDestination
(
destination
),
workspace
,
options
,
method
,
GetDestination
(
destination
),
options
,
destination
?.
SyntaxTree
.
Options
??
options
.
ParseOptions
);
// Create a clone of the original type with the new method inserted.
...
...
@@ -62,7 +59,7 @@ internal static class MethodGenerator
public
static
MethodDeclarationSyntax
GenerateMethodDeclaration
(
IMethodSymbol
method
,
CodeGenerationDestination
destination
,
Workspace
workspace
,
CodeGenerationOptions
options
,
CodeGenerationOptions
options
,
ParseOptions
parseOptions
)
{
options
??=
CodeGenerationOptions
.
Default
;
...
...
@@ -74,15 +71,15 @@ internal static class MethodGenerator
}
var
declaration
=
GenerateMethodDeclarationWorker
(
method
,
destination
,
workspace
,
options
,
parseOptions
);
method
,
destination
,
options
,
parseOptions
);
return
AddAnnotationsTo
(
method
,
ConditionallyAddDocumentationCommentTo
(
declaration
,
method
,
options
));
}
public
static
LocalFunctionStatementSyntax
GenerateLocal
Method
Declaration
(
public
static
LocalFunctionStatementSyntax
GenerateLocal
Function
Declaration
(
IMethodSymbol
method
,
CodeGenerationDestination
destination
,
Workspace
workspace
,
CodeGenerationOptions
options
,
CodeGenerationOptions
options
,
ParseOptions
parseOptions
)
{
options
??=
CodeGenerationOptions
.
Default
;
...
...
@@ -93,8 +90,8 @@ internal static class MethodGenerator
return
reusableSyntax
;
}
var
declaration
=
GenerateLocal
Method
DeclarationWorker
(
method
,
destination
,
workspace
,
options
,
parseOptions
);
var
declaration
=
GenerateLocal
Function
DeclarationWorker
(
method
,
destination
,
options
,
parseOptions
);
return
AddAnnotationsTo
(
method
,
ConditionallyAddDocumentationCommentTo
(
declaration
,
method
,
options
));
...
...
@@ -102,7 +99,7 @@ internal static class MethodGenerator
private
static
MethodDeclarationSyntax
GenerateMethodDeclarationWorker
(
IMethodSymbol
method
,
CodeGenerationDestination
destination
,
Workspace
workspace
,
CodeGenerationOptions
options
,
ParseOptions
parseOptions
)
CodeGenerationOptions
options
,
ParseOptions
parseOptions
)
{
// Don't rely on destination to decide if method body should be generated.
// Users of this service need to express their intention explicitly, either by
...
...
@@ -114,7 +111,7 @@ internal static class MethodGenerator
var
methodDeclaration
=
SyntaxFactory
.
MethodDeclaration
(
attributeLists
:
GenerateAttributes
(
method
,
options
,
explicitInterfaceSpecifier
!=
null
),
modifiers
:
GenerateModifiers
(
method
,
destination
,
workspace
,
options
,
localFunction
:
false
),
modifiers
:
GenerateModifiers
(
method
,
destination
,
options
),
returnType
:
method
.
GenerateReturnTypeSyntax
(),
explicitInterfaceSpecifier
:
explicitInterfaceSpecifier
,
identifier
:
method
.
Name
.
ToIdentifierToken
(),
...
...
@@ -125,16 +122,16 @@ internal static class MethodGenerator
expressionBody
:
default
,
semicolonToken
:
hasNoBody
?
SyntaxFactory
.
Token
(
SyntaxKind
.
SemicolonToken
)
:
default
);
methodDeclaration
=
UseExpressionBodyIfDesired
(
workspace
,
methodDeclaration
,
parseOptions
);
methodDeclaration
=
UseExpressionBodyIfDesired
(
options
,
methodDeclaration
,
parseOptions
);
return
AddFormatterAndCodeGeneratorAnnotationsTo
(
methodDeclaration
);
}
private
static
LocalFunctionStatementSyntax
GenerateLocal
Method
DeclarationWorker
(
private
static
LocalFunctionStatementSyntax
GenerateLocal
Function
DeclarationWorker
(
IMethodSymbol
method
,
CodeGenerationDestination
destination
,
Workspace
workspace
,
CodeGenerationOptions
options
,
ParseOptions
parseOptions
)
CodeGenerationOptions
options
,
ParseOptions
parseOptions
)
{
var
local
Method
Declaration
=
SyntaxFactory
.
LocalFunctionStatement
(
modifiers
:
GenerateModifiers
(
method
,
destination
,
workspace
,
options
,
localFunction
:
true
,
((
CSharpParseOptions
)
parseOptions
).
LanguageVersion
),
var
local
Function
Declaration
=
SyntaxFactory
.
LocalFunctionStatement
(
modifiers
:
GenerateModifiers
(
method
,
destination
,
options
),
returnType
:
method
.
GenerateReturnTypeSyntax
(),
identifier
:
method
.
Name
.
ToIdentifierToken
(),
typeParameterList
:
GenerateTypeParameterList
(
method
,
options
),
...
...
@@ -144,18 +141,18 @@ internal static class MethodGenerator
expressionBody
:
default
,
semicolonToken
:
default
);
local
MethodDeclaration
=
UseExpressionBodyIfDesired
(
workspace
,
localMethod
Declaration
,
parseOptions
);
return
AddFormatterAndCodeGeneratorAnnotationsTo
(
local
Method
Declaration
);
local
FunctionDeclaration
=
UseExpressionBodyIfDesired
(
options
,
localFunction
Declaration
,
parseOptions
);
return
AddFormatterAndCodeGeneratorAnnotationsTo
(
local
Function
Declaration
);
}
private
static
MethodDeclarationSyntax
UseExpressionBodyIfDesired
(
Workspace
workspace
,
MethodDeclarationSyntax
methodDeclaration
,
ParseOptions
o
ptions
)
CodeGenerationOptions
options
,
MethodDeclarationSyntax
methodDeclaration
,
ParseOptions
parseO
ptions
)
{
if
(
methodDeclaration
.
ExpressionBody
==
null
)
{
var
expressionBodyPreference
=
workspace
.
Options
.
GetOption
(
CSharpCodeStyleOptions
.
PreferExpressionBodiedMethods
).
Value
;
var
expressionBodyPreference
=
options
.
Options
.
GetOption
(
CSharpCodeStyleOptions
.
PreferExpressionBodiedMethods
).
Value
;
if
(
methodDeclaration
.
Body
.
TryConvertToArrowExpressionBody
(
methodDeclaration
.
Kind
(),
o
ptions
,
expressionBodyPreference
,
methodDeclaration
.
Kind
(),
parseO
ptions
,
expressionBodyPreference
,
out
var
expressionBody
,
out
var
semicolonToken
))
{
return
methodDeclaration
.
WithBody
(
null
)
...
...
@@ -168,22 +165,22 @@ internal static class MethodGenerator
}
private
static
LocalFunctionStatementSyntax
UseExpressionBodyIfDesired
(
Workspace
workspace
,
LocalFunctionStatementSyntax
localMethodDeclaration
,
ParseOptions
o
ptions
)
CodeGenerationOptions
options
,
LocalFunctionStatementSyntax
localFunctionDeclaration
,
ParseOptions
parseO
ptions
)
{
if
(
local
Method
Declaration
.
ExpressionBody
==
null
)
if
(
local
Function
Declaration
.
ExpressionBody
==
null
)
{
var
expressionBodyPreference
=
workspace
.
Options
.
GetOption
(
CSharpCodeStyleOptions
.
PreferExpressionBodiedLocalFunctions
).
Value
;
if
(
local
Method
Declaration
.
Body
.
TryConvertToArrowExpressionBody
(
local
MethodDeclaration
.
Kind
(),
o
ptions
,
expressionBodyPreference
,
var
expressionBodyPreference
=
options
.
Options
.
GetOption
(
CSharpCodeStyleOptions
.
PreferExpressionBodiedLocalFunctions
).
Value
;
if
(
local
Function
Declaration
.
Body
.
TryConvertToArrowExpressionBody
(
local
FunctionDeclaration
.
Kind
(),
parseO
ptions
,
expressionBodyPreference
,
out
var
expressionBody
,
out
var
semicolonToken
))
{
return
local
Method
Declaration
.
WithBody
(
null
)
return
local
Function
Declaration
.
WithBody
(
null
)
.
WithExpressionBody
(
expressionBody
)
.
WithSemicolonToken
(
semicolonToken
);
}
}
return
local
Method
Declaration
;
return
local
Function
Declaration
;
}
private
static
SyntaxList
<
AttributeListSyntax
>
GenerateAttributes
(
...
...
@@ -215,7 +212,7 @@ internal static class MethodGenerator
}
private
static
SyntaxTokenList
GenerateModifiers
(
IMethodSymbol
method
,
CodeGenerationDestination
destination
,
Workspace
workspace
,
CodeGenerationOptions
options
,
bool
localFunction
,
LanguageVersion
languageVersion
=
LanguageVersion
.
Latest
)
IMethodSymbol
method
,
CodeGenerationDestination
destination
,
CodeGenerationOptions
options
)
{
var
tokens
=
ArrayBuilder
<
SyntaxToken
>.
GetInstance
();
...
...
@@ -247,22 +244,9 @@ internal static class MethodGenerator
}
if
(
method
.
IsStatic
)
{
if
(
localFunction
)
{
var
preferStaticLocalFunction
=
workspace
.
Options
.
GetOption
(
CSharpCodeStyleOptions
.
PreferStaticLocalFunction
).
Value
;
// Static local functions are only supported in C# 8.0 and later.
if
(
preferStaticLocalFunction
&&
languageVersion
>=
LanguageVersion
.
CSharp8
)
{
tokens
.
Add
(
SyntaxFactory
.
Token
(
SyntaxKind
.
StaticKeyword
));
}
}
else
{
tokens
.
Add
(
SyntaxFactory
.
Token
(
SyntaxKind
.
StaticKeyword
));
}
}
// Don't show the readonly modifier if the containing type is already readonly
// ContainingSymbol is used to guard against methods which are not members of their ContainingType (e.g. lambdas and local functions)
...
...
src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOptions.cs
浏览文件 @
4278a17b
...
...
@@ -3,6 +3,7 @@
using
System
;
using
System.Collections.Generic
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.Simplification
;
using
Roslyn.Utilities
;
...
...
@@ -132,6 +133,8 @@ internal class CodeGenerationOptions
/// </summary>
public
bool
ReuseSyntax
{
get
;
}
public
OptionSet
Options
{
get
;
}
public
ParseOptions
ParseOptions
{
get
;
}
public
CodeGenerationOptions
(
...
...
@@ -150,6 +153,7 @@ internal class CodeGenerationOptions
bool
autoInsertionLocation
=
true
,
bool
sortMembers
=
true
,
bool
reuseSyntax
=
false
,
OptionSet
options
=
null
,
ParseOptions
parseOptions
=
null
)
{
CheckLocation
(
contextLocation
,
nameof
(
contextLocation
));
...
...
@@ -172,6 +176,7 @@ internal class CodeGenerationOptions
this
.
SortMembers
=
sortMembers
;
this
.
ReuseSyntax
=
reuseSyntax
;
this
.
Options
=
options
;
this
.
ParseOptions
=
parseOptions
??
this
.
BestLocation
?.
SourceTree
.
Options
;
}
...
...
@@ -211,6 +216,7 @@ internal Location BestLocation
Optional
<
bool
>
autoInsertionLocation
=
default
,
Optional
<
bool
>
sortMembers
=
default
,
Optional
<
bool
>
reuseSyntax
=
default
,
Optional
<
OptionSet
>
options
=
default
,
Optional
<
ParseOptions
>
parseOptions
=
default
)
{
var
newContextLocation
=
contextLocation
.
HasValue
?
contextLocation
.
Value
:
this
.
ContextLocation
;
...
...
@@ -228,6 +234,7 @@ internal Location BestLocation
var
newAutoInsertionLocation
=
autoInsertionLocation
.
HasValue
?
autoInsertionLocation
.
Value
:
this
.
AutoInsertionLocation
;
var
newSortMembers
=
sortMembers
.
HasValue
?
sortMembers
.
Value
:
this
.
SortMembers
;
var
newReuseSyntax
=
reuseSyntax
.
HasValue
?
reuseSyntax
.
Value
:
this
.
ReuseSyntax
;
var
newOptions
=
options
.
HasValue
?
options
.
Value
:
this
.
Options
;
var
newParseOptions
=
parseOptions
.
HasValue
?
parseOptions
.
Value
:
this
.
ParseOptions
;
return
new
CodeGenerationOptions
(
...
...
@@ -246,6 +253,7 @@ internal Location BestLocation
newAutoInsertionLocation
,
newSortMembers
,
newReuseSyntax
,
newOptions
,
newParseOptions
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录