|
// 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 Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Shared.Extensions;
internal static partial class SourceTextExtensions
{
/// <summary>
/// Returns the leading whitespace of the line located at the specified position in the given snapshot.
/// </summary>
public static string GetLeadingWhitespaceOfLineAtPosition(this SourceText text, int position)
{
Contract.ThrowIfNull(text);
var line = text.Lines.GetLineFromPosition(position);
var linePosition = line.GetFirstNonWhitespacePosition();
if (!linePosition.HasValue)
{
return line.ToString();
}
var lineText = line.ToString();
return lineText[..(linePosition.Value - line.Start)];
}
public static bool OverlapsHiddenPosition(
this SourceText text, TextSpan span, Func<int, CancellationToken, bool> isPositionHidden, CancellationToken cancellationToken)
{
var result = TryOverlapsHiddenPosition(text, span, isPositionHidden, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
return result;
}
/// <summary>
/// Same as OverlapsHiddenPosition but doesn't throw on cancellation. Instead, returns false
/// in that case.
/// </summary>
public static bool TryOverlapsHiddenPosition(
this SourceText text, TextSpan span, Func<int, CancellationToken, bool> isPositionHidden,
CancellationToken cancellationToken)
{
var startLineNumber = text.Lines.IndexOf(span.Start);
var endLineNumber = text.Lines.IndexOf(span.End);
// NOTE(cyrusn): It's safe to examine the start of a line because you can't have a line
// with both a pp directive and code on it. so, for example, if a node crosses a region
// then it must be the case that the start of some line from the start of the node to
// the end is hidden. i.e.:
#if false
' class C
' {
'#line hidden
' }
'#line default
#endif
// The start of the line with the } on it is hidden, and thus the node overlaps a hidden
// region.
for (var lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
var linePosition = text.Lines[lineNumber].Start;
var isHidden = isPositionHidden(linePosition, cancellationToken);
if (isHidden)
{
return true;
}
}
return false;
}
public static bool AreOnSameLine(this SourceText text, SyntaxToken token1, SyntaxToken token2)
=> token1.RawKind != 0 &&
token2.RawKind != 0 &&
text.AreOnSameLine(token1.Span.End, token2.SpanStart);
public static bool AreOnSameLine(this SourceText text, int pos1, int pos2)
=> text.Lines.IndexOf(pos1) == text.Lines.IndexOf(pos2);
}
|