1 Commits

Author SHA1 Message Date
de03df1318 Tk (#1)
* <chore>

* 1.0.7

* <adjust>

* <chore>

* <chore>

* <refactor>

* <doc>

* <doc>

* <feat> + Unicode,UnicodeDe

* <revert>

* <fix>

* bugfix

* <feat> 从资源文件读取Description

* <feat> 从资源文件读取Description-可继承

* <fix> 将一个对象序列化成json文本

* <chore>

* 调整一下日志格式

* feat: * 泛型特性本地化资源描述 * 添加测试项目

* <chore>

* feat: enum、string

* feat: long 类型增加rand方法

* feat: ToInvString

* fix: ToInvString

* fix: ToInvString

* fix: ParameterFormat bug

* [BLD] [SKIP CI]
2023-09-28 09:37:45 +08:00
41 changed files with 524 additions and 318 deletions

View File

@ -10,22 +10,31 @@ indent_style = space
insert_final_newline = false
trim_trailing_whitespace = true
[{*.json,*.yml}]
indent_size = 2
[*.cs]
dotnet_analyzer_diagnostic.severity = warning
dotnet_diagnostic.CA1200.severity = none
dotnet_diagnostic.CA1707.severity = none
dotnet_diagnostic.CA1716.severity = none
dotnet_diagnostic.CA1848.severity = none
dotnet_diagnostic.CA2254.severity = none
dotnet_diagnostic.CA5350.severity = none
dotnet_diagnostic.CA5351.severity = none
dotnet_diagnostic.IDE0005.severity = none
dotnet_diagnostic.IDE0008.severity = none
dotnet_diagnostic.IDE0010.severity = none
dotnet_diagnostic.IDE0017.severity = none
dotnet_diagnostic.IDE0048.severity = none
dotnet_diagnostic.IDE0055.severity = none
dotnet_diagnostic.IDE0058.severity = none
dotnet_diagnostic.IDE0160.severity = none
dotnet_diagnostic.IDE0270.severity = none
dotnet_diagnostic.RCS1141.severity = none
dotnet_diagnostic.RCS1142.severity = none
dotnet_diagnostic.RCS1181.severity = none
dotnet_diagnostic.RCS1186.severity = none
dotnet_diagnostic.S101.severity = none
dotnet_diagnostic.S1121.severity = none
dotnet_diagnostic.S1199.severity = none
dotnet_diagnostic.S125.severity = none
dotnet_diagnostic.S2094.severity = none
dotnet_diagnostic.S3925.severity = none
dotnet_diagnostic.S4663.severity = none
dotnet_diagnostic.SYSLIB1045.severity = none

5
.gitignore vendored
View File

@ -400,5 +400,6 @@ FodyWeavers.xsd
# User Define
dist/
nuget.config
*.[Dd]esigner.cs
refs/
*.[Dd]esigner.cs
*.db

View File

@ -1,4 +1,4 @@
[hook "startcommit"]
cmdline = code-format.cmd
cmdline = dot.clean.cmd
wait = true
show = true

View File

@ -1,14 +0,0 @@
using System.Text.RegularExpressions;
var slnFile = Directory.GetFiles(@".", "*.sln").First();
var content = File.ReadAllText(slnFile);
content = Regex.Replace(content,@"ProjectSection\(SolutionItems\) = preProject(?:.|\n)*?EndProjectSection",
$"""
ProjectSection(SolutionItems) = preProject
{string.Join('\n',
Directory.GetFiles(@".", "*").Where(x => !x.EndsWith(".sln"))
.Select(x=>$"\t\t{Path.GetFileName(x)} = {Path.GetFileName(x)}"))}
{'\t'}EndProjectSection
""");
Console.WriteLine(content);
File.WriteAllText(slnFile, content);

View File

@ -1,27 +0,0 @@
#r "nuget: Newtonsoft.Json, 13.0.0"
using System.Xml;
using System.IO;
using Newtonsoft.Json.Linq;
var path = Directory.GetFiles(@".idea", "workspace.xml", SearchOption.AllDirectories).First();
XmlDocument xdoc = new XmlDocument();
using(var fs = File.Open(path, FileMode.Open)){
xdoc.Load(fs);
fs.Seek(0, SeekOrigin.Begin);
var propertiesComponent = xdoc.SelectSingleNode("""//component[@name="PropertiesComponent"]""");
var jsonStr = propertiesComponent.InnerText;
var jsonObj = JObject.Parse(jsonStr);
var keyToStringObj = jsonObj["keyToString"] as JObject;
if (keyToStringObj.ContainsKey("rider.code.cleanup.on.save")) return;
keyToStringObj.Add(new JProperty("rider.code.cleanup.on.save", "true"));
var newNode = xdoc.CreateCDataSection(jsonObj.ToString());
propertiesComponent.InnerText=string.Empty;
propertiesComponent.AppendChild(newNode);
var settings = new XmlWriterSettings { Indent = true };
using(var writer = XmlWriter.Create(fs, settings)){
xdoc.WriteTo(writer);
}
}

View File

@ -1,21 +0,0 @@
<Project>
<PropertyGroup>
<CodeAnalysisRuleSet>../../StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
<MSBuildWarningsAsErrors>true</MSBuildWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors>true</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NSCodeAnalysis" Version="1.0.1-alpha.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@ -6,8 +6,21 @@
<BaseIntermediateOutputPath>$(SolutionDir)/dist/$(MSBuildProjectName)/obj</BaseIntermediateOutputPath>
<BaseOutputPath>$(SolutionDir)/dist/$(MSBuildProjectName)/bin</BaseOutputPath>
<Copyright>© 2006-2023 nsnail</Copyright>
<Description>A .NET extension function library</Description>
<EnableBaseIntermediateOutputPathMismatchWarning>false</EnableBaseIntermediateOutputPathMismatchWarning>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net7.0</TargetFramework>
<MinVerDefaultPreReleaseIdentifiers>beta</MinVerDefaultPreReleaseIdentifiers>
<Product>NSExt</Product>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/nsnail/NSExt.git</RepositoryUrl>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<Title>$(AssemblyName)</Title>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MinVer" Version="5.0.0-alpha.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@ -1,45 +0,0 @@
/*
for %%i in (*.png) do pngquant %%i --force --output %%i --skip-if-larger
for %%i in (*.jpg) do jpegtran -copy none -optimize -perfect %%i %%i
*
*/
var files = Directory.EnumerateFiles(".", "*.png"
, new EnumerationOptions {
RecurseSubdirectories = true
, AttributesToSkip = FileAttributes.ReparsePoint
, IgnoreInaccessible = true
})
.ToArray();
Parallel.ForEach(files, file => {
var startInfo = new ProcessStartInfo {
FileName = "pngquant"
, Arguments
= $"\"{file}\" --force --output \"{file}\" --skip-if-larger"
};
using var p = Process.Start(startInfo);
p.WaitForExit();
Console.WriteLine($"{file}: {p.ExitCode}");
});
files = new[] { "*.jpg", "*.jpeg" }
.SelectMany(x => Directory.EnumerateFiles(
".", x
, new EnumerationOptions {
RecurseSubdirectories = true
, AttributesToSkip = FileAttributes.ReparsePoint
, IgnoreInaccessible = true
}))
.ToArray();
Parallel.ForEach(files, file => {
var startInfo = new ProcessStartInfo {
FileName = "jpegtran"
, Arguments = $"-copy none -optimize -perfect \"{file}\" \"{file}\""
};
using var p = Process.Start(startInfo);
p.WaitForExit();
Console.WriteLine($"{file}: {p.ExitCode}");
});

View File

@ -3,29 +3,33 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{85E669CB-FC0A-4C1D-92DE-38D0662C257D}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitattributes = .gitattributes
.gitignore = .gitignore
.tgitconfig = .tgitconfig
AddMetaFilesToSln.csx = AddMetaFilesToSln.csx
build.cake = build.cake
code-format.cmd = code-format.cmd
CodeCleanupOnSave.csx = CodeCleanupOnSave.csx
CodeQuality.props = CodeQuality.props
code.cleanup.full.ps1 = code.cleanup.full.ps1
code.quality.props = code.quality.props
Directory.Build.props = Directory.Build.props
dot.clean.cmd = dot.clean.cmd
dotnet-tools.json = dotnet-tools.json
git-clean.cmd = git-clean.cmd
git.pr.ps1 = git.pr.ps1
git.rc.ps1 = git.rc.ps1
global.json = global.json
ImageOptimize.csx = ImageOptimize.csx
image.optimize.csx = image.optimize.csx
key.snk = key.snk
LICENSE = LICENSE
logo.png = logo.png
NSExt.sln.DotSettings = NSExt.sln.DotSettings
NSExt.sln.DotSettings.user = NSExt.sln.DotSettings.user
nuget.config = nuget.config
packable.props = packable.props
README.md = README.md
README.zh-CN.md = README.zh-CN.md
stylecop.analyzers.ruleset = stylecop.analyzers.ruleset
stylecop.json = stylecop.json
StyleCopAnalyzers.ruleset = StyleCopAnalyzers.ruleset
sync.metafiles.csx = sync.metafiles.csx
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt.Tests", "src\NSExt.Tests\NSExt.Tests.csproj", "{557FBEF6-E6D5-4531-86DF-D772A10E2261}"

View File

@ -1,8 +1,23 @@
<wpf:ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve">
<s:String x:Key="/Default/CodeEditing/GenerateMemberBody/DocumentationGenerationKind/@EntryValue">Inherit</s:String>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/SkipClosingBracesOnTabInStringLiterals/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignmentInConditionalExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_RECORD_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IOS/@EntryIndexedValue">IOS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">True</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">OFF</s:String>
@ -55,5 +70,37 @@
&lt;/Entry&gt;
&lt;/TypePattern&gt;
&lt;/Patterns&gt;</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Aigc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Biji/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Childs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Depts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=fenlei/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFFFF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Furion/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Haojia/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hongbao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=inte/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lant/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=logourl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Meituan/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=miaosha/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nicktitle/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=qudao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Responsing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Smzdm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tabao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tablename/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Taobao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Taoke/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tese/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=timesort/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=weixin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=XBOXONE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=youhui/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yugao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=YYYYMMDD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=YYYYMMDDHHMMSSFFFZZZZ/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=zhiyou/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=zhuanlan/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

View File

@ -1,3 +0,0 @@
dot rbom -w
dot trim -w
dot tolf -w

1
code.cleanup.full.ps1 Normal file
View File

@ -0,0 +1 @@
dotnet jb cleanupcode --no-build ./NSExt.sln

43
code.quality.props Normal file
View File

@ -0,0 +1,43 @@
<Project>
<PropertyGroup>
<CodeAnalysisRuleSet>$(SolutionDir)/stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
<MSBuildWarningsAsErrors>true</MSBuildWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors>true</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.507">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.5.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.11.0.78383">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="AsyncSuffixAnalyzer" Version="1.0.6285.32977">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="AsyncFixer" Version="1.6.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ProductiveRage.SealedClassVerification.Net" Version="1.7.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<!-- <PackageReference Include="NSCodeAnalysis" Version="1.0.1-alpha.0.2">-->
<!-- <PrivateAssets>all</PrivateAssets>-->
<!-- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
<!-- </PackageReference>-->
</ItemGroup>
</Project>

3
dot.clean.cmd Normal file
View File

@ -0,0 +1,3 @@
dot rbom -w -e refs -e .git -e node_modules
dot trim -w -e refs -e .git -e node_modules
dot tolf -w -e refs -e .git -e node_modules

View File

@ -1,6 +1,24 @@
{
"version": 1,
"isRoot": true,
"tools": {
"version": 1,
"isRoot": true,
"tools": {
"cake.tool": {
"version": "3.1.0",
"commands": [
"dotnet-cake"
]
},
"dotnet-script": {
"version": "1.4.0",
"commands": [
"dotnet-script"
]
},
"jetbrains.resharper.globaltools": {
"version": "2023.2.0",
"commands": [
"jb"
]
}
}
}

View File

@ -1,2 +0,0 @@
git reset --hard
git clean -d -fx .

26
git.pr.ps1 Normal file
View File

@ -0,0 +1,26 @@
$types = @{
'1' = @('FEA', '新增特性')
'2' = @('REF', '项目重构')
'3' = @('FIX', '缺陷修复')
'4' = @('PER', '性能优化')
'5' = @('RVT', '还原变更')
'6' = @('FMT', '格式整理')
'7' = @('DOC', '文档变更')
'8' = @('TST', '单元测试')
'9' = @('BLD', '工程构建')
}
git add ./
$prefix = ''
while ($null -eq $types[$prefix])
{
$prefix = Read-Host "请选择提交类型`n" $( & { param($i) $i | ForEach-Object { "$_ : $( $types[$_][0] )$( $types[$_][1] )`n" } } $types.Keys | Sort-Object )
}
git commit -m "[$($types[$prefix][0])] $(($(Read-Host '是否跳过自动构建Y/n') -eq 'n') ? '': '[SKIP CI] ')$(Read-Host '请输入提交消息')"
$branch = $(git branch --show-current)
& './dot.clean.cmd'
git add ./
git commit --amend --no-edit
git pull
git push --set-upstream origin $branch
Start-Process -FilePath "https://github.com/nsnail/NSExt/compare/main...$branch"
Pause

6
git.rc.ps1 Normal file
View File

@ -0,0 +1,6 @@
$branch = $(git branch --show-current)
git checkout main
git pull
git branch -D $branch
git branch $branch
git checkout $branch

View File

@ -1,10 +1,10 @@
{
"sdk": {
"version": "7.0.100",
"allowPrerelease": true,
"rollForward": "major"
},
"tools": {
"dotnet": "7.0.100"
}
"sdk": {
"version": "7.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
},
"tools": {
"dotnet": "7.0.0"
}
}

65
image.optimize.csx Normal file
View File

@ -0,0 +1,65 @@
/*
for %%i in (*.png) do pngquant %%i --force --output %%i --skip-if-larger
for %%i in (*.jpg) do jpegtran -copy none -optimize -perfect %%i %%i
*
*/
var files = Directory
.EnumerateFiles(
"./",
"*.png",
new EnumerationOptions
{
RecurseSubdirectories = true,
AttributesToSkip = FileAttributes.ReparsePoint,
IgnoreInaccessible = true
}
)
.ToArray();
Parallel.ForEach(
files,
file =>
{
var startInfo = new ProcessStartInfo
{
FileName = "pngquant",
Arguments = $"\"{file}\" --force --output \"{file}\" --skip-if-larger"
};
using var p = Process.Start(startInfo);
p.WaitForExit();
Console.WriteLine($"{file}: {p.ExitCode}");
}
);
files = new[] { "*.jpg", "*.jpeg" }
.SelectMany(
x =>
Directory.EnumerateFiles(
"./",
x,
new EnumerationOptions
{
RecurseSubdirectories = true,
AttributesToSkip = FileAttributes.ReparsePoint,
IgnoreInaccessible = true
}
)
)
.ToArray();
Parallel.ForEach(
files,
file =>
{
var startInfo = new ProcessStartInfo
{
FileName = "jpegtran",
Arguments = $"-copy none -optimize -perfect \"{file}\" \"{file}\""
};
using var p = Process.Start(startInfo);
p.WaitForExit();
Console.WriteLine($"{file}: {p.ExitCode}");
}
);

8
nuget.config Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.cdn.azure.cn" value="https://nuget.cdn.azure.cn/v3/index.json" />
</packageSources>
</configuration>

18
packable.props Normal file
View File

@ -0,0 +1,18 @@
<Project>
<PropertyGroup>
<AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<EmbedAllSources>true</EmbedAllSources>
<EmbedUntrackedSource>true</EmbedUntrackedSource>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<IsPackable>true</IsPackable>
<PackageIcon>logo.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/nsnail/NSExt.git</PackageProjectUrl>
<PackageTags>extensions</PackageTags>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<SignAssembly>true</SignAssembly>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
</Project>

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0-preview-23424-02"/>
<PackageReference Include="xunit" Version="2.5.2-pre.2"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NSExt\NSExt.csproj" />
<ProjectReference Include="..\NSExt\NSExt.csproj"/>
</ItemGroup>
</Project>

View File

@ -1,8 +1,3 @@
using NSExt.Attributes;
using NSExt.Extensions;
using Xunit;
using Xunit.Abstractions;
namespace NSExt.Tests;
/// <summary>
@ -10,32 +5,32 @@ namespace NSExt.Tests;
/// </summary>
public class TestCase
{
private readonly ITestOutputHelper _testOutputHelper;
public TestCase(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
public enum MyEnum1
{
[ResourceDescription<TestCase>(nameof(Description))]
Online = 1
, Offline = 2
}
public static string Description { get; set; } = "123";
/// <summary>
/// Case1
/// </summary>
[Fact]
public void Case1()
{
var test = MyEnum1.Online.ResDesc<TestCase>();
_testOutputHelper.WriteLine(test);
Assert.True(test is not null);
}
// private readonly ITestOutputHelper _testOutputHelper;
//
// public TestCase(ITestOutputHelper testOutputHelper)
// {
// _testOutputHelper = testOutputHelper;
// }
//
// public enum MyEnum1
// {
// [ResourceDescription<TestCase>(nameof(Description))]
// Online = 1
//
// , Offline = 2
// }
//
// public static string Description { get; set; } = "123";
//
// /// <summary>
// /// Case1
// /// </summary>
// [Fact]
// public void Case1()
// {
// var test = MyEnum1.Online.ResDesc<TestCase>();
//
// _testOutputHelper.WriteLine(test);
// Assert.True(test is not null);
// }
}

View File

@ -4,7 +4,7 @@ namespace NSExt.Attributes;
/// 指定本地化资源类型
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
public class LocalizationAttribute : Attribute
public sealed class LocalizationAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="LocalizationAttribute" /> class.

View File

@ -4,7 +4,7 @@ namespace NSExt.Attributes;
/// 本地化资源描述特性
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
public class ResourceDescriptionAttribute<T> : Attribute
public sealed class ResourceDescriptionAttribute<T> : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="ResourceDescriptionAttribute{T}" /> class.

View File

@ -1,19 +1,21 @@
namespace NSExt.Constant;
#pragma warning disable SYSLIB1045
// 使用 RegexGenerator 新特性会生成重复key值的xmlcomment导致出错
/// <summary>
/// 使用 RegexGenerator 新特性会生成重复key值的xmlComment导致出错
/// </summary>
internal static class Regexes
{
public static readonly Regex RegexBacksLantUnicode
= new("\\\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
= new(@"\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex RegexHtmlTag = new("<[^>]*>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex RegexMobile
= new("^(\\d{3})\\d{4}(\\d{4})$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
= new(@"^(\d{3})\d{4}(\d{4})$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex RegexPercentUnicode
= new("\\\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
= new(@"\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex RegexUpLetter = new("([A-Z])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
}

View File

@ -50,10 +50,10 @@ public static class ByteExtensions
var i = 0;
foreach (var c in me.Select(x => x.ToString(upperCase ? "X2" : "x2", CultureInfo.InvariantCulture))) {
if (i++ % splitInterval == 0) {
sb.Append(splitShar);
_ = sb.Append(splitShar);
}
sb.Append(c);
_ = sb.Append(c);
}
return sb.ToString();

View File

@ -1,8 +1,7 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
#pragma warning disable SA1300
#pragma warning disable IDE1006
#pragma warning disable SA1300, IDE1006
namespace NSExt.Extensions;
/// <summary>
@ -10,19 +9,6 @@ namespace NSExt.Extensions;
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// 将一个过去时间对象与当前时间相减转换成“xx以前”的字符串, 如2秒以前, 3天以前
/// </summary>
/// <param name="me">me</param>
/// <returns>字符串</returns>
public static string TimeAgo(this DateTime me)
{
var ts = DateTime.Now - me;
return ts.Days > 0 ? ts.Days + "天前" :
ts.Hours > 0 ? ts.Hours + "小时前" :
ts.Minutes > 0 ? ts.Minutes + "分钟前" : ts.Seconds + "秒前";
}
/// <summary>
/// 指定时间的世界协调时的unix时间戳形式
/// </summary>
@ -41,6 +27,31 @@ public static class DateTimeExtensions
return (me.ToUniversalTime().Ticks - 621355968000000000) / 10000;
}
/// <summary>
/// ToString 的 Invariant 版本
/// </summary>
public static string ToInvString(this DateTime me)
{
return me.ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// 将一个过去时间对象与当前时间相减转换成“xx以前”的字符串, 如2秒以前, 3天以前
/// </summary>
/// <param name="me">me</param>
/// <returns>字符串</returns>
public static string UtcTimeAgo(this DateTime me)
{
var ts = DateTime.UtcNow - me;
return ts.Days switch {
> 0 => ts.Days + "天前"
, _ => ts.Hours switch {
> 0 => ts.Hours + "小时前"
, _ => ts.Minutes switch { > 0 => ts.Minutes + "分钟前", _ => ts.Seconds + "秒前" }
}
};
}
/// <summary>
/// yyyy_MM
/// </summary>

View File

@ -10,7 +10,6 @@ public static class DbCommandExtensions
/// </summary>
public static string ParameterFormat(this DbCommand me)
{
// var aa = pars.ToDictionary(it => it.ParameterName, it => it.Value);
var sql = me.CommandText;
// 应逆向替换,否则由于 多个表的过滤器问题导致替换不完整 如 @TenantId1 @TenantId10
@ -24,7 +23,10 @@ public static class DbCommandExtensions
me.Parameters[i].ParameterName, "'" + me.Parameters[i].Value + "'")
, DbType.Boolean => sql.Replace( //
me.Parameters[i].ParameterName
, Convert.ToBoolean(me.Parameters[i].Value, CultureInfo.InvariantCulture) ? "1" : "0")
, me.Parameters[i].Value != DBNull.Value &&
Convert.ToBoolean(me.Parameters[i].Value, CultureInfo.InvariantCulture)
? "1"
: "0")
, _ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
};
}

View File

@ -13,7 +13,14 @@ public static class DecimalExtensions
/// <returns>处理后的值</returns>
public static decimal Round(this decimal me, int place)
{
var dec = Math.Round(me, place);
return dec;
return Math.Round(me, place);
}
/// <summary>
/// ToString 的 Invariant 版本
/// </summary>
public static string ToInvString(this decimal me)
{
return me.ToString(CultureInfo.InvariantCulture);
}
}

View File

@ -9,35 +9,6 @@ namespace NSExt.Extensions;
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// 获取枚举的description属性
/// </summary>
/// <param name="e">枚举对象</param>
/// <returns>description属性</returns>
[Obsolete(nameof(ResDesc))]
public static string Desc(this Enum e)
{
var typeOfEnum = e.GetType();
var typeOfField = typeOfEnum.GetField(Enum.GetName(typeOfEnum, e)!);
var descAttr = typeOfField!.GetCustomAttribute<DescriptionAttribute>(true);
if (descAttr is null) {
return Enum.GetName(typeOfEnum, e);
}
var str = descAttr.Description;
var locAttr = typeOfField!.GetCustomAttribute<LocalizationAttribute>(true);
return locAttr is null ? str : locAttr.ResourceClass.GetProperty(str)?.GetValue(default) as string ?? str;
}
/// <summary>
/// 通过类泛型类型获取特性
/// </summary>
public static T GetAttributeOfType<T>(this Enum me)
where T : Attribute
{
return me.GetType().GetMember(me.ToString()).First().GetCustomAttributes<T>(false).FirstOrDefault();
}
/// <summary>
/// 获取显示特性
/// </summary>
@ -58,4 +29,13 @@ public static class EnumExtensions
? Enum.GetName(typeOfEnum, e)
: typeof(T).GetProperty(resDescAttr.ResourceName)?.GetValue(default) as string;
}
/// <summary>
/// 通过类泛型类型获取特性
/// </summary>
private static T GetAttributeOfType<T>(this Enum me)
where T : Attribute
{
return me.GetType().GetMember(me.ToString())[0].GetCustomAttributes<T>(false).FirstOrDefault();
}
}

View File

@ -21,6 +21,6 @@ public static class EnumerableExtensions
/// <returns>空则返回true</returns>
public static bool NullOrEmpty<T>(this IEnumerable<T> me)
{
return me is null || !me.Any();
return me?.Any() != true;
}
}

View File

@ -23,6 +23,14 @@ public static class IntExtensions
return new Random(Guid.NewGuid().GetHashCode()).Next(me[0], me[1]);
}
/// <summary>
/// ToString 的 Invariant 版本
/// </summary>
public static string ToInvString(this int me)
{
return me.ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// 转换成ipv4
/// </summary>

View File

@ -7,28 +7,28 @@ namespace NSExt.Extensions;
/// </summary>
public static class LoggerExtensions
{
private const string _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER
private const string _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER
= "{Message} <s:{CallerName}@{CallerFilePath}:{CallerLineNumber}>";
private static readonly Action<ILogger, string, string, string, string, Exception> _logDebug
= LoggerMessage.Define<string, string, string, string>(LogLevel.Debug, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logError
= LoggerMessage.Define<string, string, string, string>(LogLevel.Error, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logFatal
= LoggerMessage.Define<string, string, string, string>(LogLevel.Critical, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logInfo
= LoggerMessage.Define<string, string, string, string>(LogLevel.Information, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logWarn
= LoggerMessage.Define<string, string, string, string>(LogLevel.Warning, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
/// <summary>
/// Debug

View File

@ -15,11 +15,28 @@ public static class LongExtensions
return (me & val) == val;
}
/// <summary>
/// 生成随机数
/// </summary>
/// <param name="me">me</param>
public static long Rand(this long[] me)
{
return new Random(Guid.NewGuid().GetHashCode()).NextInt64(me[0], me[1]);
}
/// <summary>
/// 1970毫秒数转换成日期对象
/// </summary>
public static DateTime Time(this long msFrom1970)
{
return new DateTime(1970, 1, 1).AddMilliseconds(msFrom1970).ToLocalTime();
return DateTime.UnixEpoch.AddMilliseconds(msFrom1970).ToLocalTime();
}
/// <summary>
/// ToString 的 Invariant 版本
/// </summary>
public static string ToInvString(this long me)
{
return me.ToString(CultureInfo.InvariantCulture);
}
}

View File

@ -141,7 +141,7 @@ public static class StringExtensions
/// <returns>转换后的日期对象</returns>
public static DateTime DateTimeTry(this string me, DateTime def)
{
return !System.DateTime.TryParse(me, out var ret) ? def : ret;
return !System.DateTime.TryParse(me, CultureInfo.InvariantCulture, out var ret) ? def : ret;
}
/// <summary>
@ -252,7 +252,9 @@ public static class StringExtensions
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
public static string HmacSha1(this string me, string secret, Encoding e)
{
#pragma warning disable CA5350
using var hmacSha1 = new HMACSHA1(e.GetBytes(secret));
#pragma warning restore CA5350
return BitConverter.ToString(hmacSha1.ComputeHash(e.GetBytes(me)))
.Replace("-", string.Empty)
@ -379,7 +381,9 @@ public static class StringExtensions
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
public static string Md5(this string me, Encoding e)
{
#pragma warning disable CA5351
return BitConverter.ToString(MD5.HashData(e.GetBytes(me)))
#pragma warning restore CA5351
.Replace("-", string.Empty)
.ToLower(CultureInfo.CurrentCulture);
}
@ -462,7 +466,9 @@ public static class StringExtensions
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
public static string Sha1(this string me, Encoding e)
{
#pragma warning disable CA5350
return BitConverter.ToString(SHA1.HashData(e.GetBytes(me)))
#pragma warning restore CA5350
.Replace("-", string.Empty)
.ToLower(CultureInfo.CurrentCulture);
}
@ -470,7 +476,7 @@ public static class StringExtensions
/// <summary>
/// 蛇形命名
/// </summary>
public static string Snakecase(this string me)
public static string SnakeCase(this string me)
{
return Regexes.RegexUpLetter.Replace(me, "-$1").ToLower(CultureInfo.InvariantCulture).TrimStart('-');
}
@ -531,8 +537,18 @@ public static class StringExtensions
public static string UnicodeDe(this string me)
{
const string replacement = "&#x$1;";
return me.Contains(@"\u") ? Regexes.RegexBacksLantUnicode.Replace(me, replacement).HtmlDe() :
me.Contains(@"%u") ? Regexes.RegexPercentUnicode.Replace(me, replacement).HtmlDe() : me.HtmlDe();
if (me.Contains(@"\u")) {
return Regexes.RegexBacksLantUnicode.Replace(me, replacement).HtmlDe();
}
// ReSharper disable once ConvertIfStatementToReturnStatement
#pragma warning disable IDE0046
if (me.Contains("%u")) {
#pragma warning restore IDE0046
return Regexes.RegexPercentUnicode.Replace(me, replacement).HtmlDe();
}
return me.HtmlDe();
}
/// <summary>
@ -564,7 +580,9 @@ public static class StringExtensions
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
private static string Md5Hmac(this string me, string key, Encoding e)
{
#pragma warning disable CA5351
using var md5Hmac = new HMACMD5(e.GetBytes(key));
#pragma warning restore CA5351
return BitConverter.ToString(md5Hmac.ComputeHash(e.GetBytes(me)))
.Replace("-", string.Empty)
.ToLower(CultureInfo.CurrentCulture);

View File

@ -1,4 +1,3 @@
global using System.ComponentModel;
global using System.Data;
global using System.Data.Common;
global using System.Globalization;

View File

@ -1,35 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../CodeQuality.props" />
<PropertyGroup>
<AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<Description>A .NET extension function library</Description>
<EmbedAllSources>true</EmbedAllSources>
<EmbedUntrackedSource>true</EmbedUntrackedSource>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<IsPackable>true</IsPackable>
<PackageIcon>logo.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
<PackageTags>extensions</PackageTags>
<Product>NSExt</Product>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
<SignAssembly>true</SignAssembly>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Title>$(AssemblyName)</Title>
</PropertyGroup>
<Import Project="../../code.quality.props"/>
<Import Project="../../packable.props"/>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="MinVer" Version="4.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0-rc.1.23419.4"/>
</ItemGroup>
<ItemGroup>
<None Include="../../logo.png" Pack="true" PackagePath="" />
<None Include="../../logo.png" Pack="true" PackagePath=""/>
</ItemGroup>
</Project>

View File

@ -6,7 +6,6 @@
<Rule Id="SA0001" Action="Warning"/> <!-- XML comment analysis disabled -->
<Rule Id="SA0002" Action="Warning"/> <!-- Invalid settings file -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.SpacingRules">
<Rule Id="SA1000" Action="Warning"/> <!-- Keywords should be spaced correctly -->
<Rule Id="SA1001" Action="None"/> <!-- Commas should be spaced correctly -->
@ -31,34 +30,41 @@
<Rule Id="SA1020" Action="Warning"/> <!-- Increment decrement symbols should be spaced correctly -->
<Rule Id="SA1021" Action="Warning"/> <!-- Negative signs should be spaced correctly -->
<Rule Id="SA1022" Action="Warning"/> <!-- Positive signs should be spaced correctly -->
<Rule Id="SA1023" Action="Warning"/> <!-- Dereference and access of symbols should be spaced correctly -->
<Rule Id="SA1023"
Action="Warning"/> <!-- Dereference and access of symbols should be spaced correctly -->
<Rule Id="SA1024" Action="Warning"/> <!-- Colons should be spaced correctly -->
<Rule Id="SA1025" Action="None"/> <!-- Code should not contain multiple whitespace in a row -->
<Rule Id="SA1026" Action="Warning"/> <!-- Code should not contain space after new or stackalloc keyword in implicitly typed array allocation -->
<Rule Id="SA1026"
Action="Warning"/> <!-- Code should not contain space after new or stackalloc keyword in implicitly typed array allocation -->
<Rule Id="SA1027" Action="Warning"/> <!-- Use tabs correctly -->
<Rule Id="SA1028" Action="Warning"/> <!-- Code should not contain trailing whitespace -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.ReadabilityRules">
<Rule Id="SA1100" Action="Warning"/> <!-- Do not prefix calls with base unless local implementation exists -->
<Rule Id="SA1100"
Action="Warning"/> <!-- Do not prefix calls with base unless local implementation exists -->
<Rule Id="SA1101" Action="None"/> <!-- Prefix local calls with this -->
<Rule Id="SA1102" Action="Warning"/> <!-- Query clause should follow previous clause -->
<Rule Id="SA1103" Action="Warning"/> <!-- Query clauses should be on separate lines or all on one line -->
<Rule Id="SA1104" Action="Warning"/> <!-- Query clause should begin on new line when previous clause spans multiple lines -->
<Rule Id="SA1105" Action="Warning"/> <!-- Query clauses spanning multiple lines should begin on own line -->
<Rule Id="SA1103"
Action="Warning"/> <!-- Query clauses should be on separate lines or all on one line -->
<Rule Id="SA1104"
Action="Warning"/> <!-- Query clause should begin on new line when previous clause spans multiple lines -->
<Rule Id="SA1105"
Action="Warning"/> <!-- Query clauses spanning multiple lines should begin on own line -->
<Rule Id="SA1106" Action="Warning"/> <!-- Code should not contain empty statements -->
<Rule Id="SA1107" Action="Warning"/> <!-- Code should not contain multiple statements on one line -->
<Rule Id="SA1108" Action="Warning"/> <!-- Block statements should not contain embedded comments -->
<Rule Id="SA1109" Action="Warning"/> <!-- Block statements should not contain embedded regions -->
<Rule Id="SA1110" Action="Warning"/> <!-- Opening parenthesis or bracket should be on declaration line -->
<Rule Id="SA1110"
Action="Warning"/> <!-- Opening parenthesis or bracket should be on declaration line -->
<Rule Id="SA1111" Action="Warning"/> <!-- Closing parenthesis should be on line of last parameter -->
<Rule Id="SA1112" Action="Warning"/> <!-- Closing parenthesis should be on line of opening parenthesis -->
<Rule Id="SA1112"
Action="Warning"/> <!-- Closing parenthesis should be on line of opening parenthesis -->
<Rule Id="SA1113" Action="None"/> <!-- Comma should be on the same line as previous parameter -->
<Rule Id="SA1114" Action="Warning"/> <!-- Parameter list should follow declaration -->
<Rule Id="SA1115" Action="Warning"/> <!-- Parameter should follow comma -->
<Rule Id="SA1116" Action="Warning"/> <!-- Split parameters should start on line after declaration -->
<Rule Id="SA1117" Action="None"/> <!-- Parameters should be on same line or separate lines -->
<Rule Id="SA1118" Action="Warning"/> <!-- Parameter should not span multiple lines -->
<Rule Id="SA1118" Action="None"/> <!-- Parameter should not span multiple lines -->
<Rule Id="SA1120" Action="None"/> <!-- Comments should contain text -->
<Rule Id="SA1121" Action="Warning"/> <!-- Use built-in type alias -->
<Rule Id="SA1122" Action="Warning"/> <!-- Use string.Empty for empty strings -->
@ -80,7 +86,6 @@
<Rule Id="SA1139" Action="Warning"/> <!-- Use literal suffix notation instead of casting -->
<Rule Id="SX1101" Action="Warning"/> <!-- Do not prefix local calls with 'this.' -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.OrderingRules">
<Rule Id="SA1200" Action="None"/> <!-- Using directives should be placed correctly -->
<Rule Id="SA1201" Action="Warning"/> <!-- Elements should appear in the correct order -->
@ -90,37 +95,42 @@
<Rule Id="SA1205" Action="Warning"/> <!-- Partial elements should declare access -->
<Rule Id="SA1206" Action="Warning"/> <!-- Declaration keywords should follow order -->
<Rule Id="SA1207" Action="Warning"/> <!-- Protected should come before internal -->
<Rule Id="SA1208" Action="Warning"/> <!-- System using directives should be placed before other using directives -->
<Rule Id="SA1209" Action="Warning"/> <!-- Using alias directives should be placed after other using directives -->
<Rule Id="SA1210" Action="Warning"/> <!-- Using directives should be ordered alphabetically by namespace -->
<Rule Id="SA1211" Action="Warning"/> <!-- Using alias directives should be ordered alphabetically by alias name -->
<Rule Id="SA1208"
Action="Warning"/> <!-- System using directives should be placed before other using directives -->
<Rule Id="SA1209"
Action="Warning"/> <!-- Using alias directives should be placed after other using directives -->
<Rule Id="SA1210"
Action="Warning"/> <!-- Using directives should be ordered alphabetically by namespace -->
<Rule Id="SA1211"
Action="Warning"/> <!-- Using alias directives should be ordered alphabetically by alias name -->
<Rule Id="SA1212" Action="Warning"/> <!-- Property accessors should follow order -->
<Rule Id="SA1213" Action="Warning"/> <!-- Event accessors should follow order -->
<Rule Id="SA1214" Action="Warning"/> <!-- Readonly fields should appear before non-readonly fields -->
<Rule Id="SA1216" Action="Warning"/> <!-- Using static directives should be placed at the correct location -->
<Rule Id="SA1216"
Action="Warning"/> <!-- Using static directives should be placed at the correct location -->
<Rule Id="SA1217" Action="Warning"/> <!-- Using static directives should be ordered alphabetically -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.NamingRules">
<Rule Id="SA1300" Action="Warning"/> <!-- Element should begin with upper-case letter -->
<Rule Id="SA1301" Action="Warning"/> <!-- Element should begin with lower-case letter -->
<Rule Id="SA1302" Action="Warning"/> <!-- Interface names should begin with I -->
<Rule Id="SA1303" Action="Warning"/> <!-- Const field names should begin with upper-case letter -->
<Rule Id="SA1304" Action="Warning"/> <!-- Non-private readonly fields should begin with upper-case letter -->
<Rule Id="SA1304"
Action="Warning"/> <!-- Non-private readonly fields should begin with upper-case letter -->
<Rule Id="SA1305" Action="None"/> <!-- Field names should not use Hungarian notation -->
<Rule Id="SA1306" Action="Warning"/> <!-- Field names should begin with lower-case letter -->
<Rule Id="SA1307" Action="Warning"/> <!-- Accessible fields should begin with upper-case letter -->
<Rule Id="SA1308" Action="Warning"/> <!-- Variable names should not be prefixed -->
<Rule Id="SA1309" Action="None"/> <!-- Field names should not begin with underscore -->
<Rule Id="SA1310" Action="None"/> <!-- Field names should not contain underscore -->
<Rule Id="SA1311" Action="Warning"/> <!-- Static readonly fields should begin with upper-case letter -->
<Rule Id="SA1311"
Action="Warning"/> <!-- Static readonly fields should begin with upper-case letter -->
<Rule Id="SA1312" Action="Warning"/> <!-- Variable names should begin with lower-case letter -->
<Rule Id="SA1313" Action="Warning"/> <!-- Parameter names should begin with lower-case letter -->
<Rule Id="SA1313" Action="None"/> <!-- Parameter names should begin with lower-case letter -->
<Rule Id="SA1314" Action="Warning"/> <!-- Type parameter names should begin with T -->
<Rule Id="SX1309" Action="Warning"/> <!-- Field names should begin with underscore -->
<Rule Id="SX1309S" Action="Warning"/> <!-- Static field names should begin with underscore -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.MaintainabilityRules">
<Rule Id="SA1119" Action="Warning"/> <!-- Statement should not use unnecessary parenthesis -->
<Rule Id="SA1400" Action="Warning"/> <!-- Access modifier should be declared -->
@ -134,11 +144,11 @@
<Rule Id="SA1408" Action="Warning"/> <!-- Conditional expressions should declare precedence -->
<Rule Id="SA1409" Action="Warning"/> <!-- Remove unnecessary code -->
<Rule Id="SA1410" Action="Warning"/> <!-- Remove delegate parenthesis when possible -->
<Rule Id="SA1411" Action="Warning"/> <!-- Attribute constructor should not use unnecessary parenthesis -->
<Rule Id="SA1411"
Action="Warning"/> <!-- Attribute constructor should not use unnecessary parenthesis -->
<Rule Id="SA1412" Action="None"/> <!-- Store files as UTF-8 with byte order mark -->
<Rule Id="SA1413" Action="None"/> <!-- Use trailing comma in multi-line initializers -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.LayoutRules">
<Rule Id="SA1500" Action="None"/> <!-- Braces for multi-line statements should not share line -->
<Rule Id="SA1501" Action="Warning"/> <!-- Statement should not be on a single line -->
@ -146,23 +156,26 @@
<Rule Id="SA1503" Action="Warning"/> <!-- Braces should not be omitted -->
<Rule Id="SA1504" Action="Warning"/> <!-- All accessors should be single-line or multi-line -->
<Rule Id="SA1505" Action="Warning"/> <!-- Opening braces should not be followed by blank line -->
<Rule Id="SA1506" Action="Warning"/> <!-- Element documentation headers should not be followed by blank line -->
<Rule Id="SA1506"
Action="Warning"/> <!-- Element documentation headers should not be followed by blank line -->
<Rule Id="SA1507" Action="Warning"/> <!-- Code should not contain multiple blank lines in a row -->
<Rule Id="SA1508" Action="Warning"/> <!-- Closing braces should not be preceded by blank line -->
<Rule Id="SA1509" Action="Warning"/> <!-- Opening braces should not be preceded by blank line -->
<Rule Id="SA1510" Action="Warning"/> <!-- Chained statement blocks should not be preceded by blank line -->
<Rule Id="SA1510"
Action="Warning"/> <!-- Chained statement blocks should not be preceded by blank line -->
<Rule Id="SA1511" Action="Warning"/> <!-- While-do footer should not be preceded by blank line -->
<Rule Id="SA1512" Action="Warning"/> <!-- Single-line comments should not be followed by blank line -->
<Rule Id="SA1513" Action="Warning"/> <!-- Closing brace should be followed by blank line -->
<Rule Id="SA1514" Action="Warning"/> <!-- Element documentation header should be preceded by blank line -->
<Rule Id="SA1514"
Action="Warning"/> <!-- Element documentation header should be preceded by blank line -->
<Rule Id="SA1515" Action="Warning"/> <!-- Single-line comment should be preceded by blank line -->
<Rule Id="SA1516" Action="Warning"/> <!-- Elements should be separated by blank line -->
<Rule Id="SA1517" Action="Warning"/> <!-- Code should not contain blank lines at start of file -->
<Rule Id="SA1518" Action="Warning"/> <!-- Use line endings correctly at end of file -->
<Rule Id="SA1519" Action="Warning"/> <!-- Braces should not be omitted from multi-line child statement -->
<Rule Id="SA1519"
Action="Warning"/> <!-- Braces should not be omitted from multi-line child statement -->
<Rule Id="SA1520" Action="Warning"/> <!-- Use braces consistently -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.DocumentationRules">
<Rule Id="SA1600" Action="None"/> <!-- Elements should be documented -->
<Rule Id="SA1601" Action="None"/> <!-- Partial elements should be documented -->
@ -176,21 +189,28 @@
<Rule Id="SA1609" Action="None"/> <!-- Property documentation should have value -->
<Rule Id="SA1610" Action="Warning"/> <!-- Property documentation should have value text -->
<Rule Id="SA1611" Action="None"/> <!-- Element parameters should be documented -->
<Rule Id="SA1612" Action="Warning"/> <!-- Element parameter documentation should match element parameters -->
<Rule Id="SA1613" Action="Warning"/> <!-- Element parameter documentation should declare parameter name -->
<Rule Id="SA1612"
Action="Warning"/> <!-- Element parameter documentation should match element parameters -->
<Rule Id="SA1613"
Action="Warning"/> <!-- Element parameter documentation should declare parameter name -->
<Rule Id="SA1614" Action="Warning"/> <!-- Element parameter documentation should have text -->
<Rule Id="SA1615" Action="None"/> <!-- Element return value should be documented -->
<Rule Id="SA1616" Action="Warning"/> <!-- Element return value documentation should have text -->
<Rule Id="SA1617" Action="Warning"/> <!-- Void return value should not be documented -->
<Rule Id="SA1618" Action="None"/> <!-- Generic type parameters should be documented -->
<Rule Id="SA1619" Action="None"/> <!-- Generic type parameters should be documented partial class -->
<Rule Id="SA1620" Action="Warning"/> <!-- Generic type parameter documentation should match type parameters -->
<Rule Id="SA1621" Action="Warning"/> <!-- Generic type parameter documentation should declare parameter name -->
<Rule Id="SA1619"
Action="None"/> <!-- Generic type parameters should be documented partial class -->
<Rule Id="SA1620"
Action="Warning"/> <!-- Generic type parameter documentation should match type parameters -->
<Rule Id="SA1621"
Action="Warning"/> <!-- Generic type parameter documentation should declare parameter name -->
<Rule Id="SA1622" Action="Warning"/> <!-- Generic type parameter documentation should have text -->
<Rule Id="SA1623" Action="None"/> <!-- Property summary documentation should match accessors -->
<Rule Id="SA1624" Action="Warning"/> <!-- Property summary documentation should omit accessor with restricted access -->
<Rule Id="SA1624"
Action="Warning"/> <!-- Property summary documentation should omit accessor with restricted access -->
<Rule Id="SA1625" Action="Warning"/> <!-- Element documentation should not be copied and pasted -->
<Rule Id="SA1626" Action="Warning"/> <!-- Single-line comments should not use documentation style slashes -->
<Rule Id="SA1626"
Action="Warning"/> <!-- Single-line comments should not use documentation style slashes -->
<Rule Id="SA1627" Action="Warning"/> <!-- Documentation text should not be empty -->
<Rule Id="SA1628" Action="Warning"/> <!-- Documentation text should begin with a capital letter -->
<Rule Id="SA1629" Action="None"/> <!-- Documentation text should end with a period -->
@ -202,12 +222,15 @@
<Rule Id="SA1635" Action="Warning"/> <!-- File header should have copyright text -->
<Rule Id="SA1636" Action="Warning"/> <!-- File header copyright text should match -->
<Rule Id="SA1637" Action="Warning"/> <!-- File header should contain file name -->
<Rule Id="SA1638" Action="Warning"/> <!-- File header file name documentation should match file name -->
<Rule Id="SA1638"
Action="Warning"/> <!-- File header file name documentation should match file name -->
<Rule Id="SA1639" Action="Warning"/> <!-- File header should have summary -->
<Rule Id="SA1640" Action="Warning"/> <!-- File header should have valid company text -->
<Rule Id="SA1641" Action="Warning"/> <!-- File header company name text should match -->
<Rule Id="SA1642" Action="Warning"/> <!-- Constructor summary documentation should begin with standard text -->
<Rule Id="SA1643" Action="Warning"/> <!-- Destructor summary documentation should begin with standard text -->
<Rule Id="SA1642"
Action="Warning"/> <!-- Constructor summary documentation should begin with standard text -->
<Rule Id="SA1643"
Action="Warning"/> <!-- Destructor summary documentation should begin with standard text -->
<Rule Id="SA1644" Action="Warning"/> <!-- Documentation headers should not contain blank lines -->
<Rule Id="SA1645" Action="Warning"/> <!-- Included documentation file does not exist -->
<Rule Id="SA1646" Action="Warning"/> <!-- Included documentation XPath does not exist -->
@ -216,6 +239,5 @@
<Rule Id="SA1649" Action="Warning"/> <!-- File name should match first type name -->
<Rule Id="SA1650" Action="Warning"/> <!-- Element documentation should be spelled correctly -->
<Rule Id="SA1651" Action="Warning"/> <!-- Do not use placeholder elements -->
</Rules>
</RuleSet>

20
sync.metafiles.csx Normal file
View File

@ -0,0 +1,20 @@
using System.Text.RegularExpressions;
var slnFile = Directory.GetFiles(@"./", "*.sln").First();
var content = File.ReadAllText(slnFile);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"meta\", \"meta\", \"{5198A03D-0CAC-4828-A807-34A693F73859}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}"
{{'\t'}}ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"./", "*").Where(x => !x.EndsWith(".sln") && !x.EndsWith(".user"))
.Select(x=>$"\t\t{Path.GetFileName(x)} = {Path.GetFileName(x)}")
)}}
{{'\t'}}EndProject
"""
);
Console.WriteLine(content);
File.WriteAllText(slnFile, content);