/// <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. /// Throws an ArgumentNullException if the given file or range is null. /// Throws an ArgumentOutOfRangeException if the given range is not a valid range within file. /// </summary> internal static bool ContainsTokensOverlappingWith(this FileContentManager file, LSP.Range range) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (!Utils.IsValidRange(range, file)) { 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(new Position(0, range.Start.Character))); // checking tokens overlapping with range.Start below inRange = start == end ? inRange.Where(TokensStartingBefore(new Position(0, range.End.Character))) : inRange.Concat(file.GetTokenizedLine(end).Where(TokensStartingBefore(new Position(0, range.End.Character)))); if (inRange.Any()) { QsCompilerError.Raise($"{range.DiagnosticString()} overlaps for start = {start}, end = {end}, \n\n" + $"{string.Join("\n", file.GetTokenizedLine(start).Select(x => $"{x.GetRange().DiagnosticString()}"))},\n\n " + $"{string.Join("\n", file.GetTokenizedLine(end).Select(x => $"{x.GetRange().DiagnosticString()}"))},"); return(true); } var overlapsWithStart = file.TryGetFragmentAt(range.Start, out var _); return(overlapsWithStart != null); }
// private utils related to extracting file content /// <summary> /// Checks that the given range is a valid range in file, and returns the text in the given range in concatenated form /// stripping (only) end of line comments (and not removing excess brackets). /// Note: the End position of the given range is *not* part of the returned string. /// </summary> private static string GetCodeSnippet(this FileContentManager file, LSP.Range range) { if (!Utils.IsValidRange(range, file)) { throw new ArgumentException($"cannot extract code snippet for the given range \n range: {range.DiagnosticString()}"); } string CodeLine(CodeLine line) => line.WithoutEnding + line.LineEnding; var start = range.Start.Line; var count = range.End.Line - start + 1; var firstLine = CodeLine(file.GetLine(start)); if (count == 1) { return(firstLine.Substring(range.Start.Character, range.End.Character - range.Start.Character)); } var lastLine = CodeLine(file.GetLine(range.End.Line)); var prepend = firstLine.Substring(range.Start.Character); var append = lastLine.Substring(0, range.End.Character); var middle = file.GetLines(start + 1, count - 2).Select(CodeLine).ToArray(); if (middle.Length == 0) { return(Utils.JoinLines(new string[] { prepend, append })); } else { return(Utils.JoinLines(new string[] { prepend, Utils.JoinLines(middle), append })); // Note: use JoinLines here to get accurate position infos for errors } }