|
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Shell.TableManager;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{
internal partial class StreamingFindUsagesPresenter
{
/// <summary>
/// Base type of all <see cref="Entry"/>s that represent some source location in
/// a <see cref="Document"/>. Navigation to that location is provided by this type.
/// Subclasses can be used to provide customized line text to display in the entry.
/// </summary>
private abstract class AbstractDocumentSpanEntry : AbstractItemEntry
{
private readonly object _boxedProjectGuid;
private readonly SourceText _lineText;
private readonly MappedSpanResult _mappedSpanResult;
protected AbstractDocumentSpanEntry(
AbstractTableDataSourceFindUsagesContext context,
RoslynDefinitionBucket definitionBucket,
Guid projectGuid,
SourceText lineText,
MappedSpanResult mappedSpanResult)
: base(definitionBucket, context.Presenter)
{
_boxedProjectGuid = projectGuid;
_lineText = lineText;
_mappedSpanResult = mappedSpanResult;
}
protected abstract string GetProjectName();
protected override object? GetValueWorker(string keyName)
=> keyName switch
{
StandardTableKeyNames.DocumentName => _mappedSpanResult.FilePath,
StandardTableKeyNames.Line => _mappedSpanResult.LinePositionSpan.Start.Line,
StandardTableKeyNames.Column => _mappedSpanResult.LinePositionSpan.Start.Character,
StandardTableKeyNames.ProjectName => GetProjectName(),
StandardTableKeyNames.ProjectGuid => _boxedProjectGuid,
StandardTableKeyNames.Text => _lineText.ToString().Trim(),
_ => null,
};
public static async Task<MappedSpanResult?> TryMapAndGetFirstAsync(DocumentSpan documentSpan, SourceText sourceText, CancellationToken cancellationToken)
{
var service = documentSpan.Document.Services.GetService<ISpanMappingService>();
if (service == null)
{
return new MappedSpanResult(documentSpan.Document.FilePath, sourceText.Lines.GetLinePositionSpan(documentSpan.SourceSpan), documentSpan.SourceSpan);
}
var results = await service.MapSpansAsync(
documentSpan.Document, SpecializedCollections.SingletonEnumerable(documentSpan.SourceSpan), cancellationToken).ConfigureAwait(false);
if (results.IsDefaultOrEmpty)
{
return new MappedSpanResult(documentSpan.Document.FilePath, sourceText.Lines.GetLinePositionSpan(documentSpan.SourceSpan), documentSpan.SourceSpan);
}
// if span mapping service filtered out the span, make sure
// to return null so that we remove the span from the result
return results.FirstOrNull(r => !r.IsDefault);
}
public static SourceText GetLineContainingPosition(SourceText text, int position)
{
var line = text.Lines.GetLineFromPosition(position);
return text.GetSubText(line.Span);
}
}
}
}
|