using System; using System.IO; namespace Semmle.Util { /// /// An instance of this class represents a piece of text, e.g. the text of a C# source file. /// public sealed class Text { //#################### PRIVATE VARIABLES #################### #region /// /// The text, stored line-by-line. /// private readonly string[] lines; #endregion //#################### CONSTRUCTORS #################### #region /// /// Constructs a text object from an array of lines. /// /// The lines of text. public Text(string[] lines) { this.lines = lines; } #endregion //#################### PUBLIC METHODS #################### #region /// /// Gets the whole text. /// /// The whole text. public string GetAll() { using var sw = new StringWriter(); foreach (var s in lines) { sw.WriteLine(s); } return sw.ToString(); } /// /// Gets the portion of text that lies in the specified location range. /// /// The row at which the portion starts. /// The column in the start row at which the portion starts. /// The row at which the portion ends. /// The column in the end row at which the portion ends. /// The portion of text that lies in the specified location range. public string GetPortion(int startRow, int startColumn, int endRow, int endColumn) { // Perform some basic validation on the range bounds. if (startRow < 0 || endRow < 0 || startColumn < 0 || endColumn < 0 || endRow >= lines.Length || startRow > endRow) { throw new Exception ( string.Format("Bad range ({0},{1}):({2},{3}) in a piece of text with {4} lines", startRow, startColumn, endRow, endColumn, lines.Length) ); } using var sw = new StringWriter(); string line; for (var i = startRow; i <= endRow; ++i) { if (i == startRow && i == endRow) { // This is a single-line range, so take the bit between "startColumn" and "endColumn". line = startColumn <= lines[i].Length ? lines[i].Substring(startColumn, endColumn - startColumn) : ""; } else if (i == startRow) { // This is the first line of a multi-line range, so take the bit from "startColumn" onwards. line = startColumn <= lines[i].Length ? lines[i].Substring(startColumn) : ""; } else if (i == endRow) { // This is the last line of a multi-line range, so take the bit up to "endColumn". line = endColumn <= lines[i].Length ? lines[i].Substring(0, endColumn) : lines[i]; } else { // This is a line in the middle of a multi-line range, so take the whole line. line = lines[i]; } sw.WriteLine(line); } return sw.ToString(); } #endregion } }