зеркало из 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.
|
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Immutable;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
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)
|
if (context is null)
|
||||||
{
|
{
|
||||||
|
@ -51,13 +51,13 @@ internal class DirectiveAttributeTransitionCompletionItemProvider : DirectiveAtt
|
||||||
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
||||||
{
|
{
|
||||||
// Directive attributes are only supported in components
|
// Directive attributes are only supported in components
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var owner = context.Owner;
|
var owner = context.Owner;
|
||||||
if (owner is null)
|
if (owner is null)
|
||||||
{
|
{
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var attribute = owner.Parent;
|
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 _))
|
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))
|
if (attributeNameLocation.IntersectsWith(context.AbsoluteIndex) && attributeName.StartsWith("@", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
// The transition is already provided for the attribute name
|
// The transition is already provided for the attribute name
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidCompletionPoint(context.AbsoluteIndex, prefixLocation, attributeNameLocation))
|
if (!IsValidCompletionPoint(context.AbsoluteIndex, prefixLocation, attributeNameLocation))
|
||||||
{
|
{
|
||||||
// Not operating in the attribute name area
|
// 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 | />.
|
// 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.
|
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
|
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
|
||||||
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
||||||
|
@ -23,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
||||||
// for this legacy version.
|
// for this legacy version.
|
||||||
internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
||||||
{
|
{
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
private readonly CompletionListCache _completionListCache;
|
private readonly CompletionListCache _completionListCache;
|
||||||
private static readonly Command s_retriggerCompletionCommand = new()
|
private static readonly Command s_retriggerCompletionCommand = new()
|
||||||
{
|
{
|
||||||
|
@ -34,22 +35,10 @@ internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
||||||
|
|
||||||
public bool MutatesSolutionState => false;
|
public bool MutatesSolutionState => false;
|
||||||
|
|
||||||
public LegacyRazorCompletionEndpoint(
|
public LegacyRazorCompletionEndpoint(IRazorCompletionFactsService completionFactsService, CompletionListCache completionListCache)
|
||||||
RazorCompletionFactsService completionFactsService,
|
|
||||||
CompletionListCache completionListCache)
|
|
||||||
{
|
{
|
||||||
if (completionFactsService is null)
|
_completionFactsService = completionFactsService ?? throw new ArgumentNullException(nameof(completionFactsService));
|
||||||
{
|
_completionListCache = completionListCache ?? throw new ArgumentNullException(nameof(completionListCache));
|
||||||
throw new ArgumentNullException(nameof(completionFactsService));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completionListCache is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(completionListCache));
|
|
||||||
}
|
|
||||||
|
|
||||||
_completionFactsService = completionFactsService;
|
|
||||||
_completionListCache = completionListCache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities)
|
public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities)
|
||||||
|
@ -107,7 +96,7 @@ internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
||||||
|
|
||||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(completionContext);
|
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 completionList = CreateLSPCompletionList(razorCompletionItems);
|
||||||
var completionCapability = _clientCapabilities?.TextDocument?.Completion as VSInternalCompletionSetting;
|
var completionCapability = _clientCapabilities?.TextDocument?.Completion as VSInternalCompletionSetting;
|
||||||
|
@ -140,31 +129,33 @@ internal class LegacyRazorCompletionEndpoint : IVSCompletionEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// 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 for benchmarking and testing
|
||||||
internal static VSInternalCompletionList CreateLSPCompletionList(
|
internal static VSInternalCompletionList CreateLSPCompletionList(
|
||||||
IReadOnlyList<RazorCompletionItem> razorCompletionItems,
|
ImmutableArray<RazorCompletionItem> razorCompletionItems,
|
||||||
VSInternalClientCapabilities clientCapabilities)
|
VSInternalClientCapabilities clientCapabilities)
|
||||||
{
|
{
|
||||||
var completionItems = new List<CompletionItem>();
|
using var items = new PooledArrayBuilder<CompletionItem>();
|
||||||
|
|
||||||
foreach (var razorCompletionItem in razorCompletionItems)
|
foreach (var razorCompletionItem in razorCompletionItems)
|
||||||
{
|
{
|
||||||
if (TryConvert(razorCompletionItem, clientCapabilities, out var completionItem))
|
if (TryConvert(razorCompletionItem, clientCapabilities, out var completionItem))
|
||||||
{
|
{
|
||||||
completionItems.Add(completionItem);
|
items.Add(completionItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var completionList = new VSInternalCompletionList()
|
var completionList = new VSInternalCompletionList()
|
||||||
{
|
{
|
||||||
Items = completionItems.ToArray(),
|
Items = items.ToArray(),
|
||||||
IsIncomplete = false,
|
IsIncomplete = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
var completionCapability = clientCapabilities?.TextDocument?.Completion as VSInternalCompletionSetting;
|
var completionCapability = clientCapabilities?.TextDocument?.Completion as VSInternalCompletionSetting;
|
||||||
var optimizedCompletionList = CompletionListOptimizer.Optimize(completionList, completionCapability);
|
|
||||||
return optimizedCompletionList;
|
return CompletionListOptimizer.Optimize(completionList, completionCapability);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
||||||
|
@ -20,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
||||||
|
|
||||||
internal class RazorCompletionListProvider
|
internal class RazorCompletionListProvider
|
||||||
{
|
{
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
private readonly CompletionListCache _completionListCache;
|
private readonly CompletionListCache _completionListCache;
|
||||||
private readonly ILogger<RazorCompletionListProvider> _logger;
|
private readonly ILogger<RazorCompletionListProvider> _logger;
|
||||||
private static readonly Command s_retriggerCompletionCommand = new()
|
private static readonly Command s_retriggerCompletionCommand = new()
|
||||||
|
@ -30,7 +31,7 @@ internal class RazorCompletionListProvider
|
||||||
};
|
};
|
||||||
|
|
||||||
public RazorCompletionListProvider(
|
public RazorCompletionListProvider(
|
||||||
RazorCompletionFactsService completionFactsService,
|
IRazorCompletionFactsService completionFactsService,
|
||||||
CompletionListCache completionListCache,
|
CompletionListCache completionListCache,
|
||||||
ILoggerFactory loggerFactory)
|
ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
|
@ -63,6 +64,7 @@ internal class RazorCompletionListProvider
|
||||||
CompletionTriggerKind.TriggerCharacter => CompletionReason.Typing,
|
CompletionTriggerKind.TriggerCharacter => CompletionReason.Typing,
|
||||||
_ => CompletionReason.Typing,
|
_ => CompletionReason.Typing,
|
||||||
};
|
};
|
||||||
|
|
||||||
var completionOptions = new RazorCompletionOptions(SnippetsSupported: true);
|
var completionOptions = new RazorCompletionOptions(SnippetsSupported: true);
|
||||||
var syntaxTree = await documentContext.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
|
var syntaxTree = await documentContext.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
|
||||||
var tagHelperContext = await documentContext.GetTagHelperContextAsync(cancellationToken).ConfigureAwait(false);
|
var tagHelperContext = await documentContext.GetTagHelperContextAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
@ -79,7 +81,7 @@ internal class RazorCompletionListProvider
|
||||||
|
|
||||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
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);
|
var completionList = CreateLSPCompletionList(razorCompletionItems, clientCapabilities);
|
||||||
|
|
||||||
|
@ -94,27 +96,28 @@ internal class RazorCompletionListProvider
|
||||||
|
|
||||||
// Internal for benchmarking and testing
|
// Internal for benchmarking and testing
|
||||||
internal static VSInternalCompletionList CreateLSPCompletionList(
|
internal static VSInternalCompletionList CreateLSPCompletionList(
|
||||||
IReadOnlyList<RazorCompletionItem> razorCompletionItems,
|
ImmutableArray<RazorCompletionItem> razorCompletionItems,
|
||||||
VSInternalClientCapabilities clientCapabilities)
|
VSInternalClientCapabilities clientCapabilities)
|
||||||
{
|
{
|
||||||
var completionItems = new List<CompletionItem>();
|
using var items = new PooledArrayBuilder<CompletionItem>();
|
||||||
|
|
||||||
foreach (var razorCompletionItem in razorCompletionItems)
|
foreach (var razorCompletionItem in razorCompletionItems)
|
||||||
{
|
{
|
||||||
if (TryConvert(razorCompletionItem, clientCapabilities, out var completionItem))
|
if (TryConvert(razorCompletionItem, clientCapabilities, out var completionItem))
|
||||||
{
|
{
|
||||||
completionItems.Add(completionItem);
|
items.Add(completionItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var completionList = new VSInternalCompletionList()
|
var completionList = new VSInternalCompletionList()
|
||||||
{
|
{
|
||||||
Items = completionItems.ToArray(),
|
Items = items.ToArray(),
|
||||||
IsIncomplete = false,
|
IsIncomplete = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
var completionCapability = clientCapabilities.TextDocument?.Completion as VSInternalCompletionSetting;
|
var completionCapability = clientCapabilities.TextDocument?.Completion as VSInternalCompletionSetting;
|
||||||
var optimizedCompletionList = CompletionListOptimizer.Optimize(completionList, completionCapability);
|
|
||||||
return optimizedCompletionList;
|
return CompletionListOptimizer.Optimize(completionList, completionCapability);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
@ -15,7 +17,7 @@ using Microsoft.VisualStudio.Editor.Razor;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
||||||
|
|
||||||
internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
internal class TagHelperCompletionProvider : IRazorCompletionItemProvider
|
||||||
{
|
{
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal static readonly IReadOnlyList<RazorCommitCharacter> MinimizedAttributeCommitCharacters = RazorCommitCharacter.FromArray(new[] { "=", " " });
|
internal static readonly IReadOnlyList<RazorCommitCharacter> MinimizedAttributeCommitCharacters = RazorCommitCharacter.FromArray(new[] { "=", " " });
|
||||||
|
@ -41,7 +43,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
_optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor));
|
_optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||||
{
|
{
|
||||||
if (context is null)
|
if (context is null)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +54,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
if (owner is null)
|
if (owner is null)
|
||||||
{
|
{
|
||||||
Debug.Fail("Owner should never be null.");
|
Debug.Fail("Owner should never be null.");
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = owner.Parent;
|
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
|
// 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.
|
// 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 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)
|
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.:
|
// 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.
|
// Invalid location for TagHelper completions.
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReadOnlyList<RazorCompletionItem> GetAttributeCompletions(
|
private ImmutableArray<RazorCompletionItem> GetAttributeCompletions(
|
||||||
SyntaxNode containingAttribute,
|
SyntaxNode containingAttribute,
|
||||||
string containingTagName,
|
string containingTagName,
|
||||||
string? selectedAttributeName,
|
string? selectedAttributeName,
|
||||||
|
@ -148,8 +150,9 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
ancestorIsTagHelper,
|
ancestorIsTagHelper,
|
||||||
HtmlFactsService.IsHtmlTagName);
|
HtmlFactsService.IsHtmlTagName);
|
||||||
|
|
||||||
var completionItems = new List<RazorCompletionItem>();
|
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||||
var completionResult = _tagHelperCompletionService.GetAttributeCompletions(attributeCompletionContext);
|
var completionResult = _tagHelperCompletionService.GetAttributeCompletions(attributeCompletionContext);
|
||||||
|
|
||||||
foreach (var completion in completionResult.Completions)
|
foreach (var completion in completionResult.Completions)
|
||||||
{
|
{
|
||||||
var filterText = completion.Key;
|
var filterText = completion.Key;
|
||||||
|
@ -202,13 +205,14 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
|
|
||||||
return descriptionInfo;
|
return descriptionInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
var attributeDescriptionInfo = new AggregateBoundAttributeDescription(attributeDescriptions.ToList());
|
var attributeDescriptionInfo = new AggregateBoundAttributeDescription(attributeDescriptions.ToList());
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(attributeDescriptionInfo);
|
razorCompletionItem.SetAttributeCompletionDescription(attributeDescriptionInfo);
|
||||||
|
|
||||||
completionItems.Add(razorCompletionItem);
|
completionItems.Add(razorCompletionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return completionItems;
|
return completionItems.DrainToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryResolveInsertText(string baseInsertText, AttributeContext context, [NotNullWhen(true)] out string? snippetText)
|
private bool TryResolveInsertText(string baseInsertText, AttributeContext context, [NotNullWhen(true)] out string? snippetText)
|
||||||
|
@ -231,7 +235,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReadOnlyList<RazorCompletionItem> GetElementCompletions(
|
private ImmutableArray<RazorCompletionItem> GetElementCompletions(
|
||||||
SyntaxNode containingElement,
|
SyntaxNode containingElement,
|
||||||
string containingTagName,
|
string containingTagName,
|
||||||
IEnumerable<KeyValuePair<string, string>> attributes,
|
IEnumerable<KeyValuePair<string, string>> attributes,
|
||||||
|
@ -248,7 +252,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
ancestorIsTagHelper,
|
ancestorIsTagHelper,
|
||||||
HtmlFactsService.IsHtmlTagName);
|
HtmlFactsService.IsHtmlTagName);
|
||||||
|
|
||||||
var completionItems = new List<RazorCompletionItem>();
|
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||||
var completionResult = _tagHelperCompletionService.GetElementCompletions(elementCompletionContext);
|
var completionResult = _tagHelperCompletionService.GetElementCompletions(elementCompletionContext);
|
||||||
foreach (var completion in completionResult.Completions)
|
foreach (var completion in completionResult.Completions)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +269,7 @@ internal class TagHelperCompletionProvider : RazorCompletionItemProvider
|
||||||
completionItems.Add(razorCompletionItem);
|
completionItems.Add(razorCompletionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return completionItems;
|
return completionItems.DrainToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private const string BooleanTypeString = "System.Boolean";
|
private const string BooleanTypeString = "System.Boolean";
|
||||||
|
|
|
@ -93,13 +93,13 @@ internal static class IServiceCollectionExtensions
|
||||||
services.AddSingleton<CompletionItemResolver, RazorCompletionItemResolver>();
|
services.AddSingleton<CompletionItemResolver, RazorCompletionItemResolver>();
|
||||||
services.AddSingleton<CompletionItemResolver, DelegatedCompletionItemResolver>();
|
services.AddSingleton<CompletionItemResolver, DelegatedCompletionItemResolver>();
|
||||||
services.AddSingleton<TagHelperCompletionService, LanguageServerTagHelperCompletionService>();
|
services.AddSingleton<TagHelperCompletionService, LanguageServerTagHelperCompletionService>();
|
||||||
services.AddSingleton<RazorCompletionFactsService, DefaultRazorCompletionFactsService>();
|
services.AddSingleton<IRazorCompletionFactsService, RazorCompletionFactsService>();
|
||||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveCompletionItemProvider>();
|
services.AddSingleton<IRazorCompletionItemProvider, DirectiveCompletionItemProvider>();
|
||||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
|
services.AddSingleton<IRazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
|
||||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
|
services.AddSingleton<IRazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
|
||||||
services.AddSingleton<RazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
|
services.AddSingleton<IRazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
|
||||||
services.AddSingleton<RazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();
|
services.AddSingleton<IRazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();
|
||||||
services.AddSingleton<RazorCompletionItemProvider, TagHelperCompletionProvider>();
|
services.AddSingleton<IRazorCompletionItemProvider, TagHelperCompletionProvider>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddDiagnosticServices(this IServiceCollection services)
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Composition;
|
using System.Composition;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||||
using Microsoft.VisualStudio.Editor.Razor;
|
using Microsoft.VisualStudio.Editor.Razor;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
|
|
||||||
[Shared]
|
[Shared]
|
||||||
[Export(typeof(RazorCompletionItemProvider))]
|
[Export(typeof(IRazorCompletionItemProvider))]
|
||||||
internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeCompletionItemProviderBase
|
internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeCompletionItemProviderBase
|
||||||
{
|
{
|
||||||
private static readonly RazorCompletionItem[] s_noDirectiveAttributeCompletionItems = Array.Empty<RazorCompletionItem>();
|
|
||||||
|
|
||||||
private readonly TagHelperFactsService _tagHelperFactsService;
|
private readonly TagHelperFactsService _tagHelperFactsService;
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
|
@ -32,7 +32,7 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
||||||
_tagHelperFactsService = tagHelperFactsService;
|
_tagHelperFactsService = tagHelperFactsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
public override ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||||
{
|
{
|
||||||
if (context is null)
|
if (context is null)
|
||||||
{
|
{
|
||||||
|
@ -47,31 +47,31 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
||||||
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
||||||
{
|
{
|
||||||
// Directive attributes are only supported in components
|
// Directive attributes are only supported in components
|
||||||
return s_noDirectiveAttributeCompletionItems;
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var owner = context.Owner;
|
var owner = context.Owner;
|
||||||
if (owner is null)
|
if (owner is null)
|
||||||
{
|
{
|
||||||
return s_noDirectiveAttributeCompletionItems;
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryGetAttributeInfo(owner, out _, out var attributeName, out var attributeNameLocation, out _, out _))
|
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.
|
// 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))
|
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).
|
// 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))
|
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.
|
// 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.
|
// 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 completionItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_noDirectiveAttributeCompletionItems;
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal IReadOnlyList<RazorCompletionItem> GetAttributeCompletions(
|
internal ImmutableArray<RazorCompletionItem> GetAttributeCompletions(
|
||||||
string selectedAttributeName,
|
string selectedAttributeName,
|
||||||
string containingTagName,
|
string containingTagName,
|
||||||
IEnumerable<string> attributes,
|
IEnumerable<string> attributes,
|
||||||
|
@ -100,7 +100,7 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
||||||
if (descriptorsForTag.Count == 0)
|
if (descriptorsForTag.Count == 0)
|
||||||
{
|
{
|
||||||
// If the current tag has no possible descriptors then we can't have any directive attributes.
|
// 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
|
// 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)
|
foreach (var completion in attributeCompletions)
|
||||||
{
|
{
|
||||||
var insertText = completion.Key;
|
var insertText = completion.Key;
|
||||||
|
@ -173,7 +174,7 @@ internal class DirectiveAttributeCompletionItemProvider : DirectiveAttributeComp
|
||||||
completionItems.Add(razorCompletionItem);
|
completionItems.Add(razorCompletionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return completionItems;
|
return completionItems.DrainToImmutable();
|
||||||
|
|
||||||
bool TryAddCompletion(string attributeName, BoundAttributeDescriptor boundAttributeDescriptor, TagHelperDescriptor tagHelperDescriptor)
|
bool TryAddCompletion(string attributeName, BoundAttributeDescriptor boundAttributeDescriptor, TagHelperDescriptor tagHelperDescriptor)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,14 +5,17 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
using RazorSyntaxList = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxList<Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode>;
|
using RazorSyntaxList = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxList<Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode>;
|
||||||
using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode;
|
using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
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 for testing
|
||||||
internal static bool TryGetAttributeInfo(
|
internal static bool TryGetAttributeInfo(
|
||||||
RazorSyntaxNode attributeLeafOwner,
|
RazorSyntaxNode attributeLeafOwner,
|
||||||
|
|
|
@ -5,16 +5,18 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Composition;
|
using System.Composition;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||||
using Microsoft.VisualStudio.Editor.Razor;
|
using Microsoft.VisualStudio.Editor.Razor;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
|
|
||||||
[Shared]
|
[Shared]
|
||||||
[Export(typeof(RazorCompletionItemProvider))]
|
[Export(typeof(IRazorCompletionItemProvider))]
|
||||||
internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttributeCompletionItemProviderBase
|
internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttributeCompletionItemProviderBase
|
||||||
{
|
{
|
||||||
private readonly TagHelperFactsService _tagHelperFactsService;
|
private readonly TagHelperFactsService _tagHelperFactsService;
|
||||||
|
@ -30,7 +32,7 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
||||||
_tagHelperFactsService = tagHelperFactsService;
|
_tagHelperFactsService = tagHelperFactsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
public override ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||||
{
|
{
|
||||||
if (context is null)
|
if (context is null)
|
||||||
{
|
{
|
||||||
|
@ -45,39 +47,38 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
||||||
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
|
||||||
{
|
{
|
||||||
// Directive attribute parameters are only supported in components
|
// Directive attribute parameters are only supported in components
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var owner = context.Owner;
|
var owner = context.Owner;
|
||||||
if (owner is null)
|
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))
|
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.
|
// 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))
|
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).
|
// 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))
|
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.
|
// 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 GetAttributeParameterCompletions(attributeName, parameterName, containingTagName, attributes, context.TagHelperDocumentContext);
|
||||||
return completions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal IReadOnlyList<RazorCompletionItem> GetAttributeParameterCompletions(
|
internal ImmutableArray<RazorCompletionItem> GetAttributeParameterCompletions(
|
||||||
string attributeName,
|
string attributeName,
|
||||||
string parameterName,
|
string parameterName,
|
||||||
string containingTagName,
|
string containingTagName,
|
||||||
|
@ -88,7 +89,7 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
||||||
if (descriptorsForTag.Count == 0)
|
if (descriptorsForTag.Count == 0)
|
||||||
{
|
{
|
||||||
// If the current tag has no possible descriptors then we can't have any additional attributes.
|
// 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
|
// 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)
|
foreach (var completion in attributeCompletions)
|
||||||
{
|
{
|
||||||
if (string.Equals(completion.Key, parameterName, StringComparison.Ordinal))
|
if (string.Equals(completion.Key, parameterName, StringComparison.Ordinal))
|
||||||
|
@ -150,6 +152,6 @@ internal class DirectiveAttributeParameterCompletionItemProvider : DirectiveAttr
|
||||||
completionItems.Add(razorCompletionItem);
|
completionItems.Add(razorCompletionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return completionItems;
|
return completionItems.DrainToImmutable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,19 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Composition;
|
using System.Composition;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
|
|
||||||
[Shared]
|
[Shared]
|
||||||
[Export(typeof(RazorCompletionItemProvider))]
|
[Export(typeof(IRazorCompletionItemProvider))]
|
||||||
internal class DirectiveCompletionItemProvider : RazorCompletionItemProvider
|
internal class DirectiveCompletionItemProvider : IRazorCompletionItemProvider
|
||||||
{
|
{
|
||||||
internal static readonly IReadOnlyList<RazorCommitCharacter> SingleLineDirectiveCommitCharacters = RazorCommitCharacter.FromArray(new[] { " " });
|
internal static readonly IReadOnlyList<RazorCommitCharacter> SingleLineDirectiveCommitCharacters = RazorCommitCharacter.FromArray(new[] { " " });
|
||||||
internal static readonly IReadOnlyList<RazorCommitCharacter> BlockDirectiveCommitCharacters = 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")
|
["typeparam"] = ("typeparam ${1:T}$0", "typeparam T")
|
||||||
};
|
};
|
||||||
|
|
||||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||||
{
|
{
|
||||||
if (context is null)
|
if (context is null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(context));
|
throw new ArgumentNullException(nameof(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
var completions = new List<RazorCompletionItem>();
|
using var completions = new PooledArrayBuilder<RazorCompletionItem>();
|
||||||
|
|
||||||
if (ShouldProvideCompletions(context))
|
if (ShouldProvideCompletions(context))
|
||||||
{
|
{
|
||||||
var directiveCompletions = GetDirectiveCompletionItems(context.SyntaxTree);
|
var directiveCompletions = GetDirectiveCompletionItems(context.SyntaxTree);
|
||||||
completions.AddRange(directiveCompletions);
|
completions.AddRange(directiveCompletions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return completions;
|
return completions.DrainToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
|
@ -126,11 +129,13 @@ internal class DirectiveCompletionItemProvider : RazorCompletionItemProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// 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 defaultDirectives = FileKinds.IsComponent(syntaxTree.Options.FileKind) ? Array.Empty<DirectiveDescriptor>() : s_defaultDirectives;
|
||||||
var directives = syntaxTree.Options.Directives.Concat(defaultDirectives);
|
var directives = syntaxTree.Options.Directives.Concat(defaultDirectives);
|
||||||
var completionItems = new List<RazorCompletionItem>();
|
|
||||||
|
using var completionItems = new PooledArrayBuilder<RazorCompletionItem>();
|
||||||
|
|
||||||
foreach (var directive in directives)
|
foreach (var directive in directives)
|
||||||
{
|
{
|
||||||
var completionDisplayText = directive.DisplayName ?? directive.Directive;
|
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)
|
private static IReadOnlyList<RazorCommitCharacter> GetDirectiveCommitCharacters(DirectiveKind directiveKind)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
// 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;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
|
@ -11,7 +12,7 @@ using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
|
|
||||||
internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvider
|
internal class MarkupTransitionCompletionItemProvider : IRazorCompletionItemProvider
|
||||||
{
|
{
|
||||||
private static readonly IReadOnlyList<RazorCommitCharacter> s_elementCommitCharacters = RazorCommitCharacter.FromArray(new[] { ">" });
|
private static readonly IReadOnlyList<RazorCommitCharacter> s_elementCommitCharacters = RazorCommitCharacter.FromArray(new[] { ">" });
|
||||||
|
|
||||||
|
@ -40,15 +41,10 @@ internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvi
|
||||||
|
|
||||||
public MarkupTransitionCompletionItemProvider(HtmlFactsService htmlFactsService)
|
public MarkupTransitionCompletionItemProvider(HtmlFactsService htmlFactsService)
|
||||||
{
|
{
|
||||||
if (htmlFactsService is null)
|
_htmlFactsService = htmlFactsService ?? throw new ArgumentNullException(nameof(htmlFactsService));
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(htmlFactsService));
|
|
||||||
}
|
|
||||||
|
|
||||||
_htmlFactsService = htmlFactsService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
public ImmutableArray<RazorCompletionItem> GetCompletionItems(RazorCompletionContext context)
|
||||||
{
|
{
|
||||||
if (context is null)
|
if (context is null)
|
||||||
{
|
{
|
||||||
|
@ -59,12 +55,12 @@ internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvi
|
||||||
if (owner is null)
|
if (owner is null)
|
||||||
{
|
{
|
||||||
Debug.Fail("Owner should never be null.");
|
Debug.Fail("Owner should never be null.");
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AtMarkupTransitionCompletionPoint(owner))
|
if (!AtMarkupTransitionCompletionPoint(owner))
|
||||||
{
|
{
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = owner.Parent;
|
var parent = owner.Parent;
|
||||||
|
@ -74,11 +70,10 @@ internal class MarkupTransitionCompletionItemProvider : RazorCompletionItemProvi
|
||||||
if (!_htmlFactsService.TryGetElementInfo(parent, out var containingTagNameToken, out _) ||
|
if (!_htmlFactsService.TryGetElementInfo(parent, out var containingTagNameToken, out _) ||
|
||||||
!containingTagNameToken.Span.IntersectsWith(context.AbsoluteIndex))
|
!containingTagNameToken.Span.IntersectsWith(context.AbsoluteIndex))
|
||||||
{
|
{
|
||||||
return Array.Empty<RazorCompletionItem>();
|
return ImmutableArray<RazorCompletionItem>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var completions = new List<RazorCompletionItem>() { MarkupTransitionCompletionItem };
|
return ImmutableArray.Create(MarkupTransitionCompletionItem);
|
||||||
return completions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AtMarkupTransitionCompletionPoint(RazorSyntaxNode owner)
|
private static bool AtMarkupTransitionCompletionPoint(RazorSyntaxNode owner)
|
||||||
|
|
|
@ -1,11 +1,51 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Composition;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor;
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
using Microsoft.CodeAnalysis.Razor.Tooltip;
|
||||||
|
@ -38,45 +38,25 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
||||||
}.ToImmutableArray();
|
}.ToImmutableArray();
|
||||||
|
|
||||||
private readonly VisualStudioRazorParser _parser;
|
private readonly VisualStudioRazorParser _parser;
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
private readonly ICompletionBroker _completionBroker;
|
private readonly ICompletionBroker _completionBroker;
|
||||||
private readonly VisualStudioDescriptionFactory _descriptionFactory;
|
private readonly IVisualStudioDescriptionFactory _descriptionFactory;
|
||||||
private readonly JoinableTaskFactory _joinableTaskFactory;
|
private readonly JoinableTaskFactory _joinableTaskFactory;
|
||||||
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
|
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
|
||||||
|
|
||||||
public RazorDirectiveAttributeCompletionSource(
|
public RazorDirectiveAttributeCompletionSource(
|
||||||
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
|
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
|
||||||
VisualStudioRazorParser parser,
|
VisualStudioRazorParser parser,
|
||||||
RazorCompletionFactsService completionFactsService,
|
IRazorCompletionFactsService completionFactsService,
|
||||||
ICompletionBroker completionBroker,
|
ICompletionBroker completionBroker,
|
||||||
VisualStudioDescriptionFactory descriptionFactory,
|
IVisualStudioDescriptionFactory descriptionFactory,
|
||||||
JoinableTaskFactory joinableTaskFactory)
|
JoinableTaskFactory joinableTaskFactory)
|
||||||
{
|
{
|
||||||
if (projectSnapshotManagerDispatcher is null)
|
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher ?? throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
||||||
{
|
_parser = parser ?? throw new ArgumentNullException(nameof(parser));
|
||||||
throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
_completionFactsService = completionFactsService ?? throw new ArgumentNullException(nameof(completionFactsService));
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
_completionBroker = completionBroker;
|
_completionBroker = completionBroker;
|
||||||
_descriptionFactory = descriptionFactory;
|
_descriptionFactory = descriptionFactory ?? throw new ArgumentNullException(nameof(descriptionFactory));
|
||||||
_joinableTaskFactory = joinableTaskFactory;
|
_joinableTaskFactory = joinableTaskFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +79,7 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
||||||
var razorCompletionContext = new RazorCompletionContext(absoluteIndex, owner, syntaxTree, tagHelperDocumentContext);
|
var razorCompletionContext = new RazorCompletionContext(absoluteIndex, owner, syntaxTree, tagHelperDocumentContext);
|
||||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
||||||
|
|
||||||
if (razorCompletionItems.Count == 0)
|
if (razorCompletionItems.Length == 0)
|
||||||
{
|
{
|
||||||
return CompletionContext.Empty;
|
return CompletionContext.Empty;
|
||||||
}
|
}
|
||||||
|
@ -121,8 +101,9 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
||||||
activeSession.Dismiss();
|
activeSession.Dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
var completionItems = new List<CompletionItem>();
|
using var _ = ArrayBuilderPool<CompletionItem>.GetPooledObject(out var completionItems);
|
||||||
var completionItemKinds = new HashSet<RazorCompletionItemKind>();
|
var completionItemKinds = new HashSet<RazorCompletionItemKind>();
|
||||||
|
|
||||||
foreach (var razorCompletionItem in razorCompletionItems)
|
foreach (var razorCompletionItem in razorCompletionItems)
|
||||||
{
|
{
|
||||||
if (razorCompletionItem.Kind != RazorCompletionItemKind.DirectiveAttribute &&
|
if (razorCompletionItem.Kind != RazorCompletionItemKind.DirectiveAttribute &&
|
||||||
|
@ -150,9 +131,10 @@ internal class RazorDirectiveAttributeCompletionSource : IAsyncCompletionSource
|
||||||
}
|
}
|
||||||
|
|
||||||
session.Properties.SetCompletionItemKinds(completionItemKinds);
|
session.Properties.SetCompletionItemKinds(completionItemKinds);
|
||||||
var orderedCompletionItems = completionItems.OrderBy(item => item.DisplayText);
|
|
||||||
var context = new CompletionContext(orderedCompletionItems.ToImmutableArray());
|
completionItems.Sort(CompletionItemDisplayTextComparer.Instance);
|
||||||
return context;
|
|
||||||
|
return new CompletionContext(completionItems.ToImmutable());
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,50 +23,24 @@ namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
||||||
internal class RazorDirectiveAttributeCompletionSourceProvider : IAsyncCompletionSourceProvider
|
internal class RazorDirectiveAttributeCompletionSourceProvider : IAsyncCompletionSourceProvider
|
||||||
{
|
{
|
||||||
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
|
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
private readonly ICompletionBroker _completionBroker;
|
private readonly ICompletionBroker _completionBroker;
|
||||||
private readonly VisualStudioDescriptionFactory _descriptionFactory;
|
private readonly IVisualStudioDescriptionFactory _descriptionFactory;
|
||||||
private readonly JoinableTaskContext _joinableTaskContext;
|
private readonly JoinableTaskContext _joinableTaskContext;
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
public RazorDirectiveAttributeCompletionSourceProvider(
|
public RazorDirectiveAttributeCompletionSourceProvider(
|
||||||
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
|
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
|
||||||
RazorCompletionFactsService completionFactsService,
|
IRazorCompletionFactsService completionFactsService,
|
||||||
IAsyncCompletionBroker asyncCoompletionBroker,
|
|
||||||
ICompletionBroker completionBroker,
|
ICompletionBroker completionBroker,
|
||||||
VisualStudioDescriptionFactory descriptionFactory,
|
IVisualStudioDescriptionFactory descriptionFactory,
|
||||||
JoinableTaskContext joinableTaskContext)
|
JoinableTaskContext joinableTaskContext)
|
||||||
{
|
{
|
||||||
if (projectSnapshotManagerDispatcher is null)
|
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher ?? throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
||||||
{
|
_completionFactsService = completionFactsService ?? throw new ArgumentNullException(nameof(completionFactsService));
|
||||||
throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
|
_completionBroker = completionBroker ?? throw new ArgumentNullException(nameof(completionBroker));
|
||||||
}
|
_descriptionFactory = descriptionFactory ?? throw new ArgumentNullException(nameof(descriptionFactory));
|
||||||
|
_joinableTaskContext = joinableTaskContext ?? throw new ArgumentNullException(nameof(joinableTaskContext));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAsyncCompletionSource? GetOrCreate(ITextView textView)
|
public IAsyncCompletionSource? GetOrCreate(ITextView textView)
|
||||||
|
@ -96,13 +70,12 @@ internal class RazorDirectiveAttributeCompletionSourceProvider : IAsyncCompletio
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var completionSource = new RazorDirectiveAttributeCompletionSource(
|
return new RazorDirectiveAttributeCompletionSource(
|
||||||
_projectSnapshotManagerDispatcher,
|
_projectSnapshotManagerDispatcher,
|
||||||
parser,
|
parser,
|
||||||
_completionFactsService,
|
_completionFactsService,
|
||||||
_completionBroker,
|
_completionBroker,
|
||||||
_descriptionFactory,
|
_descriptionFactory,
|
||||||
_joinableTaskContext.Factory);
|
_joinableTaskContext.Factory);
|
||||||
return completionSource;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
|
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||||
using Microsoft.CodeAnalysis.Razor.Completion;
|
using Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
using Microsoft.VisualStudio.Core.Imaging;
|
using Microsoft.VisualStudio.Core.Imaging;
|
||||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
|
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
|
||||||
|
@ -33,11 +33,11 @@ internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal readonly VisualStudioRazorParser Parser;
|
internal readonly VisualStudioRazorParser Parser;
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
|
|
||||||
public RazorDirectiveCompletionSource(
|
public RazorDirectiveCompletionSource(
|
||||||
VisualStudioRazorParser parser,
|
VisualStudioRazorParser parser,
|
||||||
RazorCompletionFactsService completionFactsService)
|
IRazorCompletionFactsService completionFactsService)
|
||||||
{
|
{
|
||||||
if (parser is null)
|
if (parser is null)
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,8 @@ internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
||||||
var razorCompletionContext = new RazorCompletionContext(absoluteIndex, owner, syntaxTree, tagHelperDocumentContext);
|
var razorCompletionContext = new RazorCompletionContext(absoluteIndex, owner, syntaxTree, tagHelperDocumentContext);
|
||||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext);
|
||||||
|
|
||||||
var completionItems = new List<CompletionItem>();
|
using var _ = ArrayBuilderPool<CompletionItem>.GetPooledObject(out var completionItems);
|
||||||
|
|
||||||
foreach (var razorCompletionItem in razorCompletionItems)
|
foreach (var razorCompletionItem in razorCompletionItems)
|
||||||
{
|
{
|
||||||
if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive)
|
if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive)
|
||||||
|
@ -96,13 +97,13 @@ internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
||||||
suffix: string.Empty,
|
suffix: string.Empty,
|
||||||
sortText: razorCompletionItem.DisplayText,
|
sortText: razorCompletionItem.DisplayText,
|
||||||
attributeIcons: ImmutableArray<ImageElement>.Empty);
|
attributeIcons: ImmutableArray<ImageElement>.Empty);
|
||||||
|
|
||||||
var completionDescription = razorCompletionItem.GetDirectiveCompletionDescription();
|
var completionDescription = razorCompletionItem.GetDirectiveCompletionDescription();
|
||||||
completionItem.Properties.AddProperty(DescriptionKey, completionDescription);
|
completionItem.Properties.AddProperty(DescriptionKey, completionDescription);
|
||||||
completionItems.Add(completionItem);
|
completionItems.Add(completionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
var context = new CompletionContext(completionItems.ToImmutableArray());
|
return new CompletionContext(completionItems.ToImmutable());
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,10 +20,10 @@ namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
||||||
[ContentType(RazorConstants.LegacyCoreContentType)]
|
[ContentType(RazorConstants.LegacyCoreContentType)]
|
||||||
internal class RazorDirectiveCompletionSourceProvider : IAsyncCompletionSourceProvider
|
internal class RazorDirectiveCompletionSourceProvider : IAsyncCompletionSourceProvider
|
||||||
{
|
{
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
public RazorDirectiveCompletionSourceProvider(RazorCompletionFactsService completionFactsService)
|
public RazorDirectiveCompletionSourceProvider(IRazorCompletionFactsService completionFactsService)
|
||||||
{
|
{
|
||||||
if (completionFactsService is null)
|
if (completionFactsService is null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,114 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
// 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.CodeAnalysis.Razor.Tooltip;
|
||||||
|
using Microsoft.VisualStudio.Core.Imaging;
|
||||||
using Microsoft.VisualStudio.Text.Adornments;
|
using Microsoft.VisualStudio.Text.Adornments;
|
||||||
|
|
||||||
namespace Microsoft.VisualStudio.Editor.Razor.Completion;
|
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
|
public class LegacyRazorCompletionEndpointTest : LanguageServerTestBase
|
||||||
{
|
{
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
private readonly CompletionListCache _completionListCache;
|
private readonly CompletionListCache _completionListCache;
|
||||||
private readonly VSInternalClientCapabilities _clientCapabilities;
|
private readonly VSInternalClientCapabilities _clientCapabilities;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class LegacyRazorCompletionEndpointTest : LanguageServerTestBase
|
||||||
var tagHelperFactsService = new DefaultTagHelperFactsService();
|
var tagHelperFactsService = new DefaultTagHelperFactsService();
|
||||||
var tagHelperCompletionService = new LanguageServerTagHelperCompletionService(tagHelperFactsService);
|
var tagHelperCompletionService = new LanguageServerTagHelperCompletionService(tagHelperFactsService);
|
||||||
|
|
||||||
var completionProviders = new RazorCompletionItemProvider[]
|
var completionProviders = new IRazorCompletionItemProvider[]
|
||||||
{
|
{
|
||||||
new DirectiveCompletionItemProvider(),
|
new DirectiveCompletionItemProvider(),
|
||||||
new DirectiveAttributeCompletionItemProvider(tagHelperFactsService),
|
new DirectiveAttributeCompletionItemProvider(tagHelperFactsService),
|
||||||
|
@ -44,7 +44,7 @@ public class LegacyRazorCompletionEndpointTest : LanguageServerTestBase
|
||||||
new TagHelperCompletionProvider(tagHelperCompletionService, new DefaultHtmlFactsService(), tagHelperFactsService, TestRazorLSPOptionsMonitor.Create())
|
new TagHelperCompletionProvider(tagHelperCompletionService, new DefaultHtmlFactsService(), tagHelperFactsService, TestRazorLSPOptionsMonitor.Create())
|
||||||
};
|
};
|
||||||
|
|
||||||
_completionFactsService = new DefaultRazorCompletionFactsService(completionProviders);
|
_completionFactsService = new RazorCompletionFactsService(completionProviders);
|
||||||
_completionListCache = new CompletionListCache();
|
_completionListCache = new CompletionListCache();
|
||||||
_clientCapabilities = new VSInternalClientCapabilities()
|
_clientCapabilities = new VSInternalClientCapabilities()
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Immutable;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -27,7 +27,6 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
private readonly CompletionListCache _completionListCache;
|
private readonly CompletionListCache _completionListCache;
|
||||||
private readonly VSInternalCompletionSetting _completionCapability;
|
private readonly VSInternalCompletionSetting _completionCapability;
|
||||||
private readonly VSInternalClientCapabilities _defaultClientCapability;
|
private readonly VSInternalClientCapabilities _defaultClientCapability;
|
||||||
private readonly VSInternalClientCapabilities _vsClientCapability;
|
|
||||||
|
|
||||||
public LegacyRazorCompletionResolveEndpointTest(ITestOutputHelper testOutput)
|
public LegacyRazorCompletionResolveEndpointTest(ITestOutputHelper testOutput)
|
||||||
: base(testOutput)
|
: base(testOutput)
|
||||||
|
@ -50,15 +49,6 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
Completion = _completionCapability,
|
Completion = _completionCapability,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
_vsClientCapability = new VSInternalClientCapabilities()
|
|
||||||
{
|
|
||||||
TextDocument = new TextDocumentClientCapabilities()
|
|
||||||
{
|
|
||||||
Completion = _completionCapability,
|
|
||||||
},
|
|
||||||
SupportsVisualStudioExtensions = true,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -69,7 +59,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.Directive);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.Directive);
|
||||||
razorCompletionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription("Test directive"));
|
razorCompletionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription("Test directive"));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single();
|
var completionItem = completionList.Items.Single();
|
||||||
var parameters = ConvertToBridgedItem(completionItem);
|
var parameters = ConvertToBridgedItem(completionItem);
|
||||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||||
|
@ -89,7 +79,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||||
var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);
|
var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);
|
||||||
razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
|
razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single();
|
var completionItem = completionList.Items.Single();
|
||||||
var parameters = ConvertToBridgedItem(completionItem);
|
var parameters = ConvertToBridgedItem(completionItem);
|
||||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||||
|
@ -117,7 +107,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single();
|
var completionItem = completionList.Items.Single();
|
||||||
var parameters = ConvertToBridgedItem(completionItem);
|
var parameters = ConvertToBridgedItem(completionItem);
|
||||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||||
|
@ -145,7 +135,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single();
|
var completionItem = completionList.Items.Single();
|
||||||
var parameters = ConvertToBridgedItem(completionItem);
|
var parameters = ConvertToBridgedItem(completionItem);
|
||||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||||
|
@ -173,7 +163,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
||||||
razorCompletionItem.SetTagHelperElementDescriptionInfo(new AggregateBoundElementDescription(Array.Empty<BoundElementDescriptionInfo>()));
|
razorCompletionItem.SetTagHelperElementDescriptionInfo(new AggregateBoundElementDescription(Array.Empty<BoundElementDescriptionInfo>()));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single();
|
var completionItem = completionList.Items.Single();
|
||||||
var parameters = ConvertToBridgedItem(completionItem);
|
var parameters = ConvertToBridgedItem(completionItem);
|
||||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||||
|
@ -201,7 +191,7 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
endpoint.ApplyCapabilities(new(), _defaultClientCapability);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>()));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single();
|
var completionItem = completionList.Items.Single();
|
||||||
var parameters = ConvertToBridgedItem(completionItem);
|
var parameters = ConvertToBridgedItem(completionItem);
|
||||||
var requestContext = CreateRazorRequestContext(documentContext: null);
|
var requestContext = CreateRazorRequestContext(documentContext: null);
|
||||||
|
@ -238,9 +228,9 @@ public class LegacyRazorCompletionResolveEndpointTest : LanguageServerTestBase
|
||||||
Assert.Null(newCompletionItem.Documentation);
|
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);
|
var resultId = _completionListCache.Add(completionList, razorCompletionItems);
|
||||||
completionList.SetResultId(resultId, completionSetting: null);
|
completionList.SetResultId(resultId, completionSetting: null);
|
||||||
return completionList;
|
return completionList;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip;
|
using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip;
|
||||||
|
@ -70,7 +70,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.Directive);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.Directive);
|
||||||
razorCompletionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription("Test directive"));
|
razorCompletionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription("Test directive"));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -88,7 +88,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);
|
var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);
|
||||||
razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
|
razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -106,7 +106,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -124,7 +124,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -142,7 +142,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
||||||
razorCompletionItem.SetTagHelperElementDescriptionInfo(_elementDescription);
|
razorCompletionItem.SetTagHelperElementDescriptionInfo(_elementDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -160,7 +160,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -178,7 +178,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttribute);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -196,7 +196,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.DirectiveAttributeParameter);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -214,7 +214,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperElement);
|
||||||
razorCompletionItem.SetTagHelperElementDescriptionInfo(_elementDescription);
|
razorCompletionItem.SetTagHelperElementDescriptionInfo(_elementDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -232,7 +232,7 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
var resolver = new RazorCompletionItemResolver(_lspTagHelperTooltipFactory, _vsLspTagHelperTooltipFactory);
|
||||||
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);
|
||||||
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
razorCompletionItem.SetAttributeCompletionDescription(_attributeDescription);
|
||||||
var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
|
var completionList = CreateLSPCompletionList(razorCompletionItem);
|
||||||
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
var completionItem = completionList.Items.Single() as VSInternalCompletionItem;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -259,9 +259,6 @@ public class RazorCompletionItemResolverTest : LanguageServerTestBase
|
||||||
Assert.Null(resolvedCompletionItem);
|
Assert.Null(resolvedCompletionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VSInternalCompletionList CreateLSPCompletionList(IReadOnlyList<RazorCompletionItem> razorCompletionItems)
|
private VSInternalCompletionList CreateLSPCompletionList(params RazorCompletionItem[] razorCompletionItems)
|
||||||
{
|
=> RazorCompletionListProvider.CreateLSPCompletionList(razorCompletionItems.ToImmutableArray(), _defaultClientCapability);
|
||||||
var completionList = RazorCompletionListProvider.CreateLSPCompletionList(razorCompletionItems, _defaultClientCapability);
|
|
||||||
return completionList;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
||||||
|
|
||||||
public class RazorCompletionListProvierTest : LanguageServerTestBase
|
public class RazorCompletionListProvierTest : LanguageServerTestBase
|
||||||
{
|
{
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
private readonly CompletionListCache _completionListCache;
|
private readonly CompletionListCache _completionListCache;
|
||||||
private readonly VSInternalClientCapabilities _clientCapabilities;
|
private readonly VSInternalClientCapabilities _clientCapabilities;
|
||||||
private readonly VSInternalCompletionContext _defaultCompletionContext;
|
private readonly VSInternalCompletionContext _defaultCompletionContext;
|
||||||
|
@ -35,7 +35,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
||||||
public RazorCompletionListProvierTest(ITestOutputHelper testOutput)
|
public RazorCompletionListProvierTest(ITestOutputHelper testOutput)
|
||||||
: base(testOutput)
|
: base(testOutput)
|
||||||
{
|
{
|
||||||
_completionFactsService = new DefaultRazorCompletionFactsService(GetCompletionProviders());
|
_completionFactsService = new RazorCompletionFactsService(GetCompletionProviders());
|
||||||
_completionListCache = new CompletionListCache();
|
_completionListCache = new CompletionListCache();
|
||||||
_clientCapabilities = new VSInternalClientCapabilities()
|
_clientCapabilities = new VSInternalClientCapabilities()
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
||||||
_defaultCompletionContext = new VSInternalCompletionContext();
|
_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.
|
// Working around strong naming restriction.
|
||||||
var tagHelperFactsService = new DefaultTagHelperFactsService();
|
var tagHelperFactsService = new DefaultTagHelperFactsService();
|
||||||
|
@ -67,7 +67,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
||||||
|
|
||||||
optionsMonitor ??= TestRazorLSPOptionsMonitor.Create();
|
optionsMonitor ??= TestRazorLSPOptionsMonitor.Create();
|
||||||
|
|
||||||
var completionProviders = new RazorCompletionItemProvider[]
|
var completionProviders = new IRazorCompletionItemProvider[]
|
||||||
{
|
{
|
||||||
new DirectiveCompletionItemProvider(),
|
new DirectiveCompletionItemProvider(),
|
||||||
new DirectiveAttributeCompletionItemProvider(tagHelperFactsService),
|
new DirectiveAttributeCompletionItemProvider(tagHelperFactsService),
|
||||||
|
@ -582,7 +582,7 @@ public class RazorCompletionListProvierTest : LanguageServerTestBase
|
||||||
var optionsMonitor = TestRazorLSPOptionsMonitor.Create();
|
var optionsMonitor = TestRazorLSPOptionsMonitor.Create();
|
||||||
await optionsMonitor.UpdateAsync(optionsMonitor.CurrentValue with { AutoInsertAttributeQuotes = false }, DisposalToken);
|
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);
|
var provider = new RazorCompletionListProvider(completionFactsService, _completionListCache, LoggerFactory);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Test.Common;
|
using Microsoft.AspNetCore.Razor.Test.Common;
|
||||||
|
@ -12,13 +13,8 @@ using Xunit.Abstractions;
|
||||||
|
|
||||||
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
namespace Microsoft.CodeAnalysis.Razor.Completion;
|
||||||
|
|
||||||
public class DefaultRazorCompletionFactsServiceTest : TestBase
|
public class DefaultRazorCompletionFactsServiceTest(ITestOutputHelper testOutput) : TestBase(testOutput)
|
||||||
{
|
{
|
||||||
public DefaultRazorCompletionFactsServiceTest(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetDirectiveCompletionItems_AllProvidersCompletionItems()
|
public void GetDirectiveCompletionItems_AllProvidersCompletionItems()
|
||||||
{
|
{
|
||||||
|
@ -27,10 +23,10 @@ public class DefaultRazorCompletionFactsServiceTest : TestBase
|
||||||
var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: null, Enumerable.Empty<TagHelperDescriptor>());
|
var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: null, Enumerable.Empty<TagHelperDescriptor>());
|
||||||
var completionItem1 = new RazorCompletionItem("displayText1", "insertText1", RazorCompletionItemKind.Directive);
|
var completionItem1 = new RazorCompletionItem("displayText1", "insertText1", RazorCompletionItemKind.Directive);
|
||||||
var context = new RazorCompletionContext(0, null, syntaxTree, tagHelperDocumentContext);
|
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 completionItem2 = new RazorCompletionItem("displayText2", "insertText2", RazorCompletionItemKind.Directive);
|
||||||
var provider2 = Mock.Of<RazorCompletionItemProvider>(p => p.GetCompletionItems(context) == new[] { completionItem2 }, MockBehavior.Strict);
|
var provider2 = Mock.Of<IRazorCompletionItemProvider>(p => p.GetCompletionItems(context) == ImmutableArray.Create(completionItem2), MockBehavior.Strict);
|
||||||
var completionFactsService = new DefaultRazorCompletionFactsService(new[] { provider1, provider2 });
|
var completionFactsService = new RazorCompletionFactsService(new[] { provider1, provider2 });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var completionItems = completionFactsService.GetCompletionItems(context);
|
var completionItems = completionFactsService.GetCompletionItems(context);
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class DirectiveAttributeParameterCompletionItemProviderTest : RazorIntegr
|
||||||
var completions = _provider.GetCompletionItems(context);
|
var completions = _provider.GetCompletionItems(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(6, completions.Count);
|
Assert.Equal(6, completions.Length);
|
||||||
AssertContains(completions, "culture");
|
AssertContains(completions, "culture");
|
||||||
AssertContains(completions, "event");
|
AssertContains(completions, "event");
|
||||||
AssertContains(completions, "format");
|
AssertContains(completions, "format");
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
public void CreateClassifiedDescription_SingleDescription_NoSeparator()
|
public void CreateClassifiedDescription_SingleDescription_NoSeparator()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -33,14 +33,14 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
var result = factory.CreateClassifiedDescription(description);
|
var result = factory.CreateClassifiedDescription(description);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.DoesNotContain(DefaultVisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
Assert.DoesNotContain(VisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateClassifiedDescription_MultipleDescription_Separator()
|
public void CreateClassifiedDescription_MultipleDescription_Separator()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -51,14 +51,14 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
var result = factory.CreateClassifiedDescription(description);
|
var result = factory.CreateClassifiedDescription(description);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Contains(DefaultVisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
Assert.Contains(VisualStudioDescriptionFactory.SeparatorElement, result.Elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateClassifiedDescription_RepresentsReturnType()
|
public void CreateClassifiedDescription_RepresentsReturnType()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -76,7 +76,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
public void CreateClassifiedDescription_RepresentsTypeName()
|
public void CreateClassifiedDescription_RepresentsTypeName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -94,7 +94,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
public void CreateClassifiedDescription_RepresentsPropertyName()
|
public void CreateClassifiedDescription_RepresentsPropertyName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -112,7 +112,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
public void CreateClassifiedDescription_RepresentsDocumentation()
|
public void CreateClassifiedDescription_RepresentsDocumentation()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("TheReturnType", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -130,7 +130,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
public void CreateClassifiedDescription_CanSimplifyKeywordReturnTypes()
|
public void CreateClassifiedDescription_CanSimplifyKeywordReturnTypes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("System.String", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("System.String", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
@ -149,7 +149,7 @@ public class DefaultVisualStudioDescriptionFactoryTest : TestBase
|
||||||
public void CreateClassifiedDescription_CanRepresentMultipleDescriptions()
|
public void CreateClassifiedDescription_CanRepresentMultipleDescriptions()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var factory = new DefaultVisualStudioDescriptionFactory();
|
var factory = new VisualStudioDescriptionFactory();
|
||||||
var description = new AggregateBoundAttributeDescription(new[]
|
var description = new AggregateBoundAttributeDescription(new[]
|
||||||
{
|
{
|
||||||
new BoundAttributeDescriptionInfo("System.String", "TheTypeName", "ThePropertyName", "The documentation"),
|
new BoundAttributeDescriptionInfo("System.String", "TheTypeName", "ThePropertyName", "The documentation"),
|
||||||
|
|
|
@ -46,11 +46,11 @@ public class RazorDirectiveAttributeCompletionSourceTest : ProjectSnapshotManage
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedResult = new ContainerElement(ContainerElementStyle.Wrapped);
|
var expectedResult = new ContainerElement(ContainerElementStyle.Wrapped);
|
||||||
var description = new AggregateBoundAttributeDescription(Array.Empty<BoundAttributeDescriptionInfo>());
|
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(
|
var source = new RazorDirectiveAttributeCompletionSource(
|
||||||
Dispatcher,
|
Dispatcher,
|
||||||
Mock.Of<VisualStudioRazorParser>(MockBehavior.Strict),
|
Mock.Of<VisualStudioRazorParser>(MockBehavior.Strict),
|
||||||
Mock.Of<RazorCompletionFactsService>(MockBehavior.Strict),
|
Mock.Of<IRazorCompletionFactsService>(MockBehavior.Strict),
|
||||||
Mock.Of<ICompletionBroker>(MockBehavior.Strict),
|
Mock.Of<ICompletionBroker>(MockBehavior.Strict),
|
||||||
descriptionFactory,
|
descriptionFactory,
|
||||||
JoinableTaskFactory);
|
JoinableTaskFactory);
|
||||||
|
@ -240,9 +240,9 @@ public class RazorDirectiveAttributeCompletionSourceTest : ProjectSnapshotManage
|
||||||
var source = new RazorDirectiveAttributeCompletionSource(
|
var source = new RazorDirectiveAttributeCompletionSource(
|
||||||
Dispatcher,
|
Dispatcher,
|
||||||
Mock.Of<VisualStudioRazorParser>(MockBehavior.Strict),
|
Mock.Of<VisualStudioRazorParser>(MockBehavior.Strict),
|
||||||
Mock.Of<RazorCompletionFactsService>(MockBehavior.Strict),
|
Mock.Of<IRazorCompletionFactsService>(MockBehavior.Strict),
|
||||||
Mock.Of<ICompletionBroker>(MockBehavior.Strict),
|
Mock.Of<ICompletionBroker>(MockBehavior.Strict),
|
||||||
Mock.Of<VisualStudioDescriptionFactory>(MockBehavior.Strict),
|
Mock.Of<IVisualStudioDescriptionFactory>(MockBehavior.Strict),
|
||||||
JoinableTaskFactory);
|
JoinableTaskFactory);
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class RazorDirectiveCompletionSourceProviderTest : ProjectSnapshotManager
|
||||||
{
|
{
|
||||||
private readonly IContentType _razorContentType;
|
private readonly IContentType _razorContentType;
|
||||||
private readonly IContentType _nonRazorContentType;
|
private readonly IContentType _nonRazorContentType;
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
|
|
||||||
public RazorDirectiveCompletionSourceProviderTest(ITestOutputHelper testOutput)
|
public RazorDirectiveCompletionSourceProviderTest(ITestOutputHelper testOutput)
|
||||||
: base(testOutput)
|
: base(testOutput)
|
||||||
|
@ -34,7 +34,7 @@ public class RazorDirectiveCompletionSourceProviderTest : ProjectSnapshotManager
|
||||||
c => c.IsOfType(It.IsAny<string>()) == false,
|
c => c.IsOfType(It.IsAny<string>()) == false,
|
||||||
MockBehavior.Strict);
|
MockBehavior.Strict);
|
||||||
|
|
||||||
_completionFactsService = Mock.Of<RazorCompletionFactsService>(MockBehavior.Strict);
|
_completionFactsService = Mock.Of<IRazorCompletionFactsService>(MockBehavior.Strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -33,12 +33,12 @@ public class RazorDirectiveCompletionSourceTest : ProjectSnapshotManagerDispatch
|
||||||
CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
|
CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly RazorCompletionFactsService _completionFactsService;
|
private readonly IRazorCompletionFactsService _completionFactsService;
|
||||||
|
|
||||||
public RazorDirectiveCompletionSourceTest(ITestOutputHelper testOutput)
|
public RazorDirectiveCompletionSourceTest(ITestOutputHelper testOutput)
|
||||||
: base(testOutput)
|
: base(testOutput)
|
||||||
{
|
{
|
||||||
_completionFactsService = new DefaultRazorCompletionFactsService(new[] { new DirectiveCompletionItemProvider() });
|
_completionFactsService = new RazorCompletionFactsService(new[] { new DirectiveCompletionItemProvider() });
|
||||||
}
|
}
|
||||||
|
|
||||||
[UIFact]
|
[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)
|
static ImmutableArray<TResult> BuildResult(ImmutableArray<T> items, Func<T, TResult> selector)
|
||||||
{
|
{
|
||||||
using var _ = ArrayBuilderPool<TResult>.GetPooledObject(out var result);
|
using var results = new PooledArrayBuilder<TResult>(capacity: items.Length);
|
||||||
result.SetCapacityIfLarger(items.Length);
|
|
||||||
|
|
||||||
foreach (var item in items)
|
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);
|
_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)
|
public void AddRange(IReadOnlyList<T> items)
|
||||||
{
|
{
|
||||||
if (items.Count == 0)
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче