SuppressionSuggestedAction.cs 4.7 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Threading;
9
using System.Threading.Tasks;
10
using Microsoft.CodeAnalysis.CodeActions;
11 12 13
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
14
using Roslyn.Utilities;
15 16 17 18 19 20 21 22 23 24 25

namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions
{
    /// <summary>
    /// Represents top-level light bulb menu item for the suppression fix.
    /// The top-level item itself does nothing. It doesn't display a preview and can't be invoked / applied.
    /// The top-level item is simply a container for the fixes displayed as sub-menu items.
    /// </summary>
    internal class SuppressionSuggestedAction : SuggestedAction, ITelemetryDiagnosticID<string>
    {
        private readonly CodeFix _fix;
26
        private readonly Func<CodeAction, SuggestedActionSet> _getFixAllSuggestedActionSet;
27 28 29 30 31 32

        public SuppressionSuggestedAction(
            Workspace workspace,
            ITextBuffer subjectBuffer,
            ICodeActionEditHandlerService editHandler,
            CodeFix fix,
33 34
            object provider,
            Func<CodeAction, SuggestedActionSet> getFixAllSuggestedActionSet) :
35 36 37
                base(workspace, subjectBuffer, editHandler, fix.Action, provider)
        {
            _fix = fix;
38
            _getFixAllSuggestedActionSet = getFixAllSuggestedActionSet;
39 40
        }

41
        public override bool HasActionSets
42 43 44
        {
            get
            {
45
                return this.CodeAction.GetCodeActions().Any();
46 47
            }
        }
48

49 50 51 52
        private IEnumerable<SuggestedActionSet> _actionSets;
        public override Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
53

54 55 56 57 58
            if (_actionSets != null)
            {
                return Task.FromResult(_actionSets);
            }

59
            if (this.CodeAction.GetCodeActions().Any())
60 61
            {
                var nestedSuggestedActions = ImmutableArray.CreateBuilder<SuggestedAction>();
62
                var fixCount = this.CodeAction.GetCodeActions().Length;
63

64
                foreach (var c in this.CodeAction.GetCodeActions())
65 66 67
                {
                    cancellationToken.ThrowIfCancellationRequested();

68
                    var fixAllSuggestedActionSet = _getFixAllSuggestedActionSet(c);
69 70
                    nestedSuggestedActions.Add(new CodeFixSuggestedAction(
                            this.Workspace, this.SubjectBuffer, this.EditHandler,
71
                            new CodeFix(c, _fix.Diagnostics), c, this.Provider, fixAllSuggestedActionSet));
72 73
                }

74 75 76 77
                _actionSets = ImmutableArray.Create(
                    new SuggestedActionSet(nestedSuggestedActions.ToImmutable()));

                return Task.FromResult(_actionSets);
78
            }
79 80

            return SpecializedTasks.Default<IEnumerable<SuggestedActionSet>>();
81 82 83 84 85 86 87 88 89 90
        }

        public override void Invoke(CancellationToken cancellationToken)
        {
            // The top-level action cannot be invoked.
            // However, the nested sub-actions returned above can be.
            throw new NotSupportedException(string.Format(EditorFeaturesResources.OperationNotSupported,
                nameof(SuppressionSuggestedAction),
                nameof(Invoke),
                nameof(ISuggestedAction),
91 92 93 94 95 96 97 98 99 100 101
                nameof(GetActionSetsAsync)));
        }

        public override bool HasPreview
        {
            get
            {
                // The top-level action won't show any preview.
                // However, the nested sub-actions returned above will show preview.
                return false;
            }
102 103
        }

104
        public override Task<object> GetPreviewAsync(CancellationToken cancellationToken)
105 106 107
        {
            // The top-level action won't show any preview.
            // However, the nested sub-actions returned above will show preview.
108
            return SpecializedTasks.Default<object>();
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
        }

        public string GetDiagnosticID()
        {
            var diagnostic = _fix.PrimaryDiagnostic;

            // we log diagnostic id as it is if it is from us
            if (diagnostic.Descriptor.CustomTags.Any(t => t == WellKnownDiagnosticTags.Telemetry))
            {
                return diagnostic.Id;
            }

            // if it is from third party, we use hashcode
            return diagnostic.GetHashCode().ToString(CultureInfo.InvariantCulture);
        }
    }
}