public static void ProcessOutRefInvocation(ISymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken, RefCounterStatus status) { using (var pooledInvocations = InvocationWalker.Borrow(block)) { foreach (var invocation in pooledInvocations.Invocations) { foreach (ArgumentSyntax arg in invocation.ArgumentList.Arguments) { if (arg.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword) || arg.RefOrOutKeyword.IsKind(SyntaxKind.RefKeyword)) { var sym = ModelExtensions.GetSymbolInfo(semanticModel, arg.Expression, cancellationToken); ISymbol argSymbol = sym.Symbol; if (symbol.Equals(argSymbol)) { status.RemainRef("init from out/ref call", arg.GetLocation()); status.IncAssignCounter("out/ref call parameter", arg.GetLocation()); if (LoopUtils.HasLoopBetween(invocation, block)) { status.Skip("loop between ref/out call and var block", arg.GetLocation()); } } } } } } }
public static void ProcessReturnStatement(ISymbol local, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken, RefCounterStatus status) { using (var walker = ReturnValueWalker.Borrow(block, Search.TopLevel, semanticModel, cancellationToken)) { foreach (var value in walker) { var returnedSymbol = semanticModel.GetSymbolSafe(value, cancellationToken); if (SymbolComparer.Equals(local, returnedSymbol)) { var method = block.FirstAncestor <MethodDeclarationSyntax>(); var access = block.FirstAncestor <AccessorDeclarationSyntax>(); bool isGet = false; if (method != null) { isGet = KnownSymbol.IsGetMethodName(method.Identifier.ToString()); } else if (access != null) { isGet = true; } if (isGet) { status.RemainRef("return value from get method", value.GetLocation()); } else { status.ReleaseReference("return value from non get", value.GetLocation()); } } } } }
public static void CalcAssignmentValue(ExpressionSyntax variable, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken, RefCounterStatus refCounterStatus) { if (InitializeFromCreation(variable)) { refCounterStatus.IncAssignCounter("initialize from new", variable.GetLocation()); refCounterStatus.AcquireReference("init from new", variable.GetLocation()); } else if (InitializeFromTypeCastParameter(variable, semanticModel, cancellationToken, out var param)) { refCounterStatus.IncAssignCounter("init cast from param", variable.GetLocation()); refCounterStatus.RemainRef("init cast from param", variable.GetLocation()); if (RightOfAssignmentUtils.RightSideOfAssignmentCount(param, block, semanticModel, cancellationToken) > 1) { refCounterStatus.Skip("cast from param also assigned to others", variable.GetLocation()); } } else if (InitializeFromNonGetMethod(variable, semanticModel, cancellationToken)) { refCounterStatus.IncAssignCounter("initialize from non-get method", variable.GetLocation()); refCounterStatus.AcquireReference("init from non-get method", variable.GetLocation()); } else if (InitializeFromGetMethod(variable, semanticModel, cancellationToken)) { refCounterStatus.IncAssignCounter("initialize from get method", variable.GetLocation()); refCounterStatus.RemainRef("init from get method", variable.GetLocation()); } else if (InitializeFromProperty(variable, semanticModel, cancellationToken)) { refCounterStatus.IncAssignCounter("initialize from field/property", variable.GetLocation()); refCounterStatus.RemainRef("init from property", variable.GetLocation()); // nothing } else if (InitializeFromElement(variable, semanticModel, cancellationToken)) { refCounterStatus.IncAssignCounter("initialize from element access", variable.GetLocation()); refCounterStatus.RemainRef("init from element access", variable.GetLocation()); } else // assigned from other local variable, class field, or other expression { refCounterStatus.IncAssignCounter("initialize from unkown", variable.GetLocation()); refCounterStatus.Skip("unsupported initialization", variable.GetLocation()); } }