internal static void FormatSql() { Gateway.SetCurrentLanguage(LangType.L_SQL); var text = GetCurrentText(); var options = new TSqlStandardFormatterOptions { BreakJoinOnSections = _settings.BreakJoinOnSections, ExpandBetweenConditions = _settings.ExpandBetweenConditions, ExpandBooleanExpressions = _settings.ExpandBooleanExpressions, ExpandCaseStatements = _settings.ExpandCaseStatements, ExpandCommaLists = _settings.ExpandCommaList, ExpandInLists = false, HTMLColoring = false, IndentString = _settings.IndentString, KeywordStandardization = _settings.KeywordStandardization, MaxLineWidth = _settings.MaxLineWidth, NewClauseLineBreaks = 0, NewStatementLineBreaks = 0, SpaceAfterExpandedComma = _settings.SpaceAfterExpandedComma, SpacesPerTab = _settings.SpacesPerTab, TrailingCommas = _settings.TrailingCommas, UppercaseKeywords = _settings.UppercaseKeywords }; var innerFormatter = new TSqlStandardFormatter(options); var tokenizer = new TSqlStandardTokenizer(); var parser = new TSqlStandardParser(); var parsedSql = parser.ParseSQL(tokenizer.TokenizeSQL(text)); Editor.SetText(innerFormatter.FormatSQLTree(parsedSql)); }
public string PrettyPrint(string sql) { var tokenizer = new TSqlStandardTokenizer(); var tokenized = tokenizer.TokenizeSQL(sql); var parser = new TSqlStandardParser(); var parsedSql = parser.ParseSQL(tokenized); return(_formatter.FormatSQLTree(parsedSql)?.TrimEnd()); }
public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span) { List <ClassificationSpan> classifiedSpans = new List <ClassificationSpan>(); // Note: best would be to avoid recalulating the output everytime on multiline SQL. // I am not sure how to achive this while avoiding chaching potentially huge documents. var tagSpans = tagger.GetTags(span); foreach (var tagSpan in tagSpans) { var snapshotSpan = tagSpan.Span.GetSpans(span.Snapshot).First(); var text = snapshotSpan.GetText(); if (!IsKnownStartOfSql(text)) { break; } // TODO: think about what is the best way to handle '{ }', both in normal // as well as in interpolated strings. most futureproof might be to // actually use the roslyn code analyzer. List <Span> stringInterpolations = new List <Span>(); int stringInterpolationIndex = 0; if (tagSpan.Tag.Interpolations != null) { // replace interpolations with "xxxx", to avoid confusing PoorMansTSqlFormatter StringBuilder b = new StringBuilder(text); foreach (var interpolation in tagSpan.Tag.Interpolations) { int relStart = interpolation.Start.Position - snapshotSpan.Start.Position; int relLength = interpolation.Length; for (int i = 0; i < relLength; ++i) { b[i + relStart] = 'x'; } stringInterpolations.Add(interpolation.Span); } text = b.ToString(); stringInterpolations.OrderBy(i => i.Start).ThenBy(i => i.Length).ToList(); } var index = 0; var tokens = tokenizer.TokenizeSQL(text); var doc = parser.ParseSQL(tokens).ToXmlDoc(); // no need to be too strict //if (doc.DocumentElement.HasAttribute("errorFound") && doc.DocumentElement.GetAttribute("errorFound").Equals("1", StringComparison.InvariantCultureIgnoreCase)) // continue; if (doc.DocumentElement == null) { continue; } //$"SELECT { --index } FROM x"; var sqlWithType = formatter.FormatSQLTree(doc); foreach (var pair in sqlWithType) { int length = pair.Value.Length; SnapshotPoint start = snapshotSpan.Start + index; index += length; string classification = pair.Key; if (classification == null) { continue; } Span cutOutinterpolation = default(Span); // cut out string interpolations, if any. while (stringInterpolationIndex < stringInterpolations.Count) { Span cutOut = stringInterpolations[stringInterpolationIndex]; if (cutOut.Start > start.Position + length) { break; } if (cutOut.Start + cutOut.Length < start.Position) { ++stringInterpolationIndex; continue; } // there is some overlap. cutOutinterpolation = cutOut; break; } if (cutOutinterpolation.IsEmpty) { AddClassification(classifiedSpans, classification, new SnapshotSpan(start, length)); } else { if (cutOutinterpolation.Start > start.Position) { AddClassification(classifiedSpans, classification, new SnapshotSpan(start, cutOutinterpolation.Start - start.Position)); } if (cutOutinterpolation.Start + cutOutinterpolation.Length < start.Position + length) { int keepStart = cutOutinterpolation.Start + cutOutinterpolation.Length; int keepLength = start.Position + length - keepStart; AddClassification(classifiedSpans, classification, new SnapshotSpan(new SnapshotPoint(start.Snapshot, keepStart), keepLength)); } } } } return(classifiedSpans); }