From 7119db3bcd1dd5ccbede9427605efbbaea35b1f1 Mon Sep 17 00:00:00 2001 From: Karl Burtram Date: Sat, 23 Jul 2016 15:05:02 -0700 Subject: [PATCH] Integrate SqlParser into the onchange diagnostics to provide error messages. --- .../LanguageSupport/LanguageService.cs | 57 +++++++++++++------ src/ServiceHost/Server/LanguageServer.cs | 8 +-- src/ServiceHost/project.json | 3 +- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/ServiceHost/LanguageSupport/LanguageService.cs b/src/ServiceHost/LanguageSupport/LanguageService.cs index 3ab77697..ff4f4a65 100644 --- a/src/ServiceHost/LanguageSupport/LanguageService.cs +++ b/src/ServiceHost/LanguageSupport/LanguageService.cs @@ -5,6 +5,8 @@ using Microsoft.SqlTools.EditorServices; using Microsoft.SqlTools.EditorServices.Session; +using Microsoft.SqlServer.Management.SqlParser.Parser; +using System.Collections.Generic; namespace Microsoft.SqlTools.LanguageSupport { @@ -13,6 +15,11 @@ namespace Microsoft.SqlTools.LanguageSupport /// public class LanguageService { + /// + /// The cached parse result from previous incremental parse + /// + private ParseResult prevParseResult; + /// /// Gets or sets the current SQL Tools context /// @@ -34,24 +41,38 @@ namespace Microsoft.SqlTools.LanguageSupport /// public ScriptFileMarker[] GetSemanticMarkers(ScriptFile scriptFile) { - // the commented out snippet is an example of how to create a error marker - // semanticMarkers = new ScriptFileMarker[1]; - // semanticMarkers[0] = new ScriptFileMarker() - // { - // Message = "Error message", - // Level = ScriptFileMarkerLevel.Error, - // ScriptRegion = new ScriptRegion() - // { - // File = scriptFile.FilePath, - // StartLineNumber = 2, - // StartColumnNumber = 2, - // StartOffset = 0, - // EndLineNumber = 4, - // EndColumnNumber = 10, - // EndOffset = 0 - // } - // }; - return new ScriptFileMarker[0]; + // parse current SQL file contents to retrieve a list of errors + ParseOptions parseOptions = new ParseOptions(); + ParseResult parseResult = Parser.IncrementalParse( + scriptFile.Contents, + prevParseResult, + parseOptions); + + // save previous result for next incremental parse + this.prevParseResult = parseResult; + + // build a list of SQL script file markers from the errors + List markers = new List(); + foreach (var error in parseResult.Errors) + { + markers.Add(new ScriptFileMarker() + { + Message = error.Message, + Level = ScriptFileMarkerLevel.Error, + ScriptRegion = new ScriptRegion() + { + File = scriptFile.FilePath, + StartLineNumber = error.Start.LineNumber, + StartColumnNumber = error.Start.ColumnNumber, + StartOffset = 0, + EndLineNumber = error.End.LineNumber, + EndColumnNumber = error.End.ColumnNumber, + EndOffset = 0 + } + }); + } + + return markers.ToArray(); } } } diff --git a/src/ServiceHost/Server/LanguageServer.cs b/src/ServiceHost/Server/LanguageServer.cs index d6719141..5dbbc310 100644 --- a/src/ServiceHost/Server/LanguageServer.cs +++ b/src/ServiceHost/Server/LanguageServer.cs @@ -122,7 +122,7 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server /// /// /// - protected Task HandleDidChangeTextDocumentNotification( + protected async Task HandleDidChangeTextDocumentNotification( DidChangeTextDocumentParams textChangeParams, EventContext eventContext) { @@ -133,7 +133,7 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server // A text change notification can batch multiple change requests foreach (var textChange in textChangeParams.ContentChanges) { - string fileUri = textChangeParams.TextDocument.Uri; + string fileUri = textChangeParams.Uri ?? textChangeParams.TextDocument.Uri; msg.AppendLine(); msg.Append(" File: "); msg.Append(fileUri); @@ -150,12 +150,12 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server Logger.Write(LogLevel.Verbose, msg.ToString()); - this.RunScriptDiagnostics( + await this.RunScriptDiagnostics( changedFiles.ToArray(), editorSession, eventContext); - return Task.FromResult(true); + await Task.FromResult(true); } protected Task HandleDidOpenTextDocumentNotification( diff --git a/src/ServiceHost/project.json b/src/ServiceHost/project.json index 11340892..91353567 100644 --- a/src/ServiceHost/project.json +++ b/src/ServiceHost/project.json @@ -5,7 +5,8 @@ "emitEntryPoint": true }, "dependencies": { - "Newtonsoft.Json": "9.0.1" + "Newtonsoft.Json": "9.0.1", + "Microsoft.SqlServer.SqlParser": "140.1.3" }, "frameworks": { "netcoreapp1.0": {