提交 8df34dbf 编写于 作者: G Gen Lu

Fix IBlockStatement implementation in C#

So the Statements property won't return any None kind operation.
上级 400a9523
......@@ -25,7 +25,18 @@ partial class BoundStatement : IStatement
partial class BoundBlock : IBlockStatement
{
ImmutableArray<IStatement> IBlockStatement.Statements => this.Statements.As<IStatement>();
private static readonly ConditionalWeakTable<BoundBlock, object> s_blockStatementsMappings =
new ConditionalWeakTable<BoundBlock, object>();
ImmutableArray<IStatement> IBlockStatement.Statements
{
get
{
return (ImmutableArray<IStatement>) s_blockStatementsMappings.GetValue(this,
blockStatement => { return blockStatement.Statements.AsImmutable<IStatement>().WhereAsArray(statement => statement.Kind != OperationKind.None); }
);
}
}
ImmutableArray<ILocalSymbol> IBlockStatement.Locals => this.Locals.As<ILocalSymbol>();
......
......@@ -1196,5 +1196,47 @@ public void M0()
.VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new NoneOperationTestAnalyzer() }, null, null, false);
}
[Fact]
public void LambdaExpressionCSharp()
{
const string source = @"
using System;
class B
{
public void M0()
{
Action<int> action1 = input => { };
Action<int> action2 = input => input++;
Func<int,bool> func1 = input => { input++; input++; if (input > 0) return true; return false; };
}
}
public delegate void MumbleEventHandler(object sender, System.EventArgs args);
class C
{
public event MumbleEventHandler Mumble;
public void OnMumble(System.EventArgs args)
{
Mumble += new MumbleEventHandler((s, e) => { });
Mumble += (s, e) => { int i = 0; i++; i++; i++; };
Mumble(this, args);
}
}
";
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new LambdaTestAnalyzer() }, null, null, false,
Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "input => { }").WithLocation(8, 31),
Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "input => input++").WithLocation(9, 31),
Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "input => { input++; input++; if (input > 0) return true; return false; }").WithLocation(10, 32),
Diagnostic(LambdaTestAnalyzer.TooManyStatementsInLambdaExpressionDescriptor.Id, "input => { input++; input++; if (input > 0) return true; return false; }").WithLocation(10, 32),
Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "(s, e) => { }").WithLocation(22, 42),
Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "(s, e) => { int i = 0; i++; i++; i++; }").WithLocation(23, 19),
Diagnostic(LambdaTestAnalyzer.TooManyStatementsInLambdaExpressionDescriptor.Id, "(s, e) => { int i = 0; i++; i++; i++; }").WithLocation(23, 19));
}
}
}
......@@ -1118,4 +1118,76 @@ public sealed override void Initialize(AnalysisContext context)
OperationKind.None);
}
}
/// <summary>Analyzer used to test LambdaExpression IOperations.</summary>
public class LambdaTestAnalyzer : DiagnosticAnalyzer
{
private const string ReliabilityCategory = "Reliability";
public static readonly DiagnosticDescriptor LambdaExpressionDescriptor = new DiagnosticDescriptor(
"LambdaExpression",
"Lambda expressionn found",
"An Lambda expression is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public static readonly DiagnosticDescriptor TooManyStatementsInLambdaExpressionDescriptor = new DiagnosticDescriptor(
"TooManyStatementsInLambdaExpression",
"Too many statements in a Lambda expression",
"More than 3 statements in a Lambda expression",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
// This warning should never be triggered.
public static readonly DiagnosticDescriptor NoneOperationInLambdaExpressionDescriptor = new DiagnosticDescriptor(
"NoneOperationInLambdaExpression",
"None Operation found in Lambda expression",
"None Operation is found Lambda expression",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(LambdaExpressionDescriptor,
TooManyStatementsInLambdaExpressionDescriptor,
NoneOperationInLambdaExpressionDescriptor); }
}
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(
(operationContext) =>
{
var lambdaExpression = (ILambdaExpression)operationContext.Operation;
operationContext.ReportDiagnostic(Diagnostic.Create(LambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
var block = lambdaExpression.Body;
// TODO: Can this possibly be null? Remove check if not.
if (block == null)
{
return;
}
if (block.Statements.Length > 3)
{
operationContext.ReportDiagnostic(Diagnostic.Create(TooManyStatementsInLambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
}
bool flag = false;
foreach (var statement in block.Statements)
{
if (statement.Kind == OperationKind.None)
{
flag = true;
break;
}
}
if (flag)
{
operationContext.ReportDiagnostic(Diagnostic.Create(NoneOperationInLambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
}
},
OperationKind.LambdaExpression);
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册