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

XFEExtension

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

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

XFEstudio/XFEExtension

为配置文件属性添加代码分析器及快速操作的实现 修改版号为1.7.6

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

代码差异

8 个文件 +202 -48
Modified XFE各类拓展.NetCore.Analyzer.Test/SystemProfile.cs +7 -1
@@ -2,11 +2,17 @@
2 2
3 3 namespace XFE各类拓展.NetCore.Analyzer.Test;
4 4
5 [AutoLoadProfile(false)]
6 5 public static partial class SystemProfile
7 6 {
8 7 [ProfileProperty]
8 [ProfilePropertyAddGet(@"Console.WriteLine(""123"")")]
9 [ProfilePropertyAddSet(@"Console.WriteLine(value)")]
10 [ProfilePropertyAddGet(@"Console.WriteLine(""456"")")]
11 [ProfilePropertyAddSet(@"Console.WriteLine()")]
9 12 private static string name = string.Empty;
10 13 [ProfileProperty]
14 [ProfilePropertyAddSet(@"_age = 1")]
15 [ProfilePropertyAddSet(@"_age = 2")]
16 [ProfilePropertyAddSet(@"_age = value")]
11 17 private static int _age;
12 18 }
Modified XFE各类拓展.NetCore.Analyzer/AnalyzerReleases.Shipped.md +2 -2
@@ -4,5 +4,5 @@
4 4
5 5 Rule ID | Category | Severity | Notes
6 6 --------|----------|----------|-------
7 XFE0002 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Error | ProfileExtensionDiagnostics
8 XFW0003 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Warning | ProfileExtensionDiagnostics
7 XFE0002 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Error | ProfileExtensionDiagnostics, [Documentation](https://www.xfegzs.com/codespace/diagnostics/XFE0002.html)
8 XFW0001 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Warning | ProfileExtensionDiagnostics, [Documentation](https://www.xfegzs.com/codespace/diagnostics/XFW0001.html)
Modified XFE各类拓展.NetCore.Analyzer/AnalyzerReleases.Unshipped.md +6 -3
@@ -1,6 +1,9 @@
1 ### New Rules
1 ; Unshipped analyzer release
2 ; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
3
4 ### New Rules
2 5
3 6 Rule ID | Category | Severity | Notes
4 7 --------|----------|----------|-------
5 XFE0002 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Error | ProfileExtensionDiagnostics
6 XFW0003 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Warning | ProfileExtensionDiagnostics
8 XFE0002 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Error | ProfileExtensionDiagnostics, [Documentation](https://www.xfegzs.com/codespace/diagnostics/XFE0002.html)
9 XFW0001 | XFE各类拓展.NetCore.Analyzer.Diagnostics | Warning | ProfileExtensionDiagnostics, [Documentation](https://www.xfegzs.com/codespace/diagnostics/XFW0001.html)
Added XFE各类拓展.NetCore.Analyzer/CodeFix/ProfileExtensionCodeFixProvider.cs +121 -0
@@ -0,0 +1,121 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CodeActions;
3 using Microsoft.CodeAnalysis.CodeFixes;
4 using Microsoft.CodeAnalysis.CSharp;
5 using Microsoft.CodeAnalysis.CSharp.Syntax;
6 using Microsoft.CodeAnalysis.Text;
7 using System;
8 using System.Collections.Generic;
9 using System.Collections.Immutable;
10 using System.Linq;
11 using System.Runtime.InteropServices;
12 using System.Text;
13 using System.Threading.Tasks;
14 using XFE各类拓展.NetCore.Analyzer.Diagnostics;
15 using XFE各类拓展.NetCore.Analyzer.Generator;
16
17 namespace XFE各类拓展.NetCore.Analyzer.CodeFix
18 {
19 [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ProfileExtensionCodeFixProvider))]
20 public class ProfileExtensionCodeFixProvider : CodeFixProvider
21 {
22 public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(ProfileExtensionDiagnostics.AddGetNoResultErrorId, ProfileExtensionDiagnostics.AddSetNoSetResultWarningId);
23
24 public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
25
26 public override Task RegisterCodeFixesAsync(CodeFixContext context)
27 {
28 foreach (var diagnostic in context.Diagnostics)
29 {
30 if (diagnostic.Id == ProfileExtensionDiagnostics.AddGetNoResultErrorId)
31 {
32 context.RegisterCodeFix(CodeAction.Create(title: "添加返回值方法",
33 createChangedDocument: c => AddReturnFuncAsync(context.Document, diagnostic.Location.SourceSpan, c),
34 equivalenceKey: "添加返回值"),
35 diagnostic: diagnostic);
36 }
37 else if (diagnostic.Id == ProfileExtensionDiagnostics.AddSetNoSetResultWarningId)
38 {
39 context.RegisterCodeFix(CodeAction.Create(title: "添加字段的设置方法",
40 createChangedDocument: c => AddSetFuncAsync(context.Document, diagnostic.Location.SourceSpan, c),
41 equivalenceKey: "添加字段的设置方法"),
42 diagnostic: diagnostic);
43 }
44 }
45 return Task.CompletedTask;
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 private async Task<Document> AddReturnFuncAsync(Document document, TextSpan sourceSpan, System.Threading.CancellationToken c)
102 {
103 var root = await document.GetSyntaxRootAsync(c);
104 var fieldDeclaration = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().First();
105 var fieldName = fieldDeclaration.Declaration.Variables.First().Identifier.ValueText;
106 var newAttribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName("ProfilePropertyAddGet")).AddArgumentListArguments(SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal($"return {fieldName}"))));
107 var newRoot = root.ReplaceNode(fieldDeclaration, fieldDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(newAttribute))));
108 return document.WithSyntaxRoot(newRoot);
109 }
110
111 private async Task<Document> AddSetFuncAsync(Document document, TextSpan sourceSpan, System.Threading.CancellationToken c)
112 {
113 var root = await document.GetSyntaxRootAsync(c);
114 var fieldDeclaration = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().First();
115 var fieldName = fieldDeclaration.Declaration.Variables.First().Identifier.ValueText;
116 var newAttribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName("ProfilePropertyAddSet")).AddArgumentListArguments(SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal($"{fieldName} = value"))));
117 var newRoot = root.ReplaceNode(fieldDeclaration, fieldDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(newAttribute))));
118 return document.WithSyntaxRoot(newRoot);
119 }
120 }
121 }
Modified XFE各类拓展.NetCore.Analyzer/Diagnostics/ProfileExtensionDiagnostics.cs +56 -34
@@ -1,33 +1,47 @@
1 1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp;
2 3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 using Microsoft.CodeAnalysis.Diagnostics;
5 using System.Collections.Immutable;
6 using System.Diagnostics;
7 using System.Linq;
3 8 using System.Text.RegularExpressions;
4 9 using XFE各类拓展.NetCore.Analyzer.Generator;
5 10
6 11 namespace XFE各类拓展.NetCore.Analyzer.Diagnostics
7 12 {
8 [Generator]
9 public class ProfileExtensionDiagnostics : ISourceGenerator
13 [DiagnosticAnalyzer(LanguageNames.CSharp)]
14 public class ProfileExtensionDiagnostics : DiagnosticAnalyzer
10 15 {
11 public static readonly DiagnosticDescriptor AddGetNoResultError = new DiagnosticDescriptor("XFE0002",
16 public const string AddGetNoResultErrorId = "XFE0002";
17 public const string AddSetNoSetResultWarningId = "XFW0001";
18 public static readonly DiagnosticDescriptor AddGetNoResultError = new DiagnosticDescriptor(AddGetNoResultErrorId,
12 19 "Get方法没有返回值",
13 20 "设置了自定义的Get方法但是没有返回值:'{0}'",
14 21 "XFE各类拓展.NetCore.Analyzer.Diagnostics",
15 22 DiagnosticSeverity.Error,
16 23 true,
17 24 "设置了自定义的Get方法但是没有返回值.",
18 null);
19 public static readonly DiagnosticDescriptor AddSetNoSetResultWarning = new DiagnosticDescriptor("XFW0003",
25 "https://www.xfegzs.com/codespace/diagnostics/XFE0002.html");
26 public static readonly DiagnosticDescriptor AddSetNoSetResultWarning = new DiagnosticDescriptor(AddSetNoSetResultWarningId,
20 27 "Set方法没有设置值",
21 "设置了自定义的Set方法但是没有设置实际的字段对应的值:'{0}'",
28 "设置了自定义的Set方法但是没有对实际字段进行操作:'{0}'",
22 29 "XFE各类拓展.NetCore.Analyzer.Diagnostics",
23 30 DiagnosticSeverity.Warning,
24 31 true,
25 "设置了自定义的Set方法但是没有设置实际的字段对应的值.",
26 );
27 public void Initialize(GeneratorInitializationContext context)
32 "设置了自定义的Set方法但是没有对实际字段进行操作.",
33 "https://www.xfegzs.com/codespace/diagnostics/XFW0001.html");
34
35 public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(AddGetNoResultError, AddSetNoSetResultWarning);
36
37
38 public override void Initialize(AnalysisContext context)
28 39 {
40 context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
41 context.EnableConcurrentExecution();
42 context.RegisterSyntaxNodeAction(ProfileExtensionAnalyzer, SyntaxKind.Attribute);
29 43 }
30 public void Execute(GeneratorExecutionContext context)
44 public void ProfileExtensionAnalyzer(SyntaxNodeAnalysisContext context)
31 45 {
32 46 foreach (var syntaxTree in context.Compilation.SyntaxTrees)
33 47 {
@@ -36,42 +50,50 @@ namespace XFE各类拓展.NetCore.Analyzer.Diagnostics
36 50 {
37 51 foreach (var fieldDeclaration in ProfilePropertyAutoGenerator.GetFieldDeclarations(classDeclaration))
38 52 {
39 var getAttributeHasResult = false;
40 var setAttributeSetResult = false;
41 foreach (var attributeSyntax in ProfilePropertyAutoGenerator.GetProfilePropertyAddGetAttributeList(fieldDeclaration))
53 if (fieldDeclaration.AttributeLists.Any(ProfilePropertyAutoGenerator.IsProfilePropertyAddGetAttribute))
42 54 {
43 if (attributeSyntax.ArgumentList is null)
55 var getAttributeHasResult = false;
56 var attributeSyntaxList = ProfilePropertyAutoGenerator.GetProfilePropertyAddGetAttributeList(fieldDeclaration);
57 foreach (var attributeSyntax in attributeSyntaxList)
44 58 {
45 continue;
59 if (attributeSyntax.ArgumentList is null)
60 {
61 continue;
62 }
63 var argument = attributeSyntax.ArgumentList.Arguments.First();
64 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText.Contains("return"))
65 {
66 getAttributeHasResult = true;
67 }
46 68 }
47 var argument = attributeSyntax.ArgumentList.Arguments.First();
48 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText.Contains("return"))
69 if (!getAttributeHasResult)
49 70 {
50 getAttributeHasResult = true;
71 var diagnostic = Diagnostic.Create(AddGetNoResultError, attributeSyntaxList.Last().GetLocation(), fieldDeclaration.Declaration.Variables.First().Identifier.ValueText);
72 context.ReportDiagnostic(diagnostic);
51 73 }
52 74 }
53 foreach (var attributeSyntax in ProfilePropertyAutoGenerator.GetProfilePropertyAddSetAttributeList(fieldDeclaration))
75 if (fieldDeclaration.AttributeLists.Any(ProfilePropertyAutoGenerator.IsProfilePropertyAddSetAttribute))
54 76 {
55 if (attributeSyntax.ArgumentList is null)
77 var setAttributeSetResult = false;
78 var attributeSyntaxList = ProfilePropertyAutoGenerator.GetProfilePropertyAddSetAttributeList(fieldDeclaration);
79 foreach (var attributeSyntax in attributeSyntaxList)
56 80 {
57 continue;
81 if (attributeSyntax.ArgumentList is null)
82 {
83 continue;
84 }
85 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"))
87 {
88 setAttributeSetResult = true;
89 }
58 90 }
59 var argument = attributeSyntax.ArgumentList.Arguments.First();
60 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && Regex.IsMatch(literalExpressionSyntax.Token.ValueText, $@"{fieldDeclaration.Declaration.Variables.First().Identifier.ValueText}\s*=\s*value"))
91 if (!setAttributeSetResult)
61 92 {
62 setAttributeSetResult = true;
93 var diagnostic = Diagnostic.Create(AddSetNoSetResultWarning, attributeSyntaxList.Last().GetLocation(), fieldDeclaration.Declaration.Variables.First().Identifier.ValueText);
94 context.ReportDiagnostic(diagnostic);
63 95 }
64 96 }
65 if (!getAttributeHasResult)
66 {
67 var diagnostic = Diagnostic.Create(AddGetNoResultError, fieldDeclaration.GetLocation(), fieldDeclaration.Declaration.Variables.First().Identifier.ValueText);
68 context.ReportDiagnostic(diagnostic);
69 }
70 if (!setAttributeSetResult)
71 {
72 var diagnostic = Diagnostic.Create(AddSetNoSetResultWarning, fieldDeclaration.GetLocation(), fieldDeclaration.Declaration.Variables.First().Identifier.ValueText);
73 context.ReportDiagnostic(diagnostic);
74 }
75 97 }
76 98 }
77 99 }
Modified XFE各类拓展.NetCore.Analyzer/XFE各类拓展.NetCore.Analyzer.csproj +2 -1
@@ -13,7 +13,8 @@
13 13
14 14 <ItemGroup>
15 15 <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
16 <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
16 <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" PrivateAssets="all" />
17 <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.9.2" />
17 18 </ItemGroup>
18 19
19 20 </Project>
Modified XFE各类拓展.NetCore/ProfileExtension/XFEProfile.cs +4 -3
@@ -1,4 +1,5 @@
1 using XFE各类拓展.NetCore.FormatExtension;
1 using System.Text.Json;
2 using XFE各类拓展.NetCore.FormatExtension;
2 3
3 4 namespace XFE各类拓展.NetCore.ProfileExtension;
4 5
@@ -7,8 +8,8 @@ namespace XFE各类拓展.NetCore.ProfileExtension;
7 8 /// </summary>
8 9 public abstract class XFEProfile
9 10 {
10 private static Func<ProfileEntryInfo, string> SaveProfilesFunc { get; set; } = x => x.Value is null ? string.Empty : x.Value;
11 private static Func<string, ProfileEntryInfo, object?> LoadProfilesFunc { get; set; } = (x, p) => Convert.ChangeType(x, p.Property.PropertyType);
11 private static Func<ProfileEntryInfo, string> SaveProfilesFunc { get; set; } = p => JsonSerializer.Serialize(p.Property.GetValue(null));
12 private static Func<string, ProfileEntryInfo, object?> LoadProfilesFunc { get; set; } = (x, p) => JsonSerializer.Deserialize(x, p.Property.PropertyType);
12 13
13 14 /// <summary>
14 15 /// 配置文件清单
Modified XFE各类拓展.NetCore/XFE各类拓展.NetCore.csproj +4 -4
@@ -19,7 +19,7 @@
19 19 <PackageTags>XFE;拓展;GPT;Server;服务器;测试;XFEExtension</PackageTags>
20 20 <PackageReleaseNotes>## 调整
21 21
22 分离了同步和异步方法,不再合并
22 为配置文件属性添加代码分析器及快速操作的实现
23 23
24 24 ## 新增
25 25
@@ -32,9 +32,9 @@
32 32 <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
33 33 <PackageLicenseFile>LICENSE</PackageLicenseFile>
34 34 <AssemblyOriginatorKeyFile>..\XFEstudio.pfx</AssemblyOriginatorKeyFile>
35 <AssemblyVersion>1.7.25.5</AssemblyVersion>
36 <FileVersion>1.7.25.5</FileVersion>
37 <Version>1.7.5</Version>
35 <AssemblyVersion>1.7.26.6</AssemblyVersion>
36 <FileVersion>1.7.26.6</FileVersion>
37 <Version>1.7.6</Version>
38 38 <Authors>XFEstudio</Authors>
39 39 </PropertyGroup>
40 40