Skip to content

Commit

Permalink
update HE 重构 支持语法块递归处理 HE 命令
Browse files Browse the repository at this point in the history
  • Loading branch information
NMSAzulX committed Jun 30, 2024
1 parent 6cbd12d commit 696b352
Show file tree
Hide file tree
Showing 18 changed files with 936 additions and 739 deletions.
40 changes: 38 additions & 2 deletions samples/WinFormsSample/HEDebug.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,44 @@
重新扫描文件!

new ApplicationContext(new Form1())

检测到空成员文件 G:\Project\OpenSource\Natasha\samples\WinFormsSample\obj\Debug\net8.0-windows\WinFormsSample.GlobalUsings.g.cs.

检测到空成员文件 G:\Project\OpenSource\Natasha\samples\WinFormsSample\obj\Release\net8.0-windows\WinFormsSample.GlobalUsings.g.cs.
Renamed: G:\Project\OpenSource\Natasha\samples\WinFormsSample\Form1.Designer.cs -> G:\Project\OpenSource\Natasha\samples\WinFormsSample\Form1.Designer.cs~RF14d970e3.TMP

Renamed: G:\Project\OpenSource\Natasha\samples\WinFormsSample\Program.cs -> G:\Project\OpenSource\Natasha\samples\WinFormsSample\Program.cs~RF5efaba5.TMP

准备执行热编译...
获取元数据....

new ApplicationContext(new Form1())

执行主入口前导方法....

A

GC

GC

GC

GC

GC

GC

Na99a54ab23654527abf6159dc1a1ee02 ��

Default ��

N59b7ef6b28574ff38d072b805e886eaf ��

AFGB

3

执行主入口回调方法....

