提交 53d2e777 编写于 作者: M Manish Jayaswal

Merge pull request #4708 from ManishJayaswal/CSharpVBResetCommand

CSharp VB reset command
// 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.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.VisualStudio.Editor.Interactive
{
/// <summary>
/// Repesents the content type for specialized interactive commands for C# and VB
/// interactive window which override the implementation of these commands in underlying
/// interactive window.
/// </summary>
public static class CSharpVBInteractiveCommandsContentTypes
{
public const string CSharpVBInteractiveCommandContentTypeName = "Specialized CSharp and VB Interactive Command";
[Export, Name(CSharpVBInteractiveCommandContentTypeName), BaseDefinition("code")]
internal static readonly ContentTypeDefinition CSharpVBInteractiveCommandContentTypeDefinition;
}
}
// 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.ObjectModel;
using System.ComponentModel.Composition;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Language.StandardClassification;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.InteractiveWindow;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Editor.Interactive;
using Microsoft.CodeAnalysis.Editor.Interactive;
namespace Microsoft.VisualStudio.InteractiveWindow.Commands
{
/// <summary>
/// Represents a reset command which can be run from a REPL window.
/// </summary>
[Export(typeof(IInteractiveWindowCommand))]
[ContentType(CSharpVBInteractiveCommandsContentTypes.CSharpVBInteractiveCommandContentTypeName)]
internal sealed class ResetCommand : IInteractiveWindowCommand
{
private const string CommandName = "reset";
private const string NoConfigParameterName = "noconfig";
private static readonly int NoConfigParameterNameLength = NoConfigParameterName.Length;
private readonly IStandardClassificationService _registry;
[ImportingConstructor]
public ResetCommand(IStandardClassificationService registry)
{
_registry = registry;
}
public string Description
{
// TODO: Needs localization...
get { return "Reset the execution environment to the initial state, keep history."; }
}
public IEnumerable<string> DetailedDescription
{
get { return null; }
}
public IEnumerable<string> Names
{
get { yield return CommandName; }
}
public string CommandLine
{
get { return "[" + NoConfigParameterName + "]"; }
}
public IEnumerable<KeyValuePair<string, string>> ParametersDescription
{
get
{
// TODO: Needs localization...
yield return new KeyValuePair<string, string>(NoConfigParameterName, "Reset to a clean environment (only mscorlib referenced), do not run initialization script.");
}
}
public Task<ExecutionResult> Execute(IInteractiveWindow window, string arguments)
{
bool initialize;
if (!TryParseArguments(arguments, out initialize))
{
ReportInvalidArguments(window);
return ExecutionResult.Failed;
}
return window.Operations.ResetAsync(initialize);
}
internal static string BuildCommandLine(bool initialize)
{
string result = CommandName;
return initialize ? result : result + " " + NoConfigParameterName;
}
public IEnumerable<ClassificationSpan> ClassifyArguments(ITextSnapshot snapshot, Span argumentsSpan, Span spanToClassify)
{
string arguments = snapshot.GetText(argumentsSpan);
int argumentsStart = argumentsSpan.Start;
foreach (var pos in GetNoConfigPositions(arguments))
{
var snapshotSpan = new SnapshotSpan(snapshot, new Span(argumentsStart + pos, NoConfigParameterNameLength));
yield return new ClassificationSpan(snapshotSpan, _registry.Keyword);
}
}
/// <remarks>
/// Internal for testing.
/// </remarks>
internal static IEnumerable<int> GetNoConfigPositions(string arguments)
{
int startIndex = 0;
while (true)
{
int index = arguments.IndexOf(NoConfigParameterName, startIndex, StringComparison.Ordinal);
if (index < 0) yield break;
if ((index == 0 || char.IsWhiteSpace(arguments[index - 1])) &&
(index + NoConfigParameterNameLength == arguments.Length || char.IsWhiteSpace(arguments[index + NoConfigParameterNameLength])))
{
yield return index;
}
startIndex = index + NoConfigParameterNameLength;
}
}
/// <remarks>
/// Accessibility is internal for testing.
/// </remarks>
internal static bool TryParseArguments(string arguments, out bool initialize)
{
var trimmed = arguments.Trim();
if (trimmed.Length == 0)
{
initialize = true;
return true;
}
else if (string.Equals(trimmed, NoConfigParameterName, StringComparison.Ordinal))
{
initialize = false;
return true;
}
initialize = false;
return false;
}
private void ReportInvalidArguments(IInteractiveWindow window)
{
var commands = (IInteractiveWindowCommands)window.Properties[typeof(IInteractiveWindowCommands)];
commands.DisplayCommandUsage(this, window.ErrorOutputWriter, displayDetails: false);
}
}
}
......@@ -148,9 +148,11 @@
<ItemGroup>
<Compile Include="CommandHandlers\InteractiveCompletionCommandHandler.cs" />
<Compile Include="CommandHandlers\InteractiveIntelliSenseCommandHandler.cs" />
<Compile Include="Extensibility\Interactive\CSharpVBResetCommand.cs" />
<Compile Include="Extensibility\Interactive\InteractiveCommandHandler.cs" />
<Compile Include="Extensibility\Interactive\InteractiveEvaluator.cs" />
<Compile Include="Extensibility\Interactive\InteractiveMetadataReferenceResolver.cs" />
<Compile Include="Extensibility\Interactive\CSharpVBInteractiveCommandContentTypes.cs" />
<Compile Include="Implementation\Completion\InteractiveCommandCompletionService.cs" />
<Compile Include="Implementation\Completion\Presentation\CompletionPresenter.cs" />
<Compile Include="Implementation\Interactive\Commands\CommandArgumentsParser.cs" />
......
// 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.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Editor.Interactive;
using Microsoft.VisualStudio.Editor.Interactive;
using Microsoft.VisualStudio.InteractiveWindow.Commands;
using Microsoft.VisualStudio.InteractiveWindow.Shell;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.InteractiveWindow.Commands;
using Microsoft.VisualStudio.InteractiveWindow.Shell;
namespace Microsoft.VisualStudio.LanguageServices.Interactive
{
......@@ -40,7 +42,8 @@ internal abstract class VsInteractiveWindowProvider
_classifierAggregator = classifierAggregator;
_contentTypeRegistry = contentTypeRegistry;
_vsWorkspace = workspace;
_commands = FilterCommands(commands, contentType: PredefinedInteractiveCommandsContentTypes.InteractiveCommandContentTypeName);
_commands = GetApplicableCommands(commands, coreContentType: PredefinedInteractiveCommandsContentTypes.InteractiveCommandContentTypeName,
specializedContentType: CSharpVBInteractiveCommandsContentTypes.CSharpVBInteractiveCommandContentTypeName);
_vsInteractiveWindowFactory = interactiveWindowFactory;
_commandsFactory = commandsFactory;
}
......@@ -114,11 +117,43 @@ public IVsInteractiveWindow Open(int instanceId, bool focus)
return _vsInteractiveWindow;
}
private static ImmutableArray<IInteractiveWindowCommand> FilterCommands(IInteractiveWindowCommand[] commands, string contentType)
private static ImmutableArray<IInteractiveWindowCommand> GetApplicableCommands(IInteractiveWindowCommand[] commands, string coreContentType, string specializedContentType)
{
return commands.Where(
// get all commands of coreContentType - generic interactive window commands
var interactiveCommands = commands.Where(
c => c.GetType().GetCustomAttributes(typeof(ContentTypeAttribute), inherit: true).Any(
a => ((ContentTypeAttribute)a).ContentTypes == contentType)).ToImmutableArray();
a => ((ContentTypeAttribute)a).ContentTypes == coreContentType)).ToArray();
// get all commands of specializedContentType - smart C#/VB command implementations
var specializedInteractiveCommands = commands.Where(
c => c.GetType().GetCustomAttributes(typeof(ContentTypeAttribute), inherit: true).Any(
a => ((ContentTypeAttribute)a).ContentTypes == specializedContentType)).ToArray();
// We should choose specialized C#/VB commands over generic core interactive window commands
// Build a map of names and associated core command first
Dictionary<string, int> interactiveCommandMap = new Dictionary<string, int>();
for (int i = 0; i < interactiveCommands.Length; i++)
{
foreach (var name in interactiveCommands[i].Names)
interactiveCommandMap.Add(name, i);
}
// swap core commands with specialized command if both exist
// Command can have multiple names. We need to compare every name to find match.
foreach (var command in specializedInteractiveCommands)
{
foreach (var name in command.Names)
{
if ( interactiveCommandMap.ContainsKey(name))
{
int value;
interactiveCommandMap.TryGetValue(name, out value);
interactiveCommands[value] = command;
break;
}
}
}
return interactiveCommands.ToImmutableArray();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册