Add linting

This commit is contained in:
Neil Brommer 2023-07-26 11:46:15 -07:00
parent b917b99a2c
commit e1cc716606
5 changed files with 126 additions and 30 deletions

View File

@ -1,4 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Scripting;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
namespace Cauldron.Core;
@ -13,8 +15,7 @@ public class RoslynHost
/// <param name="globals">Values that will be made available to the script</param>
/// <param name="cancellationToken"></param>
public static async Task RunScript(string code, string[] imports,
RoslynHostGlobals globals,
CancellationToken cancellationToken = default)
RoslynHostGlobals globals, CancellationToken cancellationToken = default)
{
ScriptOptions options = ScriptOptions.Default
.AddImports(imports);
@ -22,6 +23,16 @@ public class RoslynHost
await CSharpScript.RunAsync(code, options, globals,
cancellationToken: cancellationToken);
}
public static ImmutableArray<Diagnostic> BuildScript(string code, string[] imports,
RoslynHostGlobals globals)
{
ScriptOptions options = ScriptOptions.Default
.AddImports(imports);
Script<object> script = CSharpScript.Create(code, options, globals.GetType());
return script.GetCompilation().GetDiagnostics();
}
}
public class RoslynHostGlobals

View File

@ -413,7 +413,7 @@
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-23" y="-243"/>
<point key="canvasLocation" x="-23" y="-256"/>
</scene>
<!--Window Controller-->
<scene sceneID="ktg-sd-7li">
@ -421,11 +421,11 @@
<windowController id="JKR-xj-8kh" customClass="MainWindow" sceneMemberID="viewController">
<window key="window" title="Cauldron" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="" animationBehavior="default" tabbingMode="preferred" id="d7K-Gm-g9N">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
<rect key="contentRect" x="211" y="264" width="620" height="406"/>
<rect key="contentRect" x="211" y="264" width="749" height="445"/>
<rect key="screenRect" x="0.0" y="0.0" width="1512" height="944"/>
<value key="minSize" type="size" width="480" height="270"/>
<view key="contentView" id="3If-Oy-0LB">
<rect key="frame" x="0.0" y="0.0" width="620" height="406"/>
<rect key="frame" x="0.0" y="0.0" width="749" height="445"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<toolbar key="toolbar" implicitIdentifier="09D11707-F4A3-4FD5-970E-AC5832E91C2B" showsBaselineSeparator="NO" displayMode="iconOnly" sizeMode="regular" id="c7l-9K-zGH">
@ -463,7 +463,7 @@
</windowController>
<customObject id="Dyo-ea-3jV" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-24" y="70"/>
<point key="canvasLocation" x="-23" y="73"/>
</scene>
<!--Split View Controller-->
<scene sceneID="BCF-ui-EPb">

View File