当前将被注销的开放窗体 Form1

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ void ISourceGenerator.Execute(GeneratorExecutionContext context)
{

string coreScript = "HEProxy.SetProjectKind(HEProjectKind.Console);";
string winformAndwpfLoggerScript = @"
string debugFilePath = Path.Combine(VSCSharpProjectInfomation.MainCsprojPath,""HEDebug.txt"");
if(File.Exists(debugFilePath)){ File.Delete(debugFilePath); }
HEFileLogger logger = new HEFileLogger(debugFilePath);
HEProxy.ShowMessage = async msg => {
await logger.WriteUtf8FileAsync(msg + Environment.NewLine);
};";
var syntaxTrees = context.Compilation.SyntaxTrees;
var fileList = syntaxTrees.Select(item => item.FilePath).ToList();
var classNodes = syntaxTrees
Expand All @@ -32,15 +39,12 @@ void ISourceGenerator.Execute(GeneratorExecutionContext context)
{
// 这里可以根据判断结果执行相应的操作
// 例如生成特定的代码或输出信息
coreScript = @"
string debugFilePath = Path.Combine(VSCSharpProjectInfomation.MainCsprojPath,""HEDebug.txt"");
if(File.Exists(debugFilePath)){ File.Delete(debugFilePath); }
HEProxy.ShowMessage = msg => {
HEProxy.WriteUtf8File(debugFilePath, msg + Environment.NewLine);
};
coreScript = $@"
{winformAndwpfLoggerScript}
HEProxy.SetProjectKind(HEProjectKind.Winform);
HEProxy.ExtGlobalUsing.Add(""System.Windows.Controls"");
HEProxy.ExtGlobalUsing.Add(""System.Windows"");
HEProxy.NatashaExtGlobalUsing.Add(""System.Windows.Controls"");
HEProxy.NatashaExtGlobalUsing.Add(""System.Windows"");
DelegateHelper<System.Windows.Forms.FormCollection, System.Windows.Forms.Form>.GetDelegate(""Remove"", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
";
}
else
Expand All @@ -51,14 +55,10 @@ void ISourceGenerator.Execute(GeneratorExecutionContext context)

if (hasWPFWindowClass && fileList.Any(item => item.EndsWith(".xaml.cs")))
{
coreScript = @"
string debugFilePath = Path.Combine(VSCSharpProjectInfomation.MainCsprojPath,""HEDebug.txt"");
if(File.Exists(debugFilePath)){ File.Delete(debugFilePath); }
HEProxy.ShowMessage = msg => {
HEProxy.WriteUtf8File(debugFilePath, msg + Environment.NewLine);
};
coreScript = $@"
{winformAndwpfLoggerScript}
HEProxy.SetProjectKind(HEProjectKind.WPF);
HEProxy.ExtGlobalUsing.Add(""System.Windows.Forms"");
HEProxy.NatashaExtGlobalUsing.Add(""System.Windows.Forms"");
";
}
}
Expand All @@ -85,7 +85,7 @@ internal static void PreMain()
{coreScript}
HEProxy.SetCompileInitAction(()=>{{
NatashaManagement.RegistDomainCreator<NatashaDomainCreator>();
NatashaManagement.Preheating((asmName, @namespace) => !string.IsNullOrWhiteSpace(@namespace) && (@namespace.StartsWith(""Microsoft.VisualBasic"")|| HEProxy.ExtGlobalUsing.Contains(@namespace)),true, true);
NatashaManagement.Preheating((asmName, @namespace) => !string.IsNullOrWhiteSpace(@namespace) && (@namespace.StartsWith(""Microsoft.VisualBasic"")|| HEProxy.NatashaExtGlobalUsing.Contains(@namespace)),true, true);
}});
HEProxy.Run();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Natasha.CSharp.HotExecutor.Component
{
public static class DelegateHelper<T>
{
public static Action<T>? Execute;
public static void GetDelegate(string methodName,BindingFlags flags)
{
var methodInfo = typeof(T).GetMethod(methodName, flags);
Execute = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), methodInfo);
}
}
public static class DelegateHelper<T,R>
{
public static Action<T,R>? Execute;
public static void GetDelegate(string methodName, BindingFlags flags)
{
var methodInfo = typeof(T).GetMethod(methodName, flags);
Execute = (Action<T, R>)Delegate.CreateDelegate(typeof(Action<T, R>), methodInfo);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,9 @@ namespace Natasha.CSharp.Extension.HotExecutor
internal static class HECompiler
{
private static readonly AssemblyCSharpBuilder _builderCache;
private static readonly NatashaUsingCache? _usingCache;
private static readonly HashSet<MetadataReference> _references;
static HECompiler()
{
HEProxy.CompileInitAction();
if (VSCSharpProjectInfomation.EnableImplicitUsings)
{
_usingCache = new();
_usingCache.Using(NatashaLoadContext.DefaultContext.UsingRecorder._usings);
}

_references =[..NatashaLoadContext.DefaultContext.ReferenceRecorder.GetReferences()];
var delReference = NatashaLoadContext.DefaultContext.ReferenceRecorder.GetSingleReference(Assembly.GetEntryAssembly().GetName());
if (delReference != null)
Expand All @@ -42,18 +34,9 @@ static HECompiler()
.WithoutPreCompilationReferences()
.WithoutCombineUsingCode();
}
public static void RemoveUsings(IEnumerable<string> usings)
{
_usingCache!.Remove(usings);
}
public static UsingDirectiveSyntax[] GetDefaultUsingNodes()
{
return _usingCache!.GetUsingNodes().ToArray();
}

public static Assembly ReCompile(IEnumerable<SyntaxTree> trees,bool isRelease)
public static Task<Assembly> ReCompile(IEnumerable<SyntaxTree> trees,bool isRelease)
{

_builderCache.WithRandomAssenblyName();
_builderCache.UseRandomLoadContext();
_builderCache.SyntaxTrees.Clear();
Expand All @@ -67,7 +50,7 @@ public static Assembly ReCompile(IEnumerable<SyntaxTree> trees,bool isRelease)
{
_builderCache.WithDebugPlusCompile(debugger=>debugger.ForAssembly());
}
return _builderCache.GetAssembly();
return Task.FromResult(_builderCache.GetAssembly());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public void GetAndWaitLock()
}
}

public bool IsLocking()
{
return _lockCount == 1;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReleaseLock()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Natasha.CSharp.Extension.HotExecutor;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace Natasha.CSharp.HotExecutor.Component
{
public static class HEFileHelper
{
public async static Task<string> ReadUtf8FileAsync(string file)
{
if (!File.Exists(file))
{
#if DEBUG
HEProxy.ShowMessage($"不存在文件:{file}");
#endif
return string.Empty;
}
StreamReader stream;
do
{
try
{
stream = new(file, Encoding.UTF8);
var content = await stream.ReadToEndAsync();
stream.Dispose();
return content;
}
catch (Exception ex)
{
Debug.WriteLine("命中文件读锁!");
Thread.Sleep(200);
}


} while (true);

}
public async static Task WriteUtf8FileAsync(string file, string msg)
{
do
{
try
{
using StreamWriter stream = new(file, true, Encoding.UTF8);
await stream.WriteLineAsync(msg);
await stream.FlushAsync();
}
catch (Exception)
{
Debug.WriteLine("命中文件写锁!");
Thread.Sleep(200);
}


} while (true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Natasha.CSharp.Extension.HotExecutor;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace Natasha.CSharp.HotExecutor.Component
{
public class HEFileLogger
{
private readonly HESpinLock _fileLock = new();
//private readonly StreamWriter _writer;
private readonly string _file;
public HEFileLogger(string file)
{
var folder = Path.GetDirectoryName(file);
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
_file = file;

}

public async Task WriteUtf8FileAsync(string msg)
{
bool isWritten = false;
_fileLock.GetAndWaitLock();
do
{
try
{
using StreamWriter _writer = new(_file, true, Encoding.UTF8);
if (_writer.BaseStream.CanWrite)
{
await _writer.WriteLineAsync(msg);
isWritten = true;
_fileLock.ReleaseLock();
await _writer.FlushAsync();
}
return;
}
catch (Exception)
{
Debug.WriteLine("命中 HE 日志写锁!");
Thread.Sleep(200);
}

} while (!isWritten);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.Text;

namespace Natasha.CSharp.HotExecutor.Component.SyntaxUtils
{
internal class CS0104Analyser
{
public static string _proxyCommentCS0104Using = "//HE:CS0104".ToLower();
public static HashSet<string> Handle(CompilationUnitSyntax root)
{
HashSet<string> tempSets = [];
HashSet<SyntaxTrivia> triviaSets = [];
foreach (SyntaxNode node in root.DescendantNodesAndSelf())
{
foreach (SyntaxTrivia trivia in node.GetLeadingTrivia())
{
if (triviaSets.Contains(trivia))
{
continue;
}
if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia))
{
var commentText = trivia.ToString().Trim().ToLower();
if (commentText.Length > _proxyCommentCS0104Using.Length)
{
if (commentText.StartsWith(_proxyCommentCS0104Using))
{
triviaSets.Add(trivia);
//#if DEBUG
// Debug.WriteLine($"找到剔除点:{commentText}");
// Debug.WriteLine($"整个节点为:{node.ToFullString()}");
//#endif
var usingStrings = trivia.ToString().Trim().Substring(_proxyCommentCS0104Using.Length, commentText.Length - _proxyCommentCS0104Using.Length);
tempSets.UnionWith(usingStrings.Split([';'], StringSplitOptions.RemoveEmptyEntries).Select(item => item.Trim()));
}
}
}
}
}
return tempSets;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Natasha.CSharp.HotExecutor.Component.SyntaxUtils
{
internal static class ConsoleWriter
{
public static BlockSyntax? Handle(BlockSyntax blockSyntax)
{
if (blockSyntax.Statements.Count > 0)
{
var node = blockSyntax.Statements.Last();
if (node.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExpressionStatement))
{
if (node.ToString() == "Console.ReadKey();")
{
return blockSyntax.RemoveNode(node, SyntaxRemoveOptions.KeepExteriorTrivia);
}
}
}
return null;
}
}
}
Loading

0 comments on commit 696b352

Please sign in to comment.