/// <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
        // 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, Range range)
        {
            if (!file.ContainsRange(range))
            {
                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.Column, range.End.Column - range.Start.Column));
            }

            var lastLine = CodeLine(file.GetLine(range.End.Line));
            var prepend  = firstLine.Substring(range.Start.Column);
            var append   = lastLine.Substring(0, range.End.Column);

            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
            }
        }
예제 #3
0
        /// <summary>
        /// Return a string with the new content of the (entire) lines in the range [start, end] where start and end are
        /// the start and end line of the given change.
        /// </summary>
        /// <exception cref="ArgumentException">The range is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The range is not contained in <paramref name="file"/>.</exception>
        internal static string GetTextChangedLines(FileContentManager file, TextDocumentContentChangeEvent change)
        {
            if (!file.ContainsRange(change.Range.ToQSharp()))
            {
                throw new ArgumentOutOfRangeException(nameof(change)); // range can be empty
            }

            var first   = file.GetLine(change.Range.Start.Line).Text;
            var last    = file.GetLine(change.Range.End.Line).Text;
            var prepend = first.Substring(0, change.Range.Start.Character);
            var append  = last.Substring(change.Range.End.Character);

            return(string.Concat(prepend, change.Text, append));
        }
예제 #4
0
        /// <summary>
        /// Returns a look-up of workspace edits suggested by the compiler for the given location and context.
        /// The key of the look-up is a suitable title for the corresponding edits that can be presented to the user.
        /// Returns null if any of the given arguments is null or if suitable edits cannot be determined.
        /// </summary>
        public static ILookup <string, WorkspaceEdit>?CodeActions(this FileContentManager file, CompilationUnit compilation, Range?range, CodeActionContext?context)
        {
            if (range?.Start is null || range.End is null || !file.ContainsRange(range))
            {
                return(null);
            }
            var diagnostics = context?.Diagnostics ?? Array.Empty <Diagnostic>();

            return(file.UnknownIdSuggestions(compilation, range.Start.Line, diagnostics)
                   .Concat(file.AmbiguousIdSuggestions(compilation, diagnostics))
                   .Concat(file.DeprecatedSyntaxSuggestions(diagnostics))
                   .Concat(file.UpdateReassignStatementSuggestions(diagnostics))
                   .Concat(file.IndexRangeSuggestions(compilation, range))
                   .Concat(file.UnreachableCodeSuggestions(diagnostics))
                   .Concat(file.DocCommentSuggestions(range))
                   .ToLookup(s => s.Item1, s => s.Item2));
        }