@ -1,8 +1,13 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Timers;
using AppKit;
using Cauldron.Macos.SourceWriter;
using Cauldron.Macos.SourceWriter.LanguageFormats;
using Foundation;
using Microsoft.CodeAnalysis;
namespace Cauldron.Macos;
@ -61,6 +66,7 @@ public partial class MainWindow : NSWindowController
this.RunScriptToolbarButton.Activated += RunScript;
SourceTextView scriptTextBox = this.ScriptEditorTextBox;
scriptTextBox.OnFinishedTyping += this.BuildScript;
scriptTextBox.Font = NSFont.MonospacedSystemFont(new nfloat(14), NSFontWeight.Regular);
scriptTextBox.AutomaticQuoteSubstitutionEnabled = false;
scriptTextBox.AutomaticDashSubstitutionEnabled = false;
@ -74,6 +80,11 @@ public partial class MainWindow : NSWindowController
scriptTextBox.Formatter.Reformat();
}
public void BuildScript(object sender, ElapsedEventArgs args)
{
ScriptRunner.BuildScript(this);
}
public void RunScript(object sender, EventArgs e)
{
ScriptRunner.RunScript(this);
@ -94,6 +105,46 @@ public partial class MainWindow : NSWindowController
this.CreateNewTab();
}
public void UpdateScriptDiagnostics(ImmutableArray<Diagnostic> diagnostics)
{
Console.WriteLine(diagnostics.Select(d => $"{d.Severity}: {d.GetMessage()}").Join("\n"));
foreach (Diagnostic diagnostic in diagnostics)
{
int start = diagnostic.Location.SourceSpan.Start;
int end = diagnostic.Location.SourceSpan.End;
if (start == end && end < this.ScriptText.Length)
end += 1;
else if (start == end)
start -= 1;
NSRange range = new(start,end);
this.ScriptEditorTextBox.LayoutManager
.AddTemporaryAttribute(NSStringAttributeKey.UnderlineStyle,
new NSNumber((int)(NSUnderlineStyle.Thick | NSUnderlineStyle.PatternDot)),
range);
this.ScriptEditorTextBox.LayoutManager
.AddTemporaryAttribute(NSStringAttributeKey.ToolTip,
new NSString($"{diagnostic.Id} {diagnostic.GetMessage()}"),
range);
if (diagnostic.Severity == DiagnosticSeverity.Error)
this.ScriptEditorTextBox.LayoutManager
.AddTemporaryAttribute(NSStringAttributeKey.UnderlineColor, NSColor.SystemRed,
range);
else if (diagnostic.Severity == DiagnosticSeverity.Warning)
this.ScriptEditorTextBox.LayoutManager
.AddTemporaryAttribute(NSStringAttributeKey.UnderlineColor, NSColor.SystemGreen,
range);
else if (diagnostic.Severity == DiagnosticSeverity.Info)
this.ScriptEditorTextBox.LayoutManager
.AddTemporaryAttribute(NSStringAttributeKey.UnderlineColor, NSColor.SystemBlue,
range);
}
}
public void SetScriptRunState(bool scriptIsRunning)
{
if (scriptIsRunning)

View File

@ -7,40 +7,39 @@ using Cauldron.Core;
using System.Reflection;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.IO;
namespace Cauldron.Macos;
public static class ScriptRunner
{
public static void BuildScript(MainWindow window)
{
string script = "";
window.BeginInvokeOnMainThread(() => script = window.ScriptText);
TagBuilder body = new("body");
RoslynHostGlobals globals = new(null);
window.BeginInvokeOnMainThread(() => globals = new RoslynHostGlobals(CreateCauldronWriter(window, body)));
Task task = Task
.Run(() => RoslynHost.BuildScript(script, Array.Empty<string>(), globals))
.ContinueWith(t => window.BeginInvokeOnMainThread(
() => window.UpdateScriptDiagnostics(t.Result)));
}
public static void RunScript(MainWindow window)
{
window.SetScriptRunState(true);
TagBuilder body = new("body");
window.ScriptOutputWebView.SetOutputPanelContent(body);
string script = window.ScriptText;
window.ScriptCancellationTokenSource = new CancellationTokenSource();
TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();
CauldronWriter writer = new(obj =>
{
window.BeginInvokeOnMainThread(() =>
{
TagBuilder outputSection = new("section");
outputSection.AddCssClass("output-section");
outputSection.InnerHtml.AppendHtml(GenerateValueOutput(obj));
body.InnerHtml.AppendHtml(outputSection);
window.ScriptOutputWebView.SetOutputPanelContent(body);
});
return Task.CompletedTask;
});
window.ScriptCancellationTokenSource = new CancellationTokenSource();
string script = window.ScriptText;
// Clear the output for the new run
window.ScriptOutputWebView.SetOutputPanelContent(body);
Task task = Task
.Run(async () =>
@ -48,7 +47,7 @@ public static class ScriptRunner
try
{
await RoslynHost.RunScript(script, Array.Empty<string>(),
new RoslynHostGlobals(writer),
new RoslynHostGlobals(CreateCauldronWriter(window, body)),
window.ScriptCancellationTokenSource.Token);
}
catch (Exception ex)
@ -66,6 +65,24 @@ public static class ScriptRunner
.ContinueWith((t) => window.SetScriptRunState(false), uiThread);
}
private static CauldronWriter CreateCauldronWriter(MainWindow window, TagBuilder body)
{
return new CauldronWriter (obj =>
{
window.BeginInvokeOnMainThread(() =>
{
TagBuilder outputSection = new("section");
outputSection.AddCssClass("output-section");
outputSection.InnerHtml.AppendHtml(GenerateValueOutput(obj));
body.InnerHtml.AppendHtml(outputSection);
window.ScriptOutputWebView.SetOutputPanelContent(body);
});
return Task.CompletedTask;
});
}
private static TagBuilder GenerateValueOutput(object value)
{
if (value is null)

View File

@ -1,4 +1,5 @@
using System;
using System.Timers;
using AppKit;
using CoreGraphics;
using Foundation;
@ -435,6 +436,17 @@ public class SourceTextView : NSTextView
#region Override Methods
private Timer InputTimoutTimer { get; set; }
/// <summary>
/// The amount of time with no user input after which <see cref="OnFinishedTyping"/> will be run
/// </summary>
public TimeSpan InputTimeoutInterval { get; set; } = new TimeSpan(0, 0, 1);
/// <summary>
/// An event triggered when the user has stopped typing for a period of time defined by
/// <see cref="InputTimeoutInterval"/>
/// </summary>
public event ElapsedEventHandler OnFinishedTyping;
/// <summary>
/// Look for special keys being pressed and does specific processing based on the key.
/// </summary>
@ -570,7 +582,12 @@ public class SourceTextView : NSTextView
this.Formatter.Reformat();
//Console.WriteLine ("Key: {0}", (int)theEvent.Characters[0]);
this.InputTimoutTimer?.Stop();
this.InputTimoutTimer?.Close();
this.InputTimoutTimer = new Timer(this.InputTimeoutInterval);
this.InputTimoutTimer.AutoReset = false;
this.InputTimoutTimer.Elapsed += this.OnFinishedTyping;
this.InputTimoutTimer.Start();
}
/// <summary>