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

XFEExtension

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

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

XFEstudio/XFEExtension

删除了多个类和文件,更新了项目版本

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

代码差异

23 个文件 +7 -1536
Modified README.md +1 -169
@@ -2,7 +2,7 @@
2 2
3 3 ## 描述
4 4
5 XFEExtension是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供XUnit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等
5 XFEExtension是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等
6 6
7 7 ## 用途
8 8
@@ -14,157 +14,10 @@ XFEExtension库适用于各种C#项目,特别适合在需要提高代码可读
14 14
15 15 - **加速开发:** 通过减少样板代码,XFEExtension可以加速项目的开发过程,同时提高代码的可维护性。
16 16
17
18 ## 设置csproj文件配置
19
20 ```xml
21 <PropertyGroup>
22 <!--设置是否启用自动配置文件-->
23 <AutoProfile>true</AutoProfile>
24 <!--设置是否启用自动路径-->
25 <AutoPath>true</AutoPath>
26 <!--设置是否启用TODO待办任务提醒-->
27 <TodoList>true</TodoList>
28 <!--设置待办任务的提示级别-->
29 <TodoListWarningLevel>3</TodoListWarningLevel>
30 </PropertyGroup>
31 ```
32
33
34 17 # 示例(使用前记得进行相应的引用)
35 18
36 19 ---
37 20
38 ## TODO待办任务提醒
39
40 ```csharp
41 //TODO: 这是一个待办任务,使用默认提示级别
42
43 //TODO:1 这是一个待办任务,使用提示级别
44
45 //TODO:3 这是一个待办任务,使用错误提示级别
46
47 //提示级别:0-隐藏,1-提示,2-警告,3-错误
48 ```
49
50
51 ## 自动实现配置文件的存储
52
53 #### 基础用法
54
55 ```csharp
56 //创建配置文件类
57 partial class SystemProfile
58 {
59 [ProfileProperty]
60 string name;
61
62 [ProfileProperty]
63 int _age;
64 }
65
66 //使用配置文件
67 class Program
68 {
69 static void Main(string[] args)
70 {
71 SystemProfile.Name = "Test";//在设置值的时候会自动记录并储存
72 //SystemProfile.Age = 1;
73 Console.WriteLine(SystemProfile.Name);
74 Console.WriteLine(SystemProfile.Age);//下次打开程序会自动读取上次程序退出时储存的值
75 }
76 }
77 ```
78
79 #### 设置get和set方法
80
81 ```csharp
82 partial class SystemProfile
83 {
84 [ProfileProperty]
85 [ProfilePropertyAddGet(@"Console.WriteLine(""获取了Name"")")]
86 [ProfilePropertyAddGet("return Current.name")]
87 [ProfilePropertyAddSet(@"Console.WriteLine(""设置了Name"")")]
88 [ProfilePropertyAddSet("Current.name = value")]
89 string name = string.Empty;
90
91 [ProfileProperty]
92 [ProfilePropertyAddGet(@"Console.WriteLine(""获取了Age"")")]
93 [ProfilePropertyAddGet("return Current._age")]
94 [ProfilePropertyAddSet(@"Console.WriteLine(""设置了Age"")")]
95 [ProfilePropertyAddSet("Current._age = value")]
96 int _age;
97 }
98 ```
99
100 #### 设置初始值
101
102 ```csharp
103 partial class SystemProfile
104 {
105 [ProfileProperty]
106 string name = "John Wick";
107
108 [ProfileProperty]
109 int _age = 59;
110 }
111 ```
112
113 #### 为属性添加注释
114
115 ```csharp
116 partial class SystemProfile
117 {
118 /// <summary>
119 /// 名称
120 /// 这段注释会自动添加至自动生成的Name属性上
121 /// </summary>
122 [ProfileProperty]
123 string name;
124
125 [ProfileProperty]
126 int _age;
127 }
128 ```
129
130 #### 使用部分方法来设置get和set方法
131
132 ```csharp
133 partial class SystemProfile
134 {
135 [ProfileProperty]
136 string name;
137
138 [ProfileProperty]
139 int _age;
140
141 static partial void GetNameProperty()
142 {
143 Console.WriteLine("获取了Name");
144 }
145
146 static partial void SetNameProperty(string value)
147 {
148 Console.WriteLine($"设置了Name:从{Name}变为了{value}");
149 }
150
151 static partial void GetAgeProperty()
152 {
153 Console.WriteLine("获取了Age");
154 }
155
156 static partial void SetAgeProperty(int value)
157 {
158 Console.WriteLine($"设置了Age:从{Age}变为了{value}");
159 }
160 }
161 ```
162
163
164 21 ## 使用LANDeviceDetector来检测本地局域网内的所有设备
165 22
166 23 #### 基础用法
@@ -305,27 +158,6 @@ memorableXFEChatGPT.AskChatGPT("新的对话ID", Guid.NewGuid().ToString(), askC
305 158
306 159 ---
307 160
308 ## 自动生成实现类
309
310 ```csharp
311 [CreateImpl]
312 abstract class TestAbstractClass(int num)
313 {
314 public int Num { get; set; } = num;
315 }
316
317 class Program
318 {
319 static void Main(string[] args)
320 {
321 var testAbstractClass = new TestAbstractClassImpl(123);
322 Console.WriteLine(testAbstractClass.Num);
323 }
324 }
325 ```
326
327
328 161 ## IO流拓展操作示例
329 162
330 163 ```csharp
Deleted XFEExtension.NetCore.Analyzer/CodeFix/ProfileExtensionCodeFixProvider.cs +0 -67
@@ -1,67 +0,0 @@
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 XFEExtension.NetCore.Analyzer.Diagnostics;
15 using XFEExtension.NetCore.Analyzer.Generator;
16
17 namespace XFEExtension.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 private async Task<Document> AddReturnFuncAsync(Document document, TextSpan sourceSpan, System.Threading.CancellationToken c)
48 {
49 var root = await document.GetSyntaxRootAsync(c);
50 var fieldDeclaration = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().First();
51 var fieldName = fieldDeclaration.Declaration.Variables.First().Identifier.ValueText;
52 var newAttribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName("ProfilePropertyAddGet")).AddArgumentListArguments(SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal($"return Current.{fieldName}"))));
53 var newRoot = root.ReplaceNode(fieldDeclaration, fieldDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(newAttribute))));
54 return document.WithSyntaxRoot(newRoot);
55 }
56
57 private async Task<Document> AddSetFuncAsync(Document document, TextSpan sourceSpan, System.Threading.CancellationToken c)
58 {
59 var root = await document.GetSyntaxRootAsync(c);
60 var fieldDeclaration = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().First();
61 var fieldName = fieldDeclaration.Declaration.Variables.First().Identifier.ValueText;
62 var newAttribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName("ProfilePropertyAddSet")).AddArgumentListArguments(SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal($"Current.{fieldName} = value"))));
63 var newRoot = root.ReplaceNode(fieldDeclaration, fieldDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(newAttribute))));
64 return document.WithSyntaxRoot(newRoot);
65 }
66 }
67 }
Deleted XFEExtension.NetCore.Analyzer/Diagnostics/ProfileExtensionDiagnostics.cs +0 -127
@@ -1,127 +0,0 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp;
3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 using Microsoft.CodeAnalysis.Diagnostics;
5 using System.Collections.Immutable;
6 using System.Linq;
7 using System.Text.RegularExpressions;
8 using XFEExtension.NetCore.Analyzer.Generator;
9 namespace XFEExtension.NetCore.Analyzer.Diagnostics
10 {
11 [DiagnosticAnalyzer(LanguageNames.CSharp)]
12 public class ProfileExtensionDiagnostics : DiagnosticAnalyzer
13 {
14 public const string AddGetNoResultErrorId = "XFE0002";
15 public const string AddSetNoSetResultWarningId = "XFW0001";
16
17 public static readonly DiagnosticDescriptor AddGetNoResultError = new DiagnosticDescriptor(AddGetNoResultErrorId,
18 "Get方法没有返回值",
19 "设置了自定义的Get方法但是没有返回值:'{0}'",
20 "XFEExtension.NetCore.Analyzer.Diagnostics",
21 DiagnosticSeverity.Error,
22 true,
23 "设置了自定义的Get方法但是没有返回值.",
24 "https://www.xfegzs.com/codespace/diagnostics/XFE0002.html");
25
26 public static readonly DiagnosticDescriptor AddSetNoSetResultWarning = new DiagnosticDescriptor(AddSetNoSetResultWarningId,
27 "Set方法没有设置值",
28 "设置了自定义的Set方法但是没有对实际字段进行操作:'{0}'",
29 "XFEExtension.NetCore.Analyzer.Diagnostics",
30 DiagnosticSeverity.Warning,
31 true,
32 "设置了自定义的Set方法但是没有对实际字段进行操作.",
33 "https://www.xfegzs.com/codespace/diagnostics/XFW0001.html");
34
35 public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(AddGetNoResultError, AddSetNoSetResultWarning);
36
37 public override void Initialize(AnalysisContext context)
38 {
39 context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
40 context.EnableConcurrentExecution();
41 context.RegisterSyntaxNodeAction(ProfileExtensionAnalyzer, SyntaxKind.Attribute);
42 }
43 public void ProfileExtensionAnalyzer(SyntaxNodeAnalysisContext context)
44 {
45 foreach (var syntaxTree in context.Compilation.SyntaxTrees)
46 {
47 var root = syntaxTree.GetRoot();
48 foreach (var classDeclaration in root.DescendantNodes().OfType<ClassDeclarationSyntax>())
49 {
50 foreach (var fieldDeclaration in ProfilePropertyAutoGenerator.GetFieldDeclarations(classDeclaration))
51 {
52 if (fieldDeclaration.AttributeLists.Any(ProfilePropertyAutoGenerator.IsProfilePropertyAddGetAttribute))
53 {
54 var getAttributeHasResult = false;
55 var attributeSyntaxList = ProfilePropertyAutoGenerator.GetProfilePropertyAddGetAttributeList(fieldDeclaration);
56 foreach (var attributeSyntax in attributeSyntaxList)
57 {
58 if (attributeSyntax.ArgumentList is null)
59 {
60 continue;
61 }
62 var argument = attributeSyntax.ArgumentList.Arguments.First();
63 var funcText = string.Empty;
64 if (argument.Expression is LiteralExpressionSyntax)
65 {
66 funcText = argument.Expression.GetText().ToString();
67 }
68 else if (argument.Expression is InterpolatedStringExpressionSyntax)
69 {
70 funcText = argument.Expression.GetText().ToString();
71 }
72 else if (argument.Expression is InvocationExpressionSyntax)
73 {
74 funcText = argument.Expression.GetText().ToString();
75 }
76 if (funcText.Contains("return"))
77 {
78 getAttributeHasResult = true;
79 }
80 }
81 if (!getAttributeHasResult)
82 {
83 var diagnostic = Diagnostic.Create(AddGetNoResultError, attributeSyntaxList.Last().GetLocation(), fieldDeclaration.Declaration.Variables.First().Identifier.ValueText);
84 context.ReportDiagnostic(diagnostic);
85 }
86 }
87 if (fieldDeclaration.AttributeLists.Any(ProfilePropertyAutoGenerator.IsProfilePropertyAddSetAttribute))
88 {
89 var setAttributeSetResult = false;
90 var attributeSyntaxList = ProfilePropertyAutoGenerator.GetProfilePropertyAddSetAttributeList(fieldDeclaration);
91 foreach (var attributeSyntax in attributeSyntaxList)
92 {
93 if (attributeSyntax.ArgumentList is null)
94 {
95 continue;
96 }
97 var argument = attributeSyntax.ArgumentList.Arguments.First();
98 var funcText = string.Empty;
99 if (argument.Expression is LiteralExpressionSyntax)
100 {
101 funcText = argument.Expression.GetText().ToString();
102 }
103 else if (argument.Expression is InterpolatedStringExpressionSyntax)
104 {
105 funcText = argument.Expression.GetText().ToString();
106 }
107 else if (argument.Expression is InvocationExpressionSyntax)
108 {
109 funcText = argument.Expression.GetText().ToString();
110 }
111 if (Regex.IsMatch(funcText, $@"{fieldDeclaration.Declaration.Variables.First().Identifier.ValueText}\s*=\s*value"))
112 {
113 setAttributeSetResult = true;
114 }
115 }
116 if (!setAttributeSetResult)
117 {
118 var diagnostic = Diagnostic.Create(AddSetNoSetResultWarning, attributeSyntaxList.Last().GetLocation(), fieldDeclaration.Declaration.Variables.First().Identifier.ValueText);
119 context.ReportDiagnostic(diagnostic);
120 }
121 }
122 }
123 }
124 }
125 }
126 }
127 }
Deleted XFEExtension.NetCore.Analyzer/Diagnostics/TodoCommentAnalyzerDiagnostics.cs +0 -84
@@ -1,84 +0,0 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp;
3 using Microsoft.CodeAnalysis.Diagnostics;
4 using System;
5 using System.Collections.Immutable;
6 using System.Linq;
7 using System.Text.RegularExpressions;
8
9 namespace XFEExtension.NetCore.Analyzer.Diagnostics
10 {
11 [DiagnosticAnalyzer(LanguageNames.CSharp)]
12 public class TodoCommentAnalyzerDiagnostics : DiagnosticAnalyzer
13 {
14 public const string TodoCommentId = "TODO";
15
16 public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
17 {
18 get
19 {
20 var descriptor = new DiagnosticDescriptor(TodoCommentId,
21 "TODO��������",
22 "��������{0}",
23 "XFEExtension.NetCore.Analyzer.Diagnostics",
24 GetSeverityFromInt(GeneratorOptions.TodoListWarningLevel),
25 true,
26 "TODO�Ĵ�������.",
27 "https://www.xfegzs.com/codespace/diagnostics/TODO.html");
28 return ImmutableArray.Create(descriptor);
29 }
30 }
31
32 public override void Initialize(AnalysisContext context)
33 {
34 context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
35 context.EnableConcurrentExecution();
36 context.RegisterSyntaxTreeAction(AnalyzeSyntaxTree);
37 }
38
39 private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
40 {
41 if (!GeneratorOptions.TodoList)
42 return;
43 var root = context.Tree.GetRoot(context.CancellationToken);
44 var todoComments = root.DescendantTrivia().Where(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) && trivia.ToString().Contains("TODO:"));
45 foreach (var todoComment in todoComments)
46 {
47 var match = Regex.Match(todoComment.ToString(), @"//TODO:\s*(\d)?\s*(.*)");
48 if (match.Success)
49 {
50 var level = match.Groups[1].Value != "" ? int.Parse(match.Groups[1].Value) : GeneratorOptions.TodoListWarningLevel;
51 var task = match.Groups[2].Value;
52
53 var descriptor = new DiagnosticDescriptor(TodoCommentId,
54 "TODO��������",
55 "��������{0}",
56 "XFEExtension.NetCore.Analyzer.Diagnostics",
57 GetSeverityFromInt(level),
58 true,
59 "TODO�Ĵ�������.",
60 "https://www.xfegzs.com/codespace/diagnostics/TODO.html");
61 var diagnostic = Diagnostic.Create(descriptor, todoComment.GetLocation(), task);
62 context.ReportDiagnostic(diagnostic);
63 }
64 }
65 }
66
67 private static DiagnosticSeverity GetSeverityFromInt(int level)
68 {
69 switch (level)
70 {
71 case 0:
72 return DiagnosticSeverity.Hidden;
73 case 1:
74 return DiagnosticSeverity.Info;
75 case 2:
76 return DiagnosticSeverity.Warning;
77 case 3:
78 return DiagnosticSeverity.Error;
79 default:
80 return DiagnosticSeverity.Warning;
81 }
82 }
83 }
84 }
Deleted XFEExtension.NetCore.Analyzer/Generator/AutoPathSyntaxReceiver.cs +0 -23
@@ -1,23 +0,0 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp.Syntax;
3 using System.Collections.Generic;
4 using System.Linq;
5
6 namespace XFEExtension.NetCore.Analyzer.Generator
7 {
8 public class AutoPathSyntaxReceiver : ISyntaxReceiver
9 {
10 public List<FieldDeclarationSyntax> CandidateFields { get; } = new List<FieldDeclarationSyntax>();
11
12 public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
13 {
14 if (syntaxNode is FieldDeclarationSyntax fieldDeclarationSyntax)
15 {
16 if (fieldDeclarationSyntax.AttributeLists.Any(PathPropertyAutoGenerator.IsAutoPathAttribute))
17 {
18 CandidateFields.Add(fieldDeclarationSyntax);
19 }
20 }
21 }
22 }
23 }
Deleted XFEExtension.NetCore.Analyzer/Generator/PathPropertyAutoGenerator.cs +0 -182
@@ -1,182 +0,0 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp;
3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 using System.Collections.Generic;
5 using System.Linq;
6
7 namespace XFEExtension.NetCore.Analyzer.Generator
8 {
9 [Generator]
10 public class PathPropertyAutoGenerator : ISourceGenerator
11 {
12 public void Initialize(GeneratorInitializationContext context)
13 {
14 context.RegisterForSyntaxNotifications(() => new AutoPathSyntaxReceiver());
15 }
16
17 public void Execute(GeneratorExecutionContext context)
18 {
19 if(!GeneratorOptions.AutoPath)
20 return;
21 if (!(context.SyntaxReceiver is AutoPathSyntaxReceiver receiver))
22 return;
23 var syntaxTrees = context.Compilation.SyntaxTrees;
24 foreach (var syntaxTree in syntaxTrees)
25 {
26 var root = syntaxTree.GetRoot();
27 var classDeclarations = GetClassDeclarations(root);
28 var fileScopedNamespaceDeclarationSyntax = GetFileScopedNamespaceDeclaration(root);
29 foreach (var classDeclaration in classDeclarations)
30 {
31 var fieldDeclarationSyntaxes = GetFieldDeclarations(classDeclaration);
32 if (fieldDeclarationSyntaxes is null || !fieldDeclarationSyntaxes.Any())
33 {
34 continue;
35 }
36 var className = classDeclaration.Identifier.ValueText;
37 var properties = new List<PropertyDeclarationSyntax>();
38 var methods = new List<MethodDeclarationSyntax>();
39 var enableCheckProperties = new List<PropertyDeclarationSyntax>();
40 foreach (var fieldDeclarationSyntax in fieldDeclarationSyntaxes)
41 {
42 var variableDeclaration = fieldDeclarationSyntax.Declaration.Variables.First();
43 var fieldName = variableDeclaration.Identifier.Text;
44 var propertyName = fieldName[0] == '_' ? fieldName[1].ToString().ToUpper() + fieldName.Substring(2) : fieldName[0].ToString().ToUpper() + fieldName.Substring(1);
45 var getMethodName = $"Get{propertyName}Property";
46 var enableCheckPropertyName = $"{propertyName}EnableCheck";
47 GetAutoPathAttributeList(fieldDeclarationSyntax).ForEach(attribute =>
48 {
49 if (attribute.ArgumentList is null)
50 {
51 return;
52 }
53 var argument = attribute.ArgumentList.Arguments.First();
54 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax)
55 {
56 propertyName = literalExpressionSyntax.Token.ValueText;
57 }
58 });
59 var propertyType = fieldDeclarationSyntax.Declaration.Type;
60 var triviaText = $@"/// <inheritdoc cref=""{fieldName}""/>
61 /// <remarks>
62 /// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的路径属性<br/><br/>
63 /// </remarks>
64 ";
65 var checkEnableTriviaText = $@"/// <summary>
66 /// 是否为 <seealso cref=""{fieldName}""/> 启用检测路径<br/><br/>
67 /// </summary>
68 ";
69 var property = SyntaxFactory.PropertyDeclaration(propertyType, propertyName)
70 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
71 .WithAccessorList(SyntaxFactory.AccessorList(
72 SyntaxFactory.List(new[]
73 {
74 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
75 .WithBody(SyntaxFactory.Block(
76 SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"Options ??= new {className}()")),
77 SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"global::XFEExtension.NetCore.PathExtension.XFEAutoPath.CheckPathExistAndCreate({fieldName}, Options.{enableCheckPropertyName})")),
78 SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"{getMethodName}()")),
79 SyntaxFactory.ReturnStatement(SyntaxFactory.ParseExpression($"{fieldName}"))))
80 })))
81 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText));
82 var enableCheckProperty = SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName("bool"), enableCheckPropertyName)
83 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)))
84 .WithAccessorList(SyntaxFactory.AccessorList(
85 SyntaxFactory.List(new[]
86 {
87 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
88 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
89 })))
90 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(checkEnableTriviaText))
91 .WithInitializer(SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression("true")))
92 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
93 var getMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), getMethodName)
94 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)))
95 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
96 properties.Add(property.NormalizeWhitespace());
97 methods.Add(getMethod);
98 enableCheckProperties.Add(enableCheckProperty.NormalizeWhitespace());
99 }
100 var profileClassSyntaxTree = GeneratePathClassSyntaxTree(classDeclaration, properties, enableCheckProperties, methods, fileScopedNamespaceDeclarationSyntax);
101 context.AddSource($"{className}.g.cs", profileClassSyntaxTree.ToString());
102 }
103 }
104 }
105
106 public static bool IsAutoPathAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "AutoPath");
107
108 public static List<AttributeSyntax> GetAutoPathAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsAutoPathAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
109
110 public static FileScopedNamespaceDeclarationSyntax GetFileScopedNamespaceDeclaration(SyntaxNode rootNode)
111 {
112 var namespaceResults = rootNode.DescendantNodes().OfType<FileScopedNamespaceDeclarationSyntax>();
113 if (namespaceResults != null && namespaceResults.Count() > 0)
114 return namespaceResults.First();
115 return null;
116 }
117
118 public static IEnumerable<FieldDeclarationSyntax> GetFieldDeclarations(ClassDeclarationSyntax classDeclaration) => classDeclaration.DescendantNodes()
119 .OfType<FieldDeclarationSyntax>()
120 .Where(fieldDeclarationSyntax => fieldDeclarationSyntax.AttributeLists.Any(IsAutoPathAttribute) && fieldDeclarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword));
121
122 public static IEnumerable<ClassDeclarationSyntax> GetClassDeclarations(SyntaxNode rootNode) => rootNode.DescendantNodes()
123 .OfType<ClassDeclarationSyntax>()
124 .Where(classDeclaration => classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword));
125
126 private static SyntaxTree GeneratePathClassSyntaxTree(ClassDeclarationSyntax classDeclaration, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<PropertyDeclarationSyntax> enableCheckDeclarationSyntaxes, List<MethodDeclarationSyntax> methodDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
127 {
128 var className = classDeclaration.Identifier.ValueText;
129 var triviaText = $@"/// <remarks>
130 /// <code><seealso cref=""{className}""/> 已生成以下路径:</code><br/>
131 /// <code>
132 ";
133 triviaText += string.Join("<br/>\n", propertyDeclarationSyntaxes.Select(propertyDeclarationSyntax => $"/// ○ <seealso cref=\"{propertyDeclarationSyntax.Identifier}\"/>")) + "\n/// </code><br/>\n/// <code>来自<seealso cref=\"global::XFEExtension.NetCore.PathExtension\"/></code>\n/// </remarks>\n";
134 var memberDeclarations = new List<MemberDeclarationSyntax>()
135 {
136 SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Options")
137 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
138 .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.ProfileExtension.ProfileInstanceAttribute")))))
139 .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
140 new[]
141 {
142 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
143 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
144 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
145 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
146 })))
147 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
148 /// 配置选项<br/>
149 /// <seealso cref=""Options""/> 是 <seealso cref=""{className}""/> 类的配置选项
150 /// </summary>
151 "))
152 };
153 memberDeclarations.AddRange(propertyDeclarationSyntaxes);
154 memberDeclarations.AddRange(methodDeclarationSyntaxes);
155 memberDeclarations.AddRange(enableCheckDeclarationSyntaxes);
156 var pathClass = SyntaxFactory.ClassDeclaration(className)
157 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
158 .AddMembers(memberDeclarations.ToArray())
159 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
160 .NormalizeWhitespace();
161 MemberDeclarationSyntax memberDeclaration;
162 if (fileScopedNamespaceDeclarationSyntax is null)
163 {
164 var namespaceDeclaration = classDeclaration.FirstAncestorOrSelf<NamespaceDeclarationSyntax>();
165 if (namespaceDeclaration is null)
166 memberDeclaration = pathClass;
167 else
168 memberDeclaration = SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
169 .AddMembers(pathClass);
170 }
171 else
172 {
173 memberDeclaration = SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
174 .AddMembers(pathClass);
175 }
176 var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
177 .AddMembers(memberDeclaration)
178 .NormalizeWhitespace();
179 return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
180 }
181 }
182 }
Deleted XFEExtension.NetCore.Analyzer/Generator/ProfilePropertyAutoGenerator.cs +0 -296
@@ -1,296 +0,0 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp;
3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 using System.Collections.Generic;
5 using System.Linq;
6
7 namespace XFEExtension.NetCore.Analyzer.Generator
8 {
9 [Generator]
10 public class ProfilePropertyAutoGenerator : ISourceGenerator
11 {
12 public void Initialize(GeneratorInitializationContext context)
13 {
14 context.RegisterForSyntaxNotifications(() => new ProfilePropertySyntaxReceiver());
15 }
16
17 public void Execute(GeneratorExecutionContext context)
18 {
19 GeneratorOptions.GetOptions(context);
20 if (!GeneratorOptions.AutoProfile)
21 return;
22 var syntaxTrees = context.Compilation.SyntaxTrees;
23 foreach (var syntaxTree in syntaxTrees)
24 {
25 var root = syntaxTree.GetRoot();
26 var classDeclarations = GetClassDeclarations(root);
27 var usingDirectives = root.DescendantNodes().OfType<UsingDirectiveSyntax>().ToArray();
28 var fileScopedNamespaceDeclarationSyntax = GetFileScopedNamespaceDeclaration(root);
29 foreach (var classDeclaration in classDeclarations)
30 {
31 var fieldDeclarationSyntaxes = GetFieldDeclarations(classDeclaration);
32 if (fieldDeclarationSyntaxes is null || !fieldDeclarationSyntaxes.Any())
33 {
34 continue;
35 }
36 var className = classDeclaration.Identifier.ValueText;
37 var attributeSyntax = SyntaxFactory.AttributeList(
38 SyntaxFactory.SingletonSeparatedList(
39 SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.ProfileExtension.ProfileFieldAutoGenerateAttribute"))));
40 var properties = new List<PropertyDeclarationSyntax>();
41 var methods = new List<MethodDeclarationSyntax>();
42 foreach (var fieldDeclarationSyntax in fieldDeclarationSyntaxes)
43 {
44 var variableDeclaration = fieldDeclarationSyntax.Declaration.Variables.First();
45 var fieldName = variableDeclaration.Identifier.Text;
46 var propertyName = fieldName[0] == '_' ? fieldName[1].ToString().ToUpper() + fieldName.Substring(2) : fieldName[0].ToString().ToUpper() + fieldName.Substring(1);
47 var getMethodName = $"Get{propertyName}Property";
48 var setMethodName = $"Set{propertyName}Property";
49 GetProfilePropertyAttributeList(fieldDeclarationSyntax).ForEach(attribute =>
50 {
51 if (attribute.ArgumentList is null)
52 {
53 return;
54 }
55 var argument = attribute.ArgumentList.Arguments.First();
56 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax)
57 {
58 propertyName = literalExpressionSyntax.Token.ValueText;
59 }
60 });
61 var propertyType = fieldDeclarationSyntax.Declaration.Type;
62 #region Trivia头
63 var triviaText = $@"/// <inheritdoc cref=""{fieldName}""/>
64 /// <remarks>
65 /// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的属性<br/><br/>
66 /// <code><seealso langword=""get""/>方法已生成以下代码: ○ <seealso cref=""{className}.{getMethodName}()""/>;<br/>";
67 #endregion
68 var getExpressionStatements = new List<StatementSyntax>()
69 {
70 SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"{getMethodName}()")).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
71 };
72 if (fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAddGetAttribute))
73 {
74 GetProfilePropertyAddGetAttributeList(fieldDeclarationSyntax).ForEach(attribute =>
75 {
76 if (attribute.ArgumentList is null)
77 {
78 return;
79 }
80 var argument = attribute.ArgumentList.Arguments.First();
81 var funcText = string.Empty;
82 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax)
83 funcText = literalExpressionSyntax.Token.ValueText;
84 if (argument.Expression is InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax)
85 funcText = interpolatedStringExpressionSyntax.Contents.ToString();
86 if (argument.Expression is InvocationExpressionSyntax invocationExpressionSyntax)
87 funcText = invocationExpressionSyntax.GetText().ToString();
88 getExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(funcText)).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)));
89 #region Get方法注释
90 triviaText += $"\n///\t\t\t\t○ {funcText.Replace("\n", "<br/>").Replace("return", "<seealso langword=\"return\"/>").Replace(fieldName, $"<seealso langword=\"{fieldName}\"/>")};<br/>";
91 #endregion
92 });
93 }
94 else
95 {
96 getExpressionStatements.Add(SyntaxFactory.ReturnStatement(SyntaxFactory.ParseExpression($"Current.{fieldName}")));
97 #region Get方默认注释
98 triviaText += $@"
99 /// ○ <seealso langword=""return""/> <seealso langword=""{fieldName}""/>;";
100 #endregion
101 }
102 #region Get方法尾及Set方法头注释
103 triviaText += $@"
104 /// </code>
105 /// <br/>
106 /// <code><seealso langword=""set""/>方法已生成以下代码: ○ <seealso cref=""{className}.{setMethodName}({propertyType})""/>;<br/>";
107 #endregion
108 var setExpressionStatements = new List<StatementSyntax>()
109 {
110 SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"{setMethodName}(value)")).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
111 };
112 if (fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAddSetAttribute))
113 {
114 GetProfilePropertyAddSetAttributeList(fieldDeclarationSyntax).ForEach(attribute =>
115 {
116 if (attribute.ArgumentList is null)
117 {
118 return;
119 }
120 var argument = attribute.ArgumentList.Arguments.First();
121 var funcText = string.Empty;
122 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax)
123 funcText = literalExpressionSyntax.Token.ValueText;
124 else if (argument.Expression is InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax)
125 funcText = interpolatedStringExpressionSyntax.Contents.ToString();
126 else if (argument.Expression is InvocationExpressionSyntax invocationExpressionSyntax)
127 funcText = invocationExpressionSyntax.GetText().ToString();
128 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(funcText)).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)));
129 #region Set方法注释
130 triviaText += $"\n///\t\t\t\t○ {funcText.Replace("\n", "<br/>").Replace(fieldName, $"<seealso langword=\"{fieldName}\"/>").Replace("value", "<seealso langword=\"value\"/>")};<br/>";
131 #endregion
132 });
133 }
134 else
135 {
136 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"Current.{fieldName} = value")));
137 #region Set方法默认注释
138 triviaText += $@"
139 /// ○ <seealso langword=""{fieldName}""/> = <seealso langword=""value""/>;<br/>";
140 #endregion
141 }
142 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"global::XFEExtension.NetCore.ProfileExtension.XFEProfile.SaveProfile(typeof({className}))")));
143 #region Set方法中的保存方法的注释
144 triviaText += $@"
145 /// ○ <seealso cref=""global::XFEExtension.NetCore.ProfileExtension.XFEProfile.SaveProfile(ProfileInfo)""/>";
146 #endregion
147 #region Trivia尾
148 triviaText += @"
149 /// </code>
150 /// </remarks>
151 ";
152 #endregion
153 var property = SyntaxFactory.PropertyDeclaration(propertyType, propertyName)
154 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
155 .AddAttributeLists(attributeSyntax)
156 .WithAccessorList(SyntaxFactory.AccessorList(
157 SyntaxFactory.List(new[]
158 {
159 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
160 .WithBody(SyntaxFactory.Block(getExpressionStatements)),
161 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
162 .WithBody(SyntaxFactory.Block(setExpressionStatements))
163 })))
164 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText));
165 var getMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), getMethodName)
166 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)))
167 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
168 var setMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), setMethodName)
169 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)))
170 .AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("value")).WithType(propertyType))
171 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
172 methods.Add(getMethod);
173 methods.Add(setMethod);
174 properties.Add(property.NormalizeWhitespace());
175 }
176 var profileClassSyntaxTree = GenerateProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, methods, fileScopedNamespaceDeclarationSyntax);
177 context.AddSource($"{className}.g.cs", profileClassSyntaxTree.ToString());
178 }
179 }
180 }
181
182 public static bool IsProfilePropertyAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "ProfileProperty");
183
184 public static List<AttributeSyntax> GetProfilePropertyAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsProfilePropertyAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
185
186 public static bool IsAutoLoadProfileAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "AutoLoadProfile");
187
188 public static List<AttributeSyntax> GetAutoLoadProfileAttribute(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsAutoLoadProfileAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
189
190 public static bool IsProfilePropertyAddGetAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "ProfilePropertyAddGet");
191
192 public static List<AttributeSyntax> GetProfilePropertyAddGetAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsProfilePropertyAddGetAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
193
194 public static bool IsProfilePropertyAddSetAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "ProfilePropertyAddSet");
195
196 public static List<AttributeSyntax> GetProfilePropertyAddSetAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsProfilePropertyAddSetAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
197
198 public static FileScopedNamespaceDeclarationSyntax GetFileScopedNamespaceDeclaration(SyntaxNode rootNode)
199 {
200 var namespaceResults = rootNode.DescendantNodes().OfType<FileScopedNamespaceDeclarationSyntax>();
201 if (namespaceResults != null && namespaceResults.Count() > 0)
202 return namespaceResults.First();
203 return null;
204 }
205
206 public static IEnumerable<FieldDeclarationSyntax> GetFieldDeclarations(ClassDeclarationSyntax classDeclaration) => classDeclaration.DescendantNodes()
207 .OfType<FieldDeclarationSyntax>()
208 .Where(fieldDeclarationSyntax => fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAttribute) && !fieldDeclarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword));
209
210 public static IEnumerable<ClassDeclarationSyntax> GetClassDeclarations(SyntaxNode rootNode) => rootNode.DescendantNodes()
211 .OfType<ClassDeclarationSyntax>()
212 .Where(classDeclaration => classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword) && !classDeclaration.Modifiers.Any(SyntaxKind.StaticKeyword));
213
214 private static SyntaxTree GenerateProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MethodDeclarationSyntax> methodDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
215 {
216 var className = classDeclaration.Identifier.ValueText;
217 var triviaText = $@"/// <remarks>
218 /// <code><seealso cref=""{className}""/> 已自动实现以下属性:</code><br/>
219 /// <code>
220 ";
221 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";
222 var memberDeclarations = new List<MemberDeclarationSyntax>
223 {
224 SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
225 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
226 .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.ProfileExtension.ProfileInstanceAttribute")))))
227 .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
228 new[]
229 {
230 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
231 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
232 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
233 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
234 })))
235 .WithInitializer(SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression($"new {className}()")))
236 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
237 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
238 /// 该配置文件的实例<br/>
239 /// <seealso cref=""Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
240 /// </summary>
241 "))
242 };
243 memberDeclarations.AddRange(propertyDeclarationSyntaxes);
244 memberDeclarations.AddRange(methodDeclarationSyntaxes);
245 var staticConstructorSyntax = SyntaxFactory.ConstructorDeclaration(className)
246 .AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword))
247 .WithBody(SyntaxFactory.Block(
248 SyntaxFactory.ParseStatement($"global::XFEExtension.NetCore.ProfileExtension.XFEProfile.LoadProfiles(typeof({className}));")));
249 if (classDeclaration.AttributeLists.Any(IsAutoLoadProfileAttribute))
250 {
251 var autoLoadProfileAttribute = classDeclaration.AttributeLists.First(attributeList => IsAutoLoadProfileAttribute(attributeList)).Attributes.First();
252 if (autoLoadProfileAttribute.ArgumentList != null)
253 {
254 var argument = autoLoadProfileAttribute.ArgumentList.Arguments.First();
255 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText == "true")
256 {
257 memberDeclarations.Add(staticConstructorSyntax);
258 }
259 }
260 else
261 {
262 memberDeclarations.Add(staticConstructorSyntax);
263 }
264 }
265 else
266 {
267 memberDeclarations.Add(staticConstructorSyntax);
268 }
269 var profileClass = SyntaxFactory.ClassDeclaration(className)
270 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
271 .AddMembers(memberDeclarations.ToArray())
272 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
273 .NormalizeWhitespace();
274 MemberDeclarationSyntax memberDeclaration;
275 if (fileScopedNamespaceDeclarationSyntax is null)
276 {
277 var namespaceDeclaration = classDeclaration.FirstAncestorOrSelf<NamespaceDeclarationSyntax>();
278 if (namespaceDeclaration is null)
279 memberDeclaration = profileClass;
280 else
281 memberDeclaration = SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
282 .AddMembers(profileClass);
283 }
284 else
285 {
286 memberDeclaration = SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
287 .AddMembers(profileClass);
288 }
289 var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
290 .AddUsings(usingDirectiveSyntaxes)
291 .AddMembers(memberDeclaration)
292 .NormalizeWhitespace();
293 return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
294 }
295 }
296 }
Deleted XFEExtension.NetCore.Analyzer/Generator/ProfilePropertySyntaxReceiver.cs +0 -23
@@ -1,23 +0,0 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp.Syntax;
3 using System.Collections.Generic;
4 using System.Linq;
5
6 namespace XFEExtension.NetCore.Analyzer.Generator
7 {
8 public class ProfilePropertySyntaxReceiver : ISyntaxReceiver
9 {
10 public List<FieldDeclarationSyntax> CandidateFields { get; } = new List<FieldDeclarationSyntax>();
11
12 public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
13 {
14 if (syntaxNode is FieldDeclarationSyntax fieldDeclarationSyntax)
15 {
16 if (fieldDeclarationSyntax.AttributeLists.Any(ProfilePropertyAutoGenerator.IsProfilePropertyAttribute))
17 {
18 CandidateFields.Add(fieldDeclarationSyntax);
19 }
20 }
21 }
22 }
23 }
Deleted XFEExtension.NetCore.Analyzer/GeneratorOptions.cs +0 -27
@@ -1,27 +0,0 @@
1 using Microsoft.CodeAnalysis;
2
3 namespace XFEExtension.NetCore.Analyzer
4 {
5 public class GeneratorOptions
6 {
7 public static bool AutoProfile { get; set; } = true;
8 public static bool AutoPath { get; set; } = true;
9 public static bool AutoImplement { get; set; } = true;
10 public static bool TodoList { get; set; } = true;
11 public static int TodoListWarningLevel { get; set; } = 2;
12 public static void GetOptions(GeneratorExecutionContext context)
13 {
14 if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AutoProfile", out var autoProfile))
15 AutoProfile = autoProfile.ToLower() == "true";
16 if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AutoPath", out var autoPath))
17 AutoPath = autoPath.ToLower() == "true";
18 if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AutoImplement", out var autoImplement))
19 AutoImplement = autoImplement.ToLower() == "true";
20 if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.TodoList", out var todoList))
21 TodoList = todoList.ToLower() == "true";
22 if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.TodoListWarningLevel", out var todoListWarningLevel))
23 if (int.TryParse(todoListWarningLevel, out var warningLevel))
24 TodoListWarningLevel = warningLevel;
25 }
26 }
27 }
Modified XFEExtension.NetCore.Analyzer/XFEExtension.NetCore.Analyzer.csproj +3 -6
Deleted XFEExtension.NetCore/ImplExtension/CreateImpl.cs +0 -7
Deleted XFEExtension.NetCore/PathExtension/AutoPathAttribute.cs +0 -27
Deleted XFEExtension.NetCore/PathExtension/XFEAutoPath.cs +0 -18
Deleted XFEExtension.NetCore/ProfileExtension/AutoLoadProfileAttribute.cs +0 -14
Deleted XFEExtension.NetCore/ProfileExtension/ProfileEntryInfo.cs +0 -20
Deleted XFEExtension.NetCore/ProfileExtension/ProfileFieldAutoGenerateAttribute.cs +0 -9
Deleted XFEExtension.NetCore/ProfileExtension/ProfileInfo.cs +0 -62
Deleted XFEExtension.NetCore/ProfileExtension/ProfileInstanceAttribute.cs +0 -7
Deleted XFEExtension.NetCore/ProfileExtension/ProfilePropertyAddGetAttribute.cs +0 -14
Deleted XFEExtension.NetCore/ProfileExtension/ProfilePropertyAddSetAttribute.cs +0 -14
Deleted XFEExtension.NetCore/ProfileExtension/ProfilePropertyAttribute.cs +0 -25
Deleted XFEExtension.NetCore/ProfileExtension/XFEProfile.cs +0 -304
Modified XFEExtension.NetCore/XFEExtension.NetCore.csproj +3 -11