diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3eddd09 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'daily' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..ccffbc9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,49 @@ +name: Build + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + Solution_Name: shader-ls.sln + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + #- ubuntu-latest + #- macos-latest + - windows-latest + configuration: [Debug, Release] + + steps: + - uses: actions/checkout@v6 + + # Install the .NET Core workload + - name: Install .NET Core + uses: actions/setup-dotnet@v5 + with: + dotnet-version: 6.0.x + + - name: Setup MSBuild.exe + uses: microsoft/setup-msbuild@v2.0.0 + + - name: Execute unit tests + working-directory: Server + run: dotnet test + + - name: Build the application + working-directory: Server + run: msbuild $env:Solution_Name /t:Rebuild /p:Configuration=$env:Configuration + env: + Configuration: ${{ matrix.configuration }} diff --git a/.gitignore b/.gitignore index 3e759b7..c4f605c 100644 --- a/.gitignore +++ b/.gitignore @@ -328,3 +328,6 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ + +# OS generated +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0147e6d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. + + +## Unreleased +> Released N/A + +* N/A + +## 0.1.3 +> Released Sep 09, 2023 + +* Platform specific directories to allow linux builds ([#2](../../pull/2)) + +## 0.1.2 +> Released Aug 23, 2023 + +* Rename `ShaderLab` section to `ShaderLS` ([`b43a5ac`](../../commit/b43a5ac376f9537d014616df79e00d4912f7d86a)) + +## 0.1.1 +> Released Aug 23, 2023 + +* Fix completion in VSCode ([`d0cd9bf`](../../commit/d0cd9bfa15b175be30e5312215777c82a3e055e9)) + +## 0.1.0 +> Released May 05, 2023 + +* Fix signature help ([`c5a1781`](../../commit/c5a1781767cefa5281f36c3ba408985e1c52a837)) + +## 0.0.1 +> Released May 03, 2023 + +* Working release diff --git a/LICENSE b/LICENSE index f08a77a..e3fb64e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Shen, Jen-Chieh +Copyright (c) 2023-2025 Shen, Jen-Chieh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4141f5c..1b45c26 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,16 @@ - +

+ +

Shader Language Server

+

+ License + Release + Nuget DT +

+

+ License +

+

