|
// 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.IO;
using System.Threading;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Language.Intellisense;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Peek
{
internal static class PeekHelpers
{
internal static IDocumentPeekResult CreateDocumentPeekResult(string filePath, LinePositionSpan identifierLocation, LinePositionSpan entityOfInterestSpan, IPeekResultFactory peekResultFactory)
{
var fileName = Path.GetFileName(filePath);
var label = string.Format("{0} - ({1}, {2})", fileName, identifierLocation.Start.Line + 1, identifierLocation.Start.Character + 1);
var displayInfo = new PeekResultDisplayInfo(label: label, labelTooltip: filePath, title: fileName, titleTooltip: filePath);
return CreateDocumentPeekResult(
filePath,
identifierLocation,
entityOfInterestSpan,
displayInfo,
peekResultFactory,
isReadOnly: false);
}
internal static IDocumentPeekResult CreateDocumentPeekResult(string filePath, LinePositionSpan identifierLocation, LinePositionSpan entityOfInterestSpan, PeekResultDisplayInfo displayInfo, IPeekResultFactory peekResultFactory, bool isReadOnly)
{
return peekResultFactory.Create(
displayInfo,
filePath: filePath,
startLine: entityOfInterestSpan.Start.Line,
startIndex: entityOfInterestSpan.Start.Character,
endLine: entityOfInterestSpan.End.Line,
endIndex: entityOfInterestSpan.End.Character,
idLine: identifierLocation.Start.Line,
idIndex: identifierLocation.Start.Character,
isReadOnly: isReadOnly);
}
internal static LinePositionSpan GetEntityOfInterestSpan(ISymbol symbol, Workspace workspace, Location identifierLocation, CancellationToken cancellationToken)
{
// This is called on a background thread, but since we don't have proper asynchrony we must block
var root = identifierLocation.SourceTree.GetRoot(cancellationToken);
var node = root.FindToken(identifierLocation.SourceSpan.Start).Parent;
var syntaxFactsService = workspace.Services.GetLanguageServices(root.Language).GetService<ISyntaxFactsService>();
switch (symbol.Kind)
{
case SymbolKind.Event:
case SymbolKind.Field:
case SymbolKind.Method:
case SymbolKind.Property:
node = node.FirstAncestorOrSelf<SyntaxNode, ISyntaxFactsService>((node, syntaxFactsService) => syntaxFactsService.IsMethodLevelMember(node), syntaxFactsService) ?? node;
break;
case SymbolKind.NamedType:
case SymbolKind.Namespace:
node = node.FirstAncestorOrSelf<SyntaxNode, ISyntaxFactsService>((node, syntaxFactsService) => syntaxFactsService.IsTopLevelNodeWithMembers(node), syntaxFactsService) ?? node;
break;
}
return identifierLocation.SourceTree.GetLocation(node.Span).GetMappedLineSpan().Span;
}
}
}
|