Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
a2de1326
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,发现更多精彩内容 >>
提交
a2de1326
编写于
5月 04, 2017
作者:
I
Ivan Basov
提交者:
GitHub
5月 04, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
support of C# 7.0 foreach in ENC (#19114)
上级
37c5398d
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
760 addition
and
48 deletion
+760
-48
src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs
...rp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs
+224
-0
src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs
...p/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs
+86
-0
src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
...atures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
+370
-13
src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
...Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
+70
-25
src/Features/CSharp/Portable/EditAndContinue/StatementSyntaxComparer.cs
...Sharp/Portable/EditAndContinue/StatementSyntaxComparer.cs
+1
-1
src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
...rtable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
+5
-5
src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb
...ble/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb
+4
-4
未找到文件。
src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs
浏览文件 @
a2de1326
...
...
@@ -7851,6 +7851,230 @@ .maxstack 2
IL_0012: ldloc.s V_6
IL_0014: ret
}
"
);
}
[
Fact
]
public
void
ForeachStatement
()
{
var
source0
=
MarkedSource
(
@"
class C
{
public static (int, (bool, double))[] F() => new[] { (1, (true, 2.0)) };
public static void G()
{
foreach (var (<N:0>x</N:0>, (<N:1>y</N:1>, <N:2>z</N:2>)) in F())
{
System.Console.WriteLine(x);
}
}
}"
);
var
source1
=
MarkedSource
(
@"
class C
{
public static (int, (bool, double))[] F() => new[] { (1, (true, 2.0)) };
public static void G()
{
foreach (var (<N:0>x1</N:0>, (<N:1>y</N:1>, <N:2>z</N:2>)) in F())
{
System.Console.WriteLine(x1);
}
}
}"
);
var
source2
=
MarkedSource
(
@"
class C
{
public static (int, (bool, double))[] F() => new[] { (1, (true, 2.0)) };
public static void G()
{
foreach (var (<N:0>x1</N:0>, <N:1>yz</N:1>) in F())
{
System.Console.WriteLine(x1);
}
}
}"
);
var
compilation0
=
CreateStandardCompilation
(
source0
.
Tree
,
options
:
ComSafeDebugDll
,
references
:
s_valueTupleRefs
);
var
compilation1
=
compilation0
.
WithSource
(
source1
.
Tree
);
var
compilation2
=
compilation1
.
WithSource
(
source2
.
Tree
);
var
f0
=
compilation0
.
GetMember
<
MethodSymbol
>(
"C.G"
);
var
f1
=
compilation1
.
GetMember
<
MethodSymbol
>(
"C.G"
);
var
f2
=
compilation2
.
GetMember
<
MethodSymbol
>(
"C.G"
);
var
v0
=
CompileAndVerify
(
compilation0
);
v0
.
VerifyIL
(
"C.G"
,
@"
{
// Code size 72 (0x48)
.maxstack 2
.locals init ((int, (bool, double))[] V_0,
int V_1,
int V_2, //x
bool V_3, //y
double V_4, //z
System.ValueTuple<bool, double> V_5)
IL_0000: nop
IL_0001: nop
IL_0002: call ""(int, (bool, double))[] C.F()""
IL_0007: stloc.0
IL_0008: ldc.i4.0
IL_0009: stloc.1
IL_000a: br.s IL_0041
IL_000c: ldloc.0
IL_000d: ldloc.1
IL_000e: ldelem ""System.ValueTuple<int, (bool, double)>""
IL_0013: dup
IL_0014: ldfld ""(bool, double) System.ValueTuple<int, (bool, double)>.Item2""
IL_0019: stloc.s V_5
IL_001b: dup
IL_001c: ldfld ""int System.ValueTuple<int, (bool, double)>.Item1""
IL_0021: stloc.2
IL_0022: ldloc.s V_5
IL_0024: ldfld ""bool System.ValueTuple<bool, double>.Item1""
IL_0029: stloc.3
IL_002a: ldloc.s V_5
IL_002c: ldfld ""double System.ValueTuple<bool, double>.Item2""
IL_0031: stloc.s V_4
IL_0033: pop
IL_0034: nop
IL_0035: ldloc.2
IL_0036: call ""void System.Console.WriteLine(int)""
IL_003b: nop
IL_003c: nop
IL_003d: ldloc.1
IL_003e: ldc.i4.1
IL_003f: add
IL_0040: stloc.1
IL_0041: ldloc.1
IL_0042: ldloc.0
IL_0043: ldlen
IL_0044: conv.i4
IL_0045: blt.s IL_000c
IL_0047: ret
}
"
);
var
md0
=
ModuleMetadata
.
CreateFromImage
(
v0
.
EmittedAssemblyData
);
var
generation0
=
EmitBaseline
.
CreateInitialBaseline
(
md0
,
v0
.
CreateSymReader
().
GetEncMethodDebugInfo
);
var
diff1
=
compilation1
.
EmitDifference
(
generation0
,
ImmutableArray
.
Create
(
new
SemanticEdit
(
SemanticEditKind
.
Update
,
f0
,
f1
,
GetSyntaxMapFromMarkers
(
source0
,
source1
),
preserveLocalVariables
:
true
)));
diff1
.
VerifyIL
(
"C.G"
,
@"
{
// Code size 80 (0x50)
.maxstack 2
.locals init ([unchanged] V_0,
[int] V_1,
int V_2, //x1
bool V_3, //y
double V_4, //z
[unchanged] V_5,
(int, (bool, double))[] V_6,
int V_7,
System.ValueTuple<bool, double> V_8)
IL_0000: nop
IL_0001: nop
IL_0002: call ""(int, (bool, double))[] C.F()""
IL_0007: stloc.s V_6
IL_0009: ldc.i4.0
IL_000a: stloc.s V_7
IL_000c: br.s IL_0047
IL_000e: ldloc.s V_6
IL_0010: ldloc.s V_7
IL_0012: ldelem ""System.ValueTuple<int, (bool, double)>""
IL_0017: dup
IL_0018: ldfld ""(bool, double) System.ValueTuple<int, (bool, double)>.Item2""
IL_001d: stloc.s V_8
IL_001f: dup
IL_0020: ldfld ""int System.ValueTuple<int, (bool, double)>.Item1""
IL_0025: stloc.2
IL_0026: ldloc.s V_8
IL_0028: ldfld ""bool System.ValueTuple<bool, double>.Item1""
IL_002d: stloc.3
IL_002e: ldloc.s V_8
IL_0030: ldfld ""double System.ValueTuple<bool, double>.Item2""
IL_0035: stloc.s V_4
IL_0037: pop
IL_0038: nop
IL_0039: ldloc.2
IL_003a: call ""void System.Console.WriteLine(int)""
IL_003f: nop
IL_0040: nop
IL_0041: ldloc.s V_7
IL_0043: ldc.i4.1
IL_0044: add
IL_0045: stloc.s V_7
IL_0047: ldloc.s V_7
IL_0049: ldloc.s V_6
IL_004b: ldlen
IL_004c: conv.i4
IL_004d: blt.s IL_000e
IL_004f: ret
}
"
);
var
diff2
=
compilation2
.
EmitDifference
(
diff1
.
NextGeneration
,
ImmutableArray
.
Create
(
new
SemanticEdit
(
SemanticEditKind
.
Update
,
f1
,
f2
,
GetSyntaxMapFromMarkers
(
source1
,
source2
),
preserveLocalVariables
:
true
)));
diff2
.
VerifyIL
(
"C.G"
,
@"
{
// Code size 66 (0x42)
.maxstack 2
.locals init ([unchanged] V_0,
[int] V_1,
int V_2, //x1
[bool] V_3,
[unchanged] V_4,
[unchanged] V_5,
[unchanged] V_6,
[int] V_7,
[unchanged] V_8,
(int, (bool, double))[] V_9,
int V_10,
System.ValueTuple<bool, double> V_11, //yz
System.ValueTuple<int, (bool, double)> V_12)
IL_0000: nop
IL_0001: nop
IL_0002: call ""(int, (bool, double))[] C.F()""
IL_0007: stloc.s V_9
IL_0009: ldc.i4.0
IL_000a: stloc.s V_10
IL_000c: br.s IL_0039
IL_000e: ldloc.s V_9
IL_0010: ldloc.s V_10
IL_0012: ldelem ""System.ValueTuple<int, (bool, double)>""
IL_0017: stloc.s V_12
IL_0019: ldloc.s V_12
IL_001b: ldfld ""int System.ValueTuple<int, (bool, double)>.Item1""
IL_0020: stloc.2
IL_0021: ldloc.s V_12
IL_0023: ldfld ""(bool, double) System.ValueTuple<int, (bool, double)>.Item2""
IL_0028: stloc.s V_11
IL_002a: nop
IL_002b: ldloc.2
IL_002c: call ""void System.Console.WriteLine(int)""
IL_0031: nop
IL_0032: nop
IL_0033: ldloc.s V_10
IL_0035: ldc.i4.1
IL_0036: add
IL_0037: stloc.s V_10
IL_0039: ldloc.s V_10
IL_003b: ldloc.s V_9
IL_003d: ldlen
IL_003e: conv.i4
IL_003f: blt.s IL_000e
IL_0041: ret
}
"
);
}
}
...
...
src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs
浏览文件 @
a2de1326
...
...
@@ -3433,6 +3433,92 @@ .maxstack 2
-IL_0025: ldloc.2
IL_0026: ret
}
"
,
methodToken
:
diff1
.
UpdatedMethods
.
Single
());
}
[
Fact
]
public
void
ForEachStatement_Deconstruction
()
{
var
source
=
@"
class C
{
public static (int, (bool, double))[] F() => new[] { (1, (true, 2.0)) };
public static void G()
{
foreach (var (x, (y, z)) in F())
{
System.Console.WriteLine(x);
}
}
}"
;
var
compilation0
=
CreateStandardCompilation
(
source
,
options
:
TestOptions
.
DebugDll
,
references
:
s_valueTupleRefs
);
var
compilation1
=
compilation0
.
WithSource
(
source
);
var
testData0
=
new
CompilationTestData
();
var
bytes0
=
compilation0
.
EmitToArray
(
testData
:
testData0
);
var
methodData0
=
testData0
.
GetMethodData
(
"C.G"
);
var
method0
=
compilation0
.
GetMember
<
MethodSymbol
>(
"C.G"
);
var
generation0
=
EmitBaseline
.
CreateInitialBaseline
(
ModuleMetadata
.
CreateFromImage
(
bytes0
),
methodData0
.
EncDebugInfoProvider
());
var
method1
=
compilation1
.
GetMember
<
MethodSymbol
>(
"C.G"
);
var
diff1
=
compilation1
.
EmitDifference
(
generation0
,
ImmutableArray
.
Create
(
new
SemanticEdit
(
SemanticEditKind
.
Update
,
method0
,
method1
,
GetEquivalentNodesMap
(
method1
,
method0
),
preserveLocalVariables
:
true
)));
diff1
.
VerifyIL
(
"C.G"
,
@"
{
// Code size 80 (0x50)
.maxstack 2
.locals init ([unchanged] V_0,
[int] V_1,
int V_2, //x
bool V_3, //y
double V_4, //z
[unchanged] V_5,
(int, (bool, double))[] V_6,
int V_7,
System.ValueTuple<bool, double> V_8)
-IL_0000: nop
-IL_0001: nop
-IL_0002: call ""(int, (bool, double))[] C.F()""
IL_0007: stloc.s V_6
IL_0009: ldc.i4.0
IL_000a: stloc.s V_7
~IL_000c: br.s IL_0047
-IL_000e: ldloc.s V_6
IL_0010: ldloc.s V_7
IL_0012: ldelem ""System.ValueTuple<int, (bool, double)>""
IL_0017: dup
IL_0018: ldfld ""(bool, double) System.ValueTuple<int, (bool, double)>.Item2""
IL_001d: stloc.s V_8
IL_001f: dup
IL_0020: ldfld ""int System.ValueTuple<int, (bool, double)>.Item1""
IL_0025: stloc.2
IL_0026: ldloc.s V_8
IL_0028: ldfld ""bool System.ValueTuple<bool, double>.Item1""
IL_002d: stloc.3
IL_002e: ldloc.s V_8
IL_0030: ldfld ""double System.ValueTuple<bool, double>.Item2""
IL_0035: stloc.s V_4
IL_0037: pop
-IL_0038: nop
-IL_0039: ldloc.2
IL_003a: call ""void System.Console.WriteLine(int)""
IL_003f: nop
-IL_0040: nop
~IL_0041: ldloc.s V_7
IL_0043: ldc.i4.1
IL_0044: add
IL_0045: stloc.s V_7
-IL_0047: ldloc.s V_7
IL_0049: ldloc.s V_6
IL_004b: ldlen
IL_004c: conv.i4
IL_004d: blt.s IL_000e
-IL_004f: ret
}
"
,
methodToken
:
diff1
.
UpdatedMethods
.
Single
());
}
}
...
...
src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
浏览文件 @
a2de1326
...
...
@@ -3184,6 +3184,41 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariableBody_Update_ExpressionActive
()
{
string
src1
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
foreach ((string s, int i) in <AS:1>F()</AS:1>)
{
System.Console.Write(0);
}
}
}"
;
string
src2
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
foreach ((string s, int i) in <AS:1>F()</AS:1>)
{
System.Console.Write(1);
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachBody_Update_InKeywordActive
()
{
...
...
@@ -3219,6 +3254,41 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariableBody_Update_InKeywordActive
()
{
string
src1
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
foreach ((string s, int i) <AS:1>in</AS:1> F())
{
System.Console.Write(0);
}
}
}"
;
string
src2
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
foreach ((string s, int i) <AS:1>in</AS:1> F())
{
System.Console.Write(1);
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachBody_Update_VariableActive
()
{
...
...
@@ -3254,6 +3324,41 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariableBody_Update_VariableActive
()
{
string
src1
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
foreach (<AS:1>(string s, int i)</AS:1> in F())
{
System.Console.Write(0);
}
}
}"
;
string
src2
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
foreach (<AS:1>(string s, int i)</AS:1> in F())
{
System.Console.Write(1);
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachBody_Update_ForeachKeywordActive
()
{
...
...
@@ -3289,6 +3394,41 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariableBody_Update_ForeachKeywordActive
()
{
string
src1
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
<AS:1>foreach</AS:1> ((string s, int i) in F())
{
System.Console.Write(0);
}
}
}"
;
string
src2
=
@"
class Test
{
private static (string, int) F() { <AS:0>return null;</AS:0> }
static void Main(string[] args)
{
<AS:1>foreach</AS:1> ((string s, int i) in F())
{
System.Console.Write(1);
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariable_Update
()
{
...
...
@@ -3328,7 +3468,44 @@ static void Main(string[] args)
}
[
Fact
]
public
void
ForEach_Reorder_Leaf1
()
public
void
ForEachDeconstructionVariable_Update
()
{
string
src1
=
@"
class Test
{
private static (int, (bool, double))[] F() { <AS:0>return new[] { (1, (true, 2.0)) };</AS:0> }
static void Main(string[] args)
{
foreach (<AS:1>(int i, (bool b, double d))</AS:1> in F())
{
System.Console.Write(0);
}
}
}"
;
string
src2
=
@"
class Test
{
private static (int, (bool, double))[] F() { <AS:0>return new[] { (1, (true, 2.0)) };</AS:0> }
static void Main(string[] args)
{
foreach (<AS:1>(int i, (var b, double d))</AS:1> in F())
{
System.Console.Write(1);
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
ActiveStatementUpdate
,
"(int i, (var b, double d))"
),
Diagnostic
(
RudeEditKind
.
UpdateAroundActiveStatement
,
"foreach ( (int i, (var b, double d)) in F())"
,
CSharpFeaturesResources
.
foreach_statement
));
}
[
Fact
]
public
void
ForEach_Reorder_Leaf
()
{
string
src1
=
@"
class Test
...
...
@@ -3377,19 +3554,19 @@ static void Main(string[] args)
}
[
Fact
]
public
void
ForEach
_Update_Leaf1
()
public
void
ForEach
Variable_Reorder_Leaf
()
{
string
src1
=
@"
class Test
{
public static
int[] e1 = new int
[1];
public static
int[] e2 = new int
[1];
public static
(int, bool)[] e1 = new (int, bool)
[1];
public static
(int, bool)[] e2 = new (int, bool)
[1];
static void Main(string[] args)
{
foreach (
var a
in e1)
foreach (
(var a1, var a2)
in e1)
{
foreach (
var b
in e1)
foreach (
(int b1, bool b2)
in e1)
{
foreach (var c in e1)
{
...
...
@@ -3402,16 +3579,16 @@ static void Main(string[] args)
string
src2
=
@"
class Test
{
public static
int[] e1 = new int
[1];
public static
int[] e2 = new int
[1];
public static
(int, bool)[] e1 = new (int, bool)
[1];
public static
(int, bool)[] e2 = new (int, bool)
[1];
static void Main(string[] args)
{
foreach (
var b
in e1)
foreach (
(int b1, bool b2)
in e1)
{
foreach (var c in e1)
{
foreach (
var a
in e1)
foreach (
(var a1, var a2)
in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
...
...
@@ -3426,7 +3603,7 @@ static void Main(string[] args)
}
[
Fact
]
public
void
ForEach_Update_Leaf
2
()
public
void
ForEach_Update_Leaf
()
{
string
src1
=
@"
class Test
...
...
@@ -3468,6 +3645,49 @@ static void Main(string[] args)
Diagnostic
(
RudeEditKind
.
InsertAroundActiveStatement
,
"foreach (var a in e1)"
,
CSharpFeaturesResources
.
foreach_statement
));
}
[
Fact
]
public
void
ForEachVariable_Update_Leaf
()
{
string
src1
=
@"
class Test
{
public static (int, bool)[] e1 = new (int, bool)[1];
public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
<AS:0>System.Console.Write();</AS:0>
}
}"
;
string
src2
=
@"
class Test
{
public static (int, bool)[] e1 = new (int, bool)[1];
public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
foreach ((var a1, var a2) in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
InsertAroundActiveStatement
,
"foreach (var c in e1)"
,
CSharpFeaturesResources
.
foreach_statement
),
Diagnostic
(
RudeEditKind
.
InsertAroundActiveStatement
,
"foreach ((int b1, bool b2) in e1)"
,
CSharpFeaturesResources
.
foreach_statement
),
Diagnostic
(
RudeEditKind
.
InsertAroundActiveStatement
,
"foreach ((var a1, var a2) in e1)"
,
CSharpFeaturesResources
.
foreach_statement
));
}
[
Fact
]
public
void
ForEach_Delete_Leaf1
()
{
...
...
@@ -3514,6 +3734,52 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariable_Delete_Leaf1
()
{
string
src1
=
@"
class Test
{
public static (int, bool)[] e1 = new (int, bool)[1];
public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
foreach ((var a1, var a2) in e1)
{
foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}
}"
;
string
src2
=
@"
class Test
{
public static (int, bool)[] e1 = new (int, bool)[1];
public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
foreach ((var a1, var a2) in e1)
{
foreach ((int b1, bool b2) in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEach_Delete_Leaf2
()
{
...
...
@@ -3560,6 +3826,52 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariable_Delete_Leaf2
()
{
string
src1
=
@"
class Test
{
public static (int, bool)[] e1 = new (int, bool)[1];
public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
foreach ((var a1, var a2) in e1)
{
foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}
}"
;
string
src2
=
@"
class Test
{
public static (int, bool)[] e1 = new (int, bool)[1];
public static (int, bool)[] e2 = new (int, bool)[1];
static void Main(string[] args)
{
foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEach_Delete_Leaf3
()
{
...
...
@@ -3606,6 +3918,52 @@ static void Main(string[] args)
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEachVariable_Delete_Leaf3
()
{
string
src1
=
@"
class Test
{
public static int[] e1 = new int[1];
public static int[] e2 = new int[1];
static void Main(string[] args)
{
foreach ((var a1, var a2) in e1)
{
foreach ((int b1, bool b2) in e1)
{
foreach (var c in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}
}"
;
string
src2
=
@"
class Test
{
public static int[] e1 = new int[1];
public static int[] e2 = new int[1];
static void Main(string[] args)
{
foreach ((var a1, var a2) in e1)
{
foreach (var c in e1)
{
<AS:0>System.Console.Write();</AS:0>
}
}
}
}"
;
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
public
void
ForEach_Lambda1
()
{
...
...
@@ -8182,8 +8540,7 @@ static void F(object o)
var
edits
=
GetTopEdits
(
src1
,
src2
);
var
active
=
GetActiveStatements
(
src1
,
src2
);
edits
.
VerifyRudeDiagnostics
(
active
,
Diagnostic
(
RudeEditKind
.
UpdateAroundActiveStatement
,
"var (x, y)"
,
CSharpFeaturesResources
.
deconstruction
));
edits
.
VerifyRudeDiagnostics
(
active
);
}
[
Fact
]
...
...
src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs
浏览文件 @
a2de1326
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Composition
;
...
...
@@ -306,7 +305,8 @@ protected override SyntaxNode FindStatementAndPartner(SyntaxNode declarationBody
break
;
case
SyntaxKind
.
ForEachStatement
:
statementPart
=
(
int
)
GetStatementPart
((
ForEachStatementSyntax
)
node
,
position
);
case
SyntaxKind
.
ForEachVariableStatement
:
statementPart
=
(
int
)
GetStatementPart
((
CommonForEachStatementSyntax
)
node
,
position
);
break
;
case
SyntaxKind
.
VariableDeclaration
:
...
...
@@ -352,7 +352,7 @@ private static TextSpan GetActiveSpan(BlockSyntax node, BlockPart part)
}
}
private
static
ForEachPart
GetStatementPart
(
ForEachStatementSyntax
node
,
int
position
)
private
static
ForEachPart
GetStatementPart
(
Common
ForEachStatementSyntax
node
,
int
position
)
{
return
position
<
node
.
OpenParenToken
.
SpanStart
?
ForEachPart
.
ForEach
:
position
<
node
.
InKeyword
.
SpanStart
?
ForEachPart
.
VariableDeclaration
:
...
...
@@ -381,6 +381,27 @@ private static TextSpan GetActiveSpan(ForEachStatementSyntax node, ForEachPart p
}
}
private
static
TextSpan
GetActiveSpan
(
ForEachVariableStatementSyntax
node
,
ForEachPart
part
)
{
switch
(
part
)
{
case
ForEachPart
.
ForEach
:
return
node
.
ForEachKeyword
.
Span
;
case
ForEachPart
.
VariableDeclaration
:
return
TextSpan
.
FromBounds
(
node
.
Variable
.
SpanStart
,
node
.
Variable
.
Span
.
End
);
case
ForEachPart
.
In
:
return
node
.
InKeyword
.
Span
;
case
ForEachPart
.
Expression
:
return
node
.
Expression
.
Span
;
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
part
);
}
}
protected
override
bool
AreEquivalent
(
SyntaxNode
left
,
SyntaxNode
right
)
{
return
SyntaxFactory
.
AreEquivalent
(
left
,
right
);
...
...
@@ -601,6 +622,10 @@ protected override bool TryGetActiveSpan(SyntaxNode node, int statementPart, out
span
=
GetActiveSpan
((
ForEachStatementSyntax
)
node
,
(
ForEachPart
)
statementPart
);
return
true
;
case
SyntaxKind
.
ForEachVariableStatement
:
span
=
GetActiveSpan
((
ForEachVariableStatementSyntax
)
node
,
(
ForEachPart
)
statementPart
);
return
true
;
case
SyntaxKind
.
DoStatement
:
// The active statement of DoStatement node is the while condition,
// which is lexically not the closest breakpoint span (the body is).
...
...
@@ -732,10 +757,11 @@ protected override bool AreEquivalentActiveStatements(SyntaxNode oldStatement, S
return
true
;
case
SyntaxKind
.
ForEachStatement
:
case
SyntaxKind
.
ForEachVariableStatement
:
Debug
.
Assert
(
statementPart
!=
0
);
// only check the expression, edits in the body and the variable declaration are allowed:
return
AreEquivalentActiveStatements
((
ForEachStatementSyntax
)
oldStatement
,
(
ForEachStatementSyntax
)
newStatement
);
return
AreEquivalentActiveStatements
((
CommonForEachStatementSyntax
)
oldStatement
,
(
Common
ForEachStatementSyntax
)
newStatement
);
case
SyntaxKind
.
IfStatement
:
// only check the condition, edits in the body are allowed:
...
...
@@ -807,11 +833,30 @@ private static bool AreEquivalentActiveStatements(UsingStatementSyntax oldNode,
(
SyntaxNode
)
newNode
.
Declaration
??
newNode
.
Expression
);
}
private
static
bool
AreEquivalentActiveStatements
(
ForEachStatementSyntax
oldNode
,
ForEachStatementSyntax
newNode
)
private
static
bool
AreEquivalentActiveStatements
(
CommonForEachStatementSyntax
oldNode
,
Common
ForEachStatementSyntax
newNode
)
{
// This is conservative, we might be able to allow changing the type.
return
AreEquivalentIgnoringLambdaBodies
(
oldNode
.
Type
,
newNode
.
Type
)
&&
AreEquivalentIgnoringLambdaBodies
(
oldNode
.
Expression
,
newNode
.
Expression
);
if
(
oldNode
.
Kind
()
!=
newNode
.
Kind
()
||
!
AreEquivalentIgnoringLambdaBodies
(
oldNode
.
Expression
,
newNode
.
Expression
))
{
return
false
;
}
switch
(
oldNode
.
Kind
())
{
case
SyntaxKind
.
ForEachStatement
:
return
AreEquivalentIgnoringLambdaBodies
(((
ForEachStatementSyntax
)
oldNode
).
Type
,
((
ForEachStatementSyntax
)
newNode
).
Type
);
case
SyntaxKind
.
ForEachVariableStatement
:
return
AreEquivalentIgnoringLambdaBodies
(((
ForEachVariableStatementSyntax
)
oldNode
).
Variable
,
((
ForEachVariableStatementSyntax
)
newNode
).
Variable
);
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
oldNode
.
Kind
());
}
}
private
static
bool
AreSimilarActiveStatements
(
CommonForEachStatementSyntax
oldNode
,
CommonForEachStatementSyntax
newNode
)
{
List
<
SyntaxToken
>
oldTokens
=
null
;
List
<
SyntaxToken
>
newTokens
=
null
;
StatementSyntaxComparer
.
GetLocalNames
(
oldNode
,
ref
oldTokens
);
StatementSyntaxComparer
.
GetLocalNames
(
newNode
,
ref
newTokens
);
return
DeclareSameIdentifiers
(
oldTokens
.
ToArray
(),
newTokens
.
ToArray
());
}
internal
override
bool
IsMethod
(
SyntaxNode
declaration
)
...
...
@@ -1259,8 +1304,9 @@ internal static TextSpan GetDiagnosticSpanImpl(SyntaxKind kind, SyntaxNode node,
return
TextSpan
.
FromBounds
(
forStatement
.
ForKeyword
.
SpanStart
,
forStatement
.
CloseParenToken
.
Span
.
End
);
case
SyntaxKind
.
ForEachStatement
:
var
forEachStatement
=
(
ForEachStatementSyntax
)
node
;
return
TextSpan
.
FromBounds
(
forEachStatement
.
ForEachKeyword
.
SpanStart
,
forEachStatement
.
CloseParenToken
.
Span
.
End
);
case
SyntaxKind
.
ForEachVariableStatement
:
var
commonForEachStatement
=
(
CommonForEachStatementSyntax
)
node
;
return
TextSpan
.
FromBounds
(
commonForEachStatement
.
ForEachKeyword
.
SpanStart
,
commonForEachStatement
.
CloseParenToken
.
Span
.
End
);
case
SyntaxKind
.
LabeledStatement
:
return
((
LabeledStatementSyntax
)
node
).
Identifier
.
Span
;
...
...
@@ -1342,9 +1388,6 @@ internal static TextSpan GetDiagnosticSpanImpl(SyntaxKind kind, SyntaxNode node,
case
SyntaxKind
.
GroupClause
:
return
((
GroupClauseSyntax
)
node
).
GroupKeyword
.
Span
;
case
SyntaxKind
.
ForEachVariableStatement
:
return
((
ForEachVariableStatementSyntax
)
node
).
Variable
.
Span
;
case
SyntaxKind
.
IsPatternExpression
:
case
SyntaxKind
.
TupleType
:
case
SyntaxKind
.
TupleExpression
:
...
...
@@ -1549,6 +1592,7 @@ internal static string GetStatementDisplayNameImpl(SyntaxNode node)
return
CSharpFeaturesResources
.
lock_statement
;
case
SyntaxKind
.
ForEachStatement
:
case
SyntaxKind
.
ForEachVariableStatement
:
return
CSharpFeaturesResources
.
foreach_statement
;
case
SyntaxKind
.
CheckedStatement
:
...
...
@@ -1604,9 +1648,6 @@ internal static string GetStatementDisplayNameImpl(SyntaxNode node)
case
SyntaxKind
.
IsPatternExpression
:
return
CSharpFeaturesResources
.
is_pattern
;
case
SyntaxKind
.
ForEachVariableStatement
:
return
CSharpFeaturesResources
.
deconstruction
;
case
SyntaxKind
.
SimpleAssignmentExpression
:
if
(((
AssignmentExpressionSyntax
)
node
).
IsDeconstruction
())
{
...
...
@@ -3108,7 +3149,6 @@ private static bool IsUnsupportedCSharp7EnCNode(SyntaxNode n)
{
switch
(
n
.
Kind
())
{
case
SyntaxKind
.
ForEachVariableStatement
:
case
SyntaxKind
.
LocalFunctionStatement
:
return
true
;
default
:
...
...
@@ -3187,15 +3227,15 @@ private static CheckedStatementSyntax TryGetCheckedStatementAncestor(SyntaxNode
//
// Unlike exception regions matching where we use LCS, we allow reordering of the statements.
ReportUnmatchedStatements
<
LockStatementSyntax
>(
diagnostics
,
match
,
(
int
)
SyntaxKind
.
LockStatement
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
<
LockStatementSyntax
>(
diagnostics
,
match
,
new
[]
{
(
int
)
SyntaxKind
.
LockStatement
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
AreEquivalentActiveStatements
,
areSimilar
:
null
);
ReportUnmatchedStatements
<
FixedStatementSyntax
>(
diagnostics
,
match
,
(
int
)
SyntaxKind
.
FixedStatement
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
<
FixedStatementSyntax
>(
diagnostics
,
match
,
new
[]
{
(
int
)
SyntaxKind
.
FixedStatement
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
AreEquivalentActiveStatements
,
areSimilar
:
(
n1
,
n2
)
=>
DeclareSameIdentifiers
(
n1
.
Declaration
.
Variables
,
n2
.
Declaration
.
Variables
));
ReportUnmatchedStatements
<
UsingStatementSyntax
>(
diagnostics
,
match
,
(
int
)
SyntaxKind
.
UsingStatement
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
<
UsingStatementSyntax
>(
diagnostics
,
match
,
new
[]
{
(
int
)
SyntaxKind
.
UsingStatement
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
AreEquivalentActiveStatements
,
areSimilar
:
(
using1
,
using2
)
=>
{
...
...
@@ -3203,21 +3243,26 @@ private static CheckedStatementSyntax TryGetCheckedStatementAncestor(SyntaxNode
DeclareSameIdentifiers
(
using1
.
Declaration
.
Variables
,
using2
.
Declaration
.
Variables
);
});
ReportUnmatchedStatements
<
ForEachStatementSyntax
>(
diagnostics
,
match
,
(
int
)
SyntaxKind
.
ForEachStatement
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
<
CommonForEachStatementSyntax
>(
diagnostics
,
match
,
new
[]
{
(
int
)
SyntaxKind
.
ForEachStatement
,
(
int
)
SyntaxKind
.
ForEachVariableStatement
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
AreEquivalentActiveStatements
,
areSimilar
:
(
n1
,
n2
)
=>
SyntaxFactory
.
AreEquivalent
(
n1
.
Identifier
,
n2
.
Identifier
)
);
areSimilar
:
AreSimilarActiveStatements
);
}
private
static
bool
DeclareSameIdentifiers
(
SeparatedSyntaxList
<
VariableDeclaratorSyntax
>
oldVariables
,
SeparatedSyntaxList
<
VariableDeclaratorSyntax
>
newVariables
)
{
if
(
oldVariables
.
Count
!=
newVariables
.
Count
)
return
DeclareSameIdentifiers
(
oldVariables
.
Select
(
v
=>
v
.
Identifier
).
ToArray
(),
newVariables
.
Select
(
v
=>
v
.
Identifier
).
ToArray
());
}
private
static
bool
DeclareSameIdentifiers
(
SyntaxToken
[]
oldVariables
,
SyntaxToken
[]
newVariables
)
{
if
(
oldVariables
.
Length
!=
newVariables
.
Length
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
oldVariables
.
Count
;
i
++)
for
(
int
i
=
0
;
i
<
oldVariables
.
Length
;
i
++)
{
if
(!
SyntaxFactory
.
AreEquivalent
(
oldVariables
[
i
]
.
Identifier
,
newVariables
[
i
].
Identifier
))
if
(!
SyntaxFactory
.
AreEquivalent
(
oldVariables
[
i
]
,
newVariables
[
i
]
))
{
return
false
;
}
...
...
src/Features/CSharp/Portable/EditAndContinue/StatementSyntaxComparer.cs
浏览文件 @
a2de1326
...
...
@@ -1006,7 +1006,7 @@ private static void GetLocalNames(VariableDeclarationSyntax localDeclaration, re
}
}
private
static
void
GetLocalNames
(
CommonForEachStatementSyntax
commonForEach
,
ref
List
<
SyntaxToken
>
result
)
internal
static
void
GetLocalNames
(
CommonForEachStatementSyntax
commonForEach
,
ref
List
<
SyntaxToken
>
result
)
{
switch
(
commonForEach
.
Kind
())
{
...
...
src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs
浏览文件 @
a2de1326
...
...
@@ -1696,7 +1696,7 @@ protected void AddRudeDeleteAroundActiveStatement(List<RudeEditDiagnostic> diagn
protected
void
ReportUnmatchedStatements
<
TSyntaxNode
>(
List
<
RudeEditDiagnostic
>
diagnostics
,
Match
<
SyntaxNode
>
match
,
int
syntaxKind
,
int
[]
syntaxKinds
,
SyntaxNode
oldActiveStatement
,
SyntaxNode
newActiveStatement
,
Func
<
TSyntaxNode
,
TSyntaxNode
,
bool
>
areEquivalent
,
...
...
@@ -1704,8 +1704,8 @@ protected void AddRudeDeleteAroundActiveStatement(List<RudeEditDiagnostic> diagn
where
TSyntaxNode
:
SyntaxNode
{
List
<
SyntaxNode
>
oldNodes
=
null
,
newNodes
=
null
;
GetAncestors
(
GetEncompassingAncestor
(
match
.
OldRoot
),
oldActiveStatement
,
syntaxKind
,
ref
oldNodes
);
GetAncestors
(
GetEncompassingAncestor
(
match
.
NewRoot
),
newActiveStatement
,
syntaxKind
,
ref
newNodes
);
GetAncestors
(
GetEncompassingAncestor
(
match
.
OldRoot
),
oldActiveStatement
,
syntaxKind
s
,
ref
oldNodes
);
GetAncestors
(
GetEncompassingAncestor
(
match
.
NewRoot
),
newActiveStatement
,
syntaxKind
s
,
ref
newNodes
);
if
(
newNodes
!=
null
)
{
...
...
@@ -1836,11 +1836,11 @@ private static int IndexOfEquivalent<TSyntaxNode>(SyntaxNode newNode, List<Synta
return
-
1
;
}
private
static
void
GetAncestors
(
SyntaxNode
root
,
SyntaxNode
node
,
int
syntaxKind
,
ref
List
<
SyntaxNode
>
list
)
private
static
void
GetAncestors
(
SyntaxNode
root
,
SyntaxNode
node
,
int
[]
syntaxKinds
,
ref
List
<
SyntaxNode
>
list
)
{
while
(
node
!=
root
)
{
if
(
node
.
RawKind
==
syntaxKind
)
if
(
syntaxKinds
.
Contains
(
node
.
RawKind
)
)
{
if
(
list
==
null
)
{
...
...
src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb
浏览文件 @
a2de1326
...
...
@@ -3155,19 +3155,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue
'
' Unlike exception regions matching where we use LCS, we allow reordering of the statements.
ReportUnmatchedStatements
(
Of
SyncLockBlockSyntax
)(
diagnostics
,
match
,
SyntaxKind
.
SyncLockBlock
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
(
Of
SyncLockBlockSyntax
)(
diagnostics
,
match
,
New
Integer
()
{
SyntaxKind
.
SyncLockBlock
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
=
Function
(
n1
,
n2
)
AreEquivalentIgnoringLambdaBodies
(
n1
.
SyncLockStatement
.
Expression
,
n2
.
SyncLockStatement
.
Expression
),
areSimilar
:
=
Nothing
)
ReportUnmatchedStatements
(
Of
WithBlockSyntax
)(
diagnostics
,
match
,
SyntaxKind
.
WithBlock
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
(
Of
WithBlockSyntax
)(
diagnostics
,
match
,
New
Integer
()
{
SyntaxKind
.
WithBlock
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
=
Function
(
n1
,
n2
)
AreEquivalentIgnoringLambdaBodies
(
n1
.
WithStatement
.
Expression
,
n2
.
WithStatement
.
Expression
),
areSimilar
:
=
Nothing
)
ReportUnmatchedStatements
(
Of
UsingBlockSyntax
)(
diagnostics
,
match
,
SyntaxKind
.
UsingBlock
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
(
Of
UsingBlockSyntax
)(
diagnostics
,
match
,
New
Integer
()
{
SyntaxKind
.
UsingBlock
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
=
Function
(
n1
,
n2
)
AreEquivalentIgnoringLambdaBodies
(
n1
.
UsingStatement
.
Expression
,
n2
.
UsingStatement
.
Expression
),
areSimilar
:
=
Nothing
)
ReportUnmatchedStatements
(
Of
ForOrForEachBlockSyntax
)(
diagnostics
,
match
,
SyntaxKind
.
ForEachBlock
,
oldActiveStatement
,
newActiveStatement
,
ReportUnmatchedStatements
(
Of
ForOrForEachBlockSyntax
)(
diagnostics
,
match
,
New
Integer
()
{
SyntaxKind
.
ForEachBlock
}
,
oldActiveStatement
,
newActiveStatement
,
areEquivalent
:
=
Function
(
n1
,
n2
)
AreEquivalentIgnoringLambdaBodies
(
n1
.
ForOrForEachStatement
,
n2
.
ForOrForEachStatement
),
areSimilar
:
=
Function
(
n1
,
n2
)
AreEquivalentIgnoringLambdaBodies
(
DirectCast
(
n1
.
ForOrForEachStatement
,
ForEachStatementSyntax
).
ControlVariable
,
DirectCast
(
n2
.
ForOrForEachStatement
,
ForEachStatementSyntax
).
ControlVariable
))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录