提交 e4f2f1d5 编写于 作者: G Gen Lu

Address review comments

上级 cb7fac5b
......@@ -3,11 +3,9 @@
#nullable enable
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.Text;
......@@ -32,23 +30,5 @@ protected override Task<SyntaxContext> CreateContextAsync(Document document, int
protected override Task<bool> IsInImportsDirectiveAsync(Document document, int position, CancellationToken cancellationToken)
=> ImportCompletionProviderHelper.IsInImportsDirectiveAsync(document, position, cancellationToken);
protected override bool TryGetReceiverTypeSymbol(SyntaxContext syntaxContext, [NotNullWhen(true)] out ITypeSymbol? receiverTypeSymbol)
{
if (syntaxContext.TargetToken.Parent is MemberAccessExpressionSyntax memberAccess)
{
var symbol = syntaxContext.SemanticModel.GetSymbolInfo(memberAccess.Expression).Symbol;
if (symbol == null ||
symbol.Kind != SymbolKind.NamedType && symbol.Kind != SymbolKind.TypeParameter)
{
receiverTypeSymbol = syntaxContext.SemanticModel.GetTypeInfo(memberAccess.Expression).Type;
return receiverTypeSymbol != null;
}
}
receiverTypeSymbol = null;
return false;
}
}
}
......@@ -305,13 +305,6 @@ private static int CompareExpandedItem(CompletionItem item1, PatternMatch match1
}
public static string ConcatNamespace(string? containingNamespace, string name)
{
if (string.IsNullOrEmpty(containingNamespace))
{
return name;
}
return containingNamespace + "." + name;
}
=> string.IsNullOrEmpty(containingNamespace) ? name : containingNamespace + "." + name;
}
}
......@@ -25,12 +25,14 @@ internal enum ActionInfo
TargetTypeCompletionTicks,
ExtensionMethodCompletionTicks,
ExtensionMethodCompletionGetFilterTicks,
ExtensionMethodCompletionNoFilter,
ExtensionMethodCompletionGetSymbolTicks,
ExtensionMethodCompletionTypesChecked,
ExtensionMethodCompletionMethodsChecked,
ExtensionMethodCompletionMethodsProvided
ExtensionMethodCompletionMethodsProvided,
ExtensionMethodCompletionGetFilterTicks, // only reported when filter is available
ExtensionMethodCompletionGetSymbolWithFilterTicks,
ExtensionMethodCompletionGetSymbolNoFilterTicks,
ExtensionMethodCompletionTypesCheckedWithFilter,
ExtensionMethodCompletionTypesCheckedNoFilter,
ExtensionMethodCompletionMethodsCheckedWithFilter,
ExtensionMethodCompletionMethodsCheckedNoFilter
}
internal static void LogTypeImportCompletionTicksDataPoint(int count) =>
......@@ -51,23 +53,26 @@ internal enum ActionInfo
internal static void LogExtensionMethodCompletionTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionTicks, count);
internal static void LogExtensionMethodCompletionMethodsProvidedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsProvided, count);
internal static void LogExtensionMethodCompletionGetFilterTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetFilterTicks, count);
internal static void LogExtensionMethodCompletionGetSymbolTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetSymbolTicks, count);
internal static void LogExtensionMethodCompletionTypesCheckedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionTypesChecked, count);
internal static void LogExtensionMethodCompletionGetSymbolWithFilterTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetSymbolWithFilterTicks, count);
internal static void LogExtensionMethodCompletionGetSymbolNoFilterTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetSymbolNoFilterTicks, count);
internal static void LogExtensionMethodCompletionMethodsCheckedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsChecked, count);
internal static void LogExtensionMethodCompletionTypesCheckedWithFilterDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionTypesCheckedWithFilter, count);
internal static void LogExtensionMethodCompletionTypesCheckedNoFilterDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionTypesCheckedNoFilter, count);
internal static void LogExtensionMethodCompletionMethodsProvidedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsProvided, count);
internal static void LogExtensionMethodCompletionMethodsCheckedWithFilterDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsCheckedWithFilter, count);
internal static void LogExtensionMethodCompletionMethodsCheckedNoFilterDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsCheckedNoFilter, count);
internal static void LogExtensionMethodCompletionNoFilter() =>
s_logAggregator.IncreaseCount((int)ActionInfo.ExtensionMethodCompletionNoFilter);
internal static void ReportTelemetry()
{
......
......@@ -8,6 +8,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
namespace Microsoft.CodeAnalysis.Completion.Providers
......@@ -16,8 +17,6 @@ internal abstract class AbstractExtensionMethodImportCompletionProvider : Abstra
{
protected abstract string GenericSuffix { get; }
protected abstract bool TryGetReceiverTypeSymbol(SyntaxContext syntaxContext, [NotNullWhen(true)] out ITypeSymbol? receiverTypeSymbol);
protected override bool ShouldProvideCompletion(Document document, SyntaxContext syntaxContext)
=> syntaxContext.IsRightOfNameSeparator && IsAddingImportsSupported(document);
......@@ -28,13 +27,14 @@ protected override bool ShouldProvideCompletion(Document document, SyntaxContext
bool isExpandedCompletion,
CancellationToken cancellationToken)
{
if (TryGetReceiverTypeSymbol(syntaxContext, out var receiverTypeSymbol))
var syntaxFacts = completionContext.Document.Project.LanguageServices.GetRequiredService<ISyntaxFactsService>();
if (TryGetReceiverTypeSymbol(syntaxContext, syntaxFacts, out var receiverTypeSymbol))
{
var items = await ExtensionMethodImportCompletionService.GetUnimportExtensionMethodsAsync(
completionContext.Document,
completionContext.Position,
receiverTypeSymbol,
namespaceInScope.ToImmutableHashSet(),
namespaceInScope,
isExpandedCompletion,
cancellationToken).ConfigureAwait(false);
......@@ -42,6 +42,21 @@ protected override bool ShouldProvideCompletion(Document document, SyntaxContext
}
}
private static bool TryGetReceiverTypeSymbol(SyntaxContext syntaxContext, ISyntaxFactsService syntaxFacts, [NotNullWhen(true)] out ITypeSymbol? receiverTypeSymbol)
{
var parentNode = syntaxContext.TargetToken.Parent;
var expressionNode = syntaxFacts.GetExpressionOfMemberAccessExpression(parentNode, allowImplicitTarget: true);
if (expressionNode != null)
{
receiverTypeSymbol = syntaxContext.SemanticModel.GetTypeInfo(expressionNode).Type;
return receiverTypeSymbol != null;
}
receiverTypeSymbol = null;
return false;
}
private CompletionItem Convert(SerializableImportCompletionItem serializableItem)
{
return ImportCompletionItem.Create(
......
......@@ -127,7 +127,7 @@ private static string GetFullyQualifiedName(string namespaceName, string typeNam
{
if (item.Properties.TryGetValue(SymbolKeyData, out var symbolId))
{
return SymbolCompletionItem.DecodeSymbol(symbolId, compilation);
return SymbolKey.ResolveString(symbolId, compilation).GetAnySymbol();
}
var containingNamespace = GetContainingNamespace(item);
......
......@@ -141,7 +141,7 @@ private static void DecodeSymbols(List<string> ids, Compilation compilation, Lis
}
}
public static ISymbol DecodeSymbol(string id, Compilation compilation)
private static ISymbol DecodeSymbol(string id, Compilation compilation)
{
return SymbolKey.ResolveString(id, compilation).GetAnySymbol();
}
......
......@@ -386,7 +386,7 @@ private static async Task AddDocumentsToUpdateForProjectAsync(Project project, A
{
foreach (var document in project.Documents)
{
var info = await document.GetSyntaxTreeIndexAsync(loadOnly: false, cancellationToken).ConfigureAwait(false);
var info = await document.GetSyntaxTreeIndexAsync(cancellationToken).ConfigureAwait(false);
if (info.ContainsTupleExpressionOrTupleType &&
InfoProbablyContainsTupleFieldNames(info, tupleFieldNames))
{
......
......@@ -185,7 +185,7 @@ internal abstract partial class AbstractNavigateToSearchService
}
cancellationToken.ThrowIfCancellationRequested();
var declarationInfo = await document.GetSyntaxTreeIndexAsync(loadOnly: false, cancellationToken).ConfigureAwait(false);
var declarationInfo = await document.GetSyntaxTreeIndexAsync(cancellationToken).ConfigureAwait(false);
foreach (var declaredSymbolInfo in declarationInfo.DeclaredSymbolInfos)
{
......
......@@ -2,14 +2,10 @@
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Completion.Providers
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Friend NotInheritable Class ExtensionMethodImportCompletionProvider
......@@ -36,21 +32,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Protected Overrides Function IsInImportsDirectiveAsync(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of Boolean)
Return ImportCompletionProviderHelper.IsInImportsDirectiveAsync(document, position, cancellationToken)
End Function
Protected Overrides Function TryGetReceiverTypeSymbol(syntaxContext As SyntaxContext, ByRef receiverTypeSymbol As ITypeSymbol) As Boolean
If syntaxContext.TargetToken.Parent.Kind = SyntaxKind.SimpleMemberAccessExpression Then
Dim memberAccessNode = CType(syntaxContext.TargetToken.Parent, MemberAccessExpressionSyntax)
Dim symbol = syntaxContext.SemanticModel.GetSymbolInfo(memberAccessNode.Expression).Symbol
If symbol Is Nothing Or symbol.Kind <> SymbolKind.NamedType And symbol.Kind <> SymbolKind.TypeParameter Then
receiverTypeSymbol = syntaxContext.SemanticModel.GetTypeInfo(memberAccessNode.Expression).Type
Return receiverTypeSymbol IsNot Nothing
End If
End If
receiverTypeSymbol = Nothing
Return False
End Function
End Class
End Namespace
......@@ -32,7 +32,7 @@ public static async Task<IEnumerable<SyntaxToken>> GetConstructorInitializerToke
{
// It's very costly to walk an entire tree. So if the tree is simple and doesn't contain
// any unicode escapes in it, then we do simple string matching to find the tokens.
var info = await SyntaxTreeIndex.GetIndexAsync(document, loadOnly: false, cancellationToken).ConfigureAwait(false);
var info = await SyntaxTreeIndex.GetIndexAsync(document, cancellationToken).ConfigureAwait(false);
if (!info.ProbablyContainsIdentifier(identifier))
{
return ImmutableArray<SyntaxToken>.Empty;
......
......@@ -123,7 +123,7 @@ private async Task ProcessDocumentAsync(Document document)
private async Task ProcessDocumentWorkerAsync(Document document)
{
var index = await SyntaxTreeIndex.GetIndexAsync(
document, loadOnly: false, _cancellationToken).ConfigureAwait(false);
document, _cancellationToken).ConfigureAwait(false);
if (_searchKind == SearchKind.StringLiterals)
{
......
......@@ -56,7 +56,7 @@ private static async Task<ProjectIndex> CreateIndexAsync(Project project, Cancel
foreach (var document in project.Documents)
{
var syntaxTreeIndex = await document.GetSyntaxTreeIndexAsync(loadOnly: false, cancellationToken).ConfigureAwait(false);
var syntaxTreeIndex = await document.GetSyntaxTreeIndexAsync(cancellationToken).ConfigureAwait(false);
foreach (var info in syntaxTreeIndex.DeclaredSymbolInfos)
{
switch (info.Kind)
......
......@@ -80,7 +80,7 @@ protected Task<ImmutableArray<Document>> FindDocumentsAsync(Project project, IIm
{
return FindDocumentsAsync(project, documents, async (d, c) =>
{
var info = await SyntaxTreeIndex.GetIndexAsync(d, loadOnly: false, c).ConfigureAwait(false);
var info = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false);
foreach (var value in values)
{
if (!info.ProbablyContainsIdentifier(value))
......@@ -106,7 +106,7 @@ protected Task<ImmutableArray<Document>> FindDocumentsAsync(Project project, IIm
return FindDocumentsAsync(project, documents, async (d, c) =>
{
var info = await SyntaxTreeIndex.GetIndexAsync(d, loadOnly: false, c).ConfigureAwait(false);
var info = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false);
return info.ContainsPredefinedType(predefinedType);
}, cancellationToken);
}
......@@ -124,7 +124,7 @@ protected Task<ImmutableArray<Document>> FindDocumentsAsync(Project project, IIm
return FindDocumentsAsync(project, documents, async (d, c) =>
{
var info = await SyntaxTreeIndex.GetIndexAsync(d, loadOnly: false, c).ConfigureAwait(false);
var info = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false);
return info.ContainsPredefinedOperator(op);
}, cancellationToken);
}
......@@ -395,7 +395,7 @@ protected Task<ImmutableArray<Document>> FindDocumentsWithPredicateAsync(Project
{
return FindDocumentsAsync(project, documents, async (d, c) =>
{
var info = await SyntaxTreeIndex.GetIndexAsync(d, loadOnly: false, c).ConfigureAwait(false);
var info = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false);
return predicate(info);
}, cancellationToken);
}
......@@ -422,7 +422,7 @@ protected Task<ImmutableArray<Document>> FindDocumentsWithAwaitExpressionAsync(P
CollectMatchingReferences collectMatchingReferences,
CancellationToken cancellationToken)
{
var syntaxTreeInfo = await SyntaxTreeIndex.GetIndexAsync(document, loadOnly: false, cancellationToken).ConfigureAwait(false);
var syntaxTreeInfo = await SyntaxTreeIndex.GetIndexAsync(document, cancellationToken).ConfigureAwait(false);
if (isRelevantDocument(syntaxTreeInfo))
{
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
......
......@@ -26,7 +26,7 @@ protected override bool CanFind(IMethodSymbol symbol)
{
return FindDocumentsAsync(project, documents, async (d, c) =>
{
var index = await SyntaxTreeIndex.GetIndexAsync(d, loadOnly: false, c).ConfigureAwait(false);
var index = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false);
if (index.ContainsBaseConstructorInitializer)
{
return true;
......
......@@ -79,26 +79,45 @@ private string GetDebuggerDisplay()
}
}
public readonly struct ParameterTypeInfo
private readonly struct ParameterTypeInfo
{
public string Name { get; }
public bool IsComplexType { get; }
/// <summary>
/// This is the type name of the parameter when <see cref="IsComplexType"/> is true.
/// </summary>
public readonly string Name;
/// <summary>
/// Similar to <see cref="SyntaxTreeIndex.ExtensionMethodInfo"/>, we divide extension methods into simple
/// and complex categories for filtering purpose. Whether a method is simple is determined based on if we
/// can determine it's target type easily with a pure text matching. For complex methods, we will need to
/// rely on symbol to decide if it's feasible.
///
/// Simple types include:
/// - Primitive types
/// - Types which is not a generic method parameter
/// - By reference type of any types above
/// </summary>
public readonly bool IsComplexType;
public ParameterTypeInfo(string name, bool isComplex)
{
Name = name;
IsComplexType = isComplex;
}
public override string ToString()
=> $"{Name}, {IsComplexType}";
}
public readonly struct ExtensionMethodInfo
{
public string FullyQualifiedContainerName { get; }
/// <summary>
/// Name of the extension method.
/// This can be used to retrive corresponding symbols via <see cref="INamespaceOrTypeSymbol.GetMembers(string)"/>
/// </summary>
public readonly string Name;
public string Name { get; }
/// <summary>
/// Fully qualified name for the type that contains this extension method.
/// </summary>
public readonly string FullyQualifiedContainerName;
public ExtensionMethodInfo(string fullyQualifiedContainerName, string name)
{
......@@ -117,10 +136,6 @@ private static ParameterTypeInfo ComplexInfo
public ParameterTypeInfo GetPrimitiveType(PrimitiveTypeCode typeCode)
=> new ParameterTypeInfo(typeCode.ToString(), isComplex: false);
public ParameterTypeInfo GetArrayType(ParameterTypeInfo elementType, ArrayShape shape) => ComplexInfo;
public ParameterTypeInfo GetSZArrayType(ParameterTypeInfo elementType) => ComplexInfo;
public ParameterTypeInfo GetGenericInstantiation(ParameterTypeInfo genericType, ImmutableArray<ParameterTypeInfo> typeArguments)
=> genericType.IsComplexType
? ComplexInfo
......@@ -129,18 +144,6 @@ public ParameterTypeInfo GetGenericInstantiation(ParameterTypeInfo genericType,
public ParameterTypeInfo GetByReferenceType(ParameterTypeInfo elementType)
=> elementType;
public ParameterTypeInfo GetFunctionPointerType(MethodSignature<ParameterTypeInfo> signature) => ComplexInfo;
public ParameterTypeInfo GetGenericMethodParameter(object genericContext, int index) => ComplexInfo;
public ParameterTypeInfo GetGenericTypeParameter(object genericContext, int index) => ComplexInfo;
public ParameterTypeInfo GetModifiedType(ParameterTypeInfo modifier, ParameterTypeInfo unmodifiedType, bool isRequired) => ComplexInfo;
public ParameterTypeInfo GetPinnedType(ParameterTypeInfo elementType) => ComplexInfo;
public ParameterTypeInfo GetPointerType(ParameterTypeInfo elementType) => ComplexInfo;
public ParameterTypeInfo GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
var type = reader.GetTypeDefinition(handle);
......@@ -160,6 +163,22 @@ public ParameterTypeInfo GetTypeFromSpecification(MetadataReader reader, object
var sigReader = reader.GetBlobReader(reader.GetTypeSpecification(handle).Signature);
return new SignatureDecoder<ParameterTypeInfo, object>(Instance, reader, genericContext).DecodeType(ref sigReader);
}
public ParameterTypeInfo GetArrayType(ParameterTypeInfo elementType, ArrayShape shape) => ComplexInfo;
public ParameterTypeInfo GetSZArrayType(ParameterTypeInfo elementType) => ComplexInfo;
public ParameterTypeInfo GetFunctionPointerType(MethodSignature<ParameterTypeInfo> signature) => ComplexInfo;
public ParameterTypeInfo GetGenericMethodParameter(object genericContext, int index) => ComplexInfo;
public ParameterTypeInfo GetGenericTypeParameter(object genericContext, int index) => ComplexInfo;
public ParameterTypeInfo GetModifiedType(ParameterTypeInfo modifier, ParameterTypeInfo unmodifiedType, bool isRequired) => ComplexInfo;
public ParameterTypeInfo GetPinnedType(ParameterTypeInfo elementType) => ComplexInfo;
public ParameterTypeInfo GetPointerType(ParameterTypeInfo elementType) => ComplexInfo;
}
}
}
......@@ -51,19 +51,15 @@ internal partial class SymbolTreeInfo : IChecksummedObject
/// </summary>
private readonly OrderPreservingMultiDictionary<int, int> _inheritanceMap;
// Similar to `ExtensionMethodInfo` in SyntaxTreeInfo, we devide extension methods into simple and complex
// categories for filtering purpose. Whether a method is simple is determined based on if we can determine
// it's target type easily with a pure text matching. For complex methods, we will need to rely on symbol
// to decide if it's feasible.
// All primitive types, types in regular use form are considered simple.
/// <summary>
/// Maps the name of target type name of simple methods to its <see cref="ExtensionMethodInfo" />.
/// Maps the name of target type name of simple extension methods to its <see cref="ExtensionMethodInfo" />.
/// <see cref="ParameterTypeInfo"/> for the definition of simple/complex methods.
/// </summary>
private readonly MultiDictionary<string, ExtensionMethodInfo>? _simpleTypeNameToExtensionMethodMap;
/// <summary>
/// A list of <see cref="ExtensionMethodInfo" /> for complex methods.
/// A list of <see cref="ExtensionMethodInfo" /> for complex extension methods.
/// <see cref="ParameterTypeInfo"/> for the definition of simple/complex methods.
/// </summary>
private readonly ImmutableArray<ExtensionMethodInfo> _extensionMethodOfComplexType;
......
......@@ -783,7 +783,11 @@ private struct MetadataDefinition
public string Name { get; }
public MetadataDefinitionKind Kind { get; }
/// <summary>
/// Only applies to member kind. Represents the type info of the first parameter.
/// </summary>
public ParameterTypeInfo TargetTypeInfo { get; }
public NamespaceDefinition Namespace { get; private set; }
public TypeDefinition Type { get; private set; }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -18,7 +20,7 @@ internal partial class SyntaxTreeIndex
//
// Complex methods include:
// - Method declared in the document which includes using alias directive
// - Generic method
// - Generic method where the target type is generic
// - If the target type name is one of the following (i.e. name of the type for the first parameter)
// 1. Array type
// 2. ValueTuple type
......
......@@ -60,6 +60,9 @@ public static async Task PrecalculateAsync(Document document, CancellationToken
}
}
public static Task<SyntaxTreeIndex> GetIndexAsync(Document document, CancellationToken cancellationToken)
=> GetIndexAsync(document, loadOnly: false, cancellationToken);
public static async Task<SyntaxTreeIndex> GetIndexAsync(
Document document,
bool loadOnly,
......
......@@ -123,6 +123,7 @@ public void WriteTo(ObjectWriter writer)
_identifierInfo.WriteTo(writer);
_contextInfo.WriteTo(writer);
_declarationInfo.WriteTo(writer);
_extensionMethodInfo.WriteTo(writer);
}
private static SyntaxTreeIndex ReadFrom(
......
......@@ -92,7 +92,14 @@ public static string GetMetadataAritySuffix(int arity)
}
public abstract bool TryGetDeclaredSymbolInfo(StringTable stringTable, SyntaxNode node, string rootNamespace, out DeclaredSymbolInfo declaredSymbolInfo);
/// <summary>
/// If <paramref name="node"/> is an extension method declaration, this will return true, otherwise it returns false.
/// If the return value is true and <paramref name="targetTypeName"/> is null, then it means this is a "complex" method
/// (as described at <see cref="SyntaxTreeIndex.ExtensionMethodInfo"/>).
/// </summary>
public abstract bool TryGetTargetTypeName(SyntaxNode node, out string targetTypeName);
public abstract string GetRootNamespace(CompilationOptions compilationOptions);
}
......
......@@ -706,7 +706,7 @@ private async Task AddDocumentsWithPotentialConflicts(IEnumerable<Document> docu
continue;
}
var info = await SyntaxTreeIndex.GetIndexAsync(document, loadOnly: false, CancellationToken.None).ConfigureAwait(false);
var info = await SyntaxTreeIndex.GetIndexAsync(document, CancellationToken.None).ConfigureAwait(false);
if (info.ProbablyContainsEscapedIdentifier(_originalText))
{
_documentsIdsToBeCheckedForConflict.Add(document.Id);
......
......@@ -173,6 +173,9 @@ public static async Task<bool> IsForkedDocumentWithSyntaxChangesAsync(this Docum
}
}
public static Task<SyntaxTreeIndex> GetSyntaxTreeIndexAsync(this Document document, CancellationToken cancellationToken)
=> SyntaxTreeIndex.GetIndexAsync(document, loadOnly: false, cancellationToken);
public static Task<SyntaxTreeIndex> GetSyntaxTreeIndexAsync(this Document document, bool loadOnly, CancellationToken cancellationToken)
=> SyntaxTreeIndex.GetIndexAsync(document, loadOnly, cancellationToken);
......
......@@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.LanguageServices;
namespace Microsoft.CodeAnalysis.Remote
{
......@@ -32,8 +33,11 @@ internal partial class CodeAnalysisService : IRemoteExtensionMethodImportComplet
if (symbol is ITypeSymbol receiverTypeSymbol)
{
var syntaxFacts = document.Project.LanguageServices.GetRequiredService<ISyntaxFactsService>();
var namespaceInScopeSet = new HashSet<string>(namespaceInScope, syntaxFacts.StringComparer);
var (items, counter) = await ExtensionMethodImportCompletionService.GetUnimportExtensionMethodsInCurrentProcessAsync(
document, position, receiverTypeSymbol, namespaceInScope.ToImmutableHashSet(), isExpandedCompletion, cancellationToken).ConfigureAwait(false);
document, position, receiverTypeSymbol, namespaceInScopeSet, isExpandedCompletion, cancellationToken).ConfigureAwait(false);
return ((IList<SerializableImportCompletionItem>)items, counter);
}
......
......@@ -305,8 +305,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FindSymbols
Continue For
End If
Dim name = attribute.Name.ToString()
If name.Equals("Extension") Or name.Equals("ExtensionAttribute") Or name.EndsWith(".Extension") Or name.EndsWith(".ExtensionAttribute") Then
Dim name = attribute.Name.GetRightmostName()?.ToString()
If String.Equals(name, "Extension", StringComparison.OrdinalIgnoreCase) Or String.Equals(name, "ExtensionAttribute", StringComparison.OrdinalIgnoreCase) Then
Return True
End If
Next
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册