/// <summary>
        /// Returns true if the given file contains any tokens overlapping with the given fragment.
        /// The range of the tokens in the file is assumed to be relative to their start line (the index at which they are listed),
        /// whereas the range of the given fragment is assumed to be the absolute range.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="range"/> is not a valid range within <paramref name="file"/>.</exception>
        internal static bool ContainsTokensOverlappingWith(this FileContentManager file, Range range)
        {
            if (!file.ContainsRange(range))
            {
                throw new ArgumentOutOfRangeException(nameof(range));
            }

            var(start, end) = (range.Start.Line, range.End.Line);
            if (start != end && file.GetTokenizedLines(start + 1, end - start - 1).SelectMany(x => x).Any())
            {
                return(true);
            }

            var inRange = file.GetTokenizedLine(start).Where(TokensAfter(Position.Create(0, range.Start.Column))); // checking tokens overlapping with range.Start below

            inRange = start == end
                ? inRange.Where(TokensStartingBefore(Position.Create(0, range.End.Column)))
                : inRange.Concat(file.GetTokenizedLine(end).Where(TokensStartingBefore(Position.Create(0, range.End.Column))));

            if (inRange.Any())
            {
                QsCompilerError.Raise($"{range.DiagnosticString()} overlaps for start = {start}, end = {end}, \n\n" +
                                      $"{string.Join("\n", file.GetTokenizedLine(start).Select(x => $"{x.Range.DiagnosticString()}"))},\n\n " +
                                      $"{string.Join("\n", file.GetTokenizedLine(end).Select(x => $"{x.Range.DiagnosticString()}"))},");
                return(true);
            }

            var overlapsWithStart = file.TryGetFragmentAt(range.Start, out _);

            return(overlapsWithStart != null);
        }
示例#2
0
        /// <summary>
        /// Returns all code fragments in the specified file that overlap with the given range.
        /// Returns an empty sequence if any of the given arguments is null.
        /// </summary>
        private static IEnumerable <CodeFragment> FragmentsOverlappingWithRange(this FileContentManager file, LSP.Range range)
        {
            if (file == null || range?.Start == null || range.End == null)
            {
                return(Enumerable.Empty <CodeFragment>());
            }
            var(start, end) = (range.Start.Line, range.End.Line);

            var fragAtStart = file.TryGetFragmentAt(range.Start, out var _, includeEnd: true);
            var inRange     = file.GetTokenizedLine(start).Select(t => t.WithUpdatedLineNumber(start)).Where(ContextBuilder.TokensAfter(range.Start)); // does not include fragAtStart

            inRange = start == end
                ? inRange.Where(ContextBuilder.TokensStartingBefore(range.End))
                : inRange.Concat(file.GetTokenizedLines(start + 1, end - start - 1).SelectMany((x, i) => x.Select(t => t.WithUpdatedLineNumber(start + 1 + i))))
                      .Concat(file.GetTokenizedLine(end).Select(t => t.WithUpdatedLineNumber(end)).Where(ContextBuilder.TokensStartingBefore(range.End)));

            var fragments = ImmutableArray.CreateBuilder <CodeFragment>();

            if (fragAtStart != null)
            {
                fragments.Add(fragAtStart);
            }
            fragments.AddRange(inRange);
            return(fragments.ToImmutableArray());
        }