
I have an application where we use the SyntaxEditor for T-Sql editing. As you may or may not know, T-Sql can statements can wrap across multiple lines. For example, this is a single statement:
However, when I try to implement a class that extends TaggerBase to generate SquiggleTags for parser errors, I can't get the Squiggle Tags to fully appear.
My GetTags method is as follows:You'll notice that I'm not actually using each snapshot range. Instead, I determine when I'm getting the 'last' snapshot for the change and then I parse my entire document. The reason is that I'm using a SQL parser from Microsoft (in the Microsoft.SqlServer.Management.SqlParser.Parser namespace) to determine if parser errors are present. The Parse function needs the entire string to produce accurate errors so there's no point to using the snapshot ranges. I didn't write my own parser because the Microsoft one works correctly.
With the correct errors determined, my problem arises. Let's say we're using this SQL statement:There's an error on the second line due to the additional quote. So, when the last snapshot range is provided in GetTags, I parse the entire statement and learn of the error. Now, I create a snapshot range to match the error's starting and ending offset. It turns out the parser indicates the error is from position 9 to position 46 (since it's seeing the text as one whole line). I translate those positions into a snapshot range that encompasses the second through fourth lines of the document's text and return the TagSnapshotRange. But to my dismay, only the last line has a squiggle.
Generally, it appears that because I'm returning the TagSnapshotRanges when processing the final snapshot range, only squiggle areas that overlap the final snapshot range will be displayed.
So, I'm looking for a way to workaround this problem, or a better approach altogether. A version of GetTags that gave me the entire document's snapshot range would be perfect. Is there such a thing? Do you have recommendations on how I can use GetTags() or some other means to make Squiggles appear with the restriction that I parse the entire text instead of snapshot-by-snapshot?
FWIW, The best idea I came up with was:This isn't quite finished but the notion is to parse the text immediately and then keep returning the same snapshot ranges so they can be applied to each range in the editor. However, this is a very hacky approach so I'm hoping you can suggest something better.
Thanks,
-Craig
SELECT
ID
, CAST(('Test1_' + CAST(ID AS NVARCHAR)) AS NVARCHAR(255)) AS Column1
, CAST(('Test2_' + CAST(ID AS NVARCHAR)) AS NVARCHAR(255)) AS Column2
, CAST(('Test3_' + CAST(ID AS NVARCHAR)) AS NVARCHAR(255)) AS Column3
, CAST(('Test4_' + CAST(ID AS NVARCHAR)) AS NVARCHAR(255)) AS Column4
, CAST(('Test5_' + CAST(ID AS NVARCHAR)) AS NVARCHAR(255)) AS Column5
FROM
dbo.Number
My GetTags method is as follows:
public override IEnumerable<TagSnapshotRange<ISquiggleTag>> GetTags(NormalizedTextSnapshotRangeCollection snapshotRanges, object parameter)
{
if (snapshotRanges != null)
{
// Loop through the snapshot ranges
foreach (var snapshotRange in snapshotRanges)
{
var isLastLine = Document.CurrentSnapshot.SnapshotRange.EndPosition.Line == snapshotRange.EndPosition.Line &&
Document.CurrentSnapshot.SnapshotRange.EndPosition.Character == snapshotRange.EndPosition.Character;
if (isLastLine)
{
var documentText = Document.CurrentSnapshot.Text.Replace(Environment.NewLine, " ");
var parseResult = Parser.Parse(documentText);
foreach (var error in parseResult.Errors)
{
var tag = new SquiggleTag();
tag.ClassificationType = ClassificationTypes.SyntaxError;
tag.ContentProvider = new PlainTextContentProvider(error.Message);
yield return new TagSnapshotRange<ISquiggleTag>(new TextSnapshotRange(Document.CurrentSnapshot, error.Start.ColumnNumber, error.End.ColumnNumber), tag);
}
}
}
}
}
With the correct errors determined, my problem arises. Let's say we're using this SQL statement:
select
'TestValue''
AS Column FROM
Table
Generally, it appears that because I'm returning the TagSnapshotRanges when processing the final snapshot range, only squiggle areas that overlap the final snapshot range will be displayed.
So, I'm looking for a way to workaround this problem, or a better approach altogether. A version of GetTags that gave me the entire document's snapshot range would be perfect. Is there such a thing? Do you have recommendations on how I can use GetTags() or some other means to make Squiggles appear with the restriction that I parse the entire text instead of snapshot-by-snapshot?
FWIW, The best idea I came up with was:
public override IEnumerable<TagSnapshotRange<ISquiggleTag>> GetTags(NormalizedTextSnapshotRangeCollection snapshotRanges, object parameter)
{
_snapshotRanges = new List<TagSnapshotRange<ISquiggleTag>>();
var documentText = Document.CurrentSnapshot.Text.Replace(Environment.NewLine, " ");
var parseResult = Parser.Parse(documentText);
foreach (var error in parseResult.Errors)
{
var tag = new SquiggleTag();
tag.ClassificationType = ClassificationTypes.SyntaxError;
tag.ContentProvider = new PlainTextContentProvider(error.Message);
_snapshotRanges.Add(new TagSnapshotRange<ISquiggleTag>(new TextSnapshotRange(Document.CurrentSnapshot, error.Start.ColumnNumber, error.End.ColumnNumber), tag));
}
return _snapshotRanges;
}
Thanks,
-Craig