private static void HandleMethodParameter(SyntaxNodeAnalysisContext context, ParameterSyntax parameter) { var paramSympol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken); if (paramSympol != null) { var isRefCounter = RefCounter.IsRefCounterType(paramSympol.Type); if (isRefCounter) { var param = context.SemanticModel.GetDeclaredSymbolSafe(parameter, context.CancellationToken); if (param != null) { var method = parameter.FirstAncestorOrSelf <MethodDeclarationSyntax>(); var block = method?.Body; if (block == null) { return; } RefCounterStatus status = new RefCounterStatus(); if (method.Identifier.ToString().Equals(KnownSymbol.ReleaseReference)) { status.AcquireReference("param of ReleaseReference", method.GetLocation()); } ProcessLocalOrParamenterVar(context, param, block, status); } } } }
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()); } }
private static int IncRefInvocationCount(ISymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken, RefCounterStatus status) { int count = 0; Location loc = Location.None;; using (var pooledInvocations = InvocationWalker.Borrow(block)) { foreach (var invocation in pooledInvocations.Invocations) { var isFromSymbol = IsInvokeFrom(symbol, semanticModel, cancellationToken, invocation); var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (isFromSymbol && method.ReceiverType != null) { if (method.ReceiverType.Is(KnownSymbol.RefCounter) && method?.Name == KnownSymbol.AcquireReference) { count++; loc = invocation.GetLocation(); if (LoopUtils.HasLoopBetween(invocation, block)) { status.Skip("loop between AcquireReference call and var block", loc); } } } } } if (count > 1) { status.Skip("more than one AcquireReference", loc); } else if (count == 1) { status.AcquireReference("call AcquireReference", loc); } return(count); }