-[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) - -# shader-language-server > Language server implementation for ShaderLab ## 🚧 Status @@ -24,7 +32,7 @@ Still in development. `dotnet tool install --global shader-ls` -See [shader-lsp nuget page](). +See [shader-lsp nuget page](https://www.nuget.org/packages/shader-ls/). ## 🔨 Usage @@ -37,3 +45,25 @@ The name is `shader-ls.exe` if you are using Windows! ## 🔧 Settings - `ShaderLab.CompletionWord` - completing word in the completion service + +## ⚜️ License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +See [`LICENSE`](./LICENSE) for details. diff --git a/Server/Buffer.cs b/Server/Buffer.cs index 206ead5..eb66311 100644 --- a/Server/Buffer.cs +++ b/Server/Buffer.cs @@ -1,7 +1,5 @@ -using System.Numerics; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; using ShaderlabVS; -using static System.Net.Mime.MediaTypeNames; namespace ShaderLS { @@ -20,10 +18,27 @@ public Buffer(string text) SetWordsInDocuments(text); } + public string? GetLine(Position position) + { + if (position == null) return default; + string[] lines = _text.Split("\n"); + return lines[position.Line]; + } + + public List? GetLineSplit(Position position) + { + string? line = GetLine(position); + if (line == null) return default; + + string front = line.Substring(0, position.Character); + string back = line.Substring(position.Character, line.Length - position.Character); + + return new List { front, back }; + } + public string GetWordAtPosition(Position position) { - if (position == null) - return null; + if (position == null) return null; string[] lines = _text.Split("\n"); @@ -32,7 +47,7 @@ public string GetWordAtPosition(Position position) string lineStr = lines[line]; - string[] words = GetWords(lineStr); + string[] words = Helpers.GetWords(lineStr); if (words.Length == 0) return null; @@ -51,7 +66,7 @@ public string GetWordAtPosition(Position position) on = word; } - return on; + return on.Trim(); } private void SetWordsInDocuments(string text) @@ -68,7 +83,7 @@ private void SetWordsInDocuments(string text) continue; } - string[] words = GetWords(line); + string[] words = Helpers.GetWords(line); foreach (var word in words) { @@ -78,13 +93,5 @@ private void SetWordsInDocuments(string text) line = reader.ReadLine(); } } - - private string[] GetWords(string text) - { - return text.Split( - new char[] { '{', '}', ' ', '\t', '(', ')', '[', ']', '+', '-', '*', '/', '%', '^', '>', '<', ':', - '.', ';', '\"', '\'', '?', '\\', '&', '|', '`', '$', '#', ','}, - StringSplitOptions.RemoveEmptyEntries); - } } } diff --git a/Server/BufferService.cs b/Server/BufferService.cs index 4847437..620e365 100644 --- a/Server/BufferService.cs +++ b/Server/BufferService.cs @@ -37,6 +37,16 @@ public string GetText(DocumentUri key) return _buffers[key].GetText(); } + public string? GetLine(DocumentUri key, Position position) + { + return _buffers[key].GetLine(position); + } + + public List? GetLineSplit(DocumentUri key, Position position) + { + return _buffers[key].GetLineSplit(position); + } + public string GetWordAtPosition(DocumentUri key, Position position) { return _buffers[key].GetWordAtPosition(position); @@ -47,13 +57,6 @@ public HashSet Tokens(DocumentUri key) return _buffers[key].Tokens(); } - //public string GetText(DocumentUri key, Position position) - //{ - // string text = GetText(key); - // GetIndex(text, position); - // return ; - //} - private static int GetIndex(string buffer, Position position) { var index = 0; diff --git a/Server/Handlers/CompletionHandler.cs b/Server/Handlers/CompletionHandler.cs index 2baf27c..8b933b4 100644 --- a/Server/Handlers/CompletionHandler.cs +++ b/Server/Handlers/CompletionHandler.cs @@ -40,7 +40,7 @@ public override async Task Handle(CompletionParams request, Canc { var conf = await _configuration.GetScopedConfiguration(request.TextDocument.Uri, cancellationToken); var options = new ServerOptions(); - conf.GetSection("ShaderLab").Bind(options); + conf.GetSection("ShaderLS").Bind(options); return GenerateCompletions(request, options); } diff --git a/Server/Handlers/SignatureHelpHandler.cs b/Server/Handlers/SignatureHelpHandler.cs index 2e894f2..86a4ae3 100644 --- a/Server/Handlers/SignatureHelpHandler.cs +++ b/Server/Handlers/SignatureHelpHandler.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; +using Microsoft.Extensions.Logging; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -27,22 +28,31 @@ public SignatureHelpHandler( this._workspace = workspace; } - public override async Task Handle(SignatureHelpParams request, CancellationToken cancellationToken) + public override async Task Handle(SignatureHelpParams request, CancellationToken token) { var uri = request.TextDocument.Uri; Position position = request.Position; - string current = _workspace.BufferService.GetWordAtPosition(uri, position); + // Attempt to get function name. + List? line = _workspace.BufferService.GetLineSplit(uri, position); - int newChar = Math.Max(position.Character - current.Length, 0); - var newPos = new Position(position.Line, newChar); + if (line == null) + return null; - // Attempt to get function name. - string word = _workspace.BufferService.GetWordAtPosition(uri, newPos); + string[] func = line[0].Split("(", StringSplitOptions.RemoveEmptyEntries); + + if (func.Length == 0) + return null; + + int max = Math.Max(func.Length - 2, 0); + string[] funcNames = Helpers.GetWords(func[max]); + + if (funcNames.Length == 0) + return null; - _logger.LogWarning("word: " + word); + string word = funcNames[funcNames.Length - 1]; - var signatures = new Container(); + var signatures = new List(); ShaderlabDataManager.Instance.HLSLCGFunctions.ForEach(f => { @@ -51,7 +61,8 @@ public SignatureHelpHandler( if (f.Name.Equals(word)) { var sign = CreateSignature(item, f.Description); - signatures.Append(sign); + + signatures.Add(sign); } } }); @@ -63,13 +74,18 @@ public SignatureHelpHandler( if (f.Name.Equals(word)) { var sign = CreateSignature(item, f.Description); - signatures.Append(sign); + + signatures.Add(sign); } } }); + string paramStr = func[func.Length - 1]; + int act = Regex.Matches(paramStr, ",").Count; + return new SignatureHelp { + ActiveParameter = act, Signatures = signatures }; } @@ -85,12 +101,7 @@ protected override SignatureHelpRegistrationOptions CreateRegistrationOptions(Si private SignatureInformation CreateSignature(string sign, string documentation) { - var signature = new SignatureInformation - { - Documentation = documentation, - Label = sign, - Parameters = new() - }; + var paramLst = new Container(); //find the parameters in the method signature (expect methodname(one, two) string[] pars = sign.Split(new char[] { '(', ',', ')', ';' }, StringSplitOptions.RemoveEmptyEntries); @@ -107,19 +118,22 @@ private SignatureInformation CreateSignature(string sign, string documentation) if (locusStart >= 0) { - _logger.LogWarning("param: " + param); - var newPararm = new ParameterInformation() { Documentation = "", Label = param }; - signature.Parameters.Append(newPararm); + paramLst.Append(newPararm); } } - return signature; + return new SignatureInformation + { + Documentation = documentation, + Label = sign, + Parameters = paramLst + }; } } } diff --git a/Server/Handlers/TextDocumentSyncHandler.cs b/Server/Handlers/TextDocumentSyncHandler.cs index de40c9d..99ccc3f 100644 --- a/Server/Handlers/TextDocumentSyncHandler.cs +++ b/Server/Handlers/TextDocumentSyncHandler.cs @@ -61,7 +61,7 @@ public override async Task Handle(DidOpenTextDocumentParams notification, var conf = await _configuration.GetScopedConfiguration(uri, token); var options = new ServerOptions(); - conf.GetSection("ShaderLab").Bind(options); + conf.GetSection("ShaderLS").Bind(options); string text = notification.TextDocument.Text; _workspace.Init(uri); diff --git a/Server/Helpers.cs b/Server/Helpers.cs index 21683c4..9450967 100644 --- a/Server/Helpers.cs +++ b/Server/Helpers.cs @@ -5,10 +5,18 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Models; using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; -namespace ShaderLS.LanguageServerProtocol +namespace ShaderLS { public static class Helpers { + public static string[] GetWords(string text) + { + return text.Split( + new char[] { '{', '}', ' ', '\t', '(', ')', '[', ']', '+', '-', '*', '/', '%', '^', '>', '<', ':', + '.', ';', '\"', '\'', '?', '\\', '&', '|', '`', '$', '#', ','}, + StringSplitOptions.RemoveEmptyEntries); + } + public static DocumentUri ToUri(string fileName) => DocumentUri.File(fileName); public static string FromUri(DocumentUri uri) => uri.GetFileSystemPath().Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); diff --git a/Server/Management/ProjectInfo.cs b/Server/Management/ProjectInfo.cs index e1ee861..8d1218c 100644 --- a/Server/Management/ProjectInfo.cs +++ b/Server/Management/ProjectInfo.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using OmniSharp.Extensions.LanguageServer.Protocol; -using ShaderLS.LanguageServerProtocol; +using OmniSharp.Extensions.LanguageServer.Protocol; namespace ShaderLS.Management { diff --git a/Server/Program.cs b/Server/Program.cs index a0e331b..6ba88a1 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -49,7 +49,7 @@ private static void Configure(LanguageServerOptions options) private static void ConfigureServices(IServiceCollection services) { - services.AddSingleton(new ConfigurationItem { Section = "ShaderLab" }); + services.AddSingleton(new ConfigurationItem { Section = "ShaderLS" }); services.AddSingleton(new DocumentSelector( new DocumentFilter { Pattern = "**/*.shader" }, new DocumentFilter { Pattern = "**/*.cginc" }, diff --git a/Server/ShaderlabVS.Data/Attributes.cs b/Server/ShaderlabVS.Data/Attributes.cs index d986a3a..9dbecbf 100644 --- a/Server/ShaderlabVS.Data/Attributes.cs +++ b/Server/ShaderlabVS.Data/Attributes.cs @@ -1,6 +1,4 @@ -using System; - -namespace ShaderlabVS.Data +namespace ShaderlabVS.Data { [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)] sealed class DefinationKeyAttribute : Attribute diff --git a/Server/ShaderlabVS.Data/DefinationDataProvider.cs b/Server/ShaderlabVS.Data/DefinationDataProvider.cs index 298229d..317416e 100644 --- a/Server/ShaderlabVS.Data/DefinationDataProvider.cs +++ b/Server/ShaderlabVS.Data/DefinationDataProvider.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using System.Reflection; namespace ShaderlabVS.Data { diff --git a/Server/ShaderlabVS.Data/DefinationReader.cs b/Server/ShaderlabVS.Data/DefinationReader.cs index c25edaa..0ce5230 100644 --- a/Server/ShaderlabVS.Data/DefinationReader.cs +++ b/Server/ShaderlabVS.Data/DefinationReader.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.IO; -using System.Text; +using System.Text; using System.Text.RegularExpressions; namespace ShaderlabVS.Data diff --git a/Server/ShaderlabVS.Data/Models.cs b/Server/ShaderlabVS.Data/Models.cs index 0672996..7c9e9d8 100644 --- a/Server/ShaderlabVS.Data/Models.cs +++ b/Server/ShaderlabVS.Data/Models.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ShaderlabVS.Data +namespace ShaderlabVS.Data { #region Common public class ModelBase diff --git a/Server/ShaderlabVS.Data/ShaderlabDataManager.cs b/Server/ShaderlabVS.Data/ShaderlabDataManager.cs index f2955e9..fdffee2 100644 --- a/Server/ShaderlabVS.Data/ShaderlabDataManager.cs +++ b/Server/ShaderlabVS.Data/ShaderlabDataManager.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; +using System.Reflection; namespace ShaderlabVS.Data { @@ -12,15 +8,15 @@ namespace ShaderlabVS.Data public class ShaderlabDataManager { #region Constants - public const string HLSL_CG_DATATYPE_DEFINATIONFILE = "Data\\HLSL_CG_datatype.def"; - public const string HLSL_CG_FUNCTION_DEFINATIONFILE = "Data\\HLSL_CG_functions.def"; - public const string HLSL_CG_KEYWORD_DEFINATIONFILE = "Data\\HLSL_CG_Keywords.def"; - - public const string UNITY3D_DATATYPE_DEFINATIONFILE = "Data\\Unity3D_datatype.def"; - public const string UNITY3D_FUNCTION_DEFINATIONFILE = "Data\\Unity3D_functions.def"; - public const string UNITY3D_KEYWORD_DEFINATIONFILE = "Data\\Unity3D_keywords.def"; - public const string UNITY3D_MACROS_DEFINATIONFILE = "Data\\Unity3D_macros.def"; - public const string UNITY3D_VALUES_DEFINATIONFILE = "Data\\Unity3D_values.def"; + public static string HLSL_CG_DATATYPE_DEFINATIONFILE = Path.Combine("Data", "HLSL_CG_datatype.def"); + public static string HLSL_CG_FUNCTION_DEFINATIONFILE = Path.Combine("Data", "HLSL_CG_functions.def"); + public static string HLSL_CG_KEYWORD_DEFINATIONFILE = Path.Combine("Data", "HLSL_CG_Keywords.def"); + + public static string UNITY3D_DATATYPE_DEFINATIONFILE = Path.Combine("Data", "Unity3D_datatype.def"); + public static string UNITY3D_FUNCTION_DEFINATIONFILE = Path.Combine("Data", "Unity3D_functions.def"); + public static string UNITY3D_KEYWORD_DEFINATIONFILE = Path.Combine("Data", "Unity3D_keywords.def"); + public static string UNITY3D_MACROS_DEFINATIONFILE = Path.Combine("Data", "Unity3D_macros.def"); + public static string UNITY3D_VALUES_DEFINATIONFILE = Path.Combine("Data", "Unity3D_values.def"); #endregion #region Properties @@ -69,7 +65,7 @@ public static ShaderlabDataManager Instance private ShaderlabDataManager() { - string currentAssemblyDir = (new FileInfo(Assembly.GetExecutingAssembly().CodeBase.Substring(8))).DirectoryName; + string currentAssemblyDir = (new FileInfo(Assembly.GetExecutingAssembly().Location)).DirectoryName; HLSLCGFunctions = DefinationDataProvider.ProvideFromFile(Path.Combine(currentAssemblyDir, ShaderlabDataManager.HLSL_CG_FUNCTION_DEFINATIONFILE)); List hlslcgKeywords = DefinationDataProvider.ProvideFromFile(Path.Combine(currentAssemblyDir, ShaderlabDataManager.HLSL_CG_KEYWORD_DEFINATIONFILE)); diff --git a/Server/ShaderlabVS/Utilities.cs b/Server/ShaderlabVS/Utilities.cs index 734d787..8edf39a 100644 --- a/Server/ShaderlabVS/Utilities.cs +++ b/Server/ShaderlabVS/Utilities.cs @@ -1,6 +1,4 @@ -using System; - -namespace ShaderlabVS +namespace ShaderlabVS { internal class Utilities { diff --git a/Server/shader-ls.csproj b/Server/shader-ls.csproj index 0a3d2fc..f28930a 100644 --- a/Server/shader-ls.csproj +++ b/Server/shader-ls.csproj @@ -19,7 +19,7 @@ https://github.com/jcs090218/shader-language-server git language-server;shader;unity - 0.0.1 + 0.1.3 diff --git a/etc/logo.png b/etc/logo.png index b0f9a9a..1571491 100644 Binary files a/etc/logo.png and b/etc/logo.png differ