in ClrHeapAllocationsAnalyzer/ConcatenationAllocationAnalyzer.cs [23:62]
protected override void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var node = context.Node;
var semanticModel = context.SemanticModel;
Action<Diagnostic> reportDiagnostic = context.ReportDiagnostic;
var cancellationToken = context.CancellationToken;
string filePath = node.SyntaxTree.FilePath;
var binaryExpressions = node.DescendantNodesAndSelf().OfType<BinaryExpressionSyntax>().Reverse(); // need inner most expressions
int stringConcatenationCount = 0;
foreach (var binaryExpression in binaryExpressions) {
if (binaryExpression.Left == null || binaryExpression.Right == null) {
continue;
}
bool isConstant = semanticModel.GetConstantValue(binaryExpression, cancellationToken).HasValue;
if (isConstant) {
continue;
}
var left = semanticModel.GetTypeInfo(binaryExpression.Left, cancellationToken);
var leftConversion = semanticModel.GetConversion(binaryExpression.Left, cancellationToken);
CheckTypeConversion(left, leftConversion, reportDiagnostic, binaryExpression.Left.GetLocation(), filePath);
var right = semanticModel.GetTypeInfo(binaryExpression.Right, cancellationToken);
var rightConversion = semanticModel.GetConversion(binaryExpression.Right, cancellationToken);
CheckTypeConversion(right, rightConversion, reportDiagnostic, binaryExpression.Right.GetLocation(), filePath);
// regular string allocation
if (left.Type?.SpecialType == SpecialType.System_String || right.Type?.SpecialType == SpecialType.System_String) {
stringConcatenationCount++;
}
}
if (stringConcatenationCount > 3)
{
reportDiagnostic(Diagnostic.Create(StringConcatenationAllocationRule, node.GetLocation(), EmptyMessageArgs));
HeapAllocationAnalyzerEventSource.Logger.StringConcatenationAllocation(filePath);
}
}