Example #1
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
            }
        }
Example #2
0
 /// <summary>
 /// Computes excess bracket errors for the given range of lines in file based on the corresponding CodeLine.
 /// Throws an ArgumentOutOfRangeException if the range [start, start + count) is not within file.
 /// </summary>
 private static IEnumerable <Diagnostic> ComputeScopeDiagnostics(this FileContentManager file, int start, int count)
 {
     foreach (var line in file.GetLines(start, count))
     {
         foreach (var pos in line.ExcessBracketPositions)
         {
             yield return(Errors.ExcessBracketError(file.FileName, Position.Create(start, pos)));
         }
         ++start;
     }
 }
Example #3
0
 /// <summary>
 /// Computes excess bracket errors for the given range of lines in file based on the corresponding CodeLine.
 /// Throws an ArgumentNullException if file is null.
 /// Throws an ArgumentOutOfRangeException if the range [start, start + count) is not within file.
 /// </summary>
 private static IEnumerable <Diagnostic> ComputeScopeDiagnostics(this FileContentManager file, int start, int count)
 {
     if (file == null)
     {
         throw new ArgumentNullException(nameof(file));
     }
     foreach (var line in file.GetLines(start, count))
     {
         foreach (var pos in line.ExcessBracketPositions)
         {
             yield return(Errors.ExcessBracketError(file.FileName.Value, new Position(start, pos)));
         }
         ++start;
     }
 }
Example #4
0
 /// <summary>
 /// Computes excess bracket errors for the given range of lines in file based on the corresponding CodeLine.
 /// </summary>
 /// <exception cref="ArgumentOutOfRangeException">The range [<paramref name="start"/>, <paramref name="start"/> + <paramref name="count"/>) is not within <paramref name="file"/>.</exception>
 private static IEnumerable <Diagnostic> ComputeScopeDiagnostics(this FileContentManager file, int start, int count)
 {
     foreach (var line in file.GetLines(start, count))
     {
         foreach (var pos in line.ExcessBracketPositions)
         {
             yield return(Errors.ExcessBracketError(file.FileName, Position.Create(start, pos)));
         }
         foreach (var pos in line.ErrorDelimiterPositions)
         {
             yield return(Errors.InvalidCharacterInInterpolatedArgument(file.FileName, Position.Create(start, pos), file.GetLine(start).Text[pos]));
         }
         ++start;
     }
 }
Example #5
0
        /// <summary>
        /// Computes the excess closing and scope error updates for the given replacements at the position specified by start and count in the given file.
        /// Returns a sequence of CodeLines for the remaining file, if the made replacements require updating the remaining file as well, and null otherwise.
        /// Throws an ArgumentNullException if file or replacements is null.
        /// Throws an ArgumentException if replacements does not at least contain one CodeLine.
        /// Throws an ArgumentOutOfRangeException if the range defined by start and count is not within the given file, where count needs to be at least one.
        /// </summary>
        private static IEnumerable <CodeLine> ComputeUpdates(FileContentManager file, int start, int count, CodeLine[] replacements)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (replacements == null)
            {
                throw new ArgumentNullException(nameof(replacements));
            }
            if (start < 0 || start >= file.NrLines())
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }
            if (count < 1 || start + count > file.NrLines())
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }
            if (replacements.Length == 0)
            {
                throw new ArgumentException("replacements cannot be empty");
            }
            var continueAtInFile = start + count;
            var remainingLines   = file.GetLines(continueAtInFile, file.NrLines() - continueAtInFile);

            // how much the effective indentation (i.e. absolute indentation plus nr of excess closings up to that point) changed determines how much an what we need to update:
            var indentationChange             = GetIndentationChange(file, continueAtInFile, replacements.Last());
            var requiresStringDelimiterUpdate = ContinueString(file.GetLine(continueAtInFile - 1)) ^ ContinueString(replacements.Last());

            if (requiresStringDelimiterUpdate)
            // we need to recompute everything if the interpretation of what is code and what is a string changes...
            // since the interpretation of the remaining file changed, we need to update the entire file from start onwards
            {
                return(ComputeCodeLines(remainingLines.Select(line => line.Text), replacements.Last()).ToList());
            }
            else if (indentationChange != 0)
            // if the replacements has more effective closing brackets (not just excess closings!) than the current part that will be replaced has,
            // then we need check the text of the remaining file as well in order to compute the correct update
            // if it has less (indentationChange > 0), then we could in principle simplify things somewhat by simply discarding the corresponding number of excess closing brackets
            {
                return(remainingLines.GetUpdatedLines(remainingLines.First().Indentation + indentationChange));
            }
            else
            {
                return(null);
            }
        }