Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
28dc5966
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,发现更多精彩内容 >>
提交
28dc5966
编写于
4月 19, 2017
作者:
C
CyrusNajmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix issue with definite-assignment checking in 'inline-decl' with 'var-typed' locals.
上级
6744226e
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
69 addition
and
14 deletion
+69
-14
src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs
...arpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs
+38
-0
src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs
...eDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs
+31
-14
未找到文件。
src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs
浏览文件 @
28dc5966
...
...
@@ -1967,6 +1967,44 @@ void M()
Console.WriteLine(_);
}
}
}"
);
}
[
WorkItem
(
18668
,
"https://github.com/dotnet/roslyn/issues/18668"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInlineDeclaration
)]
public
async
Task
TestDefiniteAssignmentIssueWithVar
()
{
await
TestMissingInRegularAndScriptAsync
(
@"
using System;
class C
{
static void M(bool condition)
{
[|var|] x = 1;
var result = condition && int.TryParse(""2"", out x);
Console.WriteLine(x);
}
}"
);
}
[
WorkItem
(
18668
,
"https://github.com/dotnet/roslyn/issues/18668"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInlineDeclaration
)]
public
async
Task
TestDefiniteAssignmentIssueWithNonVar
()
{
await
TestMissingInRegularAndScriptAsync
(
@"
using System;
class C
{
static void M(bool condition)
{
[|int|] x = 1;
var result = condition && int.TryParse(""2"", out x);
Console.WriteLine(x);
}
}"
);
}
}
...
...
src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs
浏览文件 @
28dc5966
...
...
@@ -127,8 +127,8 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
}
var
semanticModel
=
context
.
SemanticModel
;
var
out
Symbol
=
semanticModel
.
GetSymbolInfo
(
argumentExpression
,
cancellationToken
).
Symbol
;
if
(
out
Symbol
?.
Kind
!=
SymbolKind
.
Loca
l
)
var
out
LocalSymbol
=
semanticModel
.
GetSymbolInfo
(
argumentExpression
,
cancellationToken
).
Symbol
as
ILocal
Symbol
;
if
(
out
LocalSymbol
==
nul
l
)
{
// The out-argument wasn't referencing a local. So we don't have an local
// declaration that we can attempt to inline here.
...
...
@@ -139,7 +139,7 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
// Trying to do things like inline a var-decl in a for-statement is just too
// esoteric and would make us have to write a lot more complex code to support
// that scenario.
var
localReference
=
outSymbol
.
DeclaringSyntaxReferences
.
FirstOrDefault
();
var
localReference
=
out
Local
Symbol
.
DeclaringSyntaxReferences
.
FirstOrDefault
();
var
localDeclarator
=
localReference
?.
GetSyntax
(
cancellationToken
)
as
VariableDeclaratorSyntax
;
if
(
localDeclarator
==
null
)
{
...
...
@@ -196,7 +196,7 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
// Make sure that variable is not accessed outside of that scope.
var
dataFlow
=
semanticModel
.
AnalyzeDataFlow
(
outArgumentScope
);
if
(
dataFlow
.
ReadOutside
.
Contains
(
out
Symbol
)
||
dataFlow
.
WrittenOutside
.
Contains
(
out
Symbol
))
if
(
dataFlow
.
ReadOutside
.
Contains
(
out
LocalSymbol
)
||
dataFlow
.
WrittenOutside
.
Contains
(
outLocal
Symbol
))
{
// The variable is read or written from outside the block that the new variable
// would be scoped in. This would cause a break.
...
...
@@ -207,7 +207,7 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
}
// Make sure the variable isn't ever accessed before the usage in this out-var.
if
(
IsAccessed
(
semanticModel
,
outSymbol
,
enclosingBlockOfLocalStatement
,
if
(
IsAccessed
(
semanticModel
,
out
Local
Symbol
,
enclosingBlockOfLocalStatement
,
localStatement
,
argumentNode
,
cancellationToken
))
{
return
;
...
...
@@ -216,8 +216,8 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
// See if inlining this variable would make it so that some variables were no
// longer definitely assigned.
if
(
WouldCauseDefiniteAssignmentErrors
(
semanticModel
,
localDeclarat
or
,
enclosingBlockOfLocalStatement
,
out
Symbol
,
cancellationToken
))
semanticModel
,
localDeclarat
ion
,
localDeclarator
,
enclosingBlockOfLocalStatement
,
outLocal
Symbol
,
cancellationToken
))
{
return
;
}
...
...
@@ -243,8 +243,12 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
}
private
bool
WouldCauseDefiniteAssignmentErrors
(
SemanticModel
semanticModel
,
VariableDeclaratorSyntax
localDeclarator
,
BlockSyntax
enclosingBlock
,
ISymbol
outSymbol
,
CancellationToken
cancellationToken
)
SemanticModel
semanticModel
,
VariableDeclarationSyntax
localDeclaration
,
VariableDeclaratorSyntax
localDeclarator
,
BlockSyntax
enclosingBlock
,
ILocalSymbol
outLocalSymbol
,
CancellationToken
cancellationToken
)
{
// See if we have something like:
//
...
...
@@ -260,12 +264,12 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
// Find all the current read-references to the local.
var
query
=
from
t
in
enclosingBlock
.
DescendantTokens
()
where
t
.
Kind
()
==
SyntaxKind
.
IdentifierToken
where
t
.
ValueText
==
outSymbol
.
Name
where
t
.
ValueText
==
out
Local
Symbol
.
Name
let
id
=
t
.
Parent
as
IdentifierNameSyntax
where
id
!=
null
where
!
id
.
IsOnlyWrittenTo
()
let
symbol
=
semanticModel
.
GetSymbolInfo
(
id
).
GetAnySymbol
()
where
outSymbol
.
Equals
(
symbol
)
where
out
Local
Symbol
.
Equals
(
symbol
)
select
id
;
var
references
=
query
.
ToImmutableArray
<
SyntaxNode
>();
...
...
@@ -274,16 +278,29 @@ where outSymbol.Equals(symbol)
// Ensure we can track the references and the local variable as we make edits
// to the tree.
var
rootWithTrackedNodes
=
root
.
TrackNodes
(
references
.
Concat
(
localDeclarator
).
Concat
(
enclosingBlock
));
var
rootWithTrackedNodes
=
root
.
TrackNodes
(
references
.
Concat
(
ImmutableArray
.
Create
<
SyntaxNode
>(
localDeclarator
,
localDeclaration
,
enclosingBlock
)));
// Now, take the local variable and remove it's initializer. Then go to all
// the locations where we read from it. If they're definitely assigned, then
// that means the out-var did it's work and assigned the variable across all
// paths. If it's not definitely assigned, then we can't inline this variable.
var
currentLocalDeclarator
=
rootWithTrackedNodes
.
GetCurrentNode
(
localDeclarator
);
var
currentLocalDeclaration
=
rootWithTrackedNodes
.
GetCurrentNode
(
localDeclaration
);
var
updatedDeclaration
=
currentLocalDeclaration
.
ReplaceNode
(
currentLocalDeclarator
,
currentLocalDeclarator
.
WithInitializer
(
null
));
// If the declaration was a "var" declaration, then replace "var" with the actual
// type of the local. This way we don't get a "'var v' requires an initializer" which
// will suppress the message about definite assignment later.
if
(
updatedDeclaration
.
Type
.
IsVar
)
{
updatedDeclaration
=
updatedDeclaration
.
WithType
(
outLocalSymbol
.
Type
.
GenerateTypeSyntax
());
}
var
rootWithoutInitializer
=
rootWithTrackedNodes
.
ReplaceNode
(
currentLocalDeclarator
,
currentLocalDeclarator
.
WithInitializer
(
null
));
currentLocalDeclaration
,
updatedDeclaration
);
var
rootWithoutInitializerTree
=
root
.
SyntaxTree
.
WithRootAndOptions
(
rootWithoutInitializer
,
root
.
SyntaxTree
.
Options
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录