// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using System.Collections.Generic; namespace Microsoft.SqlTools.ServiceLayer.BatchParser { /// /// This class gives information about lines being parsed by /// the Batch Parser /// public class LineInfo { private IEnumerable tokens; private IEnumerable variableRefs; /// /// Constructor method for the LineInfo class /// public LineInfo(IEnumerable tokens, IEnumerable variableRefs) { this.tokens = tokens; this.variableRefs = variableRefs; } /// /// Gets the stream position for offset and returns a PositionStruct /// public PositionStruct GetStreamPositionForOffset(int offset) { if (variableRefs != null) { offset = CalculateVarsUnresolvedOffset(offset); } int charCount = 0; Token lastToken = null; foreach (Token token in tokens) { lastToken = token; if (charCount + token.Text.Length > offset) { int line, column; CalculateLineColumnForOffset(token, offset - charCount, out line, out column); return new PositionStruct(line, column, token.Begin.Offset + (offset - charCount), token.Filename); } charCount += token.Text.Length; } if (lastToken != null) { return new PositionStruct(lastToken.End.Line, lastToken.End.Column, lastToken.End.Offset, lastToken.Filename); } else { return new PositionStruct(1, 1, 0, string.Empty); } } internal static void CalculateLineColumnForOffset(Token token, int offset, out int line, out int column) { CalculateLineColumnForOffset(token.Text, offset, 0, token.Begin.Line, token.Begin.Column, out line, out column); } internal static void CalculateLineColumnForOffset(string text, int offset, int offsetDelta, int lineDelta, int columnDelta, out int line, out int column) { line = lineDelta; column = columnDelta; int counter = offsetDelta; while (counter < offset) { bool newLineWithCR = false; if (text[counter] == '\r') { newLineWithCR = true; } else if (text[counter] == '\n') { line++; column = 0; } counter++; if (newLineWithCR && counter < text.Length && text[counter] != '\n') { line++; column = 0; } column++; } } private int CalculateVarsUnresolvedOffset(int offset) { // find offset of the beginning of variable substitution (if offset points to the middle of it) int diff = 0; foreach (VariableReference reference in variableRefs) { if (reference.Start >= offset) { break; } else if (reference.VariableValue != null && offset < reference.Start + reference.VariableValue.Length) { offset = reference.Start; break; } if (reference.VariableValue != null) { diff += reference.Length - reference.VariableValue.Length; } } return offset + diff; } } }