|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Microsoft.CodeAnalysis
{
internal static class UnexpectedOperationHandler
{
// No-op in release builds, but fails in debug builds when
// encountering an unexpected operation. InvalidOperation is skipped because
// it is expected that any part of the control-flow graph may contain an
// InvalidOperation for code that doesn't compile (for example, in an intermediate
// state while editing).
[Conditional ("DEBUG")]
public static void Handle (IOperation operation)
{
// NoneOperation represents operations which are unimplemented by Roslyn
// (don't have specific I*Operation types), such as pointer dereferences.
if (operation.Kind is OperationKind.None)
return;
if (operation.Kind is OperationKind.Invalid)
return;
// It's also possible to hit a case where the operation is an unexpected operation kind,
// but the code is in an invalid state where the unexpected operation is not IInvalidOperation, yet one
// of its child operations is. For example:
//
// a + = 3;
//
// This is represented as an assignment where the target is an IBinaryOperation (a +) whose right-hand side
// is an IInvalidOperation. The assignment logic doesn't support assigning to a binary operation,
// but this should still not fail.
foreach (var descendant in operation.Descendants()) {
if (descendant.Kind is OperationKind.Invalid)
return;
}
// Throw on anything else as it means we need to implement support for it
// but do not throw in Release builds as it means new Roslyn version could cause the analyzer to crash
// which is not fixable by the user. The analyzer is not going to be 100% correct no
// matter what we do so effectively ignoring constructs it doesn't understand is OK.
// This is surfaced as warning AD0001 in Debug builds.
throw new NotImplementedException ($"Unexpected operation type {operation.GetType ()}: {operation.Syntax.GetLocation ().GetLineSpan ()}");
}
}
}
|