|
// 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.
#if HAS_IOPERATION
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Analyzer.Utilities.Extensions
{
internal static class OperationBlockAnalysisContextExtension
{
#pragma warning disable RS1012 // Start action has no registered actions.
public static bool IsMethodNotImplementedOrSupported(this OperationBlockStartAnalysisContext context, bool checkPlatformNotSupported = false)
#pragma warning restore RS1012 // Start action has no registered actions.
{
// Note that VB method bodies with 1 action have 3 operations.
// The first is the actual operation, the second is a label statement, and the third is a return
// statement. The last two are implicit in these scenarios.
var operationBlocks = context.OperationBlocks.WhereAsArray(operation => !operation.IsOperationNoneRoot());
IBlockOperation? methodBlock = null;
if (operationBlocks.Length == 1 && operationBlocks[0].Kind == OperationKind.Block)
{
methodBlock = (IBlockOperation)operationBlocks[0];
}
else if (operationBlocks.Length > 1)
{
foreach (var block in operationBlocks)
{
if (block.Kind == OperationKind.Block)
{
methodBlock = (IBlockOperation)block;
break;
}
}
}
if (methodBlock != null)
{
static bool IsSingleStatementBody(IBlockOperation body)
{
return body.Operations.Length == 1 ||
(body.Operations.Length == 3 && body.Syntax.Language == LanguageNames.VisualBasic &&
body.Operations[1] is ILabeledOperation labeledOp && labeledOp.IsImplicit &&
body.Operations[2] is IReturnOperation returnOp && returnOp.IsImplicit);
}
if (IsSingleStatementBody(methodBlock) &&
methodBlock.Operations[0].GetTopmostExplicitDescendants() is { } descendants &&
descendants.Length == 1 &&
descendants[0] is IThrowOperation throwOperation &&
throwOperation.GetThrownExceptionType() is ITypeSymbol createdExceptionType)
{
if (SymbolEqualityComparer.Default.Equals(
context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNotImplementedException),
createdExceptionType.OriginalDefinition) ||
SymbolEqualityComparer.Default.Equals(
context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNotSupportedException),
createdExceptionType.OriginalDefinition) ||
(checkPlatformNotSupported &&
SymbolEqualityComparer.Default.Equals(
context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemPlatformNotSupportedException),
createdExceptionType.OriginalDefinition)))
{
return true;
}
}
}
return false;
}
}
}
#endif
|