This commit is contained in:
Noah Kim 2020-07-17 14:13:13 -04:00
Родитель 35d7d411fd
Коммит 4068b86e7c
4 изменённых файлов: 78 добавлений и 12 удалений

Просмотреть файл

@ -169,6 +169,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer
services.AddSingleton<RazorHoverInfoService, DefaultRazorHoverInfoService>();
services.AddSingleton<HtmlFactsService, DefaultHtmlFactsService>();
// Refactoring
services.AddSingleton<RazorComponentSearchEngine, DefaultRazorComponentSearchEngine>();
// Code actions
services.AddSingleton<RazorCodeActionProvider, ExtractToCodeBehindCodeActionProvider>();
services.AddSingleton<RazorCodeActionResolver, ExtractToCodeBehindCodeActionResolver>();

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring
{
internal class DefaultRazorComponentSearchEngine : RazorComponentSearchEngine
{
private readonly ForegroundDispatcher _foregroundDispatcher;
public DefaultRazorComponentSearchEngine(ForegroundDispatcher dispatcher)
{
_foregroundDispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
}
public async override Task<Tuple<Uri, DocumentSnapshot, RazorCodeDocument>> TryLocateComponent(ProjectSnapshot project, string name, string fullyQualifiedName, CancellationToken cancellationToken)
{
foreach (var path in project.DocumentFilePaths)
{
// Rule out if not Razor component with correct name
if (!Path.GetFileName(path).Equals($"{name}.razor", StringComparison.Ordinal))
{
continue;
}
// Get document and code document
var documentSnapshot = await Task.Factory.StartNew(() => project.GetDocument(path), cancellationToken, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler).ConfigureAwait(false);
var razorCodeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false);
var namespaceNode = (NamespaceDeclarationIntermediateNode)razorCodeDocument
.GetDocumentIntermediateNode()
.FindDescendantNodes<IntermediateNode>()
.FirstOrDefault(n => n is NamespaceDeclarationIntermediateNode);
// Make sure we have the right namespace of the fully qualified name
DefaultRazorTagHelperBinderPhase.ComponentDirectiveVisitor.TrySplitNamespaceAndType(fullyQualifiedName, out var namespaceNameSpan, out var typeNameSpan);
var namespaceName = DefaultRazorTagHelperBinderPhase.ComponentDirectiveVisitor.GetTextSpanContent(namespaceNameSpan, fullyQualifiedName);
var typeName = DefaultRazorTagHelperBinderPhase.ComponentDirectiveVisitor.GetTextSpanContent(typeNameSpan, fullyQualifiedName);
if (!$"{namespaceNode.Content}".Equals(namespaceName, StringComparison.Ordinal))
{
continue;
}
var uri = new UriBuilder
{
Scheme = "file",
Path = path,
Host = string.Empty,
}.Uri;
return Tuple.Create(uri, documentSnapshot, razorCodeDocument);
}
return null;
}
}
}

Просмотреть файл

@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring
{
private readonly ForegroundDispatcher _foregroundDispatcher;
private readonly DocumentResolver _documentResolver;
private readonly RazorComponentSearchEngine _componentSearchEngine;
private readonly ILogger _logger;
private RenameCapability _capability;
@ -32,6 +33,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring
public RazorComponentRenameEndpoint(
ForegroundDispatcher foregroundDispatcher,
DocumentResolver documentResolver,
RazorComponentSearchEngine componentSearchEngine,
ILoggerFactory loggerFactory)
{
if (loggerFactory is null)
@ -41,6 +43,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring
_foregroundDispatcher = foregroundDispatcher ?? throw new ArgumentNullException(nameof(foregroundDispatcher));
_documentResolver = documentResolver ?? throw new ArgumentNullException(nameof(documentResolver));
_componentSearchEngine = componentSearchEngine ?? throw new ArgumentNullException(nameof(componentSearchEngine));
_logger = loggerFactory.CreateLogger<RazorComponentRenameEndpoint>();
}
@ -71,22 +74,24 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring
return null;
}
// RazorComponentSearchEngine.Execute()
var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false);
if (codeDocument.IsUnsupported())
{
return null;
}
RazorComponentSearchEngine.Execute(documentSnapshot);
if (!FileKinds.IsComponent(codeDocument.GetFileKind()))
{
return null;
}
var originTagHelperBinding = await GetOriginTagHelperBindingAsync(documentSnapshot, codeDocument, request.Position).ConfigureAwait(false);
var originTagDescriptor = originTagHelperBinding.Descriptors.First();
_logger.LogDebug($"rename: {originTagHelperBinding.TagName}, {originTagDescriptor.Name}");
var result = await _componentSearchEngine.TryLocateComponent(documentSnapshot.Project, originTagHelperBinding.TagName, originTagDescriptor.Name, cancellationToken).ConfigureAwait(false);
_logger.LogDebug($"rename: {result}");
var documentChanges = new List<WorkspaceEditDocumentChange>();
AddEditsForCodeDocument(documentChanges, originTagHelperBinding, request.TextDocument.Uri, codeDocument, request.NewName);

Просмотреть файл

@ -1,17 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Components;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring
{
internal class RazorComponentSearchEngine
internal abstract class RazorComponentSearchEngine
{
public abstract Task<Tuple<Uri, DocumentSnapshot, RazorCodeDocument>> TryLocateComponent(ProjectSnapshot project, string name, string fullyQualifiedName, CancellationToken cancellationToken);
}
}