Skip to content

Commit

Permalink
Merge pull request #15688 from rchande/fastersymbolcompletion
Browse files Browse the repository at this point in the history
Don't use symbolid in symbol completion
  • Loading branch information
Ravi Chande authored Jan 4, 2017
2 parents 5a8bacc + c1fe0af commit 16a48cd
Show file tree
Hide file tree
Showing 21 changed files with 297 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private async Task<ImmutableArray<CompletionItem>> GetNameEqualsItemsAsync(
var text = await semanticModel.SyntaxTree.GetTextAsync(context.CancellationToken).ConfigureAwait(false);
var q = from p in attributeNamedParameters
where !existingNamedParameters.Contains(p.Name)
select SymbolCompletionItem.Create(
select SymbolCompletionItem.CreateWithSymbolId(
displayText: p.Name.ToIdentifierToken().ToString() + SpaceEqualsString,
insertionText: null,
symbol: p,
Expand All @@ -165,7 +165,7 @@ private async Task<IEnumerable<CompletionItem>> GetNameColonItemsAsync(
return from pl in parameterLists
from p in pl
where !existingNamedParameters.Contains(p.Name)
select SymbolCompletionItem.Create(
select SymbolCompletionItem.CreateWithSymbolId(
displayText: p.Name.ToIdentifierToken().ToString() + ColonString,
insertionText: null,
symbol: p,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
internal sealed class CrefCompletionProvider : CommonCompletionProvider
internal sealed class CrefCompletionProvider : AbstractCrefCompletionProvider
{

public static readonly SymbolDisplayFormat QualifiedCrefFormat =
new SymbolDisplayFormat(
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted,
Expand Down Expand Up @@ -60,10 +61,33 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
var options = context.Options;
var cancellationToken = context.CancellationToken;

var (token, semanticModel, symbols) = await GetSymbolsAsync(document, position, options, cancellationToken).ConfigureAwait(false);

if (symbols.Length == 0)
{
return;
}

context.IsExclusive = true;

var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var span = GetCompletionItemSpan(text, position);
var hideAdvancedMembers = options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language);
var serializedOptions = ImmutableDictionary<string, string>.Empty.Add(HideAdvancedMembers, hideAdvancedMembers.ToString());

var items = CreateCompletionItems(document.Project.Solution.Workspace,
semanticModel, symbols, token, span, position, serializedOptions);

context.AddItems(items);
}

protected override async Task<(SyntaxToken, SemanticModel, ImmutableArray<ISymbol>)> GetSymbolsAsync(
Document document, int position, OptionSet options, CancellationToken cancellationToken)
{
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
if (!tree.IsEntirelyWithinCrefSyntax(position, cancellationToken))
{
return;
return (default(SyntaxToken), null, ImmutableArray<ISymbol>.Empty);
}

var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDocumentationComments: true)
Expand All @@ -75,28 +99,18 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
_testSpeculativeNodeCallbackOpt?.Invoke(parentNode);
if (parentNode == null)
{
return;
return (default(SyntaxToken), null, ImmutableArray<ISymbol>.Empty);
}

var semanticModel = await document.GetSemanticModelForNodeAsync(
parentNode, cancellationToken).ConfigureAwait(false);

var symbols = GetSymbols(token, semanticModel, cancellationToken);

symbols = symbols.FilterToVisibleAndBrowsableSymbols(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation);

if (!symbols.Any())
{
return;
}

context.IsExclusive = true;

var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var span = GetCompletionItemSpan(text, position);
var symbols = GetSymbols(token, semanticModel, cancellationToken)
.FilterToVisibleAndBrowsableSymbols(
options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language),
semanticModel.Compilation);

var items = CreateCompletionItems(document.Project.Solution.Workspace, semanticModel, symbols, token, span);
context.AddItems(items);
return (token, semanticModel, symbols);
}

private static bool IsCrefStartContext(SyntaxToken token)
Expand Down Expand Up @@ -230,15 +244,15 @@ private static TextSpan GetCompletionItemSpan(SourceText text, int position)
}

private IEnumerable<CompletionItem> CreateCompletionItems(
Workspace workspace, SemanticModel semanticModel, IEnumerable<ISymbol> symbols, SyntaxToken token, TextSpan itemSpan)
Workspace workspace, SemanticModel semanticModel, IEnumerable<ISymbol> symbols, SyntaxToken token, TextSpan itemSpan, int position, ImmutableDictionary<string, string> options)
{
var builder = SharedPools.Default<StringBuilder>().Allocate();
try
{
foreach (var symbol in symbols)
{
builder.Clear();
yield return CreateItem(workspace, semanticModel, symbol, token, builder);
yield return CreateItem(workspace, semanticModel, symbol, token, position, builder, options);
}
}
finally
Expand All @@ -248,10 +262,8 @@ private IEnumerable<CompletionItem> CreateCompletionItems(
}

private CompletionItem CreateItem(
Workspace workspace, SemanticModel semanticModel, ISymbol symbol, SyntaxToken token, StringBuilder builder)
Workspace workspace, SemanticModel semanticModel, ISymbol symbol, SyntaxToken token, int position, StringBuilder builder, ImmutableDictionary<string, string> options)
{
int position = token.SpanStart;

if (symbol is INamespaceOrTypeSymbol && token.IsKind(SyntaxKind.DotToken))
{
// Handle qualified namespace and type names.
Expand All @@ -262,7 +274,7 @@ private CompletionItem CreateItem(
{
// Handle unqualified namespace and type names, or member names.

builder.Append(symbol.ToMinimalDisplayString(semanticModel, position, CrefFormat));
builder.Append(symbol.ToMinimalDisplayString(semanticModel, token.SpanStart, CrefFormat));

var parameters = symbol.GetParameters();
if (!parameters.IsDefaultOrEmpty)
Expand Down Expand Up @@ -303,18 +315,16 @@ private CompletionItem CreateItem(
.Replace('>', '}')
.ToString();

return SymbolCompletionItem.Create(
return SymbolCompletionItem.CreateWithNameAndKind(
displayText: insertionText,
insertionText: insertionText,
symbol: symbol,
symbols: ImmutableArray.Create(symbol),
contextPosition: position,
sortText: symbolText,
properties: options,
rules: GetRules(insertionText));
}

protected override Task<CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
=> SymbolCompletionItem.GetDescriptionAsync(item, document, cancellationToken);

private static readonly CharacterSetModificationRule s_WithoutOpenBrace = CharacterSetModificationRule.Create(CharacterSetModificationKind.Remove, '{');
private static readonly CharacterSetModificationRule s_WithoutOpenParen = CharacterSetModificationRule.Create(CharacterSetModificationKind.Remove, '(');

Expand Down Expand Up @@ -342,7 +352,6 @@ private CompletionItemRules GetRules(string displayText)
}
}


private static readonly string InsertionTextProperty = "insertionText";

protected override Task<TextChange?> GetTextChangeAsync(CompletionItem selectedItem, char? ch, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
var workspace = document.Project.Solution.Workspace;
var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false);

var item = SymbolCompletionItem.Create(
var item = SymbolCompletionItem.CreateWithSymbolId(
displayText: displayText,
insertionText: null,
symbol: alias ?? type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
semanticModel, namePosition, s_signatureDisplayFormat);
var insertionText = displayText;

var item = SymbolCompletionItem.Create(
var item = SymbolCompletionItem.CreateWithSymbolId(
displayText,
insertionText: insertionText,
symbol: member,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
// exact match.
var escapedName = parameter.Name.ToIdentifierToken().ToString();

context.AddItem(SymbolCompletionItem.Create(
context.AddItem(SymbolCompletionItem.CreateWithSymbolId(
displayText: escapedName + ColonString,
insertionText: null,
symbol: parameter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
Expand Down
4 changes: 3 additions & 1 deletion src/Features/CSharp/Portable/project.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"dependencies": { },
"dependencies": {
"System.ValueTuple": "4.3.0"
},
"frameworks": {
"netstandard1.3": {
"imports": [ "portable-net45+win8", "dotnet" ]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis.Options;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.CodeAnalysis.Completion.Providers
{
abstract class AbstractCrefCompletionProvider : CommonCompletionProvider
{
protected const string HideAdvancedMembers = nameof(HideAdvancedMembers);

protected override async Task<CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
{
var position = SymbolCompletionItem.GetContextPosition(item);

// What EditorBrowsable settings were we previously passed in (if it mattered)?
bool hideAdvancedMembers = false;
if (item.Properties.TryGetValue(HideAdvancedMembers, out var hideAdvancedMembersString))
{
bool.TryParse(hideAdvancedMembersString, out hideAdvancedMembers);
}

var options = document.Project.Solution.Workspace.Options
.WithChangedOption(new OptionKey(CompletionOptions.HideAdvancedMembers, document.Project.Language), hideAdvancedMembers);

var (token, semanticModel, symbols) = await GetSymbolsAsync(document, position, options, cancellationToken).ConfigureAwait(false);
var name = SymbolCompletionItem.GetSymbolName(item);
var kind = SymbolCompletionItem.GetKind(item);
var bestSymbols = symbols.WhereAsArray(s => s.Kind == kind && s.Name == name);
return await SymbolCompletionItem.GetDescriptionAsync(item, bestSymbols, document, semanticModel, cancellationToken).ConfigureAwait(false);
}

protected abstract Task<(SyntaxToken, SemanticModel, ImmutableArray<ISymbol>)> GetSymbolsAsync(
Document document, int position, OptionSet options, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected override CompletionItem CreateItem(
SyntaxContext context, bool preselect,
SupportedPlatformData supportedPlatformData)
{
return SymbolCompletionItem.Create(
return SymbolCompletionItem.CreateWithSymbolId(
displayText: displayText,
insertionText: insertionText,
filterText: GetFilterText(symbols[0], displayText, context),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)

foreach (var uninitializedMember in uninitializedMembers)
{
context.AddItem(SymbolCompletionItem.Create(
context.AddItem(SymbolCompletionItem.CreateWithSymbolId(
displayText: uninitializedMember.Name,
insertionText: null,
symbol: uninitializedMember,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private CompletionItem CreateCompletionItem(
{
var displayAndInsertionText = GetDisplayAndInsertionText(symbol, context);

return SymbolCompletionItem.Create(
return SymbolCompletionItem.CreateWithSymbolId(
displayText: displayAndInsertionText.Item1,
insertionText: displayAndInsertionText.Item2,
symbol: symbol,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Recommendations;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.CodeAnalysis.Completion.Providers
{
Expand All @@ -35,10 +38,10 @@ protected override async Task<ImmutableArray<ISymbol>> GetPreselectedSymbolsWork
}

var symbols = await recommender.GetRecommendedSymbolsAtPositionAsync(
context.Workspace,
context.SemanticModel,
position,
options,
context.Workspace,
context.SemanticModel,
context.Position,
options,
cancellationToken).ConfigureAwait(false);

// Don't preselect intrinsic type symbols so we can preselect their keywords instead.
Expand All @@ -64,7 +67,7 @@ protected override CompletionItem CreateItem(string displayText, string insertio
rules = rules.WithSelectionBehavior(PreselectedItemSelectionBehavior);
}

return SymbolCompletionItem.Create(
return SymbolCompletionItem.CreateWithNameAndKind(
displayText: displayText,
insertionText: insertionText,
filterText: GetFilterText(symbols[0], displayText, context),
Expand Down Expand Up @@ -100,5 +103,26 @@ private static int ComputeSymbolMatchPriority(ISymbol symbol)

return SymbolMatchPriority.PreferType;
}

protected override async Task<CompletionDescription> GetDescriptionWorkerAsync(
Document document, CompletionItem item, CancellationToken cancellationToken)
{
var position = SymbolCompletionItem.GetContextPosition(item);
var name = SymbolCompletionItem.GetSymbolName(item);
var kind = SymbolCompletionItem.GetKind(item);
var relatedDocumentIds = document.Project.Solution.GetRelatedDocumentIds(document.Id).Concat(document.Id);
var options = document.Project.Solution.Workspace.Options;
var totalSymbols = await base.GetPerContextSymbols(document, position, options, relatedDocumentIds, preselect: false, cancellationToken: cancellationToken).ConfigureAwait(false);
foreach (var info in totalSymbols)
{
var bestSymbols = info.Item3.Where(s => kind != null && s.Kind == kind && s.Name == name).ToImmutableArray();
if (bestSymbols.Any())
{
return await SymbolCompletionItem.GetDescriptionAsync(item, bestSymbols, document, info.Item2.SemanticModel, cancellationToken).ConfigureAwait(false);
}
}

return CompletionDescription.Empty;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ protected virtual CompletionItem CreateItem(
SyntaxContext context, bool preselect,
SupportedPlatformData supportedPlatformData)
{
return SymbolCompletionItem.Create(
return SymbolCompletionItem.CreateWithSymbolId(
displayText: displayText,
insertionText: insertionText,
filterText: GetFilterText(symbols[0], displayText, context),
Expand All @@ -129,9 +129,6 @@ protected virtual CompletionItem CreateItem(
rules: GetCompletionItemRules(symbols, context));
}

protected override Task<CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
=> SymbolCompletionItem.GetDescriptionAsync(item, document, cancellationToken);

protected virtual string GetFilterText(ISymbol symbol, string displayText, SyntaxContext context)
{
return (displayText == symbol.Name) ||
Expand All @@ -148,6 +145,9 @@ protected virtual Task<ImmutableArray<ISymbol>> GetPreselectedSymbolsWorker(Synt
return SpecializedTasks.EmptyImmutableArray<ISymbol>();
}

protected override Task<CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
=> SymbolCompletionItem.GetDescriptionAsync(item, document, cancellationToken);

public override async Task ProvideCompletionsAsync(CompletionContext context)
{
var document = context.Document;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static CompletionItem Create(
.Add("Modifiers", modifiers.ToString())
.Add("TokenSpanEnd", token.Span.End.ToString());

return SymbolCompletionItem.Create(
return SymbolCompletionItem.CreateWithSymbolId(
displayText: displayText,
symbol: symbol,
glyph: glyph,
Expand Down
Loading

0 comments on commit 16a48cd

Please sign in to comment.