提交 50924c3a 编写于 作者: J John Hamby

Add instrumentation of bound pattern switch statements.

上级 06c25e54
......@@ -163,6 +163,11 @@ public override BoundStatement InstrumentSwitchStatement(BoundSwitchStatement or
return Previous.InstrumentSwitchStatement(original, rewritten);
}
public override BoundStatement InstrumentBoundPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
{
return Previous.InstrumentBoundPatternSwitchStatement(original, rewritten);
}
public override BoundStatement InstrumentUsingTargetCapture(BoundUsingStatement original, BoundStatement usingTargetCapture)
{
return Previous.InstrumentUsingTargetCapture(original, usingTargetCapture);
......
......@@ -359,6 +359,20 @@ public override BoundStatement InstrumentSwitchStatement(BoundSwitchStatement or
hasErrors: false);
}
public override BoundStatement InstrumentBoundPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
{
SwitchStatementSyntax switchSyntax = (SwitchStatementSyntax)original.Syntax;
TextSpan switchSequencePointSpan = TextSpan.FromBounds(
switchSyntax.SwitchKeyword.SpanStart,
switchSyntax.CloseParenToken.Span.End);
return new BoundSequencePointWithSpan(
syntax: switchSyntax,
statementOpt: base.InstrumentBoundPatternSwitchStatement(original, rewritten),
span: switchSequencePointSpan,
hasErrors: false);
}
public override BoundStatement InstrumentUsingTargetCapture(BoundUsingStatement original, BoundStatement usingTargetCapture)
{
return AddSequencePoint((UsingStatementSyntax)original.Syntax,
......
......@@ -213,6 +213,11 @@ public override BoundStatement InstrumentSwitchStatement(BoundSwitchStatement or
return AddDynamicAnalysis(original, base.InstrumentSwitchStatement(original, rewritten));
}
public override BoundStatement InstrumentBoundPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
{
return AddDynamicAnalysis(original, base.InstrumentBoundPatternSwitchStatement(original, rewritten));
}
public override BoundStatement InstrumentUsingTargetCapture(BoundUsingStatement original, BoundStatement usingTargetCapture)
{
return AddDynamicAnalysis(original, base.InstrumentUsingTargetCapture(original, usingTargetCapture));
......@@ -303,6 +308,9 @@ private static CSharpSyntaxNode SyntaxForSpan(BoundStatement statement)
case BoundKind.SwitchStatement:
syntaxForSpan = ((BoundSwitchStatement)statement).Expression.Syntax;
break;
case BoundKind.PatternSwitchStatement:
syntaxForSpan = ((BoundPatternSwitchStatement)statement).Expression.Syntax;
break;
default:
syntaxForSpan = statement.Syntax;
break;
......
......@@ -244,6 +244,12 @@ public virtual BoundStatement InstrumentSwitchStatement(BoundSwitchStatement ori
return InstrumentStatement(original, rewritten);
}
public virtual BoundStatement InstrumentBoundPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
{
Debug.Assert(original.Syntax.Kind() == SyntaxKind.SwitchStatement);
return InstrumentStatement(original, rewritten);
}
public virtual BoundStatement InstrumentUsingTargetCapture(BoundUsingStatement original, BoundStatement usingTargetCapture)
{
Debug.Assert(!original.WasCompilerGenerated);
......
......@@ -49,7 +49,15 @@ public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatemen
}
result.Add(_factory.Label(node.BreakLabel));
var translatedSwitch = _factory.Block(pslr.DeclaredTemps.ToImmutableArray().Concat(node.InnerLocals), node.InnerLocalFunctions, result.ToImmutableAndFree());
BoundStatement translatedSwitch = _factory.Block(pslr.DeclaredTemps.ToImmutableArray().Concat(node.InnerLocals), node.InnerLocalFunctions, result.ToImmutableAndFree());
// Create the sequence point if generating debug info and
// node is not compiler generated
if (this.Instrument && !node.WasCompilerGenerated)
{
translatedSwitch = _instrumenter.InstrumentBoundPatternSwitchStatement(node, translatedSwitch);
}
return translatedSwitch;
}
......
......@@ -364,6 +364,65 @@ int Wilma
"(60,8)-(60,17)");
}
[Fact]
public void TestPatternSpans()
{
string source = @"
using System;
public class C
{
public static void Main() // Method 0
{
Student s = new Student();
s.Name = ""Bozo"";
s.GPA = 2.3;
Operate(s);
}
static string Operate(Person p) // Method 1
{
switch (p)
{
case Student s when s.GPA > 3.5:
return $""Student {s.Name} ({s.GPA:N1})"";
case Student s:
return $""Student {s.Name} ({s.GPA:N1})"";
case Teacher t:
return $""Teacher {t.Name} of {t.Subject}"";
default:
return $""Person {p.Name}"";
}
}
}
class Person { public string Name; }
class Teacher : Person { public string Subject; }
class Student : Person { public double GPA; }
";
var c = CreateCompilationWithMscorlib(Parse(source + InstrumentationHelperSource, @"C:\myproject\doc1.cs"));
var peImage = c.EmitToArray(EmitOptions.Default.WithInstrument("Test.Flag"));
var peReader = new PEReader(peImage);
var reader = DynamicAnalysisDataReader.TryCreateFromPE(peReader, "<DynamicAnalysisData>");
VerifySpans(reader, reader.Methods[0],
"(5,4)-(11,5)",
"(7,8)-(7,34)",
"(8,8)-(8,24)",
"(9,8)-(9,20)",
"(10,8)-(10,19)");
VerifySpans(reader, reader.Methods[1],
"(13,4)-(26,5)",
"(18,16)-(18,56)",
"(20,16)-(20,56)",
"(22,16)-(22,58)",
"(24,16)-(24,42)",
"(15,16)-(15,17)");
}
[Fact]
public void TestDynamicAnalysisResourceMissingWhenInstrumentationFlagIsDisabled()
{
......
......@@ -1287,6 +1287,90 @@ File 1
CompileAndVerify(source + InstrumentationHelperSource, expectedOutput: expectedOutput);
}
[Fact]
public void PatternsCoverage()
{
string source = @"
using System;
public class C
{
public static void Main()
{
TestMain();
Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();
}
static void TestMain() // Method 2
{
Student s = new Student();
s.Name = ""Bozo"";
s.GPA = 2.3;
Operate(s);
}
static string Operate(Person p) // Method 3
{
switch (p)
{
case Student s when s.GPA > 3.5:
return $""Student {s.Name} ({s.GPA:N1})"";
case Student s:
return $""Student {s.Name} ({s.GPA:N1})"";
case Teacher t:
return $""Teacher {t.Name} of {t.Subject}"";
default:
return $""Person {p.Name}"";
}
}
}
class Person { public string Name; }
class Teacher : Person { public string Subject; }
class Student : Person { public double GPA; }
";
string expectedOutput = @"Flushing
Method 1
File 1
True
True
True
Method 2
File 1
True
True
True
True
True
Method 3
File 1
True
False
True
False
False
True
Method 9
File 1
True
True
False
True
True
True
True
True
True
True
True
True
True
True
";
CompileAndVerify(source + InstrumentationHelperSource, expectedOutput: expectedOutput);
}
[Fact]
public void LambdaCoverage()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册