Upsilon-VsCode/UpsilonLanguageServer/UpsilonLanguageServer/DiagnosticsProvider.cs

91 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using LanguageServer.VsCode.Contracts;
using LanguageServer.VsCode.Server;
using Upsilon;
using Upsilon.Evaluator;
namespace UpsilonLanguageServer
{
public class DiagnosticProvider
{
public DiagnosticProvider()
{
}
public static async Task<IEnumerable<Diagnostic>> LintDocument(TextDocument document, SessionDocument session,
int maxNumberOfProblems)
{
var diag = new List<Diagnostic>();
var content = document.Content;
if (string.IsNullOrWhiteSpace(content))
{
diag.Add(new Diagnostic(DiagnosticSeverity.Hint,
new Range(new Position(0, 0), document.PositionAt(content?.Length ?? 0)),
"DLS", "DLS0001", "Empty document. Try typing something, such as \".net core\"."));
return diag;
}
var task = RealLint(document, maxNumberOfProblems, session, content, diag);
// either wait until the script is linted, or until a second has passed (timeout)
await Task.WhenAny(task, Task.Delay(1000));
return diag;
}
private static async Task RealLint(TextDocument document, int maxNumberOfProblems, SessionDocument session,
string content, List<Diagnostic> diag)
{
try
{
using (var script = new Script(content))
{
session.SourceText = script.ScriptString;
if (script.Diagnostics.Messages.Count > 0)
{
foreach (var error in script.Diagnostics.Messages)
{
diag.Add(ConvertToVsCodeDiagnostic(error));
}
return;
}
var bound = script.Bind();
foreach (var error in script.Diagnostics.Messages)
{
diag.Add(ConvertToVsCodeDiagnostic(error));
}
if (script.Diagnostics.Messages.Count == 0)
{
session.Bound = bound;
}
}
}
catch (Exception e)
{
diag.Add(new Diagnostic(DiagnosticSeverity.Error,
new Range(new Position(0, 0), document.PositionAt(content?.Length ?? 0)),
"DLS", "DLS0001", e.ToString()));
}
}
private static Diagnostic ConvertToVsCodeDiagnostic(DiagnosticsMessage error)
{
var (startPosition, startPositionOnLine) = error.GetStartLine();
var (endPosition, endPositionOnLine) = error.GetEndLine();
var sourceString = error.Diagnostics.ScriptString;
if (endPosition >= sourceString.GetLineCount())
endPosition = sourceString.GetLineCount();
var range = new Range(startPosition, startPositionOnLine, endPosition,
endPositionOnLine);
return new Diagnostic(DiagnosticSeverity.Error, range, error.AtError(), "ERR001", error.Message);
}
}
}