XFEExtension
【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等
关注
0
Fork
0
Star
0
返回提交历史
Modified
XFE各类拓展.NetCore.Analyzer.Test/SystemProfile.cs
+7
-1
Modified
XFE各类拓展.NetCore.Analyzer/AnalyzerReleases.Shipped.md
+2
-2
Modified
XFE各类拓展.NetCore.Analyzer/AnalyzerReleases.Unshipped.md
+6
-3
Added
XFE各类拓展.NetCore.Analyzer/CodeFix/ProfileExtensionCodeFixProvider.cs
+121
-0
Modified
XFE各类拓展.NetCore.Analyzer/Diagnostics/ProfileExtensionDiagnostics.cs
+56
-34
Modified
XFE各类拓展.NetCore.Analyzer/XFE各类拓展.NetCore.Analyzer.csproj
+2
-1
Modified
XFE各类拓展.NetCore/ProfileExtension/XFEProfile.cs
+4
-3
Modified
XFE各类拓展.NetCore/XFE各类拓展.NetCore.csproj
+4
-4
XFEstudio/XFEExtension
为配置文件属性添加代码分析器及快速操作的实现 修改版号为1.7.6
01a1725
代码差异
8 个文件
+202
-48
@@ -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
}
@@ -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)
@@ -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)
@@ -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
}
@@ -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
}
@@ -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>
@@ -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
/// 配置文件清单
@@ -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