diff --git a/src/ServiceHost/Workspace/ScriptFile.cs b/src/ServiceHost/Workspace/ScriptFile.cs index 90d66244..166b50ea 100644 --- a/src/ServiceHost/Workspace/ScriptFile.cs +++ b/src/ServiceHost/Workspace/ScriptFile.cs @@ -106,6 +106,13 @@ namespace Microsoft.SqlTools.EditorServices #region Constructors + /// + /// Add a default constructor for testing + /// + public ScriptFile() + { + } + /// /// Creates a new ScriptFile instance by reading file contents from /// the given TextReader. @@ -433,11 +440,11 @@ namespace Microsoft.SqlTools.EditorServices return new BufferRange(startPosition, endPosition); } - #endregion - - #region Private Methods - - private void SetFileContents(string fileContents) + /// + /// Set the script files contents + /// + /// + public void SetFileContents(string fileContents) { // Split the file contents into lines and trim // any carriage returns from the strings. @@ -451,6 +458,10 @@ namespace Microsoft.SqlTools.EditorServices this.ParseFileContents(); } + #endregion + + #region Private Methods + /// /// Parses the current file contents to get the AST, tokens, /// and parse errors. diff --git a/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs b/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs new file mode 100644 index 00000000..70fd2acd --- /dev/null +++ b/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs @@ -0,0 +1,116 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.EditorServices; +using Microsoft.SqlTools.EditorServices.Session; +using Microsoft.SqlTools.LanguageSupport; +using Xunit; + +namespace Microsoft.SqlTools.Test.LanguageServer +{ + /// + /// Tests for the ServiceHost Language Service tests + /// + public class LanguageServiceTests + { + /// + /// Create a test language service instance + /// + /// + private LanguageService CreateTestService() + { + return new LanguageService(new SqlToolsContext(null, null)); + } + + #region "Diagnostics tests" + + /// + /// Verify that the SQL parser correctly detects errors in text + /// + [Fact] + public void ParseSelectStatementWithoutErrors() + { + // sql statement with no errors + const string sqlWithErrors = "SELECT * FROM sys.objects"; + + // get the test service + LanguageService service = CreateTestService(); + + // parse the sql statement + var scriptFile = new ScriptFile(); + scriptFile.SetFileContents(sqlWithErrors); + ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile); + + // verify there are no errors + Assert.Equal(0, fileMarkers.Length); + } + + /// + /// Verify that the SQL parser correctly detects errors in text + /// + [Fact] + public void ParseSelectStatementWithError() + { + // sql statement with errors + const string sqlWithErrors = "SELECT *** FROM sys.objects"; + + // get test service + LanguageService service = CreateTestService(); + + // parse sql statement + var scriptFile = new ScriptFile(); + scriptFile.SetFileContents(sqlWithErrors); + ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile); + + // verify there is one error + Assert.Equal(1, fileMarkers.Length); + + // verify the position of the error + Assert.Equal(9, fileMarkers[0].ScriptRegion.StartColumnNumber); + Assert.Equal(1, fileMarkers[0].ScriptRegion.StartLineNumber); + Assert.Equal(10, fileMarkers[0].ScriptRegion.EndColumnNumber); + Assert.Equal(1, fileMarkers[0].ScriptRegion.EndLineNumber); + } + + /// + /// Verify that the SQL parser correctly detects errors in text + /// + [Fact] + public void ParseMultilineSqlWithErrors() + { + // multiline sql with errors + const string sqlWithErrors = + "SELECT *** FROM sys.objects;\n" + + "GO\n" + + "SELECT *** FROM sys.objects;\n"; + + // get test service + LanguageService service = CreateTestService(); + + // parse sql + var scriptFile = new ScriptFile(); + scriptFile.SetFileContents(sqlWithErrors); + ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile); + + // verify there are two errors + Assert.Equal(2, fileMarkers.Length); + + // check position of first error + Assert.Equal(9, fileMarkers[0].ScriptRegion.StartColumnNumber); + Assert.Equal(1, fileMarkers[0].ScriptRegion.StartLineNumber); + Assert.Equal(10, fileMarkers[0].ScriptRegion.EndColumnNumber); + Assert.Equal(1, fileMarkers[0].ScriptRegion.EndLineNumber); + + // check position of second error + Assert.Equal(9, fileMarkers[1].ScriptRegion.StartColumnNumber); + Assert.Equal(3, fileMarkers[1].ScriptRegion.StartLineNumber); + Assert.Equal(10, fileMarkers[1].ScriptRegion.EndColumnNumber); + Assert.Equal(3, fileMarkers[1].ScriptRegion.EndLineNumber); + } + + #endregion + } +} +