From 72e5b23e5216b5f4f602a1e7f9937b5fa2352ba2 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Fri, 3 Jan 2025 20:19:53 +1100 Subject: [PATCH 1/2] Address some warnings --- YarnSpinner/CRC32.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/YarnSpinner/CRC32.cs b/YarnSpinner/CRC32.cs index 468f2ade6..7305c6c70 100644 --- a/YarnSpinner/CRC32.cs +++ b/YarnSpinner/CRC32.cs @@ -8,12 +8,11 @@ namespace Yarn.Utility /// public static class CRC32 { - private static readonly uint[] LookupTable; + private static readonly uint[] LookupTable = new uint[256]; static CRC32() { uint seedPolynomial = 0xedb88320; - LookupTable = new uint[256]; uint temp; for (uint i = 0; i < LookupTable.Length; ++i) { @@ -43,6 +42,11 @@ static CRC32() /// name="bytes"/>. public static uint GetChecksum(byte[] bytes) { + if (bytes == null) + { + throw new System.ArgumentNullException(nameof(bytes)); + } + uint crc = 0xffffffff; for (int i = 0; i < bytes.Length; ++i) { From 7e57129ebb3a719c0e9038707b41ef43ab1e5098 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Fri, 24 Jan 2025 14:31:47 +1100 Subject: [PATCH 2/2] Show node group complexity in code lenses --- CHANGELOG.md | 1 + YarnSpinner.Compiler/Compiler.cs | 24 +++++++++++++++++++ .../src/Server/Handlers/CodeLensHandler.cs | 24 +++++++++++++++---- .../src/Server/Visitors/ReferencesVisitor.cs | 2 ++ .../src/Server/Workspace/NodeInfo.cs | 20 +++++++++++----- .../src/Server/Workspace/Project.cs | 4 ++-- .../src/Server/Workspace/Workspace.cs | 2 +- 7 files changed, 64 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 305d6da26..de6c5942b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - For example, the following code will emit a warning, because the last `>` character is likely a typo: `<>>` - Added a new method, `Dialogue.GetHeaders`, which returns the collection of headers present on a node. - Added a new method, `Dialogue.GetHeaderValue`, which returns the value of the specified header on a node. +- Language Server: Nodes that are part of a node group now show their condition complexity as a code lens. ### Changed diff --git a/YarnSpinner.Compiler/Compiler.cs b/YarnSpinner.Compiler/Compiler.cs index 162999479..db5bdc364 100644 --- a/YarnSpinner.Compiler/Compiler.cs +++ b/YarnSpinner.Compiler/Compiler.cs @@ -1366,6 +1366,30 @@ internal int ConditionCount } } + public partial class NodeContext + { + /// + /// Gets the computed total complexity of this node's 'when' + /// conditions. + /// + /// + /// If this node has no such conditions, this value is -1. + /// + public int ComplexityScore + { + get + { + var headers = this.GetWhenHeaders(); + if (headers == null || !headers.Any()) + { + return -1; + } + + return headers.Sum(h => h.ComplexityScore); + } + } + } + /// public partial class When_headerContext { diff --git a/YarnSpinner.LanguageServer/src/Server/Handlers/CodeLensHandler.cs b/YarnSpinner.LanguageServer/src/Server/Handlers/CodeLensHandler.cs index 35a5aa599..7180d7238 100644 --- a/YarnSpinner.LanguageServer/src/Server/Handlers/CodeLensHandler.cs +++ b/YarnSpinner.LanguageServer/src/Server/Handlers/CodeLensHandler.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; @@ -30,8 +31,9 @@ public Task Handle(CodeLensParams request, CancellationToken return Task.FromResult(new CodeLensContainer()); } - var results = yarnFile.NodeDefinitions.SelectMany(titleToken => + var results = yarnFile.NodeInfos.SelectMany(nodeInfo => { + var titleToken = nodeInfo.TitleToken; if (titleToken.StartIndex == -1) { // This is an error token - the node doesn't actually @@ -52,8 +54,7 @@ public Task Handle(CodeLensParams request, CancellationToken ContractResolver = new CamelCasePropertyNamesContractResolver(), }; - return new CodeLens[] - { + List lenses = new() { new CodeLens { Range = PositionHelper.GetRange(yarnFile.LineStarts, titleToken), Command = new Command @@ -81,6 +82,21 @@ public Task Handle(CodeLensParams request, CancellationToken }, }, }; + + if (nodeInfo.NodeGroupComplexity >= 0) + { + lenses.Add(new CodeLens + { + Range = PositionHelper.GetRange(yarnFile.LineStarts, titleToken), + Command = new Command + { + Name = string.Empty, + Title = $"Complexity: {nodeInfo.NodeGroupComplexity}", + }, + }); + } + + return lenses; }); CodeLensContainer result = new CodeLensContainer(results); diff --git a/YarnSpinner.LanguageServer/src/Server/Visitors/ReferencesVisitor.cs b/YarnSpinner.LanguageServer/src/Server/Visitors/ReferencesVisitor.cs index a2ff47539..b57d4154e 100644 --- a/YarnSpinner.LanguageServer/src/Server/Visitors/ReferencesVisitor.cs +++ b/YarnSpinner.LanguageServer/src/Server/Visitors/ReferencesVisitor.cs @@ -54,6 +54,8 @@ public override bool VisitNode([NotNull] YarnSpinnerParser.NodeContext context) // antlr lines start at 1, but LSP lines start at 0 HeaderStartLine = context.Start.Line - 1, + + NodeGroupComplexity = context.ComplexityScore, }; // Get the first few lines of the node's body as a preview diff --git a/YarnSpinner.LanguageServer/src/Server/Workspace/NodeInfo.cs b/YarnSpinner.LanguageServer/src/Server/Workspace/NodeInfo.cs index fdebfe6eb..9bfb176f8 100644 --- a/YarnSpinner.LanguageServer/src/Server/Workspace/NodeInfo.cs +++ b/YarnSpinner.LanguageServer/src/Server/Workspace/NodeInfo.cs @@ -37,10 +37,10 @@ public record NodeInfo public int HeaderStartLine { get; set; } = 0; [JsonProperty("headers")] - public List Headers { get; init; } = new (); + public List Headers { get; init; } = new(); [JsonProperty("jumps")] - public List Jumps { get; init; } = new (); + public List Jumps { get; init; } = new(); /// /// Gets or sets the text that can be shown as a short preview of the @@ -53,10 +53,18 @@ public record NodeInfo internal IToken TitleToken { get; set; } - internal List FunctionCalls { get; init; } = new (); - internal List CommandCalls { get; init; } = new (); - internal List VariableReferences { get; init; } = new (); - internal List<(string Name, int LineIndex)> CharacterNames { get; init; } = new (); + internal List FunctionCalls { get; init; } = new(); + internal List CommandCalls { get; init; } = new(); + internal List VariableReferences { get; init; } = new(); + internal List<(string Name, int LineIndex)> CharacterNames { get; init; } = new(); + + /// + /// Gets the computed complexity for this node. + /// + /// + /// If this node is not part of a node group, this value is -1. + /// + public int NodeGroupComplexity { get; internal set; } = -1; /// /// Gets a value indicating whether this has a valid diff --git a/YarnSpinner.LanguageServer/src/Server/Workspace/Project.cs b/YarnSpinner.LanguageServer/src/Server/Workspace/Project.cs index d553dd2e0..f582d5696 100644 --- a/YarnSpinner.LanguageServer/src/Server/Workspace/Project.cs +++ b/YarnSpinner.LanguageServer/src/Server/Workspace/Project.cs @@ -54,7 +54,7 @@ internal IEnumerable Diagnostics private JsonConfigFile? DefinitionsFile { get; set; } - public event System.Action? OnProjectCompiled; + public event System.Action? OnProjectCompiled; private readonly Yarn.Compiler.Project yarnProject; @@ -259,7 +259,7 @@ public Yarn.Compiler.CompilationResult CompileProject(bool notifyOnComplete, Yar if (notifyOnComplete) { - OnProjectCompiled?.Invoke(); + OnProjectCompiled?.Invoke(compilationResult); } return compilationResult; diff --git a/YarnSpinner.LanguageServer/src/Server/Workspace/Workspace.cs b/YarnSpinner.LanguageServer/src/Server/Workspace/Workspace.cs index 0af74f91d..fd9355660 100644 --- a/YarnSpinner.LanguageServer/src/Server/Workspace/Workspace.cs +++ b/YarnSpinner.LanguageServer/src/Server/Workspace/Workspace.cs @@ -179,7 +179,7 @@ internal void ReloadWorkspace() project.NotificationSender = this; // When a project reloads, publish diagnostics. - project.OnProjectCompiled += () => + project.OnProjectCompiled += (compilationResult) => { PublishDiagnostics(); PublishNodeInfos();