XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension

【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEExtension

现在,配置文件生成的注释会自动显示getset方法中的内容

ce25a10
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

5 个文件 +182 -74
Modified XFEExtension.NetCore.Analyzer.Test/SystemProfile.cs +10 -7
@@ -4,15 +4,18 @@ namespace XFEExtension.NetCore.Analyzer.Test;
4 4
5 5 public static partial class SystemProfile
6 6 {
7 #region Name
8 /// <summary>
9 /// 名称
10 /// </summary>
7 11 [ProfileProperty]
8 [ProfilePropertyAddGet(@"Console.WriteLine(""123"")")]
9 [ProfilePropertyAddSet(@"Console.WriteLine(value)")]
10 [ProfilePropertyAddGet(@"Console.WriteLine(""456"")")]
11 [ProfilePropertyAddSet(@"Console.WriteLine()")]
12 [ProfilePropertyAddGet("Console.WriteLine()")]
13 [ProfilePropertyAddGet("Console.WriteLine()")]
14 [ProfilePropertyAddGet($@"return name")]
15 [ProfilePropertyAddSet("Console.WriteLine(value)")]
16 [ProfilePropertyAddSet("name = value")]
12 17 private static string name = string.Empty;
18 #endregion
13 19 [ProfileProperty]
14 [ProfilePropertyAddSet(@"_age = 1")]
15 [ProfilePropertyAddSet(@"_age = 2")]
16 [ProfilePropertyAddSet(@"_age = value")]
17 20 private static int _age;
18 21 }
Modified XFEExtension.NetCore.Analyzer.Test/TestClass.cs +2 -4
@@ -4,9 +4,7 @@ internal class TestClass
4 4 {
5 5 static void Main(string[] args)
6 6 {
7 var task = new Task(() =>
8 {
9 Console.WriteLine("Hello World");
10 });
7 Console.WriteLine(SystemProfile.Name);
8 Console.WriteLine(SystemProfile.Age);
11 9 }
12 10 }
Modified XFEExtension.NetCore.Analyzer/CodeFix/ProfileExtensionCodeFixProvider.cs +0 -54
@@ -44,60 +44,6 @@ namespace XFEExtension.NetCore.Analyzer.CodeFix
44 44 }
45 45 return Task.CompletedTask;
46 46 }
47 [DllImport("user32.dll")]
48 [return: MarshalAs(UnmanagedType.Bool)]
49 public static extern bool OpenClipboard(IntPtr hWndNewOwner);
50
51 [DllImport("user32.dll")]
52 [return: MarshalAs(UnmanagedType.Bool)]
53 public static extern bool EmptyClipboard();
54
55 [DllImport("user32.dll")]
56 public static extern IntPtr SetClipboardData(uint uFormat, IntPtr data);
57
58 [DllImport("user32.dll")]
59 [return: MarshalAs(UnmanagedType.Bool)]
60 public static extern bool CloseClipboard();
61
62 [DllImport("kernel32.dll", SetLastError = true)]
63 public static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
64
65 [DllImport("kernel32.dll", SetLastError = true)]
66 public static extern IntPtr GlobalLock(IntPtr hMem);
67
68 [DllImport("kernel32.dll", SetLastError = true)]
69 [return: MarshalAs(UnmanagedType.Bool)]
70 public static extern bool GlobalUnlock(IntPtr hMem);
71 public static bool SetClipboardText(string text)
72 {
73 // 打开剪切板
74 if (!OpenClipboard(IntPtr.Zero))
75 return false;
76
77 // 清空剪切板
78 EmptyClipboard();
79
80 // 分配内存
81 IntPtr hGlobal = GlobalAlloc(0x2000, (UIntPtr)((text.Length + 1) * 2)); // 0x2000 是GMEM_MOVEABLE
82
83 // 锁定内存
84 IntPtr pGlobal = GlobalLock(hGlobal);
85
86 // 将文本复制到内存
87 byte[] bytes = Encoding.Unicode.GetBytes(text);
88 Marshal.Copy(bytes, 0, pGlobal, bytes.Length);
89
90 // 解锁内存
91 GlobalUnlock(hGlobal);
92
93 // 将内存设置到剪切板
94 SetClipboardData(13, hGlobal);
95
96 // 关闭剪切板
97 CloseClipboard();
98
99 return true;
100 }
101 47 private async Task<Document> AddReturnFuncAsync(Document document, TextSpan sourceSpan, System.Threading.CancellationToken c)
102 48 {
103 49 var root = await document.GetSyntaxRootAsync(c);
Modified XFEExtension.NetCore.Analyzer/Diagnostics/ProfileExtensionDiagnostics.cs +30 -3
@@ -3,10 +3,11 @@ using Microsoft.CodeAnalysis.CSharp;
3 3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 4 using Microsoft.CodeAnalysis.Diagnostics;
5 5 using System.Collections.Immutable;
6 using System.Diagnostics;
7 6 using System.Linq;
8 7 using System.Text.RegularExpressions;
8 using XFEExtension.NetCore.Analyzer.CodeFix;
9 9 using XFEExtension.NetCore.Analyzer.Generator;
10 using static System.Net.Mime.MediaTypeNames;
10 11
11 12 namespace XFEExtension.NetCore.Analyzer.Diagnostics
12 13 {
@@ -61,7 +62,20 @@ namespace XFEExtension.NetCore.Analyzer.Diagnostics
61 62 continue;
62 63 }
63 64 var argument = attributeSyntax.ArgumentList.Arguments.First();
64 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText.Contains("return"))
65 var funcText = string.Empty;
66 if (argument.Expression is LiteralExpressionSyntax)
67 {
68 funcText = argument.Expression.GetText().ToString();
69 }
70 else if (argument.Expression is InterpolatedStringExpressionSyntax)
71 {
72 funcText = argument.Expression.GetText().ToString();
73 }
74 else if (argument.Expression is InvocationExpressionSyntax)
75 {
76 funcText = argument.Expression.GetText().ToString();
77 }
78 if (funcText.Contains("return"))
65 79 {
66 80 getAttributeHasResult = true;
67 81 }
@@ -83,7 +97,20 @@ namespace XFEExtension.NetCore.Analyzer.Diagnostics
83 97 continue;
84 98 }
85 99 var argument = attributeSyntax.ArgumentList.Arguments.First();
86 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && Regex.IsMatch(literalExpressionSyntax.Token.ValueText, $@"{fieldDeclaration.Declaration.Variables.First().Identifier.ValueText}\s*=\s*value"))
100 var funcText = string.Empty;
101 if (argument.Expression is LiteralExpressionSyntax)
102 {
103 funcText = argument.Expression.GetText().ToString();
104 }
105 else if (argument.Expression is InterpolatedStringExpressionSyntax)
106 {
107 funcText = argument.Expression.GetText().ToString();
108 }
109 else if (argument.Expression is InvocationExpressionSyntax)
110 {
111 funcText = argument.Expression.GetText().ToString();
112 }
113 if (Regex.IsMatch(funcText, $@"{fieldDeclaration.Declaration.Variables.First().Identifier.ValueText}\s*=\s*value"))
87 114 {
88 115 setAttributeSetResult = true;
89 116 }
Modified XFEExtension.NetCore.Analyzer/Generator/ProfilePropertyAutoGenerator.cs +140 -6
@@ -1,8 +1,12 @@
1 1 using Microsoft.CodeAnalysis;
2 2 using Microsoft.CodeAnalysis.CSharp;
3 3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 using System;
4 5 using System.Collections.Generic;
5 6 using System.Linq;
7 using System.Reflection;
8 using System.Runtime.InteropServices;
9 using System.Text;
6 10
7 11 namespace XFEExtension.NetCore.Analyzer.Generator
8 12 {
@@ -51,7 +55,14 @@ namespace XFEExtension.NetCore.Analyzer.Generator
51 55 }
52 56 });
53 57 var propertyType = fieldDeclarationSyntax.Declaration.Type;
58 #region Trivia头
59 var triviaText = $@"/// <remarks>
60 /// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的属性<br/><br/>
61 /// <code><seealso langword=""get""/>方法已生成以下代码:";
62 #endregion
54 63 var getExpressionStatements = new List<StatementSyntax>();
64 var getIndex = 0;
65 var setIndex = 0;
55 66 if (fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAddGetAttribute))
56 67 {
57 68 GetProfilePropertyAddGetAttributeList(fieldDeclarationSyntax).ForEach(attribute =>
@@ -61,16 +72,43 @@ namespace XFEExtension.NetCore.Analyzer.Generator
61 72 return;
62 73 }
63 74 var argument = attribute.ArgumentList.Arguments.First();
75 var funcText = string.Empty;
64 76 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax)
77 funcText = literalExpressionSyntax.Token.ValueText;
78 if (argument.Expression is InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax)
79 funcText = interpolatedStringExpressionSyntax.Contents.ToString();
80 if (argument.Expression is InvocationExpressionSyntax invocationExpressionSyntax)
81 funcText = invocationExpressionSyntax.GetText().ToString();
82 getExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(funcText)));
83 if (getIndex == 0)
65 84 {
66 getExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(literalExpressionSyntax.Token.ValueText)));
85 #region Get方法首个注释
86 triviaText += $"\t○ {funcText.Replace("\n", "<br/>").Replace("return", "<seealso langword=\"return\"/>").Replace(fieldName, $"<seealso langword=\"{fieldName}\"/>")};<br/>";
87 #endregion
67 88 }
89 else
90 {
91 #region Get剩余方法注释
92 triviaText += $"\n///\t\t\t\t○ {funcText.Replace("\n", "<br/>").Replace("return", "<seealso langword=\"return\"/>").Replace(fieldName, $"<seealso langword=\"{fieldName}\"/>")};<br/>";
93 #endregion
94 }
95 getIndex++;
68 96 });
69 97 }
70 98 else
71 99 {
72 100 getExpressionStatements.Add(SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(fieldName)));
101 #region Get方默认注释
102 triviaText += $@" ○ <seealso langword=""return""/> <seealso langword=""{fieldName}""/>;";
103 #endregion
104 getIndex++;
73 105 }
106 #region Get方法尾及Set方法头注释
107 triviaText += @"
108 /// </code>
109 /// <br/>
110 /// <code><seealso langword=""set""/>方法已生成以下代码:";
111 #endregion
74 112 var setExpressionStatements = new List<StatementSyntax>();
75 113 if (fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAddSetAttribute))
76 114 {
@@ -81,17 +119,58 @@ namespace XFEExtension.NetCore.Analyzer.Generator
81 119 return;
82 120 }
83 121 var argument = attribute.ArgumentList.Arguments.First();
122 var funcText = string.Empty;
84 123 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax)
124 funcText = literalExpressionSyntax.Token.ValueText;
125 else if (argument.Expression is InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax)
126 funcText = interpolatedStringExpressionSyntax.Contents.ToString();
127 else if (argument.Expression is InvocationExpressionSyntax invocationExpressionSyntax)
128 funcText = invocationExpressionSyntax.GetText().ToString();
129 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(funcText)));
130 if (setIndex == 0)
131 {
132 #region Set方法首个注释
133 triviaText += $"\t○ {funcText.Replace("\n", "<br/>").Replace(fieldName, $"<seealso langword=\"{fieldName}\"/>").Replace("value", "<seealso langword=\"value\"/>")};<br/>";
134 #endregion
135 }
136 else
85 137 {
86 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(literalExpressionSyntax.Token.ValueText)));
138 #region Set剩余方法注释
139 triviaText += $"\n///\t\t\t\t○ {funcText.Replace("\n", "<br/>").Replace(fieldName, $"<seealso langword=\"{fieldName}\"/>").Replace("value", "<seealso langword=\"value\"/>")};<br/>";
140 #endregion
87 141 }
142 setIndex++;
88 143 });
89 144 }
90 145 else
91 146 {
92 147 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"{fieldName} = value")));
148 #region Set方法默认注释
149 triviaText += $@" ○ <seealso langword=""{fieldName}""/> = <seealso langword=""value""/>;<br/>";
150 #endregion
151 setIndex++;
93 152 }
94 153 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"global::XFEExtension.NetCore.ProfileExtension.XFEProfile.SaveProfile(typeof({className}))")));
154 if (setIndex == 0)
155 {
156 #region Set方法中的保存方法在第一位情况的注释
157 triviaText += $@" ○ <seealso cref=""global::XFEExtension.NetCore.ProfileExtension.XFEProfile.SaveProfile(ProfileInfo)""/>";
158 #endregion
159 }
160 else
161 {
162 #region Set方法中的保存方法在非第一位情况的注释
163 triviaText += $"\n///\t\t\t\t○ <seealso cref=\"global::XFEExtension.NetCore.ProfileExtension.XFEProfile.SaveProfile(ProfileInfo)\"/>;";
164 #endregion
165 }
166 #region Trivia尾
167 triviaText += @"
168 /// </code>
169 /// </remarks>
170 ";
171 #endregion
172 var leadingTrivia = fieldDeclarationSyntax.DescendantTrivia().ToList();
173 leadingTrivia.AddRange(SyntaxFactory.ParseLeadingTrivia(triviaText));
95 174 var property = SyntaxFactory.PropertyDeclaration(propertyType, propertyName)
96 175 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
97 176 .AddAttributeLists(attributeSyntax)
@@ -103,7 +182,7 @@ namespace XFEExtension.NetCore.Analyzer.Generator
103 182 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
104 183 .WithBody(SyntaxFactory.Block(setExpressionStatements))
105 184 })))
106 .WithLeadingTrivia(fieldDeclarationSyntax.GetLeadingTrivia());
185 .WithLeadingTrivia(leadingTrivia);
107 186 return property.NormalizeWhitespace();
108 187 });
109 188 var profileClassSyntaxTree = GenerateProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, fileScopedNamespaceDeclarationSyntax);
@@ -163,11 +242,11 @@ namespace XFEExtension.NetCore.Analyzer.Generator
163 242 private static SyntaxTree GenerateProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, IEnumerable<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
164 243 {
165 244 var className = classDeclaration.Identifier.ValueText;
166 var summaryText = $@"/// <remarks>
245 var triviaText = $@"/// <remarks>
167 246 /// <code><seealso cref=""{className}""/> 已自动实现以下属性:</code><br/>
168 247 /// <code>
169 248 ";
170 summaryText += string.Join("<br/>\n", propertyDeclarationSyntaxes.Select(propertyDeclarationSyntax => $"/// ○ <seealso cref=\"{propertyDeclarationSyntax.Identifier}\"/>")) + "\n/// </code><br/>\n/// <code>来自<seealso cref=\"global::XFEExtension.NetCore.ProfileExtension.XFEProfile\"/></code>\n/// </remarks>\n";
249 triviaText += string.Join("<br/>\n", propertyDeclarationSyntaxes.Select(propertyDeclarationSyntax => $"/// ○ <seealso cref=\"{propertyDeclarationSyntax.Identifier}\"/>")) + "\n/// </code><br/>\n/// <code>来自<seealso cref=\"global::XFEExtension.NetCore.ProfileExtension.XFEProfile\"/></code>\n/// </remarks>\n";
171 250 var memberDeclarations = new List<MemberDeclarationSyntax>();
172 251 memberDeclarations.AddRange(propertyDeclarationSyntaxes);
173 252 var staticConstructorSyntax = SyntaxFactory.ConstructorDeclaration(className)
@@ -197,7 +276,7 @@ namespace XFEExtension.NetCore.Analyzer.Generator
197 276 var profileClass = SyntaxFactory.ClassDeclaration(className)
198 277 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
199 278 .AddMembers(memberDeclarations.ToArray())
200 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(summaryText))
279 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
201 280 .NormalizeWhitespace();
202 281 MemberDeclarationSyntax memberDeclaration;
203 282 if (fileScopedNamespaceDeclarationSyntax is null)
@@ -220,5 +299,60 @@ namespace XFEExtension.NetCore.Analyzer.Generator
220 299 .NormalizeWhitespace();
221 300 return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
222 301 }
302 // 定义Windows API
303 [DllImport("user32.dll")]
304 [return: MarshalAs(UnmanagedType.Bool)]
305 public static extern bool OpenClipboard(IntPtr hWndNewOwner);
306
307 [DllImport("user32.dll")]
308 [return: MarshalAs(UnmanagedType.Bool)]
309 public static extern bool EmptyClipboard();
310
311 [DllImport("user32.dll")]
312 public static extern IntPtr SetClipboardData(uint uFormat, IntPtr data);
313
314 [DllImport("user32.dll")]
315 [return: MarshalAs(UnmanagedType.Bool)]
316 public static extern bool CloseClipboard();
317
318 [DllImport("kernel32.dll", SetLastError = true)]
319 public static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
320
321 [DllImport("kernel32.dll", SetLastError = true)]
322 public static extern IntPtr GlobalLock(IntPtr hMem);
323
324 [DllImport("kernel32.dll", SetLastError = true)]
325 [return: MarshalAs(UnmanagedType.Bool)]
326 public static extern bool GlobalUnlock(IntPtr hMem);
327 public static bool SetClipboardText(string text)
328 {
329 // 打开剪切板
330 if (!OpenClipboard(IntPtr.Zero))
331 return false;
332
333 // 清空剪切板
334 EmptyClipboard();
335
336 // 分配内存
337 IntPtr hGlobal = GlobalAlloc(0x2000, (UIntPtr)((text.Length + 1) * 2)); // 0x2000 是GMEM_MOVEABLE
338
339 // 锁定内存
340 IntPtr pGlobal = GlobalLock(hGlobal);
341
342 // 将文本复制到内存
343 byte[] bytes = Encoding.Unicode.GetBytes(text);
344 Marshal.Copy(bytes, 0, pGlobal, bytes.Length);
345
346 // 解锁内存
347 GlobalUnlock(hGlobal);
348
349 // 将内存设置到剪切板
350 SetClipboardData(13, hGlobal);
351
352 // 关闭剪切板
353 CloseClipboard();
354
355 return true;
356 }
223 357 }
224 358 }