|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.AddImport;
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private readonly struct SearchResult(string? desiredName, TSimpleNameSyntax nameNode, IReadOnlyList<string> nameParts, double weight)
{
public readonly IReadOnlyList<string> NameParts = nameParts;
// How good a match this was. 0 means it was a perfect match. Larger numbers are less
// and less good.
public readonly double Weight = weight;
// The desired name to change the user text to if this was a fuzzy (spell-checking) match.
public readonly string? DesiredName = desiredName;
// The node to convert to the desired name
public readonly TSimpleNameSyntax NameNode = nameNode;
public SearchResult(SymbolResult<INamespaceOrTypeSymbol> result)
: this(result.DesiredName, result.NameNode, INamespaceOrTypeSymbolExtensions.GetNameParts(result.Symbol), result.Weight)
{
}
public bool DesiredNameDiffersFromSourceName()
{
return !string.IsNullOrEmpty(DesiredName) &&
NameNode != null &&
NameNode.GetFirstToken().ValueText != DesiredName;
}
public bool DesiredNameDiffersFromSourceNameOnlyByCase()
{
Debug.Assert(DesiredNameDiffersFromSourceName());
return StringComparer.OrdinalIgnoreCase.Equals(
NameNode.GetFirstToken().ValueText, DesiredName);
}
public bool DesiredNameMatchesSourceName(Document document)
{
if (!DesiredNameDiffersFromSourceName())
{
// Names match in any language.
return true;
}
var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
// Names differ. But in a case insensitive language they may match.
if (!syntaxFacts.IsCaseSensitive &&
DesiredNameDiffersFromSourceNameOnlyByCase())
{
return true;
}
// Name are totally different in any language.
return false;
}
}
private readonly struct SymbolResult<T>(string desiredName, TSimpleNameSyntax nameNode, T symbol, double weight) where T : ISymbol
{
// The symbol that matched the string being searched for.
public readonly T Symbol = symbol;
// How good a match this was. 0 means it was a perfect match. Larger numbers are less
// and less good.
public readonly double Weight = weight;
// The desired name to change the user text to if this was a fuzzy (spell-checking) match.
public readonly string DesiredName = desiredName;
// The node to convert to the desired name
public readonly TSimpleNameSyntax NameNode = nameNode;
public SymbolResult<T2> WithSymbol<T2>(T2 symbol) where T2 : ISymbol
=> new(DesiredName, NameNode, symbol, Weight);
internal SymbolResult<T> WithDesiredName(string desiredName)
=> new(desiredName, NameNode, Symbol, Weight);
}
private struct SymbolResult
{
public static SymbolResult<T> Create<T>(string desiredName, TSimpleNameSyntax nameNode, T symbol, double weight) where T : ISymbol
=> new(desiredName, nameNode, symbol, weight);
}
}
|