提交 849e4310 编写于 作者: D David Poeschl

Targeted Completion Prototype

上级 3b71c1c0
......@@ -207,6 +207,9 @@ public static ImageId GetImageId(this Glyph glyph)
case Glyph.NuGet:
return new ImageId(ImageCatalogGuid, KnownImageIds.NuGet);
case Glyph.MatchingType:
return new ImageId(ImageCatalogGuid, KnownImageIds.Sync);
default:
throw new ArgumentException(nameof(glyph));
}
......
......@@ -109,6 +109,7 @@ internal enum Glyph
CompletionWarning,
AddReference,
NuGet
NuGet,
MatchingType
}
}
......@@ -174,6 +174,9 @@ private static Glyph GetGlyph(string tag, ImmutableArray<string> allTags)
return Glyph.InterfacePublic;
}
case WellKnownTags.MatchingType:
return Glyph.MatchingType;
case WellKnownTags.Intrinsic:
return Glyph.Intrinsic;
......
......@@ -78,6 +78,7 @@ public bool Matches(CompletionItem item)
public static readonly CompletionItemFilter LocalAndParameterFilter = new CompletionItemFilter(FeaturesResources.Locals_and_parameters, ImmutableArray.Create(WellKnownTags.Local, WellKnownTags.Parameter), 'l');
public static readonly CompletionItemFilter KeywordFilter = new CompletionItemFilter(FeaturesResources.Keywords, ImmutableArray.Create(WellKnownTags.Keyword), 'k');
public static readonly CompletionItemFilter SnippetFilter = new CompletionItemFilter(FeaturesResources.Snippets, ImmutableArray.Create(WellKnownTags.Snippet), 't');
public static readonly CompletionItemFilter MatchingTypeFilter = new CompletionItemFilter(FeaturesResources.Matching_type, ImmutableArray.Create(WellKnownTags.MatchingType), 'j');
public static readonly ImmutableArray<CompletionItemFilter> NamespaceFilters = ImmutableArray.Create(NamespaceFilter);
public static readonly ImmutableArray<CompletionItemFilter> ClassFilters = ImmutableArray.Create(ClassFilter);
......@@ -95,6 +96,7 @@ public bool Matches(CompletionItem item)
public static readonly ImmutableArray<CompletionItemFilter> LocalAndParameterFilters = ImmutableArray.Create(LocalAndParameterFilter);
public static readonly ImmutableArray<CompletionItemFilter> KeywordFilters = ImmutableArray.Create(KeywordFilter);
public static readonly ImmutableArray<CompletionItemFilter> SnippetFilters = ImmutableArray.Create(SnippetFilter);
public static readonly ImmutableArray<CompletionItemFilter> MatchingTypeFilters = ImmutableArray.Create(MatchingTypeFilter);
public static ImmutableArray<CompletionItemFilter> AllFilters { get; } =
ImmutableArray.Create(
......@@ -113,6 +115,7 @@ public bool Matches(CompletionItem item)
DelegateFilter,
NamespaceFilter,
KeywordFilter,
SnippetFilter);
SnippetFilter,
MatchingTypeFilter);
}
}
......@@ -46,18 +46,65 @@ protected virtual CompletionItemRules GetCompletionItemRules(IReadOnlyList<ISymb
private ImmutableArray<CompletionItem> CreateItems(
ImmutableArray<ISymbol> symbols,
SyntaxContext context,
bool preselect)
bool preselect,
ImmutableArray<ITypeSymbol> inferredTypes = default)
{
var tree = context.SyntaxTree;
var symbolGroups = from symbol in symbols
let texts = GetDisplayAndSuffixAndInsertionText(symbol, context)
group symbol by texts into g
select g;
var q = from symbol in symbols
let texts = GetDisplayAndSuffixAndInsertionText(symbol, context)
group symbol by texts into g
select this.CreateItem(
g.Key.displayText, g.Key.suffix, g.Key.insertionText, g.ToList(), context,
var itemListBuilder = ImmutableArray.CreateBuilder<CompletionItem>();
foreach (var symbolGroup in symbolGroups)
{
var item = this.CreateItem(
symbolGroup.Key.displayText, symbolGroup.Key.suffix, symbolGroup.Key.insertionText, symbolGroup.ToList(), context,
invalidProjectMap: null, totalProjects: null, preselect: preselect);
return q.ToImmutableArray();
if (symbolGroup.Any(s => ShouldIncludeInTargetTypedCompletionList(s, inferredTypes, context.SemanticModel, context.Position)))
{
item = item.AddTag("MatchingType");
}
itemListBuilder.Add(item);
}
return itemListBuilder.ToImmutable();
}
private bool ShouldIncludeInTargetTypedCompletionList(ISymbol symbol, ImmutableArray<ITypeSymbol> inferredTypes, SemanticModel semanticModel, int position)
{
// When searching for identifiers of type C, exclude the symbol for the `C` type itself.
if (symbol.Kind == SymbolKind.NamedType)
{
return false;
}
// Avoid offering object.ToString() when a string is expected, for example.
if (symbol.ContainingType?.SpecialType == SpecialType.System_Object)
{
return false;
}
// Don't offer locals on the right-hand-side of their declaration: `int x = x`
if (symbol.Kind == SymbolKind.Local)
{
var local = (ILocalSymbol)symbol;
var declarationSyntax = symbol.DeclaringSyntaxReferences.Select(r => r.GetSyntax()).SingleOrDefault();
if (declarationSyntax != null && position < declarationSyntax.FullSpan.End)
{
return false;
}
}
var type = symbol.GetMemberType() ?? symbol.GetSymbolType();
if (type == null)
{
return false;
}
return inferredTypes.Any(inferredType => semanticModel.Compilation.ClassifyCommonConversion(type, inferredType).IsImplicit);
}
/// <summary>
......@@ -203,7 +250,11 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
if (relatedDocumentIds.IsEmpty)
{
var itemsForCurrentDocument = await GetSymbolsWorker(position, preselect, context, options, cancellationToken).ConfigureAwait(false);
return CreateItems(itemsForCurrentDocument, context, preselect);
var inferenceService = document.GetLanguageService<ITypeInferenceService>();
var inferredTypes = inferenceService.InferTypes(context.SemanticModel, position, cancellationToken);
return CreateItems(itemsForCurrentDocument, context, preselect, inferredTypes);
}
var contextAndSymbolLists = await GetPerContextSymbols(document, position, options, new[] { document.Id }.Concat(relatedDocumentIds), preselect, cancellationToken).ConfigureAwait(false);
......
......@@ -2304,6 +2304,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Matching type.
/// </summary>
internal static string Matching_type {
get {
return ResourceManager.GetString("Matching_type", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Member name can be simplified.
/// </summary>
......
......@@ -1614,4 +1614,7 @@ This version used in: {2}</value>
<data name="Add_parameter_to_constructor" xml:space="preserve">
<value>Add parameter to constructor</value>
</data>
<data name="Matching_type" xml:space="preserve">
<value>Matching type</value>
</data>
</root>
\ No newline at end of file
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -192,6 +192,11 @@
<target state="new">Make local function 'static'</target>
<note />
</trans-unit>
<trans-unit id="Matching_type">
<source>Matching type</source>
<target state="new">Matching type</target>
<note />
</trans-unit>
<trans-unit id="Merge_with_nested_0_statement">
<source>Merge with nested '{0}' statement</source>
<target state="new">Merge with nested '{0}' statement</target>
......
......@@ -52,6 +52,7 @@ public static class WellKnownTags
internal const string AddReference = nameof(AddReference);
internal const string NuGet = nameof(NuGet);
internal const string MatchingType = nameof(MatchingType);
}
internal static class WellKnownTagArrays
......@@ -128,6 +129,7 @@ internal static class WellKnownTagArrays
internal static readonly ImmutableArray<string> AddReference = ImmutableArray.Create(WellKnownTags.AddReference);
internal static readonly ImmutableArray<string> NuGet = ImmutableArray.Create(WellKnownTags.NuGet);
internal static readonly ImmutableArray<string> MatchingType = ImmutableArray.Create(WellKnownTags.MatchingType);
internal static readonly ImmutableArray<string> CSharpFile = ImmutableArray.Create(WellKnownTags.File, LanguageNames.CSharp);
internal static readonly ImmutableArray<string> VisualBasicFile = ImmutableArray.Create(WellKnownTags.File, LanguageNames.VisualBasic);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册