|
// 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.
#nullable disable
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Navigation;
internal static partial class NavigableItemFactory
{
public static INavigableItem GetItemFromSymbolLocation(
Solution solution, ISymbol symbol, Location location,
ImmutableArray<TaggedText>? displayTaggedParts)
{
return new SymbolLocationNavigableItem(
solution, symbol, location, displayTaggedParts);
}
public static ImmutableArray<INavigableItem> GetItemsFromPreferredSourceLocations(
Solution solution,
ISymbol symbol,
ImmutableArray<TaggedText>? displayTaggedParts,
CancellationToken cancellationToken)
{
var locations = GetPreferredSourceLocations(solution, symbol, cancellationToken);
return locations.SelectAsArray(loc => GetItemFromSymbolLocation(
solution, symbol, loc, displayTaggedParts));
}
public static IEnumerable<Location> GetPreferredSourceLocations(
Solution solution, ISymbol symbol, CancellationToken cancellationToken)
{
// Prefer non-generated source locations over generated ones.
var sourceLocations = GetPreferredSourceLocations(symbol);
var candidateLocationGroups = from c in sourceLocations
let doc = solution.GetDocument(c.SourceTree)
where doc != null
group c by doc.IsGeneratedCode(cancellationToken);
var generatedSourceLocations = candidateLocationGroups.SingleOrDefault(g => g.Key) ?? SpecializedCollections.EmptyEnumerable<Location>();
var nonGeneratedSourceLocations = candidateLocationGroups.SingleOrDefault(g => !g.Key) ?? SpecializedCollections.EmptyEnumerable<Location>();
return nonGeneratedSourceLocations.Any() ? nonGeneratedSourceLocations : generatedSourceLocations;
}
private static IEnumerable<Location> GetPreferredSourceLocations(ISymbol symbol)
{
var locations = symbol.Locations;
// First return visible source locations if we have them. Else, go to the non-visible
// source locations.
var visibleSourceLocations = locations.Where(loc => loc.IsVisibleSourceLocation());
return visibleSourceLocations.Any()
? visibleSourceLocations
: locations.Where(loc => loc.IsInSource);
}
}
|