зеркало из https://github.com/dotnet/razor.git
Merge pull request #9194 from DustinCampbell/completion-cleanup
Clean up completion to return ImmutableArray<T> rather than IReadOnlyList<T>
This commit is contained in:
Коммит
548eefdfed
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
||||
|
@ -39,9 +39,9 @@ internal class DirectiveAttributeTransitionCompletionItemProvider : DirectiveAtt
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly IReadOnlyList<RazorCompletionItem> s_completions = new[] { TransitionCompletionItem };
|
||||
private static readonly ImmutableArray<RazorCompletionItem> s_completions = ImmutableArray.Create(TransitionCompletionItem);
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
public override ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
|
@ -51,13 +51,13 @@ internal class DirectiveAttributeTransitionCompletionItemProvider : DirectiveAtt
|
|||
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
||||
{
|
||||
// Directive attributes are only supported in components
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var owner = context.Owner;
|
||||
if (owner is null)
|
||||
{
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var attribute = owner.Parent;
|
||||
|
@ -69,19 +69,19 @@ internal class DirectiveAttributeTransitionCompletionItemProvider : DirectiveAtt
|
|||
|
||||
if (!TryGetAttributeInfo(owner, out var prefixLocation, out var attributeName, out var attributeNameLocation, out _, out _))
|
||||
{
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (attributeNameLocation.IntersectsWith(context.AbsoluteIndex) && attributeName.StartsWith("@", StringComparison.Ordinal))
|
||||
{
|
||||
// The transition is already provided for the attribute name
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!IsValidCompletionPoint(context.AbsoluteIndex, prefixLocation, attributeNameLocation))
|
||||
{
|
||||
// Not operating in the attribute name area
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
// This represents a tag when there's no attribute content <InputText | />.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT license. 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.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Razor.Language;
|
|||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
|
||||
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
||||
|
@ -23,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
|||
// for this legacy version.
|
||||
internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
||||
{
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
private readonly CompletionListCache _completionListCache;
|
||||
private static readonly Command s_retriggerCompletionCommand = new()
|
||||
{
|
||||
|
@ -34,22 +35,10 @@ internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
|||
|
||||
public bool MutatesSolutionState => false;
|
||||
|
||||
public LegacyRazorCompletionEndpoint(
|
||||
RazorCompletionFactsService completionFactsService,
|
||||
CompletionListCache completionListCache)
|
||||
public LegacyRazorCompletionEndpoint(IRazorCompletionFactsService completionFactsService, CompletionListCache completionListCache)
|
||||
{
|
||||
if (completionFactsService is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionFactsService));
|
||||
}
|
||||
|
||||
if (completionListCache is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionListCache));
|
||||
}
|
||||
|
||||
_completionFactsService = completionFactsService;
|
||||
_completionListCache = completionListCache;
|
||||
_completionFactsService = completionFactsService ?? throw new ArgumentNullException(nameof(completionFactsService));
|
||||
_completionListCache = completionListCache ?? throw new ArgumentNullException(nameof(completionListCache));
|
||||
}
|
||||
|
||||
public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities)
|
||||
|
@ -107,7 +96,7 @@ internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
|||
|
||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(completionContext);
|
||||
|
||||
requestContext.Logger.LogTrace("Resolved {razorCompletionItemsCount} completion items.", razorCompletionItems.Count);
|
||||
requestContext.Logger.LogTrace("Resolved {razorCompletionItemsCount} completion items.", razorCompletionItems.Length);
|
||||
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItems);
|
||||
var completionCapability = _clientCapabilities?.TextDocument?.Completion as VSInternalCompletionSetting;
|
||||
|
@ -140,31 +129,33 @@ internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
|||
}
|
||||
|
||||
// Internal for testing
|
||||
internal VSInternalCompletionList CreateLSPCompletionList(IReadOnlyList<RazorCompletionItem> razorCompletionItems) => CreateLSPCompletionList(razorCompletionItems, _clientCapabilities!);
|
||||
internal VSInternalCompletionList CreateLSPCompletionList(ImmutableArray<RazorCompletionItem> razorCompletionItems)
|
||||
=> CreateLSPCompletionList(razorCompletionItems, _clientCapabilities!);
|
||||
|
||||
// Internal for benchmarking and testing
|
||||
internal static VSInternalCompletionList CreateLSPCompletionList(
|
||||
IReadOnlyList<RazorCompletionItem> razorCompletionItems,
|
||||
ImmutableArray<RazorCompletionItem> razorCompletionItems,
|
||||
VSInternalClientCapabilities clientCapabilities)
|
||||
{
|
||||
var completionItems = new List<CompletionItem>();
|
||||
using var items = new PooledArrayBuilder<CompletionItem>();
|
||||
|
||||
foreach (var razorCompletionItem in razorCompletionItems)
|
||||
{
|
||||
if (TryConvert(razorCompletionItem, clientCapabilities, out var completionItem))
|
||||
{
|
||||
completionItems.Add(completionItem);
|
||||
items.Add(completionItem);
|
||||
}
|
||||
}
|
||||
|
||||
var completionList = new VSInternalCompletionList()
|
||||
{
|
||||
Items = completionItems.ToArray(),
|
||||
Items = items.ToArray(),
|
||||
IsIncomplete = false,
|
||||
};
|
||||
|
||||
var completionCapability = clientCapabilities?.TextDocument?.Completion as VSInternalCompletionSetting;
|
||||
var optimizedCompletionList = CompletionListOptimizer.Optimize(completionList, completionCapability);
|
||||
return optimizedCompletionList;
|
||||
|
||||
return CompletionListOptimizer.Optimize(completionList, completionCapability);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
||||
|
@ -20,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
|||
|
||||
internal class RazorCompletionListProvider
|
||||
{
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
private readonly CompletionListCache _completionListCache;
|
||||
private readonly ILogger<RazorCompletionListProvider> _logger;
|
||||
private static readonly Command s_retriggerCompletionCommand = new()
|
||||
|
@ -30,7 +31,7 @@ internal class RazorCompletionListProvider
|
|||
};
|
||||
|
||||
public RazorCompletionListProvider(
|
||||
RazorCompletionFactsService completionFactsService,
|
||||
IRazorCompletionFactsService completionFactsService,
|
||||
CompletionListCache completionListCache,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
|
@ -63,6 +64,7 @@ internal class RazorCompletionListProvider
|
|||
CompletionTriggerKind.TriggerCharacter => CompletionReason.Typing,
|
||||
_ => CompletionReason.Typing,
|
||||
};
|
||||
|
||||
var completionOptions = new RazorCompletionOptions(SnippetsSupported: true);
|
||||
var syntaxTree = await documentContext.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
|
||||
var tagHelperContext = await documentContext.GetTagHelperContextAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
@ -79,7 +81,7 @@ internal class RazorCompletionListProvider
|
|||
|
||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
||||
|
||||
_logger.LogTrace("Resolved {razorCompletionItemsCount} completion items.", razorCompletionItems.Count);
|
||||
_logger.LogTrace("Resolved {razorCompletionItemsCount} completion items.", razorCompletionItems.Length);
|
||||
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItems, clientCapabilities);
|
||||
|
||||
|
@ -94,27 +96,28 @@ internal class RazorCompletionListProvider
|
|||
|
||||
// Internal for benchmarking and testing
|
||||
internal static VSInternalCompletionList CreateLSPCompletionList(
|
||||
IReadOnlyList<RazorCompletionItem> razorCompletionItems,
|
||||
ImmutableArray<RazorCompletionItem> razorCompletionItems,
|
||||
VSInternalClientCapabilities clientCapabilities)
|
||||
{
|
||||
var completionItems = new List<CompletionItem>();
|
||||
using var items = new PooledArrayBuilder<CompletionItem>();
|
||||
|
||||
foreach (var razorCompletionItem in razorCompletionItems)
|
||||
{
|
||||
if (TryConvert(razorCompletionItem, clientCapabilities, out var completionItem))
|
||||
{
|
||||
completionItems.Add(completionItem);
|
||||
items.Add(completionItem);
|
||||
}
|
||||
}
|
||||
|
||||
var completionList = new VSInternalCompletionList()
|
||||
{
|
||||
Items = completionItems.ToArray(),
|
||||
Items = items.ToArray(),
|
||||
IsIncomplete = false,
|
||||
};
|
||||
|
||||
var completionCapability = clientCapabilities.TextDocument?.Completion as VSInternalCompletionSetting;
|
||||
var optimizedCompletionList = CompletionListOptimizer.Optimize(completionList, completionCapability);
|
||||
return optimizedCompletionList;
|
||||
|
||||
return CompletionListOptimizer.Optimize(completionList, completionCapability);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
@ -15,7 +17,7 @@ using Microsoft.VisualStudio.Editor.Razor;
|
|||
|
||||
namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
||||
|
||||
internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||
internal class TagHelperCompletionProvider : IRazorCompletionItemProvider
|
||||
{
|
||||
// Internal for testing
|
||||
internal static readonly IReadOnlyList<RazorCommitCharacter> MinimizedAttributeCommitCharacters = RazorCommitCharacter.FromArray(new[] { "=", " " });
|
||||
|
@ -41,7 +43,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
_optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor));
|
||||
}
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
|
@ -52,7 +54,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
if (owner is null)
|
||||
{
|
||||
Debug.Fail("Owner should never be null.");
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var parent = owner.Parent;
|
||||
|
@ -102,13 +104,13 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
//
|
||||
// Will be interpreted as having an `@code` attribute name due to multi-line attributes being a thing. Ultimately this is mostly a
|
||||
// heuristic that we have to apply in order to workaround limitations of the Razor compiler.
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var stringifiedAttributes = _tagHelperFactsService.StringifyAttributes(attributes);
|
||||
var attributeCompletions = GetAttributeCompletions(parent, containingTagNameToken.Content, selectedAttributeName, stringifiedAttributes, context.TagHelperDocumentContext, context.Options);
|
||||
return attributeCompletions;
|
||||
|
||||
return GetAttributeCompletions(parent, containingTagNameToken.Content, selectedAttributeName, stringifiedAttributes, context.TagHelperDocumentContext, context.Options);
|
||||
|
||||
static bool InOrAtEndOfAttribute(SyntaxNode attributeSyntax, int absoluteIndex)
|
||||
{
|
||||
// When we are in the middle of writing an attribute it is treated as a minimilized one, e.g.:
|
||||
|
@ -123,10 +125,10 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
}
|
||||
|
||||
// Invalid location for TagHelper completions.
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
private IReadOnlyList<RazorCompletionItem> GetAttributeCompletions(
|
||||
private ImmutableArray<RazorCompletionItem> GetAttributeCompletions(
|
||||
SyntaxNode containingAttribute,
|
||||
string containingTagName,
|
||||
string? selectedAttributeName,
|
||||
|
@ -148,8 +150,9 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
ancestorIsTagHelper,
|
||||
HtmlFactsService.IsHtmlTagName);
|
||||
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
var completionResult = _tagHelperCompletionService.GetAttributeCompletions(attributeCompletionContext);
|
||||
|
||||
foreach (var completion in completionResult.Completions)
|
||||
{
|
||||
var filterText = completion.Key;
|
||||
|
@ -202,13 +205,14 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
|
||||
return descriptionInfo;
|
||||
});
|
||||
|
||||
var attributeDescriptionInfo = new AggregateBoundAttributeDescription(attributeDescriptions.ToList());
|
||||
razorCompletionItem.SetAttributeCompletionDescription(attributeDescriptionInfo);
|
||||
|
||||
completionItems.Add(razorCompletionItem);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
return completionItems.DrainToImmutable();
|
||||
}
|
||||
|
||||
private bool TryResolveInsertText(string baseInsertText, AttributeContext context, [NotNullWhen(true)] out string? snippetText)
|
||||
|
@ -231,7 +235,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
return false;
|
||||
}
|
||||
|
||||
private IReadOnlyList<RazorCompletionItem> GetElementCompletions(
|
||||
private ImmutableArray<RazorCompletionItem> GetElementCompletions(
|
||||
SyntaxNode containingElement,
|
||||
string containingTagName,
|
||||
IEnumerable<KeyValuePair<string, string>> attributes,
|
||||
|
@ -248,7 +252,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
ancestorIsTagHelper,
|
||||
HtmlFactsService.IsHtmlTagName);
|
||||
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
var completionResult = _tagHelperCompletionService.GetElementCompletions(elementCompletionContext);
|
||||
foreach (var completion in completionResult.Completions)
|
||||
{
|
||||
|
@ -265,7 +269,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
|||
completionItems.Add(razorCompletionItem);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
return completionItems.DrainToImmutable();
|
||||
}
|
||||
|
||||
private const string BooleanTypeString = "System.Boolean";
|
||||
|
|
|
@ -93,13 +93,13 @@ internal static class IServiceCollectionExtensions
|
|||
services.AddSingleton<CompletionItemResolver, RazorCompletionItemResolver>();
|
||||
services.AddSingleton<CompletionItemResolver, DelegatedCompletionItemResolver>();
|
||||
services.AddSingleton<TagHelperCompletionService, LanguageServerTagHelperCompletionService>();
|
||||
services.AddSingleton<RazorCompletionFactsService, DefaultRazorCompletionFactsService>();
|
||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveCompletionItemProvider>();
|
||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
|
||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
|
||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
|
||||
services.AddSingleton<RazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();
|
||||
services.AddSingleton<RazorCompletionItemProvider, TagHelperCompletionProvider>();
|
||||
services.AddSingleton<IRazorCompletionFactsService, RazorCompletionFactsService>();
|
||||
services.AddSingleton<IRazorCompletionItemProvider, DirectiveCompletionItemProvider>();
|
||||
services.AddSingleton<IRazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
|
||||
services.AddSingleton<IRazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
|
||||
services.AddSingleton<IRazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
|
||||
services.AddSingleton<IRazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();
|
||||
services.AddSingleton<IRazorCompletionItemProvider, TagHelperCompletionProvider>();
|
||||
}
|
||||
|
||||
public static void AddDiagnosticServices(this IServiceCollection services)
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
[Shared]
|
||||
[Export(typeof(RazorCompletionFactsService))]
|
||||
internal class DefaultRazorCompletionFactsService : RazorCompletionFactsService
|
||||
{
|
||||
private readonly IReadOnlyList<RazorCompletionItemProvider> _completionItemProviders;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultRazorCompletionFactsService([ImportMany] IEnumerable<RazorCompletionItemProvider> completionItemProviders)
|
||||
{
|
||||
if (completionItemProviders is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionItemProviders));
|
||||
}
|
||||
|
||||
_completionItemProviders = completionItemProviders.ToArray();
|
||||
}
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (context.TagHelperDocumentContext is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context.TagHelperDocumentContext));
|
||||
}
|
||||
|
||||
var completions = new List<RazorCompletionItem>();
|
||||
for (var i = 0; i < _completionItemProviders.Count; i++)
|
||||
{
|
||||
var completionItemProvider = _completionItemProviders[i];
|
||||
var items = completionItemProvider.GetCompletionItems(context);
|
||||
completions.AddRange(items);
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
}
|
|
@ -5,20 +5,20 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
using Microsoft.VisualStudio.Editor.Razor;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
[Shared]
|
||||
[Export(typeof(RazorCompletionItemProvider))]
|
||||
[Export(typeof(IRazorCompletionItemProvider))]
|
||||
internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeCompletionItemProviderBase
|
||||
{
|
||||
private static readonly RazorCompletionItem[] s_noDirectiveAttributeCompletionItems = Array.Empty<RazorCompletionItem>();
|
||||
|
||||
private readonly TagHelperFactsService _tagHelperFactsService;
|
||||
|
||||
[ImportingConstructor]
|
||||
|
@ -32,7 +32,7 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
|||
_tagHelperFactsService = tagHelperFactsService;
|
||||
}
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
public override ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
|
@ -47,31 +47,31 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
|||
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
||||
{
|
||||
// Directive attributes are only supported in components
|
||||
return s_noDirectiveAttributeCompletionItems;
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var owner = context.Owner;
|
||||
if (owner is null)
|
||||
{
|
||||
return s_noDirectiveAttributeCompletionItems;
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!TryGetAttributeInfo(owner, out _, out var attributeName, out var attributeNameLocation, out _, out _))
|
||||
{
|
||||
// Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions.
|
||||
return s_noDirectiveAttributeCompletionItems;
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!attributeNameLocation.IntersectsWith(context.AbsoluteIndex))
|
||||
{
|
||||
// We're trying to retrieve completions on a portion of the name that is not supported (such as a parameter).
|
||||
return s_noDirectiveAttributeCompletionItems;
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes))
|
||||
{
|
||||
// This should never be the case, it means that we're operating on an attribute that doesn't have a tag.
|
||||
return s_noDirectiveAttributeCompletionItems;
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
// At this point we've determined that completions have been requested for the name portion of the selected attribute.
|
||||
|
@ -86,11 +86,11 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
|||
return completionItems;
|
||||
}
|
||||
|
||||
return s_noDirectiveAttributeCompletionItems;
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal IReadOnlyList<RazorCompletionItem> GetAttributeCompletions(
|
||||
internal ImmutableArray<RazorCompletionItem> GetAttributeCompletions(
|
||||
string selectedAttributeName,
|
||||
string containingTagName,
|
||||
IEnumerable<string> attributes,
|
||||
|
@ -100,7 +100,7 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
|||
if (descriptorsForTag.Count == 0)
|
||||
{
|
||||
// If the current tag has no possible descriptors then we can't have any directive attributes.
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
// Attributes are case sensitive when matching
|
||||
|
@ -141,7 +141,8 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
|||
}
|
||||
}
|
||||
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
|
||||
foreach (var completion in attributeCompletions)
|
||||
{
|
||||
var insertText = completion.Key;
|
||||
|
@ -173,7 +174,7 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
|||
completionItems.Add(razorCompletionItem);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
return completionItems.DrainToImmutable();
|
||||
|
||||
bool TryAddCompletion(string attributeName, BoundAttributeDescriptor boundAttributeDescriptor, TagHelperDescriptor tagHelperDescriptor)
|
||||
{
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||
using RazorSyntaxList = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxList<Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode>;
|
||||
using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
internal abstract class DirectiveAttributeCompletionItemProviderBase : RazorCompletionItemProvider
|
||||
internal abstract class DirectiveAttributeCompletionItemProviderBase : IRazorCompletionItemProvider
|
||||
{
|
||||
public abstract ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context);
|
||||
|
||||
// Internal for testing
|
||||
internal static bool TryGetAttributeInfo(
|
||||
RazorSyntaxNode attributeLeafOwner,
|
||||
|
|
|
@ -5,16 +5,18 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
using Microsoft.VisualStudio.Editor.Razor;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
[Shared]
|
||||
[Export(typeof(RazorCompletionItemProvider))]
|
||||
[Export(typeof(IRazorCompletionItemProvider))]
|
||||
internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttributeCompletionItemProviderBase
|
||||
{
|
||||
private readonly TagHelperFactsService _tagHelperFactsService;
|
||||
|
@ -30,7 +32,7 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
|||
_tagHelperFactsService = tagHelperFactsService;
|
||||
}
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
public override ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
|
@ -45,39 +47,38 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
|||
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
||||
{
|
||||
// Directive attribute parameters are only supported in components
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var owner = context.Owner;
|
||||
if (owner is null)
|
||||
{
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!TryGetAttributeInfo(owner, out _, out var attributeName, out _, out var parameterName, out var parameterNameLocation))
|
||||
{
|
||||
// Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions.
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!parameterNameLocation.IntersectsWith(context.AbsoluteIndex))
|
||||
{
|
||||
// We're trying to retrieve completions on a portion of the name that is not supported (such as the name, i.e., |@bind|:format).
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes))
|
||||
{
|
||||
// This should never be the case, it means that we're operating on an attribute that doesn't have a tag.
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var completions = GetAttributeParameterCompletions(attributeName, parameterName, containingTagName, attributes, context.TagHelperDocumentContext);
|
||||
return completions;
|
||||
return GetAttributeParameterCompletions(attributeName, parameterName, containingTagName, attributes, context.TagHelperDocumentContext);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal IReadOnlyList<RazorCompletionItem> GetAttributeParameterCompletions(
|
||||
internal ImmutableArray<RazorCompletionItem> GetAttributeParameterCompletions(
|
||||
string attributeName,
|
||||
string parameterName,
|
||||
string containingTagName,
|
||||
|
@ -88,7 +89,7 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
|||
if (descriptorsForTag.Count == 0)
|
||||
{
|
||||
// If the current tag has no possible descriptors then we can't have any additional attributes.
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
// Attribute parameters are case sensitive when matching
|
||||
|
@ -130,7 +131,8 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
|||
}
|
||||
}
|
||||
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
|
||||
foreach (var completion in attributeCompletions)
|
||||
{
|
||||
if (string.Equals(completion.Key, parameterName, StringComparison.Ordinal))
|
||||
|
@ -150,6 +152,6 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
|||
completionItems.Add(razorCompletionItem);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
return completionItems.DrainToImmutable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,17 +5,19 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
[Shared]
|
||||
[Export(typeof(RazorCompletionItemProvider))]
|
||||
internal class DirectiveCompletionItemProvider : RazorCompletionItemProvider
|
||||
[Export(typeof(IRazorCompletionItemProvider))]
|
||||
internal class DirectiveCompletionItemProvider : IRazorCompletionItemProvider
|
||||
{
|
||||
internal static readonly IReadOnlyList<RazorCommitCharacter> SingleLineDirectiveCommitCharacters = RazorCommitCharacter.FromArray(new[] { " " });
|
||||
internal static readonly IReadOnlyList<RazorCommitCharacter> BlockDirectiveCommitCharacters = RazorCommitCharacter.FromArray(new[] { " ", "{" });
|
||||
|
@ -46,21 +48,22 @@ internal class DirectiveCompletionItemProvider : RazorCompletionItemProvider
|
|||
["typeparam"] = ("typeparam ${1:T}$0", "typeparam T")
|
||||
};
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var completions = new List<RazorCompletionItem>();
|
||||
using var completions = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
|
||||
if (ShouldProvideCompletions(context))
|
||||
{
|
||||
var directiveCompletions = GetDirectiveCompletionItems(context.SyntaxTree);
|
||||
completions.AddRange(directiveCompletions);
|
||||
}
|
||||
|
||||
return completions;
|
||||
return completions.DrainToImmutable();
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
|
@ -126,11 +129,13 @@ internal class DirectiveCompletionItemProvider : RazorCompletionItemProvider
|
|||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static List<RazorCompletionItem> GetDirectiveCompletionItems(RazorSyntaxTree syntaxTree)
|
||||
internal static ImmutableArray<RazorCompletionItem> GetDirectiveCompletionItems(RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
var defaultDirectives = FileKinds.IsComponent(syntaxTree.Options.FileKind) ? Array.Empty<DirectiveDescriptor>() : s_defaultDirectives;
|
||||
var directives = syntaxTree.Options.Directives.Concat(defaultDirectives);
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
|
||||
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
|
||||
foreach (var directive in directives)
|
||||
{
|
||||
var completionDisplayText = directive.DisplayName ?? directive.Directive;
|
||||
|
@ -164,7 +169,7 @@ internal class DirectiveCompletionItemProvider : RazorCompletionItemProvider
|
|||
}
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
return completionItems.DrainToImmutable();
|
||||
}
|
||||
|
||||
private static IReadOnlyList<RazorCommitCharacter> GetDirectiveCommitCharacters(DirectiveKind directiveKind)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
internal abstract class RazorCompletionItemProvider
|
||||
internal interface IRazorCompletionFactsService
|
||||
{
|
||||
public abstract IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context);
|
||||
ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext razorCompletionContext);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
internal interface IRazorCompletionItemProvider
|
||||
{
|
||||
ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context);
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||
|
@ -11,7 +12,7 @@ using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode;
|
|||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvider
|
||||
internal class MarkupTransitionCompletionItemProvider : IRazorCompletionItemProvider
|
||||
{
|
||||
private static readonly IReadOnlyList<RazorCommitCharacter> s_elementCommitCharacters = RazorCommitCharacter.FromArray(new[] { ">" });
|
||||
|
||||
|
@ -40,15 +41,10 @@ internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvi
|
|||
|
||||
public MarkupTransitionCompletionItemProvider(HtmlFactsService htmlFactsService)
|
||||
{
|
||||
if (htmlFactsService is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(htmlFactsService));
|
||||
}
|
||||
|
||||
_htmlFactsService = htmlFactsService;
|
||||
_htmlFactsService = htmlFactsService ?? throw new ArgumentNullException(nameof(htmlFactsService));
|
||||
}
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
|
@ -59,12 +55,12 @@ internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvi
|
|||
if (owner is null)
|
||||
{
|
||||
Debug.Fail("Owner should never be null.");
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
if (!AtMarkupTransitionCompletionPoint(owner))
|
||||
{
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var parent = owner.Parent;
|
||||
|
@ -74,11 +70,10 @@ internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvi
|
|||
if (!_htmlFactsService.TryGetElementInfo(parent, out var containingTagNameToken, out _) ||
|
||||
!containingTagNameToken.Span.IntersectsWith(context.AbsoluteIndex))
|
||||
{
|
||||
return Array.Empty<RazorCompletionItem>();
|
||||
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||
}
|
||||
|
||||
var completions = new List<RazorCompletionItem>() { MarkupTransitionCompletionItem };
|
||||
return completions;
|
||||
return ImmutableArray.Create(MarkupTransitionCompletionItem);
|
||||
}
|
||||
|
||||
private static bool AtMarkupTransitionCompletionPoint(RazorSyntaxNode owner)
|
||||
|
|
|
@ -1,11 +1,51 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Composition;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
internal abstract class RazorCompletionFactsService
|
||||
[Shared]
|
||||
[Export(typeof(IRazorCompletionFactsService))]
|
||||
internal class RazorCompletionFactsService : IRazorCompletionFactsService
|
||||
{
|
||||
public abstract IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext razorCompletionContext);
|
||||
private readonly ImmutableArray<IRazorCompletionItemProvider> _providers;
|
||||
|
||||
[ImportingConstructor]
|
||||
public RazorCompletionFactsService([ImportMany] IEnumerable<IRazorCompletionItemProvider> providers)
|
||||
{
|
||||
if (providers is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(providers));
|
||||
}
|
||||
|
||||
_providers = providers.ToImmutableArray();
|
||||
}
|
||||
|
||||
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (context.TagHelperDocumentContext is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context.TagHelperDocumentContext));
|
||||
}
|
||||
|
||||
using var completions = new PooledArrayBuilder<RazorCompletionItem>();
|
||||
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
var items = provider.GetCompletionItems(context);
|
||||
completions.AddRange(items);
|
||||
}
|
||||
|
||||
return completions.DrainToImmutable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
||||
|
||||
/// <summary>
|
||||
/// Compares <see cref="CompletionItem"/>s by display text using the current culture.
|
||||
/// </summary>
|
||||
internal sealed class CompletionItemDisplayTextComparer : IComparer<CompletionItem>
|
||||
{
|
||||
public static readonly CompletionItemDisplayTextComparer Instance = new();
|
||||
|
||||
private CompletionItemDisplayTextComparer()
|
||||
{
|
||||
}
|
||||
|
||||
public int Compare(CompletionItem x, CompletionItem y)
|
||||
{
|
||||
var displayText1 = x?.DisplayText;
|
||||
var displayText2 = y?.DisplayText;
|
||||
|
||||
if (displayText1 is null)
|
||||
{
|
||||
if (displayText2 is not null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (displayText2 is null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return StringComparer.CurrentCulture.Compare(displayText1, displayText2);
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
using Microsoft.VisualStudio.Core.Imaging;
|
||||
using Microsoft.VisualStudio.Text.Adornments;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
||||
|
||||
[Shared]
|
||||
[Export(typeof(VisualStudioDescriptionFactory))]
|
||||
internal class DefaultVisualStudioDescriptionFactory : VisualStudioDescriptionFactory
|
||||
{
|
||||
// Internal for testing
|
||||
internal static readonly ContainerElement SeparatorElement = new(
|
||||
ContainerElementStyle.Wrapped,
|
||||
new ClassifiedTextElement(
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Comment, "------------")));
|
||||
|
||||
// Hardcoding the Guid here to avoid a reference to Microsoft.VisualStudio.ImageCatalog.dll
|
||||
// that is not present in Visual Studio for Mac
|
||||
private static readonly Guid s_imageCatalogGuid = new("{ae27a6b0-e345-4288-96df-5eaf394ee369}");
|
||||
private static readonly ImageElement s_propertyGlyph = new(
|
||||
new ImageId(s_imageCatalogGuid, 2429), // KnownImageIds.Type = 2429
|
||||
"Razor Attribute Glyph");
|
||||
private static readonly ClassifiedTextRun s_spaceLiteral = new(PredefinedClassificationNames.Literal, " ");
|
||||
private static readonly ClassifiedTextRun s_dotLiteral = new(PredefinedClassificationNames.Literal, ".");
|
||||
|
||||
public override ContainerElement CreateClassifiedDescription(AggregateBoundAttributeDescription completionDescription)
|
||||
{
|
||||
if (completionDescription is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionDescription));
|
||||
}
|
||||
|
||||
var descriptionElements = new List<object>();
|
||||
foreach (var descriptionInfo in completionDescription.DescriptionInfos)
|
||||
{
|
||||
if (descriptionElements.Count > 0)
|
||||
{
|
||||
descriptionElements.Add(SeparatorElement);
|
||||
}
|
||||
|
||||
var returnTypeClassification = PredefinedClassificationNames.Type;
|
||||
if (TypeNameStringResolver.TryGetSimpleName(descriptionInfo.ReturnTypeName, out var returnTypeName))
|
||||
{
|
||||
returnTypeClassification = PredefinedClassificationNames.Keyword;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnTypeName = descriptionInfo.ReturnTypeName;
|
||||
}
|
||||
|
||||
var tagHelperTypeName = descriptionInfo.TypeName;
|
||||
var tagHelperTypeNamePrefix = string.Empty;
|
||||
var tagHelperTypeNameProper = tagHelperTypeName;
|
||||
|
||||
var lastDot = tagHelperTypeName.LastIndexOf('.');
|
||||
if (lastDot > 0)
|
||||
{
|
||||
var afterLastDot = lastDot + 1;
|
||||
|
||||
// We're pulling apart the type name so the prefix looks like:
|
||||
//
|
||||
// Microsoft.AspnetCore.Components.
|
||||
tagHelperTypeNamePrefix = tagHelperTypeName[..afterLastDot];
|
||||
|
||||
// And the type name looks like BindBinds
|
||||
tagHelperTypeNameProper = tagHelperTypeName[afterLastDot..];
|
||||
}
|
||||
|
||||
descriptionElements.Add(
|
||||
new ContainerElement(
|
||||
ContainerElementStyle.Wrapped,
|
||||
s_propertyGlyph,
|
||||
new ClassifiedTextElement(
|
||||
new ClassifiedTextRun(returnTypeClassification, returnTypeName),
|
||||
s_spaceLiteral,
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Literal, tagHelperTypeNamePrefix),
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Type, tagHelperTypeNameProper),
|
||||
s_dotLiteral,
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Identifier, descriptionInfo.PropertyName))));
|
||||
|
||||
if (descriptionInfo.Documentation != null)
|
||||
{
|
||||
descriptionElements.Add(
|
||||
new ContainerElement(
|
||||
ContainerElementStyle.Wrapped,
|
||||
new ClassifiedTextElement(
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.NaturalLanguage, descriptionInfo.Documentation))));
|
||||
}
|
||||
}
|
||||
|
||||
var descriptionContainer = new ContainerElement(ContainerElementStyle.Stacked, descriptionElements);
|
||||
return descriptionContainer;
|
||||
}
|
||||
|
||||
private static class PredefinedClassificationNames
|
||||
{
|
||||
public const string Keyword = "keyword";
|
||||
|
||||
public const string Literal = "literal";
|
||||
|
||||
public const string Type = "Type";
|
||||
|
||||
public const string Identifier = "identifier";
|
||||
|
||||
public const string Comment = "comment";
|
||||
|
||||
public const string NaturalLanguage = "natural language";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
using Microsoft.VisualStudio.Text.Adornments;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
||||
|
||||
internal interface IVisualStudioDescriptionFactory
|
||||
{
|
||||
ContainerElement CreateClassifiedDescription(AggregateBoundAttributeDescription description);
|
||||
}
|
|
@ -4,11 +4,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
|
@ -38,45 +38,25 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
|||
}.ToImmutableArray();
|
||||
|
||||
private readonly VisualStudioRazorParser _parser;
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
private readonly ICompletionBroker _completionBroker;
|
||||
private readonly VisualStudioDescriptionFactory _descriptionFactory;
|
||||
private readonly IVisualStudioDescriptionFactory _descriptionFactory;
|
||||
private readonly JoinableTaskFactory _joinableTaskFactory;
|
||||
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
|
||||
|
||||
public RazorDirectiveAttributeCompletionSource(
|
||||
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
|
||||
VisualStudioRazorParser parser,
|
||||
RazorCompletionFactsService completionFactsService,
|
||||
IRazorCompletionFactsService completionFactsService,
|
||||
ICompletionBroker completionBroker,
|
||||
VisualStudioDescriptionFactory descriptionFactory,
|
||||
IVisualStudioDescriptionFactory descriptionFactory,
|
||||
JoinableTaskFactory joinableTaskFactory)
|
||||
{
|
||||
if (projectSnapshotManagerDispatcher is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
||||
}
|
||||
|
||||
if (parser is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parser));
|
||||
}
|
||||
|
||||
if (completionFactsService is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionFactsService));
|
||||
}
|
||||
|
||||
if (descriptionFactory is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(descriptionFactory));
|
||||
}
|
||||
|
||||
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher;
|
||||
_parser = parser;
|
||||
_completionFactsService = completionFactsService;
|
||||
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher ?? throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
||||
_parser = parser ?? throw new ArgumentNullException(nameof(parser));
|
||||
_completionFactsService = completionFactsService ?? throw new ArgumentNullException(nameof(completionFactsService));
|
||||
_completionBroker = completionBroker;
|
||||
_descriptionFactory = descriptionFactory;
|
||||
_descriptionFactory = descriptionFactory ?? throw new ArgumentNullException(nameof(descriptionFactory));
|
||||
_joinableTaskFactory = joinableTaskFactory;
|
||||
}
|
||||
|
||||
|
@ -99,7 +79,7 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
|||
var razorCompletionContext = new RazorCompletionContext(absoluteIndex, owner, syntaxTree, tagHelperDocumentContext);
|
||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
||||
|
||||
if (razorCompletionItems.Count == 0)
|
||||
if (razorCompletionItems.Length == 0)
|
||||
{
|
||||
return CompletionContext.Empty;
|
||||
}
|
||||
|
@ -121,8 +101,9 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
|||
activeSession.Dismiss();
|
||||
}
|
||||
|
||||
var completionItems = new List<CompletionItem>();
|
||||
using var _ = ArrayBuilderPool<CompletionItem>.GetPooledObject(out var completionItems);
|
||||
var completionItemKinds = new HashSet<RazorCompletionItemKind>();
|
||||
|
||||
foreach (var razorCompletionItem in razorCompletionItems)
|
||||
{
|
||||
if (razorCompletionItem.Kind != RazorCompletionItemKind.DirectiveAttribute &&
|
||||
|
@ -150,9 +131,10 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
|||
}
|
||||
|
||||
session.Properties.SetCompletionItemKinds(completionItemKinds);
|
||||
var orderedCompletionItems = completionItems.OrderBy(item => item.DisplayText);
|
||||
var context = new CompletionContext(orderedCompletionItems.ToImmutableArray());
|
||||
return context;
|
||||
|
||||
completionItems.Sort(CompletionItemDisplayTextComparer.Instance);
|
||||
|
||||
return new CompletionContext(completionItems.ToImmutable());
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
|
|
@ -23,50 +23,24 @@ namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
|||
internal class RazorDirectiveAttributeCompletionSourceProvider : IAsyncCompletionSourceProvider
|
||||
{
|
||||
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
private readonly ICompletionBroker _completionBroker;
|
||||
private readonly VisualStudioDescriptionFactory _descriptionFactory;
|
||||
private readonly IVisualStudioDescriptionFactory _descriptionFactory;
|
||||
private readonly JoinableTaskContext _joinableTaskContext;
|
||||
|
||||
[ImportingConstructor]
|
||||
public RazorDirectiveAttributeCompletionSourceProvider(
|
||||
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
|
||||
RazorCompletionFactsService completionFactsService,
|
||||
IAsyncCompletionBroker asyncCoompletionBroker,
|
||||
IRazorCompletionFactsService completionFactsService,
|
||||
ICompletionBroker completionBroker,
|
||||
VisualStudioDescriptionFactory descriptionFactory,
|
||||
IVisualStudioDescriptionFactory descriptionFactory,
|
||||
JoinableTaskContext joinableTaskContext)
|
||||
{
|
||||
if (projectSnapshotManagerDispatcher is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
||||
}
|
||||
|
||||
if (completionFactsService is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionFactsService));
|
||||
}
|
||||
|
||||
if (asyncCoompletionBroker is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(asyncCoompletionBroker));
|
||||
}
|
||||
|
||||
if (descriptionFactory is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(descriptionFactory));
|
||||
}
|
||||
|
||||
if (joinableTaskContext is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(joinableTaskContext));
|
||||
}
|
||||
|
||||
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher;
|
||||
_completionFactsService = completionFactsService;
|
||||
_completionBroker = completionBroker;
|
||||
_descriptionFactory = descriptionFactory;
|
||||
_joinableTaskContext = joinableTaskContext;
|
||||
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher ?? throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
||||
_completionFactsService = completionFactsService ?? throw new ArgumentNullException(nameof(completionFactsService));
|
||||
_completionBroker = completionBroker ?? throw new ArgumentNullException(nameof(completionBroker));
|
||||
_descriptionFactory = descriptionFactory ?? throw new ArgumentNullException(nameof(descriptionFactory));
|
||||
_joinableTaskContext = joinableTaskContext ?? throw new ArgumentNullException(nameof(joinableTaskContext));
|
||||
}
|
||||
|
||||
public IAsyncCompletionSource? GetOrCreate(ITextView textView)
|
||||
|
@ -96,13 +70,12 @@ internal class RazorDirectiveAttributeCompletionSourceProvider : IAsyncCompletio
|
|||
return null;
|
||||
}
|
||||
|
||||
var completionSource = new RazorDirectiveAttributeCompletionSource(
|
||||
return new RazorDirectiveAttributeCompletionSource(
|
||||
_projectSnapshotManagerDispatcher,
|
||||
parser,
|
||||
_completionFactsService,
|
||||
_completionBroker,
|
||||
_descriptionFactory,
|
||||
_joinableTaskContext.Factory);
|
||||
return completionSource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||
using Microsoft.VisualStudio.Core.Imaging;
|
||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
|
||||
|
@ -33,11 +33,11 @@ internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
|||
|
||||
// Internal for testing
|
||||
internal readonly VisualStudioRazorParser Parser;
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
|
||||
public RazorDirectiveCompletionSource(
|
||||
VisualStudioRazorParser parser,
|
||||
RazorCompletionFactsService completionFactsService)
|
||||
IRazorCompletionFactsService completionFactsService)
|
||||
{
|
||||
if (parser is null)
|
||||
{
|
||||
|
@ -77,7 +77,8 @@ internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
|||
var razorCompletionContext = new RazorCompletionContext(absoluteIndex, owner, syntaxTree, tagHelperDocumentContext);
|
||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
||||
|
||||
var completionItems = new List<CompletionItem>();
|
||||
using var _ = ArrayBuilderPool<CompletionItem>.GetPooledObject(out var completionItems);
|
||||
|
||||
foreach (var razorCompletionItem in razorCompletionItems)
|
||||
{
|
||||
if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive)
|
||||
|
@ -96,13 +97,13 @@ internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
|||
suffix: string.Empty,
|
||||
sortText: razorCompletionItem.DisplayText,
|
||||
attributeIcons: ImmutableArray<ImageElement>.Empty);
|
||||
|
||||
var completionDescription = razorCompletionItem.GetDirectiveCompletionDescription();
|
||||
completionItem.Properties.AddProperty(DescriptionKey, completionDescription);
|
||||
completionItems.Add(completionItem);
|
||||
}
|
||||
|
||||
var context = new CompletionContext(completionItems.ToImmutableArray());
|
||||
return context;
|
||||
return new CompletionContext(completionItems.ToImmutable());
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
|
|
@ -20,10 +20,10 @@ namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
|||
[ContentType(RazorConstants.LegacyCoreContentType)]
|
||||
internal class RazorDirectiveCompletionSourceProvider : IAsyncCompletionSourceProvider
|
||||
{
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
|
||||
[ImportingConstructor]
|
||||
public RazorDirectiveCompletionSourceProvider(RazorCompletionFactsService completionFactsService)
|
||||
public RazorDirectiveCompletionSourceProvider(IRazorCompletionFactsService completionFactsService)
|
||||
{
|
||||
if (completionFactsService is null)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,114 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||
using Microsoft.VisualStudio.Core.Imaging;
|
||||
using Microsoft.VisualStudio.Text.Adornments;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
||||
|
||||
internal abstract class VisualStudioDescriptionFactory
|
||||
[Shared]
|
||||
[Export(typeof(IVisualStudioDescriptionFactory))]
|
||||
internal class VisualStudioDescriptionFactory : IVisualStudioDescriptionFactory
|
||||
{
|
||||
public abstract ContainerElement CreateClassifiedDescription(AggregateBoundAttributeDescription completionDescription);
|
||||
// Internal for testing
|
||||
internal static readonly ContainerElement SeparatorElement = new(
|
||||
ContainerElementStyle.Wrapped,
|
||||
new ClassifiedTextElement(
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Comment, "------------")));
|
||||
|
||||
// Hardcoding the Guid here to avoid a reference to Microsoft.VisualStudio.ImageCatalog.dll
|
||||
// that is not present in Visual Studio for Mac
|
||||
private static readonly Guid s_imageCatalogGuid = new("{ae27a6b0-e345-4288-96df-5eaf394ee369}");
|
||||
private static readonly ImageElement s_propertyGlyph = new(
|
||||
new ImageId(s_imageCatalogGuid, 2429), // KnownImageIds.Type = 2429
|
||||
"Razor Attribute Glyph");
|
||||
private static readonly ClassifiedTextRun s_spaceLiteral = new(PredefinedClassificationNames.Literal, " ");
|
||||
private static readonly ClassifiedTextRun s_dotLiteral = new(PredefinedClassificationNames.Literal, ".");
|
||||
|
||||
public ContainerElement CreateClassifiedDescription(AggregateBoundAttributeDescription description)
|
||||
{
|
||||
if (description is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(description));
|
||||
}
|
||||
|
||||
var descriptionElements = new List<object>();
|
||||
foreach (var descriptionInfo in description.DescriptionInfos)
|
||||
{
|
||||
if (descriptionElements.Count > 0)
|
||||
{
|
||||
descriptionElements.Add(SeparatorElement);
|
||||
}
|
||||
|
||||
var returnTypeClassification = PredefinedClassificationNames.Type;
|
||||
if (TypeNameStringResolver.TryGetSimpleName(descriptionInfo.ReturnTypeName, out var returnTypeName))
|
||||
{
|
||||
returnTypeClassification = PredefinedClassificationNames.Keyword;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnTypeName = descriptionInfo.ReturnTypeName;
|
||||
}
|
||||
|
||||
var tagHelperTypeName = descriptionInfo.TypeName;
|
||||
var tagHelperTypeNamePrefix = string.Empty;
|
||||
var tagHelperTypeNameProper = tagHelperTypeName;
|
||||
|
||||
var lastDot = tagHelperTypeName.LastIndexOf('.');
|
||||
if (lastDot > 0)
|
||||
{
|
||||
var afterLastDot = lastDot + 1;
|
||||
|
||||
// We're pulling apart the type name so the prefix looks like:
|
||||
//
|
||||
// Microsoft.AspnetCore.Components.
|
||||
tagHelperTypeNamePrefix = tagHelperTypeName[..afterLastDot];
|
||||
|
||||
// And the type name looks like BindBinds
|
||||
tagHelperTypeNameProper = tagHelperTypeName[afterLastDot..];
|
||||
}
|
||||
|
||||
descriptionElements.Add(
|
||||
new ContainerElement(
|
||||
ContainerElementStyle.Wrapped,
|
||||
s_propertyGlyph,
|
||||
new ClassifiedTextElement(
|
||||
new ClassifiedTextRun(returnTypeClassification, returnTypeName),
|
||||
s_spaceLiteral,
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Literal, tagHelperTypeNamePrefix),
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Type, tagHelperTypeNameProper),
|
||||
s_dotLiteral,
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.Identifier, descriptionInfo.PropertyName))));
|
||||
|
||||
if (descriptionInfo.Documentation is { } documentation)
|
||||
{
|
||||
descriptionElements.Add(
|
||||
new ContainerElement(
|
||||
ContainerElementStyle.Wrapped,
|
||||
new ClassifiedTextElement(
|
||||
new ClassifiedTextRun(PredefinedClassificationNames.NaturalLanguage, documentation))));
|
||||
}
|
||||
}
|
||||
|
||||
return new ContainerElement(ContainerElementStyle.Stacked, descriptionElements);
|
||||
}
|
||||
|
||||
private static class PredefinedClassificationNames
|
||||
{
|
||||
public const string Keyword = "keyword";
|
||||
|
||||
public const string Literal = "literal";
|
||||
|
||||
public const string Type = "Type";
|
||||
|
||||
public const string Identifier = "identifier";
|
||||
|
||||
public const string Comment = "comment";
|
||||
|
||||
public const string NaturalLanguage = "natural language";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
|||
|
||||
public class LegacyRazorCompletionEndpointTest : LanguageServerTestBase
|
||||
{
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
private readonly CompletionListCache _completionListCache;
|
||||
private readonly VSInternalClientCapabilities _clientCapabilities;
|
||||
|
||||
|
@ -36,7 +36,7 @@ public class LegacyRazorCompletionEndpointTest : LanguageServerTestBase
|
|||
var tagHelperFactsService = new DefaultTagHelperFactsService();
|
||||
var tagHelperCompletionService = new LanguageServerTagHelperCompletionService(tagHelperFactsService);
|
||||
|
||||
var completionProviders = new RazorCompletionItemProvider[]
|
||||
var completionProviders = new IRazorCompletionItemProvider[]
|
||||
{
|
||||
new DirectiveCompletionItemProvider(),
|
||||
new DirectiveAttributeCompletionItemProvider(tagHelperFactsService),
|
||||
|
@ -44,7 +44,7 @@ public class LegacyRazorCompletionEndpointTest : LanguageServerTestBase
|
|||
new TagHelperCompletionProvider(tagHelperCompletionService, new DefaultHtmlFactsService(), tagHelperFactsService, TestRazorLSPOptionsMonitor.Create())
|
||||
};
|
||||
|
||||
_completionFactsService = new DefaultRazorCompletionFactsService(completionProviders);
|
||||
_completionFactsService = new RazorCompletionFactsService(completionProviders);
|
||||
_completionListCache = new CompletionListCache();
|
||||
_clientCapabilities = new VSInternalClientCapabilities()
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -27,7 +27,6 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
private readonly CompletionListCache _completionListCache;
|
||||
private readonly VSInternalCompletionSetting _completionCapability;
|
||||
private readonly VSInternalClientCapabilities _defaultClientCapability;
|
||||
private readonly VSInternalClientCapabilities _vsClientCapability;
|
||||
|
||||
public LegacyRazorCompletionResolveEndpointTest(ITestOutputHelper testOutput)
|
||||
: base(testOutput)
|
||||
|
@ -50,15 +49,6 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
Completion = _completionCapability,
|
||||
},
|
||||
};
|
||||
|
||||
_vsClientCapability = new VSInternalClientCapabilities()
|
||||
{
|
||||
TextDocument = new TextDocumentClientCapabilities()
|
||||
{
|
||||
Completion = _completionCapability,
|
||||
},
|
||||
SupportsVisualStudioExtensions = true,
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -69,7 +59,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.Directive);
|
||||
razorCompletionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription("Test directive"));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single();
|
||||
var parameters = ConvertToBridgedItem(completionItem);
|
||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||
|
@ -89,7 +79,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||
var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);
|
||||
razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single();
|
||||
var parameters = ConvertToBridgedItem(completionItem);
|
||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||
|
@ -117,7 +107,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single();
|
||||
var parameters = ConvertToBridgedItem(completionItem);
|
||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||
|
@ -145,7 +135,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single();
|
||||
var parameters = ConvertToBridgedItem(completionItem);
|
||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||
|
@ -173,7 +163,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
||||
razorCompletionItem.SetTagHelperElementDescriptionInfo(new AggregateBoundElementDescription(Array.Empty<BoundElementDescriptionInfo>()));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single();
|
||||
var parameters = ConvertToBridgedItem(completionItem);
|
||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||
|
@ -201,7 +191,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single();
|
||||
var parameters = ConvertToBridgedItem(completionItem);
|
||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||
|
@ -238,9 +228,9 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
|||
Assert.Null(newCompletionItem.Documentation);
|
||||
}
|
||||
|
||||
private VSInternalCompletionList CreateLSPCompletionList(IReadOnlyList<RazorCompletionItem> razorCompletionItems)
|
||||
private VSInternalCompletionList CreateLSPCompletionList(params RazorCompletionItem[] razorCompletionItems)
|
||||
{
|
||||
var completionList = LegacyRazorCompletionEndpoint.CreateLSPCompletionList(razorCompletionItems, _defaultClientCapability);
|
||||
var completionList = LegacyRazorCompletionEndpoint.CreateLSPCompletionList(razorCompletionItems.ToImmutableArray(), _defaultClientCapability);
|
||||
var resultId = _completionListCache.Add(completionList, razorCompletionItems);
|
||||
completionList.SetResultId(resultId, completionSetting: null);
|
||||
return completionList;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip;
|
||||
|
@ -70,7 +70,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.Directive);
|
||||
razorCompletionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription("Test directive"));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -88,7 +88,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);
|
||||
razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -106,7 +106,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -124,7 +124,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -142,7 +142,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
||||
razorCompletionItem.SetTagHelperElementDescriptionInfo(_elementDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -160,7 +160,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -178,7 +178,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -196,7 +196,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -214,7 +214,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
||||
razorCompletionItem.SetTagHelperElementDescriptionInfo(_elementDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -232,7 +232,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
||||
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||
|
||||
// Act
|
||||
|
@ -259,9 +259,6 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
|||
Assert.Null(resolvedCompletionItem);
|
||||
}
|
||||
|
||||
private VSInternalCompletionList CreateLSPCompletionList(IReadOnlyList<RazorCompletionItem> razorCompletionItems)
|
||||
{
|
||||
var completionList = RazorCompletionListProvider.CreateLSPCompletionList(razorCompletionItems, _defaultClientCapability);
|
||||
return completionList;
|
||||
}
|
||||
private VSInternalCompletionList CreateLSPCompletionList(params RazorCompletionItem[] razorCompletionItems)
|
||||
=> RazorCompletionListProvider.CreateLSPCompletionList(razorCompletionItems.ToImmutableArray(), _defaultClientCapability);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
|||
|
||||
public class RazorCompletionListProvierTest : LanguageServerTestBase
|
||||
{
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
private readonly CompletionListCache _completionListCache;
|
||||
private readonly VSInternalClientCapabilities _clientCapabilities;
|
||||
private readonly VSInternalCompletionContext _defaultCompletionContext;
|
||||
|
@ -35,7 +35,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
|||
public RazorCompletionListProvierTest(ITestOutputHelper testOutput)
|
||||
: base(testOutput)
|
||||
{
|
||||
_completionFactsService = new DefaultRazorCompletionFactsService(GetCompletionProviders());
|
||||
_completionFactsService = new RazorCompletionFactsService(GetCompletionProviders());
|
||||
_completionListCache = new CompletionListCache();
|
||||
_clientCapabilities = new VSInternalClientCapabilities()
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
|||
_defaultCompletionContext = new VSInternalCompletionContext();
|
||||
}
|
||||
|
||||
private static IEnumerable<RazorCompletionItemProvider> GetCompletionProviders(IOptionsMonitor<RazorLSPOptions> optionsMonitor = null)
|
||||
private static IEnumerable<IRazorCompletionItemProvider> GetCompletionProviders(IOptionsMonitor<RazorLSPOptions> optionsMonitor = null)
|
||||
{
|
||||
// Working around strong naming restriction.
|
||||
var tagHelperFactsService = new DefaultTagHelperFactsService();
|
||||
|
@ -67,7 +67,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
|||
|
||||
optionsMonitor ??= TestRazorLSPOptionsMonitor.Create();
|
||||
|
||||
var completionProviders = new RazorCompletionItemProvider[]
|
||||
var completionProviders = new IRazorCompletionItemProvider[]
|
||||
{
|
||||
new DirectiveCompletionItemProvider(),
|
||||
new DirectiveAttributeCompletionItemProvider(tagHelperFactsService),
|
||||
|
@ -582,7 +582,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
|||
var optionsMonitor = TestRazorLSPOptionsMonitor.Create();
|
||||
await optionsMonitor.UpdateAsync(optionsMonitor.CurrentValue with { AutoInsertAttributeQuotes = false }, DisposalToken);
|
||||
|
||||
var completionFactsService = new DefaultRazorCompletionFactsService(GetCompletionProviders(optionsMonitor));
|
||||
var completionFactsService = new RazorCompletionFactsService(GetCompletionProviders(optionsMonitor));
|
||||
var provider = new RazorCompletionListProvider(completionFactsService, _completionListCache, LoggerFactory);
|
||||
|
||||
// Act
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Test.Common;
|
||||
|
@ -12,13 +13,8 @@ using Xunit.Abstractions;
|
|||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||
|
||||
public class DefaultRazorCompletionFactsServiceTest : TestBase
|
||||
public class DefaultRazorCompletionFactsServiceTest(ITestOutputHelper testOutput) : TestBase(testOutput)
|
||||
{
|
||||
public DefaultRazorCompletionFactsServiceTest(ITestOutputHelper testOutput)
|
||||
: base(testOutput)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDirectiveCompletionItems_AllProvidersCompletionItems()
|
||||
{
|
||||
|
@ -27,10 +23,10 @@ public class DefaultRazorCompletionFactsServiceTest : TestBase
|
|||
var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: null, Enumerable.Empty<TagHelperDescriptor>());
|
||||
var completionItem1 = new RazorCompletionItem("displayText1", "insertText1", RazorCompletionItemKind.Directive);
|
||||
var context = new RazorCompletionContext(0, null, syntaxTree, tagHelperDocumentContext);
|
||||
var provider1 = Mock.Of<RazorCompletionItemProvider>(p => p.GetCompletionItems(context) == new[] { completionItem1 }, MockBehavior.Strict);
|
||||
var provider1 = Mock.Of<IRazorCompletionItemProvider>(p => p.GetCompletionItems(context) == ImmutableArray.Create(completionItem1), MockBehavior.Strict);
|
||||
var completionItem2 = new RazorCompletionItem("displayText2", "insertText2", RazorCompletionItemKind.Directive);
|
||||
var provider2 = Mock.Of<RazorCompletionItemProvider>(p => p.GetCompletionItems(context) == new[] { completionItem2 }, MockBehavior.Strict);
|
||||
var completionFactsService = new DefaultRazorCompletionFactsService(new[] { provider1, provider2 });
|
||||
var provider2 = Mock.Of<IRazorCompletionItemProvider>(p => p.GetCompletionItems(context) == ImmutableArray.Create(completionItem2), MockBehavior.Strict);
|
||||
var completionFactsService = new RazorCompletionFactsService(new[] { provider1, provider2 });
|
||||
|
||||
// Act
|
||||
var completionItems = completionFactsService.GetCompletionItems(context);
|
||||
|
|
|
@ -93,7 +93,7 @@ public class DirectiveAttributeParameterCompletionItemProviderTest : RazorIntegr
|
|||
var completions = _provider.GetCompletionItems(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(6, completions.Count);
|
||||
Assert.Equal(6, completions.Length);
|
||||
AssertContains(completions, "culture");
|
||||
AssertContains(completions, "event");
|
||||
AssertContains(completions, "format");
|
||||
|
|
|
@ -23,7 +23,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
public void CreateClassifiedDescription_SingleDescription_NoSeparator()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -33,14 +33,14 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
var result = factory.CreateClassifiedDescription(description);
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain(DefaultVisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
||||
Assert.DoesNotContain(VisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateClassifiedDescription_MultipleDescription_Separator()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -51,14 +51,14 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
var result = factory.CreateClassifiedDescription(description);
|
||||
|
||||
// Assert
|
||||
Assert.Contains(DefaultVisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
||||
Assert.Contains(VisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateClassifiedDescription_RepresentsReturnType()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -76,7 +76,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
public void CreateClassifiedDescription_RepresentsTypeName()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -94,7 +94,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
public void CreateClassifiedDescription_RepresentsPropertyName()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -112,7 +112,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
public void CreateClassifiedDescription_RepresentsDocumentation()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -130,7 +130,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
public void CreateClassifiedDescription_CanSimplifyKeywordReturnTypes()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("System.String", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
@ -149,7 +149,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
|||
public void CreateClassifiedDescription_CanRepresentMultipleDescriptions()
|
||||
{
|
||||
// Arrange
|
||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
||||
var factory = new VisualStudioDescriptionFactory();
|
||||
var description = new AggregateBoundAttributeDescription(new[]
|
||||
{
|
||||
new BoundAttributeDescriptionInfo("System.String", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||
|
|
|
@ -46,11 +46,11 @@ public class RazorDirectiveAttributeCompletionSourceTest : ProjectSnapshotManage
|
|||
// Arrange
|
||||
var expectedResult = new ContainerElement(ContainerElementStyle.Wrapped);
|
||||
var description = new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>());
|
||||
var descriptionFactory = Mock.Of<VisualStudioDescriptionFactory>(factory => factory.CreateClassifiedDescription(description) == expectedResult, MockBehavior.Strict);
|
||||
var descriptionFactory = Mock.Of<IVisualStudioDescriptionFactory>(factory => factory.CreateClassifiedDescription(description) == expectedResult, MockBehavior.Strict);
|
||||
var source = new RazorDirectiveAttributeCompletionSource(
|
||||
Dispatcher,
|
||||
Mock.Of<VisualStudioRazorParser>(MockBehavior.Strict),
|
||||
Mock.Of<RazorCompletionFactsService>(MockBehavior.Strict),
|
||||
Mock.Of<IRazorCompletionFactsService>(MockBehavior.Strict),
|
||||
Mock.Of<ICompletionBroker>(MockBehavior.Strict),
|
||||
descriptionFactory,
|
||||
JoinableTaskFactory);
|
||||
|
@ -240,9 +240,9 @@ public class RazorDirectiveAttributeCompletionSourceTest : ProjectSnapshotManage
|
|||
var source = new RazorDirectiveAttributeCompletionSource(
|
||||
Dispatcher,
|
||||
Mock.Of<VisualStudioRazorParser>(MockBehavior.Strict),
|
||||
Mock.Of<RazorCompletionFactsService>(MockBehavior.Strict),
|
||||
Mock.Of<IRazorCompletionFactsService>(MockBehavior.Strict),
|
||||
Mock.Of<ICompletionBroker>(MockBehavior.Strict),
|
||||
Mock.Of<VisualStudioDescriptionFactory>(MockBehavior.Strict),
|
||||
Mock.Of<IVisualStudioDescriptionFactory>(MockBehavior.Strict),
|
||||
JoinableTaskFactory);
|
||||
return source;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public class RazorDirectiveCompletionSourceProviderTest : ProjectSnapshotManager
|
|||
{
|
||||
private readonly IContentType _razorContentType;
|
||||
private readonly IContentType _nonRazorContentType;
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
|
||||
public RazorDirectiveCompletionSourceProviderTest(ITestOutputHelper testOutput)
|
||||
: base(testOutput)
|
||||
|
@ -34,7 +34,7 @@ public class RazorDirectiveCompletionSourceProviderTest : ProjectSnapshotManager
|
|||
c => c.IsOfType(It.IsAny<string>()) == false,
|
||||
MockBehavior.Strict);
|
||||
|
||||
_completionFactsService = Mock.Of<RazorCompletionFactsService>(MockBehavior.Strict);
|
||||
_completionFactsService = Mock.Of<IRazorCompletionFactsService>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
@ -33,12 +33,12 @@ public class RazorDirectiveCompletionSourceTest : ProjectSnapshotManagerDispatch
|
|||
CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
|
||||
};
|
||||
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||
|
||||
public RazorDirectiveCompletionSourceTest(ITestOutputHelper testOutput)
|
||||
: base(testOutput)
|
||||
{
|
||||
_completionFactsService = new DefaultRazorCompletionFactsService(new[] { new DirectiveCompletionItemProvider() });
|
||||
_completionFactsService = new RazorCompletionFactsService(new[] { new DirectiveCompletionItemProvider() });
|
||||
}
|
||||
|
||||
[UIFact]
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
internal static class EnumerableExtensions
|
||||
{
|
||||
public static ImmutableArray<TResult> SelectAsArray<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector)
|
||||
{
|
||||
if (source is IReadOnlyList<T> list)
|
||||
{
|
||||
return list.SelectAsArray(selector);
|
||||
}
|
||||
|
||||
return BuildResult(source, selector);
|
||||
|
||||
static ImmutableArray<TResult> BuildResult(IEnumerable<T> items, Func<T, TResult> selector)
|
||||
{
|
||||
using var results = new PooledArrayBuilder<TResult>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
results.Add(selector(item));
|
||||
}
|
||||
|
||||
return results.DrainToImmutable();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -73,15 +73,14 @@ internal static class ImmutableArrayExtensions
|
|||
|
||||
static ImmutableArray<TResult> BuildResult(ImmutableArray<T> items, Func<T, TResult> selector)
|
||||
{
|
||||
using var _ = ArrayBuilderPool<TResult>.GetPooledObject(out var result);
|
||||
result.SetCapacityIfLarger(items.Length);
|
||||
using var results = new PooledArrayBuilder<TResult>(capacity: items.Length);
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
result.Add(selector(item));
|
||||
results.Add(selector(item));
|
||||
}
|
||||
|
||||
return result.DrainToImmutable();
|
||||
return results.DrainToImmutable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,17 @@ internal ref struct PooledArrayBuilder<T>
|
|||
_builder.Add(item);
|
||||
}
|
||||
|
||||
public void AddRange(ImmutableArray<T> items)
|
||||
{
|
||||
if (items.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_builder ??= GetBuilder();
|
||||
_builder.AddRange(items);
|
||||
}
|
||||
|
||||
public void AddRange(IReadOnlyList<T> items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
internal static class ReadOnlyListExtensions
|
||||
{
|
||||
public static ImmutableArray<TResult> SelectAsArray<T, TResult>(this IReadOnlyList<T> source, Func<T, TResult> selector)
|
||||
{
|
||||
return source switch
|
||||
{
|
||||
[] => ImmutableArray<TResult>.Empty,
|
||||
[var item] => ImmutableArray.Create(selector(item)),
|
||||
[var item1, var item2] => ImmutableArray.Create(selector(item1), selector(item2)),
|
||||
[var item1, var item2, var item3] => ImmutableArray.Create(selector(item1), selector(item2), selector(item3)),
|
||||
[var item1, var item2, var item3, var item4] => ImmutableArray.Create(selector(item1), selector(item2), selector(item3), selector(item4)),
|
||||
var items => BuildResult(items, selector)
|
||||
};
|
||||
|
||||
static ImmutableArray<TResult> BuildResult(IReadOnlyList<T> items, Func<T, TResult> selector)
|
||||
{
|
||||
using var results = new PooledArrayBuilder<TResult>(capacity: items.Count);
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
results.Add(selector(items[i]));
|
||||
}
|
||||
|
||||
return results.DrainToImmutable();
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче