Skip to content

Commit 9561d3d

Browse files
committed
Add getDocumentState to language server
1 parent 641dc95 commit 9561d3d

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

YarnSpinner.LanguageServer/src/Server/Commands/Commands.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,6 @@ public static class Commands
7373
/// The command to get all projects in the current workspace.
7474
/// </summary>
7575
public const string ListProjects = "yarnspinner.listProjects";
76+
77+
public const string GetDocumentState = "yarnspinner.getDocumentState";
7678
}

YarnSpinner.LanguageServer/src/Server/Workspace/CompilerOutput.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Converters;
3+
using OmniSharp.Extensions.LanguageServer.Protocol;
24
using System.Collections.Generic;
35

46
namespace YarnLanguageServer;
@@ -32,3 +34,37 @@ public record CompilerOutput
3234
[JsonProperty("errors")]
3335
public string[]? Errors { get; set; }
3436
}
37+
38+
39+
public record DocumentStateOutput
40+
{
41+
[JsonProperty("uri")]
42+
public string? Uri { get; set; }
43+
[JsonProperty("nodes")]
44+
public List<NodeInfo>? Nodes { get; set; } = new();
45+
46+
[JsonConverter(typeof(StringEnumConverter))]
47+
public enum DocumentState
48+
{
49+
Unknown,
50+
NotFound,
51+
InvalidUri,
52+
ContainsErrors,
53+
Valid,
54+
};
55+
56+
[JsonProperty("state")]
57+
public DocumentState State { get; set; } = DocumentState.Unknown;
58+
59+
private DocumentStateOutput()
60+
{
61+
}
62+
63+
public static readonly DocumentStateOutput InvalidUri = new() { State = DocumentState.InvalidUri };
64+
65+
public DocumentStateOutput(DocumentUri uri)
66+
{
67+
this.Uri = uri.ToString();
68+
}
69+
70+
}

YarnSpinner.LanguageServer/src/Server/YarnLanguageServer.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Google.Protobuf;
22
using Microsoft.Extensions.DependencyInjection;
33
using Newtonsoft.Json.Linq;
4+
using OmniSharp.Extensions.LanguageServer.Protocol;
45
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
56
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
67
using OmniSharp.Extensions.LanguageServer.Protocol.Window;
@@ -166,6 +167,14 @@ public static LanguageServerOptions ConfigureOptions(LanguageServerOptions optio
166167
}
167168
);
168169

170+
// Register 'get document state' command
171+
options.OnExecuteCommand<DocumentStateOutput>(
172+
(commandParams) => GetDocumentStateAsync(workspace, commandParams), (_, _) => new ExecuteCommandRegistrationOptions
173+
{
174+
Commands = new[] { Commands.GetDocumentState }
175+
}
176+
);
177+
169178
return options;
170179
}
171180

@@ -213,6 +222,55 @@ private static Task<Container<ProjectInfo>> ListProjectsAsync(Workspace workspac
213222
return Task.FromResult(Container.From(info));
214223
}
215224

225+
private static Task<DocumentStateOutput> GetDocumentStateAsync(Workspace workspace, ExecuteCommandParams<DocumentStateOutput> commandParams)
226+
{
227+
if (commandParams.Arguments?.Count < 1)
228+
{
229+
throw new ArgumentException("Expected at least one argument passed to " + Commands.GetDocumentState);
230+
}
231+
if (commandParams.Arguments![0].Type != JTokenType.String)
232+
{
233+
throw new ArgumentException("Expected parameter 0 of " + Commands.GetDocumentState + " to be a string");
234+
}
235+
236+
237+
DocumentUri uri;
238+
try
239+
{
240+
uri = DocumentUri.Parse((string)commandParams.Arguments[0], strict: true);
241+
}
242+
catch
243+
{
244+
return Task.FromResult(DocumentStateOutput.InvalidUri);
245+
}
246+
247+
var projects = workspace.GetProjectsForUri(uri);
248+
249+
if (!projects.Any())
250+
{
251+
return Task.FromResult(new DocumentStateOutput(uri)
252+
{
253+
State = DocumentStateOutput.DocumentState.NotFound
254+
});
255+
}
256+
257+
var nodes = projects
258+
.SelectMany(project => project.Nodes.Where(n => n.File != null && uri == n.File.Uri))
259+
.NonNull()
260+
.DistinctBy(n => n.UniqueTitle)
261+
;
262+
263+
// The document contains errors if any of its projects have an error
264+
// diagnostic attributable to this file
265+
var containsErrors = projects.SelectMany(p => p.Diagnostics.Where(d => d.FileName == uri.ToString())).Any(d => d.Severity == Yarn.Compiler.Diagnostic.DiagnosticSeverity.Error);
266+
267+
return Task.FromResult(new DocumentStateOutput(uri)
268+
{
269+
Nodes = nodes.ToList(),
270+
State = containsErrors ? DocumentStateOutput.DocumentState.ContainsErrors : DocumentStateOutput.DocumentState.Valid
271+
});
272+
}
273+
216274
private static Task<TextDocumentEdit> AddNodeToDocumentAsync(Workspace workspace, ExecuteCommandParams<TextDocumentEdit> commandParams)
217275
{
218276
if (commandParams.Arguments == null)

0 commit comments

Comments
 (0)