Add linting
This commit is contained in:
parent
b917b99a2c
commit
e1cc716606
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
// Clear the output for the new run
|
||||
window.ScriptOutputWebView.SetOutputPanelContent(body);
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
window.ScriptCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
string script = window.ScriptText;
|
||||
|
||||
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)
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue