|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.CodeAnalysis;
namespace Analyzer.Utilities.FlowAnalysis.Analysis.PropertySetAnalysis
{
/// <summary>
/// Determines if usage of a <see cref="PropertySetAbstractValue"/> is hazardous or not.
/// </summary>
#pragma warning disable CA1812 // Is too instantiated.
internal sealed class HazardousUsageEvaluator
#pragma warning restore CA1812
{
/// <summary>
/// Evaluates if the method invocation with a given <see cref="PropertySetAbstractValue"/> is hazardous or not.
/// </summary>
/// <param name="methodSymbol">Invoked method.</param>
/// <param name="propertySetAbstractValue">Abstract value of the type being tracked by PropertySetAnalysis.</param>
/// <returns>Evaluation result of whether the usage is hazardous.</returns>
public delegate HazardousUsageEvaluationResult InvocationEvaluationCallback(IMethodSymbol methodSymbol, PropertySetAbstractValue propertySetAbstractValue);
/// <summary>
/// Evaluates if a given <see cref="PropertySetAbstractValue"/> is hazardous or not.
/// </summary>
/// <param name="propertySetAbstractValue">Abstract value of the type being tracked by PropertySetAnalysis.</param>
/// <returns>Evaluation result of whether the usage is hazardous.</returns>
public delegate HazardousUsageEvaluationResult EvaluationCallback(PropertySetAbstractValue propertySetAbstractValue);
/// <summary>
/// Initializes a <see cref="HazardousUsageEvaluator"/> that evaluates a method invocation on the type being tracked by PropertySetAnalysis.
/// </summary>
/// <param name="trackedTypeMethodName">Name of the method within the tracked type.</param>
/// <param name="evaluator">Evaluation callback.</param>
/// <param name="derivedClass">Whether to consider derived class.</param>
public HazardousUsageEvaluator(string trackedTypeMethodName, InvocationEvaluationCallback evaluator, bool derivedClass = false)
{
MethodName = trackedTypeMethodName ?? throw new ArgumentNullException(nameof(trackedTypeMethodName));
InvocationEvaluator = evaluator ?? throw new ArgumentNullException(nameof(evaluator));
Kind = HazardousUsageEvaluatorKind.Invocation;
DerivedClass = derivedClass;
}
/// <summary>
/// Initializes a <see cref="HazardousUsageEvaluator"/> that evaluates a method invocation with an argument of the type being tracked by PropertySetAnalysis.
/// </summary>
/// <param name="containingType">Name of the instance that the method is invoked on.</param>
/// <param name="methodName">Name of the method within <paramref name="containingType"/>.</param>
/// <param name="parameterNameOfPropertySetObject">Name of the method parameter containing the type being tracked by PropertySetAnalysis.</param>
/// <param name="evaluator">Evaluation callback.</param>
/// <param name="derivedClass">Whether to consider derived class.</param>
public HazardousUsageEvaluator(string containingType, string methodName, string parameterNameOfPropertySetObject, InvocationEvaluationCallback evaluator, bool derivedClass = false)
{
ContainingTypeName = containingType ?? throw new ArgumentNullException(nameof(containingType));
MethodName = methodName ?? throw new ArgumentNullException(nameof(methodName));
ParameterNameOfPropertySetObject = parameterNameOfPropertySetObject ?? throw new ArgumentNullException(nameof(parameterNameOfPropertySetObject));
InvocationEvaluator = evaluator ?? throw new ArgumentNullException(nameof(evaluator));
DerivedClass = derivedClass;
Kind = HazardousUsageEvaluatorKind.Invocation;
}
/// <summary>
/// Initializes a <see cref="HazardousUsageEvaluator"/> that evaluates a return statement with a return value of the tracked type.
/// </summary>
/// <param name="evaluator">Evaluation callback.</param>
/// <param name="derivedClass">Whether to consider derived class.</param>
public HazardousUsageEvaluator(HazardousUsageEvaluatorKind kind, EvaluationCallback evaluator, bool derivedClass = false)
{
if (kind is not HazardousUsageEvaluatorKind.Return and not HazardousUsageEvaluatorKind.Initialization and not HazardousUsageEvaluatorKind.Argument)
{
throw new ArgumentException(
"kind must be Return or Initialization or Argument. Use other constructors for Invocation.",
nameof(kind));
}
Kind = kind;
DerivedClass = derivedClass;
ValueEvaluator = evaluator ?? throw new ArgumentNullException(nameof(evaluator));
}
private HazardousUsageEvaluator()
{
}
public HazardousUsageEvaluatorKind Kind { get; }
/// <summary>
/// Name of the type containing the method, or null if method is part of the type being tracked by PropertySetAnalysis or this is for a return statement.
/// </summary>
public string? ContainingTypeName { get; }
/// <summary>
/// Name of the method being invoked, or null if this is for a return statement.
/// </summary>
public string? MethodName { get; }
/// <summary>
/// Name of the parameter containing the object containing the type being tracked by PropertySetAnalysis, or null if the method is part of the type being tracked by PropertySetAnalysis.
/// </summary>
public string? ParameterNameOfPropertySetObject { get; }
/// <summary>
/// Evaluates if the method invocation with a given <see cref="PropertySetAbstractValue"/> is hazardous or not.
/// </summary>
public InvocationEvaluationCallback? InvocationEvaluator { get; }
/// <summary>
/// Determines whether consider the derived classes of the containing type.
/// </summary>
public bool DerivedClass { get; }
/// <summary>
/// Evaluates if the return statement or initialization value with a given <see cref="PropertySetAbstractValue"/> is hazardous or not.
/// </summary>
public EvaluationCallback? ValueEvaluator { get; }
public override int GetHashCode()
{
return RoslynHashCode.Combine(
this.ContainingTypeName.GetHashCodeOrDefault(),
this.MethodName.GetHashCodeOrDefault(),
this.ParameterNameOfPropertySetObject.GetHashCodeOrDefault(),
this.DerivedClass.GetHashCode(),
this.InvocationEvaluator.GetHashCodeOrDefault());
}
public override bool Equals(object obj)
{
return this.Equals(obj as HazardousUsageEvaluator);
}
public bool Equals(HazardousUsageEvaluator? other)
{
return other != null
&& this.ContainingTypeName == other.ContainingTypeName
&& this.MethodName == other.MethodName
&& this.ParameterNameOfPropertySetObject == other.ParameterNameOfPropertySetObject
&& this.DerivedClass == other.DerivedClass
&& this.InvocationEvaluator == other.InvocationEvaluator;
}
}
}
|