File: Interactive\InteractiveWindowResetCommand.cs
Web Access
Project: src\src\EditorFeatures\Core.Wpf\Microsoft.CodeAnalysis.EditorFeatures.Wpf_tpal30ww_wpftmp.csproj (Microsoft.CodeAnalysis.EditorFeatures.Wpf)
// 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.
 
#nullable disable
 
extern alias InteractiveHost;
 
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.InteractiveWindow;
using Microsoft.VisualStudio.InteractiveWindow.Commands;
using Microsoft.VisualStudio.Language.StandardClassification;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using InteractiveHost::Microsoft.CodeAnalysis.Interactive;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Interactive
{
    /// <summary>
    /// Represents a reset command which can be run from a REPL window.
    /// </summary>
    [Export(typeof(IInteractiveWindowCommand))]
    [ContentType(InteractiveWindowContentTypes.CommandContentTypeName)]
    internal sealed class InteractiveWindowResetCommand : IInteractiveWindowCommand
    {
        private const string CommandName = "reset";
        private const string NoConfigParameterName = "noconfig";
        private const string PlatformCore = "core";
        private const string PlatformDesktop32 = "32";
        private const string PlatformDesktop64 = "64";
        private const string PlatformNames = PlatformCore + "|" + PlatformDesktop32 + "|" + PlatformDesktop64;
 
        private static readonly int s_noConfigParameterNameLength = NoConfigParameterName.Length;
        private readonly IStandardClassificationService _registry;
 
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public InteractiveWindowResetCommand(IStandardClassificationService registry)
            => _registry = registry;
 
        public string Description
            => EditorFeaturesWpfResources.Reset_the_execution_environment_to_the_initial_state_and_keep_history_with_the_option_to_switch_the_runtime_of_the_host_process;
 
        public IEnumerable<string> DetailedDescription
            => null;
 
        public IEnumerable<string> Names
            => [CommandName];
 
        public string CommandLine
            => "[" + NoConfigParameterName + "] [" + PlatformNames + "]";
 
        public IEnumerable<KeyValuePair<string, string>> ParametersDescription
        {
            get
            {
                yield return KeyValuePairUtil.Create(NoConfigParameterName, EditorFeaturesWpfResources.Reset_to_a_clean_environment_only_mscorlib_referenced_do_not_run_initialization_script);
                yield return KeyValuePairUtil.Create(PlatformNames, EditorFeaturesWpfResources.Interactive_host_process_platform);
            }
        }
 
        public Task<ExecutionResult> Execute(IInteractiveWindow window, string arguments)
        {
            if (!TryParseArguments(arguments, out var initialize, out var platform))
            {
                ReportInvalidArguments(window);
                return ExecutionResult.Failed;
            }
 
            var evaluator = (CSharpInteractiveEvaluator)window.Evaluator;
            evaluator.ResetOptions = new InteractiveEvaluatorResetOptions(platform);
            return window.Operations.ResetAsync(initialize);
        }
 
        public IEnumerable<ClassificationSpan> ClassifyArguments(ITextSnapshot snapshot, Span argumentsSpan, Span spanToClassify)
        {
            var arguments = snapshot.GetText(argumentsSpan);
            var argumentsStart = argumentsSpan.Start;
            foreach (var pos in GetNoConfigPositions(arguments))
            {
                var snapshotSpan = new SnapshotSpan(snapshot, new Span(argumentsStart + pos, s_noConfigParameterNameLength));
                yield return new ClassificationSpan(snapshotSpan, _registry.Keyword);
            }
        }
        /// <remarks>
        /// Internal for testing.
        /// </remarks>
        internal static IEnumerable<int> GetNoConfigPositions(string arguments)
        {
            var startIndex = 0;
            while (true)
            {
                var index = arguments.IndexOf(NoConfigParameterName, startIndex, StringComparison.Ordinal);
                if (index < 0)
                    yield break;
 
                if ((index == 0 || char.IsWhiteSpace(arguments[index - 1])) &&
                    (index + s_noConfigParameterNameLength == arguments.Length || char.IsWhiteSpace(arguments[index + s_noConfigParameterNameLength])))
                {
                    yield return index;
                }
 
                startIndex = index + s_noConfigParameterNameLength;
            }
        }
 
        /// <remarks>
        /// Accessibility is internal for testing.
        /// </remarks>
        internal static bool TryParseArguments(string arguments, out bool initialize, out InteractiveHostPlatform? platform)
        {
            platform = null;
            initialize = true;
 
            var noConfigSpecified = false;
 
            foreach (var argument in arguments.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
            {
                switch (argument.ToLowerInvariant())
                {
                    case PlatformDesktop32:
                        if (platform != null)
                        {
                            return false;
                        }
 
                        platform = InteractiveHostPlatform.Desktop32;
                        break;
 
                    case PlatformDesktop64:
                        if (platform != null)
                        {
                            return false;
                        }
 
                        platform = InteractiveHostPlatform.Desktop64;
                        break;
 
                    case PlatformCore:
                        if (platform != null)
                        {
                            return false;
                        }
 
                        platform = InteractiveHostPlatform.Core;
                        break;
 
                    case NoConfigParameterName:
                        if (noConfigSpecified)
                        {
                            return false;
                        }
 
                        noConfigSpecified = true;
                        initialize = false;
                        break;
 
                    default:
                        return false;
                }
            }
 
            return true;
        }
 
        internal static string GetCommandLine(bool initialize, InteractiveHostPlatform? platform)
            => CommandName + (initialize ? "" : " " + NoConfigParameterName) + platform switch
            {
                null => "",
                InteractiveHostPlatform.Core => " " + PlatformCore,
                InteractiveHostPlatform.Desktop64 => " " + PlatformDesktop64,
                InteractiveHostPlatform.Desktop32 => " " + PlatformDesktop32,
                _ => throw ExceptionUtilities.Unreachable()
            };
 
        private void ReportInvalidArguments(IInteractiveWindow window)
        {
            var commands = (IInteractiveWindowCommands)window.Properties[typeof(IInteractiveWindowCommands)];
            commands.DisplayCommandUsage(this, window.ErrorOutputWriter, displayDetails: false);
        }
    }
}