Skip to content

Commit

Permalink
Add Xaml command hanler for CreateEventHandler command (#51670)
Browse files Browse the repository at this point in the history
* Add Xaml command handler for CreateEventHandler command

* code review comments

* address cr comments

* Move command title to const string
  • Loading branch information
LinglingTong authored Mar 5, 2021
1 parent 3d685b3 commit b8f5462
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;

namespace Microsoft.VisualStudio.LanguageServices.Xaml.Features.Commands
{
internal interface IXamlCommandService : ILanguageService
{
/// <summary>
/// Execute the <paramref name="command"/> with the <paramref name="commandArguments"/>
/// </summary>
/// <param name="document">TextDocument command was triggered on</param>
/// <param name="command">The command that will be executed</param>
/// <param name="commandArguments">The arguments need by the command</param>
/// <param name="cancellationToken">cancellationToken</param>
/// <returns>True if the command has been executed, otherwise false</returns>
Task<bool> ExecuteCommandAsync(TextDocument document, string command, object[]? commandArguments, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ internal class XamlCompletionItem
public ClassifiedTextElement Description { get; set; }
public ImageElement Icon { get; set; }
public ISymbol Symbol { get; set; }
public XamlEventDescription? EventDescription { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// 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.

using System.Collections.Immutable;

namespace Microsoft.VisualStudio.LanguageServices.Xaml.Features.Completion
{
internal struct XamlEventDescription
{
public string ClassName { get; set; }
public string EventName { get; set; }
public string ReturnType { get; set; }
public ImmutableArray<(string Name, string ParameterType, string Modifier)> Parameters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Editor.Xaml;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler;

Expand All @@ -28,6 +29,7 @@ internal static class XamlCapabilities
},
SupportsDiagnosticRequests = true,
OnTypeRenameProvider = new DocumentOnTypeRenameOptions { WordPattern = OnTypeRenameHandler.NamePattern },
ExecuteCommandProvider = new ExecuteCommandOptions { Commands = new[] { StringConstants.CreateEventHandlerCommand } },
};

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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.

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Xaml;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LanguageServices.Xaml.Features.Commands;
using Microsoft.VisualStudio.LanguageServices.Xaml.Features.Completion;
using Newtonsoft.Json.Linq;
using Roslyn.Utilities;

namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Commands
{
/// <summary>
/// Handle the command that adds an event handler method in code
/// </summary>
internal class CreateEventCommandHandler : AbstractExecuteWorkspaceCommandHandler
{
public override string Command => StringConstants.CreateEventHandlerCommand;

public override bool MutatesSolutionState => false;

public override bool RequiresLSPSolution => true;

public override TextDocumentIdentifier? GetTextDocumentIdentifier(ExecuteCommandParams request)
=> ((JToken)request.Arguments.First()).ToObject<TextDocumentIdentifier>();

public override async Task<object> HandleRequestAsync(ExecuteCommandParams request, RequestContext context, CancellationToken cancellationToken)
{
Contract.ThrowIfNull(request.Arguments);

var document = context.Document;
if (document == null)
{
return false;
}

var commandService = document.Project.LanguageServices.GetService<IXamlCommandService>();
if (commandService == null)
{
return false;
}

// request.Arguments has two argument for CreateEventHandlerCommand
// Arguments[0]: TextDocumentIdentifier
// Arguments[1]: XamlEventDescription
var arguments = new object[] { ((JToken)request.Arguments[1]).ToObject<XamlEventDescription>() };
return await commandService.ExecuteCommandAsync(document, request.Command, arguments, cancellationToken).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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.

using System;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Editor.Xaml;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands;

namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Commands
{
[ExportLspRequestHandlerProvider(StringConstants.XamlLanguageName), Shared]
[ProvidesCommand(StringConstants.CreateEventHandlerCommand)]
internal class CreateEventCommandHandlerProvider : AbstractRequestHandlerProvider
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CreateEventCommandHandlerProvider()
{
}

public override ImmutableArray<IRequestHandler> CreateRequestHandlers()
{
return ImmutableArray.Create<IRequestHandler>(new CreateEventCommandHandler());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler
internal class CompletionHandler : AbstractStatelessRequestHandler<CompletionParams, CompletionList?>
{
public override string Method => Methods.TextDocumentCompletionName;
private const string CreateEventHandlerCommandTitle = "Create Event Handler";

public override bool MutatesSolutionState => false;
public override bool RequiresLSPSolution => true;
Expand Down Expand Up @@ -58,12 +59,12 @@ public CompletionHandler()

return new VSCompletionList
{
Items = completionResult.Completions.Select(c => CreateCompletionItem(c, document.Id, text, request.Position)).ToArray(),
Items = completionResult.Completions.Select(c => CreateCompletionItem(c, document.Id, text, request.Position, request.TextDocument)).ToArray(),
SuggestionMode = false,
};
}

private static CompletionItem CreateCompletionItem(XamlCompletionItem xamlCompletion, DocumentId documentId, SourceText text, Position position)
private static CompletionItem CreateCompletionItem(XamlCompletionItem xamlCompletion, DocumentId documentId, SourceText text, Position position, TextDocumentIdentifier textDocument)
{
var item = new VSCompletionItem
{
Expand All @@ -89,6 +90,16 @@ private static CompletionItem CreateCompletionItem(XamlCompletionItem xamlComple
};
}

if (xamlCompletion.EventDescription.HasValue)
{
item.Command = new Command()
{
CommandIdentifier = StringConstants.CreateEventHandlerCommand,
Arguments = new object[] { textDocument, xamlCompletion.EventDescription },
Title = CreateEventHandlerCommandTitle
};
}

return item;
}

Expand Down
2 changes: 2 additions & 0 deletions src/VisualStudio/Xaml/Impl/StringConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ internal static class StringConstants
public const string XamlFileExtension = ".xaml";

public const string EnableLspIntelliSense = "Xaml.EnableLspIntelliSense";

public const string CreateEventHandlerCommand = "Xaml.CreateEventHandler";
}
}

0 comments on commit b8f5462

Please sign in to comment.