in resharper/resharper-unity/src/Unity/CSharp/Daemon/Stages/Analysis/UnityLifetimeChecksHelper.cs [18:87]
public class UnityLifetimeChecksHelper(ISolution solution, HighlightingSettingsManager highlightingSettingsManager)
{
private readonly IClrTypeName myNotDestroyedAttribute = new ClrTypeName("JetBrains.Annotations.NotDestroyedAttribute");
public bool IsNullPatternMatchingWarningEnabled(IPsiSourceFile sourceFile) => highlightingSettingsManager.GetConfigurableSeverity(UnityObjectNullPatternMatchingWarning.HIGHLIGHTING_ID, sourceFile, sourceFile.GetLazySettingsStoreWithEditorConfig(solution)) >= Severity.HINT;
public void AddNullPatternMatchingWarnings(IPattern? pattern, IHighlightingConsumer consumer)
{
Stack<IPattern>? pendingPatterns = null;
do
{
ITreeNode? node = null;
switch (pattern)
{
case IParenthesizedPattern { Pattern: { } operand }:
pattern = operand;
continue;
case INegatedPattern { Pattern: { } negatedOperand }:
pattern = negatedOperand;
continue;
case IBinaryPattern { LeftPattern: {} leftPattern, RightPattern: var rightPattern }:
pattern = leftPattern;
if (rightPattern != null)
(pendingPatterns ??= new Stack<IPattern>()).Push(rightPattern);
continue;
case IBinaryPattern { RightPattern: { } rightPattern }:
pattern = rightPattern;
continue;
case IConstantOrTypePattern constantOrTypePattern:
node = constantOrTypePattern.Expression;
break;
case IRecursivePattern recursivePattern:
node = (ITreeNode?)recursivePattern.TypeUsage ?? recursivePattern.PropertyPatternClause?.LBrace;
break;
case ITypePattern typePattern:
node = typePattern.TypeUsage;
break;
}
if (node != null)
consumer.AddHighlighting(new UnityObjectNullPatternMatchingWarning(node));
pattern = pendingPatterns?.TryPop();
} while (pattern != null);
}
public bool CanBeDestroyed(ICSharpExpression expression)
{
if (!UnityTypeUtils.IsUnityObject(expression.Type()))
return false;
var hasNotDestroyedAttribute = GetAttributeSet(expression) is {} attributesSet && attributesSet.HasAttributeInstance(myNotDestroyedAttribute, AttributesSource.All);
return !hasNotDestroyedAttribute;
}
private static IAttributesSet? GetAttributeSet(ICSharpExpression expression)
{
return expression switch
{
IInvocationExpression { InvokedExpression: IReferenceExpression { Reference: var reference } } when reference.Resolve().DeclaredElement is IMethod method => method.ReturnTypeAttributes,
IReferenceExpression { Reference: var reference } => reference.Resolve().DeclaredElement switch
{
IAttributesOwner attributesOwner => attributesOwner,
ILocalVariableDeclaration { Initializer: IExpressionInitializer { Value: { } value } } => GetAttributeSet(value),
ISingleVariableDesignation { Parent: IVarPattern { Parent: IIsExpression { Operand: {} operand } } } => GetAttributeSet(operand),
_ => null
},
_ => null
};
}
}