From 7941e871d96680567c8a5fc3295ba6f1a0052318 Mon Sep 17 00:00:00 2001 From: Benjin Dubishar Date: Tue, 28 Feb 2023 09:40:20 -0800 Subject: [PATCH] Adding SqlProject service support for entries (#1884) * Implementation * NoneScript test * patching up test * Updating comments --- .../Contracts/NoneScripts/AddNoneScript.cs | 18 ++++ .../Contracts/NoneScripts/DeleteNoneScript.cs | 18 ++++ .../NoneScripts/ExcludeNoneScript.cs | 18 ++++ .../Contracts/NoneScripts/GetNoneScripts.cs | 16 ++++ .../Contracts/NoneScripts/MoveNoneScript.cs | 20 ++++ .../SqlProjects/SqlProjectsService.cs | 45 ++++++++- .../SqlProjects/SqlProjectsServiceTests.cs | 93 +++++++++++++++++++ 7 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/AddNoneScript.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/DeleteNoneScript.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/ExcludeNoneScript.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/GetNoneScripts.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/MoveNoneScript.cs diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/AddNoneScript.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/AddNoneScript.cs new file mode 100644 index 00000000..99bc39b1 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/AddNoneScript.cs @@ -0,0 +1,18 @@ +// +// 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.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts +{ + /// + /// Add a SQL object script to a project + /// + public class AddNoneScriptRequest + { + public static readonly RequestType Type = RequestType.Create("sqlProjects/addNoneScript"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/DeleteNoneScript.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/DeleteNoneScript.cs new file mode 100644 index 00000000..6940569b --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/DeleteNoneScript.cs @@ -0,0 +1,18 @@ +// +// 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.Hosting.Protocol.Contracts; + +using Microsoft.SqlTools.ServiceLayer.Utility; +namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts +{ + /// + /// Delete a SQL object script from a project + /// + public class DeleteNoneScriptRequest + { + public static readonly RequestType Type = RequestType.Create("sqlProjects/deleteNoneScript"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/ExcludeNoneScript.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/ExcludeNoneScript.cs new file mode 100644 index 00000000..c96d1bda --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/ExcludeNoneScript.cs @@ -0,0 +1,18 @@ +// +// 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.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts +{ + /// + /// Exclude a SQL object script from a project + /// + public class ExcludeNoneScriptRequest + { + public static readonly RequestType Type = RequestType.Create("sqlProjects/excludeNoneScript"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/GetNoneScripts.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/GetNoneScripts.cs new file mode 100644 index 00000000..b2eeef89 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/GetNoneScripts.cs @@ -0,0 +1,16 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#nullable disable + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts +{ + public class GetNoneScriptsRequest + { + public static readonly RequestType Type = RequestType.Create("sqlProjects/getNoneScripts"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/MoveNoneScript.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/MoveNoneScript.cs new file mode 100644 index 00000000..72835c91 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/NoneScripts/MoveNoneScript.cs @@ -0,0 +1,20 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#nullable disable + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts +{ + /// + /// Move a SQL object script in a project + /// + public class MoveNoneScriptRequest + { + public static readonly RequestType Type = RequestType.Create("sqlProjects/moveNoneScript"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs index b73d66f7..66a4a1a4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs @@ -67,6 +67,13 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects serviceHost.SetRequestHandler(ExcludePostDeploymentScriptRequest.Type, HandleExcludePostDeploymentScriptRequest, isParallelProcessingSupported: false); serviceHost.SetRequestHandler(MovePostDeploymentScriptRequest.Type, HandleMovePostDeploymentScriptRequest, isParallelProcessingSupported: false); + // None script functions + serviceHost.SetRequestHandler(GetNoneScriptsRequest.Type, HandleGetNoneScriptsRequest, isParallelProcessingSupported: true); + serviceHost.SetRequestHandler(AddNoneScriptRequest.Type, HandleAddNoneScriptRequest, isParallelProcessingSupported: false); + serviceHost.SetRequestHandler(DeleteNoneScriptRequest.Type, HandleDeleteNoneScriptRequest, isParallelProcessingSupported: false); + serviceHost.SetRequestHandler(ExcludeNoneScriptRequest.Type, HandleExcludeNoneScriptRequest, isParallelProcessingSupported: false); + serviceHost.SetRequestHandler(MoveNoneScriptRequest.Type, HandleMoveNoneScriptRequest, isParallelProcessingSupported: false); + // Folder functions serviceHost.SetRequestHandler(GetFoldersRequest.Type, HandleGetFoldersRequest, isParallelProcessingSupported: true); serviceHost.SetRequestHandler(AddFolderRequest.Type, HandleAddFolderRequest, isParallelProcessingSupported: false); @@ -237,6 +244,43 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects #endregion + #region None script functions + + internal async Task HandleGetNoneScriptsRequest(SqlProjectParams requestParams, RequestContext requestContext) + { + await RunWithErrorHandling(() => + { + return new GetScriptsResult() + { + Success = true, + ErrorMessage = null, + Scripts = GetProject(requestParams.ProjectUri).NoneScripts.Select(x => x.Path).ToArray() + }; + }, requestContext); + } + + internal async Task HandleAddNoneScriptRequest(SqlProjectScriptParams requestParams, RequestContext requestContext) + { + await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).NoneScripts.Add(new NoneScript(requestParams.Path!)), requestContext); + } + + internal async Task HandleDeleteNoneScriptRequest(SqlProjectScriptParams requestParams, RequestContext requestContext) + { + await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).NoneScripts.Delete(requestParams.Path!), requestContext); + } + + internal async Task HandleExcludeNoneScriptRequest(SqlProjectScriptParams requestParams, RequestContext requestContext) + { + await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).NoneScripts.Exclude(requestParams.Path!), requestContext); + } + + internal async Task HandleMoveNoneScriptRequest(MoveItemParams requestParams, RequestContext requestContext) + { + await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).NoneScripts.Move(requestParams.Path, requestParams.DestinationPath), requestContext); + } + + #endregion + #region Folder functions internal async Task HandleGetFoldersRequest(SqlProjectParams requestParams, RequestContext requestContext) @@ -370,7 +414,6 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects #endregion - #region SQLCMD variable functions internal async Task HandleGetSqlCmdVariablesRequest(SqlProjectParams requestParams, RequestContext requestContext) diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs index 86f04e99..48b04201 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs @@ -189,6 +189,99 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects Assert.IsFalse(File.Exists(movedScriptAbsolutePath), $"{movedScriptAbsolutePath} expected to have been deleted from disk"); } + [Test] + public async Task TestNoneScriptOperations() + { + // Setup + SqlProjectsService service = new(); + string projectUri = await service.CreateSqlProject(); + Assert.AreEqual(0, service.Projects[projectUri].NoneScripts.Count, "Baseline number of NoneScripts"); + + // Validate adding a None script + MockRequest requestMock = new(); + string relativePath = "NoneIncludeFile.json"; + string absolutePath = Path.Join(Path.GetDirectoryName(projectUri), relativePath); + + #pragma warning disable JSON002 // Probable JSON string detected + await File.WriteAllTextAsync(absolutePath, @"{""included"" : false }"); + #pragma warning restore JSON002 // Probable JSON string detected + + Assert.IsTrue(File.Exists(absolutePath), $"{absolutePath} expected to be on disk"); + + await service.HandleAddNoneScriptRequest(new SqlProjectScriptParams() + { + ProjectUri = projectUri, + Path = relativePath + }, requestMock.Object); + + requestMock.AssertSuccess(nameof(service.HandleAddNoneScriptRequest)); + Assert.AreEqual(1, service.Projects[projectUri].NoneScripts.Count, "NoneScripts count after add"); + Assert.IsTrue(service.Projects[projectUri].NoneScripts.Contains(relativePath), $"NoneScripts expected to contain {relativePath}"); + + // Validate getting a list of the None scripts + MockRequest getMock = new(); + await service.HandleGetNoneScriptsRequest(new SqlProjectParams() + { + ProjectUri = projectUri + }, getMock.Object); + + getMock.AssertSuccess(nameof(service.HandleGetNoneScriptsRequest)); + Assert.AreEqual(1, getMock.Result.Scripts.Length); + Assert.AreEqual(relativePath, getMock.Result.Scripts[0]); + + // Validate excluding a None script + requestMock = new(); + await service.HandleExcludeNoneScriptRequest(new SqlProjectScriptParams() + { + ProjectUri = projectUri, + Path = relativePath + }, requestMock.Object); + + requestMock.AssertSuccess(nameof(service.HandleExcludeNoneScriptRequest)); + Assert.AreEqual(0, service.Projects[projectUri].NoneScripts.Count, "NoneScripts count after exclude"); + Assert.IsTrue(File.Exists(absolutePath), $"{absolutePath} expected to still exist on disk"); + + // Re-add to set up for Delete + requestMock = new(); + await service.HandleAddNoneScriptRequest(new SqlProjectScriptParams() + { + ProjectUri = projectUri, + Path = relativePath + }, requestMock.Object); + + requestMock.AssertSuccess(nameof(service.HandleAddNoneScriptRequest)); + Assert.AreEqual(1, service.Projects[projectUri].NoneScripts.Count, "NoneScripts count after re-add"); + + // Validate moving a None script + string movedScriptRelativePath = @"SubPath\RenamedNoneIncludeFile.json"; + string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), movedScriptRelativePath); + Directory.CreateDirectory(Path.GetDirectoryName(movedScriptAbsolutePath)!); + + requestMock = new(); + await service.HandleMoveNoneScriptRequest(new MoveItemParams() + { + ProjectUri = projectUri, + Path = relativePath, + DestinationPath = movedScriptRelativePath + }, requestMock.Object); + + requestMock.AssertSuccess(nameof(service.HandleMoveNoneScriptRequest)); + Assert.IsTrue(File.Exists(movedScriptAbsolutePath), "Script should exist at new location"); + Assert.AreEqual(1, service.Projects[projectUri].NoneScripts.Count, "NoneScripts count after move"); + + // Validate deleting a None script + requestMock = new(); + await service.HandleDeleteNoneScriptRequest(new SqlProjectScriptParams() + { + ProjectUri = projectUri, + Path = movedScriptRelativePath + }, requestMock.Object); + + requestMock.AssertSuccess(nameof(service.HandleDeleteNoneScriptRequest)); + Assert.AreEqual(0, service.Projects[projectUri].NoneScripts.Count, "NoneScripts count after delete"); + Assert.IsFalse(File.Exists(movedScriptAbsolutePath), $"{movedScriptAbsolutePath} expected to have been deleted from disk"); + } + [Test] public async Task TestPreDeploymentScriptOperations() {