From 83f6a73a539ccfff84036d7ca274bb8fd24cb4a4 Mon Sep 17 00:00:00 2001 From: Andrei Sergeev Date: Mon, 13 Apr 2026 22:48:41 +0400 Subject: [PATCH 1/3] release/v0.1.0 --- .gitignore | 68 ++++-- CodeAnalysis.sln | 28 --- LICENSE | 2 +- README.md | 5 +- docs/codeanalysis-extensions/README.md | 3 + docs/codeanalysis-sourcebuilder/README.md | 3 + docs/codeanalysis/README.md | 3 + .../CodeAnalysis.Extensions.csproj | 86 ++++---- .../Extensions/CodeAnalysisExtensions.cs | 50 +++-- .../Extensions/Ext.AsStringSourceCodeOr.cs | 34 +-- ...t.Attribute.GetConstructorArgumentValue.cs | 38 ++-- .../Ext.Attribute.GetNamedArgumentValue.cs | 41 ++-- .../Extensions/Ext.GetCollectionType.cs | 164 +++++++-------- .../Extensions/Ext.GetDisplayedData.cs | 194 +++++++++--------- .../Extensions/Ext.GetEnumFields.cs | 50 ++--- .../Extensions/Ext.GetEnumUnderlyingType.cs | 18 +- .../Extensions/Ext.GetJsonProperties.cs | 70 +++---- .../Extensions/Ext.GetJsonPropertyName.cs | 56 ++--- .../Extensions/Ext.IsAnyType.cs | 52 ++--- .../Extensions/Ext.IsType.cs | 32 +-- .../TypeData/DisplayedTypeData.cs | 30 +-- .../CodeAnalysis.SourceBuilder.csproj | 78 ++++--- .../SourceBuilder/Builder.AddAlias.cs | 51 +++-- .../SourceBuilder/Builder.AddUsing.cs | 95 ++++----- .../SourceBuilder/Builder.AppendCodeLine.cs | 33 ++- .../SourceBuilder/Builder.AppendDirective.cs | 38 ++-- .../SourceBuilder/Builder.AppendEmptyLine.cs | 18 +- .../SourceBuilder/Builder.BeginArguments.cs | 18 +- .../SourceBuilder/Builder.BeginCodeBlock.cs | 22 +- .../Builder.BeginCollectionExpression.cs | 22 +- .../SourceBuilder/Builder.BeginLambda.cs | 19 +- .../SourceBuilder/Builder.Build.cs | 89 ++++---- .../SourceBuilder/Builder.EndArguments.cs | 18 +- .../SourceBuilder/Builder.EndCodeBlock.cs | 32 +-- .../Builder.EndCollectionExpression.cs | 32 +-- .../SourceBuilder/Builder.EndLambda.cs | 18 +- .../SourceBuilder/SourceBuilder.cs | 92 +++++---- src/CodeAnalysis.slnx | 5 + src/CodeAnalysis/CodeAnalysis.csproj | 42 ++++ 39 files changed, 902 insertions(+), 847 deletions(-) delete mode 100644 CodeAnalysis.sln create mode 100644 docs/codeanalysis-extensions/README.md create mode 100644 docs/codeanalysis-sourcebuilder/README.md create mode 100644 docs/codeanalysis/README.md create mode 100644 src/CodeAnalysis.slnx create mode 100644 src/CodeAnalysis/CodeAnalysis.csproj diff --git a/.gitignore b/.gitignore index 8a30d25..47a94ef 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.user *.userosscache *.sln.docstates +*.env # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -21,17 +22,37 @@ mono_crash.* [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ -x64/ -x86/ + +[Dd]ebug/x64/ +[Dd]ebugPublic/x64/ +[Rr]elease/x64/ +[Rr]eleases/x64/ +bin/x64/ +obj/x64/ + +[Dd]ebug/x86/ +[Dd]ebugPublic/x86/ +[Rr]elease/x86/ +[Rr]eleases/x86/ +bin/x86/ +obj/x86/ + [Ww][Ii][Nn]32/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ +[Aa][Rr][Mm]64[Ee][Cc]/ bld/ -[Bb]in/ [Oo]bj/ +[Oo]ut/ [Ll]og/ [Ll]ogs/ +# Build results on 'Bin' directories +**/[Bb]in/* +# Uncomment if you have tasks that rely on *.refresh files to move binaries +# (https://github.com/github/gitignore/pull/3736) +#!**/[Bb]in/*.refresh + # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot @@ -43,12 +64,16 @@ Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* +*.trx # NUnit *.VisualState.xml TestResult.xml nunit-*.xml +# Approval Tests result files +*.received.* + # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ @@ -75,6 +100,7 @@ StyleCopReport.xml *.ilk *.meta *.obj +*.idb *.iobj *.pch *.pdb @@ -82,6 +108,8 @@ StyleCopReport.xml *.pgc *.pgd *.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp *.sbr *.tlb *.tli @@ -153,6 +181,7 @@ coverage*.info # NCrunch _NCrunch_* +.NCrunch_* .*crunch*.local.xml nCrunchTemp_* @@ -294,9 +323,6 @@ node_modules/ # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - # Visual Studio 6 workspace and project file (working project files containing files to include in project) *.dsw *.dsp @@ -314,22 +340,22 @@ node_modules/ _Pvt_Extensions # Paket dependency manager -.paket/paket.exe +**/.paket/paket.exe paket-files/ # FAKE - F# Make -.fake/ +**/.fake/ # CodeRush personal settings -.cr/personal +**/.cr/personal # Python Tools for Visual Studio (PTVS) -__pycache__/ +**/__pycache__/ *.pyc # Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config +#tools/** +#!tools/packages.config # Tabs Studio *.tss @@ -351,15 +377,19 @@ ASALocalRun/ # MSBuild Binary and Structured Log *.binlog +MSBuild_Logs/ + +# AWS SAM Build and Temporary Artifacts folder +.aws-sam # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder -.mfractor/ +**/.mfractor/ # Local History for Visual Studio -.localhistory/ +**/.localhistory/ # Visual Studio History (VSHistory) files .vshistory/ @@ -371,7 +401,7 @@ healthchecksdb MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder -.ionide/ +**/.ionide/ # Fody - auto-generated XML schema FodyWeavers.xsd @@ -382,17 +412,17 @@ FodyWeavers.xsd !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json -*.code-workspace +!.vscode/*.code-snippets # Local History for Visual Studio Code .history/ +# Built Visual Studio Code Extensions +*.vsix + # Windows Installer files from build outputs *.cab *.msi *.msix *.msm *.msp - -# JetBrains Rider -*.sln.iml diff --git a/CodeAnalysis.sln b/CodeAnalysis.sln deleted file mode 100644 index 8b290b0..0000000 --- a/CodeAnalysis.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis.Extensions", "src\CodeAnalysis.Extensions\CodeAnalysis.Extensions.csproj", "{B6C02DFB-D60E-4199-B880-F4CB6037B428}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis.SourceBuilder", "src\CodeAnalysis.SourceBuilder\CodeAnalysis.SourceBuilder.csproj", "{AFF0B5A4-3339-4CA8-B875-0D66CB784005}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B6C02DFB-D60E-4199-B880-F4CB6037B428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B6C02DFB-D60E-4199-B880-F4CB6037B428}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B6C02DFB-D60E-4199-B880-F4CB6037B428}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B6C02DFB-D60E-4199-B880-F4CB6037B428}.Release|Any CPU.Build.0 = Release|Any CPU - {AFF0B5A4-3339-4CA8-B875-0D66CB784005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AFF0B5A4-3339-4CA8-B875-0D66CB784005}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AFF0B5A4-3339-4CA8-B875-0D66CB784005}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AFF0B5A4-3339-4CA8-B875-0D66CB784005}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/LICENSE b/LICENSE index 2c39b4e..ff84acd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 PrimeFuncPack Foundation +Copyright (c) 2024-2026 Andrei Sergeev, Pavel Moskovoy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 162aa22..21670d7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ -# early-codeanalysis -EarlyFuncPack CodeAnalysis is a library for .NET for use in building source generators +# PrimeFuncPack CodeAnalysis + +PrimeFuncPack CodeAnalysis is a library pack for .NET for use in building source generators. diff --git a/docs/codeanalysis-extensions/README.md b/docs/codeanalysis-extensions/README.md new file mode 100644 index 0000000..bc38156 --- /dev/null +++ b/docs/codeanalysis-extensions/README.md @@ -0,0 +1,3 @@ +# PrimeFuncPack CodeAnalysis.Extensions + +PrimeFuncPack CodeAnalysis.Extensions is a library for .NET with special extensions for use in building source generators. diff --git a/docs/codeanalysis-sourcebuilder/README.md b/docs/codeanalysis-sourcebuilder/README.md new file mode 100644 index 0000000..ea393ca --- /dev/null +++ b/docs/codeanalysis-sourcebuilder/README.md @@ -0,0 +1,3 @@ +# PrimeFuncPack CodeAnalysis.SourceBuilder + +PrimeFuncPack CodeAnalysis.SourceBuilder is a library for .NET with a source builder for use in building source generators. diff --git a/docs/codeanalysis/README.md b/docs/codeanalysis/README.md new file mode 100644 index 0000000..21670d7 --- /dev/null +++ b/docs/codeanalysis/README.md @@ -0,0 +1,3 @@ +# PrimeFuncPack CodeAnalysis + +PrimeFuncPack CodeAnalysis is a library pack for .NET for use in building source generators. diff --git a/src/CodeAnalysis.Extensions/CodeAnalysis.Extensions.csproj b/src/CodeAnalysis.Extensions/CodeAnalysis.Extensions.csproj index e6811d4..9fc5d94 100644 --- a/src/CodeAnalysis.Extensions/CodeAnalysis.Extensions.csproj +++ b/src/CodeAnalysis.Extensions/CodeAnalysis.Extensions.csproj @@ -1,45 +1,41 @@ - - - - netstandard2.0 - latest - true - disable - enable - true - true - $(NoWarn);IDE0130;IDE0290 - true - LICENSE - README.md - https://github.com/pfpack/early-codeanalysis - https://github.com/pfpack/early-codeanalysis - pfpack - Andrei Sergeev, Pavel Moskovoy - Copyright © 2025 Andrei Sergeev, Pavel Moskovoy - EarlyFuncPack CodeAnalysis is a library for .NET for use in building source generators. - PrimeFuncPack - EarlyFuncPack.CodeAnalysis.Extensions - 0.0.1 - - - - - True - - - - True - - - - - - - - - - - - - \ No newline at end of file + + + + net10.0;netstandard2.0 + latest + true + disable + enable + true + true + $(NoWarn);IDE0130;IDE0290 + true + LICENSE + README.md + https://github.com/pfpack/early-codeanalysis + https://github.com/pfpack/early-codeanalysis + pfpack + Andrei Sergeev, Pavel Moskovoy + Copyright © 2024-2026 Andrei Sergeev, Pavel Moskovoy + PrimeFuncPack CodeAnalysis.Extensions is a library for .NET with special extensions for use in building source generators. + PrimeFuncPack + EarlyFuncPack.CodeAnalysis.Extensions + 0.1.0 + + + + + True + + + + True + + + + + + + + + diff --git a/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs b/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs index f19b4a4..b421b71 100644 --- a/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs +++ b/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs @@ -1,23 +1,29 @@ -namespace PrimeFuncPack; - -public static partial class CodeAnalysisExtensions -{ - private const string SystemNamespace = "System"; - - private const string SystemTextJsonSerializationNamespace = "System.Text.Json.Serialization"; - - private static string InnerWithCamelCase(this string source) - { - if (string.IsNullOrEmpty(source)) - { - return string.Empty; - } - - if (source.Length is 1) - { - return source.ToLowerInvariant(); - } - - return source[0].ToString().ToLowerInvariant() + source.Substring(1); - } +using System; + +namespace PrimeFuncPack; + +public static partial class CodeAnalysisExtensions +{ + private const StringComparison CodeLineComparison = StringComparison.InvariantCulture; + + private static string InnerToCamelCase(this string source) + { + if (string.IsNullOrEmpty(source)) + { + return ""; + } + +#if NET + return string.Concat([Char.ToLowerInvariant(source[0])], source.AsSpan(1)); +#else + return string.Concat(Char.ToLowerInvariant(source[0]).ToString(), source.Substring(1)); +#endif + } + + private static class InnerNamespaces + { + internal const string System = "System"; + + internal const string SystemTextJsonSerialization = "System.Text.Json.Serialization"; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs index bcff3b7..c8e5a85 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs @@ -1,18 +1,18 @@ -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static string AsStringSourceCodeOr(this string? source, string defaultSourceCode = "\"\"") - => - string.IsNullOrEmpty(source) ? defaultSourceCode : InnerWrapStringSourceCode(source!); - - public static string AsStringSourceCodeOrStringEmpty(this string? source) - => - string.IsNullOrEmpty(source) ? "string.Empty" : InnerWrapStringSourceCode(source!); - - private static string InnerWrapStringSourceCode(string source) - { - var encodedString = source.Replace("\"", "\\\""); - return $"\"{encodedString}\""; - } +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static string AsStringSourceCodeOr(this string? source, string defaultSourceCode = "\"\"") + => + string.IsNullOrEmpty(source) ? defaultSourceCode : InnerWrapStringSourceCode(source!); + + public static string AsStringSourceCodeOrStringEmpty(this string? source) + => + string.IsNullOrEmpty(source) ? "string.Empty" : InnerWrapStringSourceCode(source!); + + private static string InnerWrapStringSourceCode(string source) + { + var encodedString = source.Replace("\"", "\\\""); + return $"\"{encodedString}\""; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs index a558255..3f31215 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs @@ -1,20 +1,20 @@ -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static T? GetConstructorArgumentValue(this AttributeData attributeData, int constructorOrder) - => - (T?)attributeData.InnerGetConstructorArgumentValue(constructorOrder); - - private static object? InnerGetConstructorArgumentValue(this AttributeData? attributeData, int constructorOrder) - { - if (attributeData?.ConstructorArguments.Length <= constructorOrder) - { - return default; - } - - return attributeData?.ConstructorArguments[constructorOrder].Value; - } +using Microsoft.CodeAnalysis; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static T? GetConstructorArgumentValue(this AttributeData attributeData, int constructorOrder) + => + (T?)attributeData.InnerGetConstructorArgumentValue(constructorOrder); + + private static object? InnerGetConstructorArgumentValue(this AttributeData? attributeData, int constructorOrder) + { + if (attributeData?.ConstructorArguments.Length <= constructorOrder) + { + return default; + } + + return attributeData?.ConstructorArguments[constructorOrder].Value; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs index 914561d..7bafc9c 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs @@ -1,22 +1,21 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static T? GetNamedArgumentValue(this AttributeData attributeData, string propertyName) - => - (T?)attributeData.InnerGetNamedArgumentValue(propertyName); - - private static object? InnerGetNamedArgumentValue(this AttributeData? attributeData, string propertyName) - { - return attributeData?.NamedArguments.FirstOrDefault(IsNameMatched).Value.Value; - - bool IsNameMatched(KeyValuePair pair) - => - string.Equals(pair.Key, propertyName, StringComparison.InvariantCulture); - } +using Microsoft.CodeAnalysis; +using System.Collections.Generic; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static T? GetNamedArgumentValue(this AttributeData attributeData, string propertyName) + => + (T?)attributeData.InnerGetNamedArgumentValue(propertyName); + + private static object? InnerGetNamedArgumentValue(this AttributeData? attributeData, string propertyName) + { + return attributeData?.NamedArguments.FirstOrDefault(IsNameMatched).Value.Value; + + bool IsNameMatched(KeyValuePair pair) + => + string.Equals(pair.Key, propertyName, CodeLineComparison); + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs index 1f91144..42696f3 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs @@ -1,83 +1,83 @@ -using System; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static ITypeSymbol? GetCollectionTypeOrDefault(this ITypeSymbol typeSymbol) - { - if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol) - { - return arrayTypeSymbol.ElementType; - } - - if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) - { - return null; - } - - var enumerableInterface = namedTypeSymbol.AllInterfaces.FirstOrDefault(IsGenericEnumerable); - if (enumerableInterface is not null) - { - return enumerableInterface.TypeArguments[0]; - } - - return typeSymbol.GetMembers().OfType().Where(IsEnumeratorMethod).Select(GetEnumeratorType).FirstOrDefault(NotNull); - - static bool IsGenericEnumerable(INamedTypeSymbol symbol) - => - InnerIsType(symbol, "System.Collections.Generic", "IEnumerable") && symbol.TypeArguments.Length is 1; - - static bool IsEnumeratorMethod(IMethodSymbol methodSymbol) - => - methodSymbol.IsGenericMethod is false && - methodSymbol.Parameters.Length is 0 && - string.Equals(methodSymbol.Name, "GetEnumerator", StringComparison.InvariantCulture); - - static ITypeSymbol? GetEnumeratorType(IMethodSymbol methodSymbol) - => - methodSymbol.ReturnType?.InnerGetEnumeratorTypeOrDefault(); - - static bool NotNull(ITypeSymbol? typeSymbol) - => - typeSymbol is not null; - } - - private static ITypeSymbol? InnerGetEnumeratorTypeOrDefault(this ITypeSymbol typeSymbol) - { - if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) - { - return null; - } - - var enumeratorInterface = namedTypeSymbol.AllInterfaces.FirstOrDefault(IsGenericEnumerator); - if (enumeratorInterface is not null) - { - return enumeratorInterface.TypeArguments[0]; - } - - if (namedTypeSymbol.GetMembers().OfType().Any(IsMoveNextMethod) is false) - { - return null; - } - - return namedTypeSymbol.GetMembers().OfType().FirstOrDefault(IsCurrentProperty)?.Type; - - static bool IsGenericEnumerator(INamedTypeSymbol symbol) - => - InnerIsType(symbol, "System.Collections.Generic", "IEnumerator") && symbol.TypeArguments.Length is 1; - - static bool IsMoveNextMethod(IMethodSymbol methodSymbol) - => - methodSymbol.IsGenericMethod is false && - methodSymbol.Parameters.Length is 0 && - methodSymbol.ReturnType.InnerIsType(SystemNamespace, "Boolean") && - string.Equals(methodSymbol.Name, "MoveNext", StringComparison.InvariantCulture); - - static bool IsCurrentProperty(IPropertySymbol propertySymbol) - => - string.Equals(propertySymbol.Name, "Current", StringComparison.InvariantCulture); - } +using Microsoft.CodeAnalysis; +using System; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static ITypeSymbol? GetCollectionTypeOrDefault(this ITypeSymbol typeSymbol) + { + if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol) + { + return arrayTypeSymbol.ElementType; + } + + if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) + { + return null; + } + + var enumerableInterface = namedTypeSymbol.AllInterfaces.FirstOrDefault(IsGenericEnumerable); + if (enumerableInterface is not null) + { + return enumerableInterface.TypeArguments[0]; + } + + return typeSymbol.GetMembers().OfType().Where(IsEnumeratorMethod).Select(GetEnumeratorType).FirstOrDefault(NotNull); + + static bool IsGenericEnumerable(INamedTypeSymbol symbol) + => + InnerIsType(symbol, "System.Collections.Generic", "IEnumerable") && symbol.TypeArguments.Length is 1; + + static bool IsEnumeratorMethod(IMethodSymbol methodSymbol) + => + methodSymbol.IsGenericMethod is false && + methodSymbol.Parameters.Length is 0 && + string.Equals(methodSymbol.Name, "GetEnumerator", CodeLineComparison); + + static ITypeSymbol? GetEnumeratorType(IMethodSymbol methodSymbol) + => + methodSymbol.ReturnType?.InnerGetEnumeratorTypeOrDefault(); + + static bool NotNull(ITypeSymbol? typeSymbol) + => + typeSymbol is not null; + } + + private static ITypeSymbol? InnerGetEnumeratorTypeOrDefault(this ITypeSymbol typeSymbol) + { + if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) + { + return null; + } + + var enumeratorInterface = namedTypeSymbol.AllInterfaces.FirstOrDefault(IsGenericEnumerator); + if (enumeratorInterface is not null) + { + return enumeratorInterface.TypeArguments[0]; + } + + if (namedTypeSymbol.GetMembers().OfType().Any(IsMoveNextMethod) is false) + { + return null; + } + + return namedTypeSymbol.GetMembers().OfType().FirstOrDefault(IsCurrentProperty)?.Type; + + static bool IsGenericEnumerator(INamedTypeSymbol symbol) + => + InnerIsType(symbol, "System.Collections.Generic", "IEnumerator") && symbol.TypeArguments.Length is 1; + + static bool IsMoveNextMethod(IMethodSymbol methodSymbol) + => + methodSymbol.IsGenericMethod is false && + methodSymbol.Parameters.Length is 0 && + methodSymbol.ReturnType.InnerIsType(InnerNamespaces.System, "Boolean") && + string.Equals(methodSymbol.Name, "MoveNext", CodeLineComparison); + + static bool IsCurrentProperty(IPropertySymbol propertySymbol) + => + string.Equals(propertySymbol.Name, "Current", CodeLineComparison); + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs index c6ab7a9..0d8878a 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs @@ -1,98 +1,98 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static DisplayedTypeData GetDisplayedData(this ITypeSymbol typeSymbol, bool withNullableSymbol = false) - => - InnerGetDisplayedData( - typeSymbol: typeSymbol ?? throw new ArgumentNullException(nameof(typeSymbol)), - withNullableSymbol: withNullableSymbol); - - private static DisplayedTypeData InnerGetDisplayedData(ITypeSymbol typeSymbol, bool withNullableSymbol) - { - var symbol = typeSymbol; - var nullableSymbol = string.Empty; - - if (typeSymbol.InnerGetNullableBaseType() is ITypeSymbol baseTypeSymbol) - { - symbol = baseTypeSymbol; - if (withNullableSymbol) - { - nullableSymbol = "?"; - } - } - - if (symbol is IArrayTypeSymbol arrayTypeSymbol) - { - var elementTypeData = InnerGetChildrenDisplayedData(arrayTypeSymbol.ElementType); - - List elementTypeNameParts = [elementTypeData.DisplayedTypeName]; - elementTypeNameParts.AddRange(Enumerable.Repeat("[]", arrayTypeSymbol.Rank)); - - return new DisplayedTypeData( - allNamespaces: elementTypeData.AllNamespaces, - displayedTypeName: string.Concat(elementTypeNameParts) + nullableSymbol); - } - - if (symbol is not INamedTypeSymbol namedTypeSymbol || namedTypeSymbol.TypeArguments.Length is not > 0) - { - var typeNamespace = symbol.ContainingNamespace?.ToString(); - var typeNamespaces = new List(1); - - if (string.IsNullOrEmpty(typeNamespace) is false) - { - typeNamespaces.Add(typeNamespace ?? string.Empty); - } - - return new( - allNamespaces: typeNamespaces, - displayedTypeName: symbol.Name + nullableSymbol); - } - - var argumentTypes = namedTypeSymbol.TypeArguments.Select(InnerGetChildrenDisplayedData); - - return new( - allNamespaces: new List(argumentTypes.SelectMany(GetNamespaces)) - { - symbol.ContainingNamespace.ToString() - }, - displayedTypeName: $"{symbol.Name}<{string.Join(", ", argumentTypes.Select(GetName))}>{nullableSymbol}"); - - static DisplayedTypeData InnerGetChildrenDisplayedData(ITypeSymbol typeSymbol) - => - InnerGetDisplayedData(typeSymbol, true); - - static IEnumerable GetNamespaces(DisplayedTypeData typeData) - => - typeData.AllNamespaces; - - static string GetName(DisplayedTypeData typeData) - => - typeData.DisplayedTypeName; - } - - private static ITypeSymbol? InnerGetNullableBaseType(this ITypeSymbol typeSymbol) - { - if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) - { - return null; - } - - if (namedTypeSymbol.IsValueType is false) - { - return namedTypeSymbol.NullableAnnotation is NullableAnnotation.Annotated ? typeSymbol : null; - } - - if (namedTypeSymbol.TypeArguments.Length is 1 && namedTypeSymbol.InnerIsType(SystemNamespace, "Nullable")) - { - return namedTypeSymbol.TypeArguments[0]; - } - - return null; - } +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static DisplayedTypeData GetDisplayedData(this ITypeSymbol typeSymbol, bool withNullableSuffix = false) + => + InnerGetDisplayedData( + typeSymbol: typeSymbol ?? throw new ArgumentNullException(nameof(typeSymbol)), + withNullableSuffix: withNullableSuffix); + + private static DisplayedTypeData InnerGetDisplayedData(ITypeSymbol typeSymbol, bool withNullableSuffix) + { + var symbol = typeSymbol; + var nullableSuffix = ""; + + if (typeSymbol.InnerGetNullableBaseType() is ITypeSymbol baseTypeSymbol) + { + symbol = baseTypeSymbol; + if (withNullableSuffix) + { + nullableSuffix = "?"; + } + } + + if (symbol is IArrayTypeSymbol arrayTypeSymbol) + { + var elementTypeData = InnerGetChildrenDisplayedData(arrayTypeSymbol.ElementType); + + // TODO: Replace declaration of arrays of arrays to multidimensional arrays, + // like `[size1]`, `[size1, size2]` and so on, instead of `[][]` and so on. + IEnumerable elementTypeNameParts = + [elementTypeData.DisplayedTypeName, .. Enumerable.Repeat("[]", arrayTypeSymbol.Rank), nullableSuffix]; + + return new( + allNamespaces: elementTypeData.AllNamespaces, + displayedTypeName: string.Concat(elementTypeNameParts)); + } + + if (symbol is not INamedTypeSymbol namedTypeSymbol || namedTypeSymbol.TypeArguments.Length is not > 0) + { + var typeNamespace = symbol.ContainingNamespace?.ToString(); + IReadOnlyCollection typeNamespaces = string.IsNullOrEmpty(typeNamespace) ? [] : [typeNamespace!]; + + return new( + allNamespaces: typeNamespaces, + displayedTypeName: symbol.Name + nullableSuffix); + } + + var argumentTypes = namedTypeSymbol.TypeArguments.Select(InnerGetChildrenDisplayedData); + + var namespaces = argumentTypes.SelectMany(GetNamespaces); + if (symbol.ContainingNamespace?.ToString() is { } containingNamespace) + { + namespaces = namespaces.Append(containingNamespace); + } + + return new( + allNamespaces: [.. namespaces], + displayedTypeName: $"{symbol.Name}<{string.Join(", ", argumentTypes.Select(GetName))}>{nullableSuffix}"); + + static DisplayedTypeData InnerGetChildrenDisplayedData(ITypeSymbol typeSymbol) + => + InnerGetDisplayedData(typeSymbol, true); + + static IEnumerable GetNamespaces(DisplayedTypeData typeData) + => + typeData.AllNamespaces; + + static string GetName(DisplayedTypeData typeData) + => + typeData.DisplayedTypeName; + } + + private static ITypeSymbol? InnerGetNullableBaseType(this ITypeSymbol typeSymbol) + { + if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) + { + return null; + } + + if (namedTypeSymbol.IsValueType is false) + { + return namedTypeSymbol.NullableAnnotation is NullableAnnotation.Annotated ? typeSymbol : null; + } + + if (namedTypeSymbol.TypeArguments.Length is 1 && namedTypeSymbol.InnerIsType(InnerNamespaces.System, "Nullable")) + { + return namedTypeSymbol.TypeArguments[0]; + } + + return null; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs index edab470..66d06e0 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs @@ -1,26 +1,26 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static IEnumerable GetEnumFields(this ITypeSymbol typeSymbol) - { - if (typeSymbol is null) - { - return []; - } - - return typeSymbol.GetMembers().OfType().Where(IsPublic).Where(IsNameNotEmpty); - - static bool IsPublic(IFieldSymbol fieldSymbol) - => - fieldSymbol.DeclaredAccessibility is Accessibility.Public; - - static bool IsNameNotEmpty(IFieldSymbol fieldSymbol) - => - string.IsNullOrEmpty(fieldSymbol.Name) is false; - } +using Microsoft.CodeAnalysis; +using System.Collections.Generic; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static IEnumerable GetEnumFields(this ITypeSymbol typeSymbol) + { + if (typeSymbol is null) + { + return []; + } + + return typeSymbol.GetMembers().OfType().Where(IsPublic).Where(IsNameNotEmpty); + + static bool IsPublic(IFieldSymbol fieldSymbol) + => + fieldSymbol.DeclaredAccessibility is Accessibility.Public; + + static bool IsNameNotEmpty(IFieldSymbol fieldSymbol) + => + string.IsNullOrEmpty(fieldSymbol.Name) is false; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs index 75de027..8df736b 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static INamedTypeSymbol? GetEnumUnderlyingType(this ITypeSymbol typeSymbol) - => - typeSymbol is INamedTypeSymbol namedTypeSymbol ? namedTypeSymbol.EnumUnderlyingType : null; +using Microsoft.CodeAnalysis; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static INamedTypeSymbol? GetEnumUnderlyingType(this ITypeSymbol typeSymbol) + => + typeSymbol is INamedTypeSymbol namedTypeSymbol ? namedTypeSymbol.EnumUnderlyingType : null; } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs index 77ce25e..f908619 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs @@ -1,36 +1,36 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static IReadOnlyCollection GetJsonProperties(this ITypeSymbol typeSymbol) - { - if (typeSymbol is null) - { - return []; - } - - return typeSymbol.GetMembers().OfType().Where(IsPublic).Where(IsNotIgnored).ToArray(); - - static bool IsPublic(IPropertySymbol propertySymbol) - => - propertySymbol.DeclaredAccessibility is Accessibility.Public; - - static bool IsNotIgnored(IPropertySymbol propertySymbol) - => - propertySymbol.GetAttributes().Any(IsJsonIgnoreAttribute) is false; - - static bool IsJsonIgnoreAttribute(AttributeData attributeData) - { - if (InnerIsType(attributeData?.AttributeClass, SystemTextJsonSerializationNamespace, "JsonIgnoreAttribute") is not true) - { - return false; - } - - return attributeData.InnerGetNamedArgumentValue("Condition") is null or 1; - } - } +using Microsoft.CodeAnalysis; +using System.Collections.Generic; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static IReadOnlyCollection GetJsonProperties(this ITypeSymbol typeSymbol) + { + if (typeSymbol is null) + { + return []; + } + + return [.. typeSymbol.GetMembers().OfType().Where(IsPublic).Where(IsNotIgnored)]; + + static bool IsPublic(IPropertySymbol propertySymbol) + => + propertySymbol.DeclaredAccessibility is Accessibility.Public; + + static bool IsNotIgnored(IPropertySymbol propertySymbol) + => + propertySymbol.GetAttributes().Any(IsJsonIgnoreAttribute) is false; + + static bool IsJsonIgnoreAttribute(AttributeData attributeData) + { + if (InnerIsType(attributeData?.AttributeClass, InnerNamespaces.SystemTextJsonSerialization, "JsonIgnoreAttribute") is false) + { + return false; + } + + return attributeData.InnerGetNamedArgumentValue("Condition") is null or 1; + } + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs index f3d9198..8bc81c3 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs @@ -1,29 +1,29 @@ -using System; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static string GetJsonPropertyName(this IPropertySymbol propertySymbol) - { - _ = propertySymbol ?? throw new ArgumentNullException(nameof(propertySymbol)); - - var jsonPropertyNameAttribute = propertySymbol.GetAttributes().FirstOrDefault(IsJsonPropertyNameAttribute); - if (jsonPropertyNameAttribute is not null) - { - var name = jsonPropertyNameAttribute.InnerGetConstructorArgumentValue(0)?.ToString(); - if (string.IsNullOrEmpty(name) is false) - { - return name!; - } - } - - return propertySymbol.Name.InnerWithCamelCase(); - - static bool IsJsonPropertyNameAttribute(AttributeData attributeData) - => - InnerIsType(attributeData.AttributeClass, "System.Text.Json.Serialization", "JsonPropertyNameAttribute"); - } +using Microsoft.CodeAnalysis; +using System; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static string GetJsonPropertyName(this IPropertySymbol propertySymbol) + { + _ = propertySymbol ?? throw new ArgumentNullException(nameof(propertySymbol)); + + var jsonPropertyNameAttribute = propertySymbol.GetAttributes().FirstOrDefault(IsJsonPropertyNameAttribute); + if (jsonPropertyNameAttribute is not null) + { + var name = jsonPropertyNameAttribute.InnerGetConstructorArgumentValue(0)?.ToString(); + if (string.IsNullOrEmpty(name) is false) + { + return name!; + } + } + + return propertySymbol.Name.InnerToCamelCase(); + + static bool IsJsonPropertyNameAttribute(AttributeData attributeData) + => + InnerIsType(attributeData.AttributeClass, "System.Text.Json.Serialization", "JsonPropertyNameAttribute"); + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs index 8cb7abd..2e12ba3 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs @@ -1,27 +1,27 @@ -using System; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static bool IsAnyType(this ITypeSymbol typeSymbol, string @namespace, params string[] types) - { - if (typeSymbol is null || types?.Length is not > 0) - { - return false; - } - - if (string.Equals(typeSymbol.ContainingNamespace?.ToString(), @namespace, StringComparison.InvariantCulture) is false) - { - return false; - } - - return types.Any(IsEqualToType); - - bool IsEqualToType(string type) - => - string.Equals(typeSymbol.Name, type, StringComparison.InvariantCulture); - } +using Microsoft.CodeAnalysis; +using System; +using System.Linq; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static bool IsAnyType(this ITypeSymbol typeSymbol, string @namespace, params string[] types) + { + if (typeSymbol is null || types?.Length is not > 0) + { + return false; + } + + if (string.Equals(typeSymbol.ContainingNamespace?.ToString(), @namespace, CodeLineComparison) is false) + { + return false; + } + + return types.Any(IsEqualToType); + + bool IsEqualToType(string type) + => + string.Equals(typeSymbol.Name, type, CodeLineComparison); + } } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs index 867a211..be8e472 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs @@ -1,17 +1,17 @@ -using System; -using Microsoft.CodeAnalysis; - -namespace PrimeFuncPack; - -partial class CodeAnalysisExtensions -{ - public static bool IsType(this ITypeSymbol typeSymbol, string @namespace, string typeName) - => - InnerIsType(typeSymbol, @namespace, typeName); - - private static bool InnerIsType(this ITypeSymbol? typeSymbol, string @namespace, string typeName) - => - typeSymbol is not null && - string.Equals(typeSymbol.ContainingNamespace?.ToString(), @namespace, StringComparison.InvariantCulture) && - string.Equals(typeSymbol.Name, typeName, StringComparison.InvariantCulture); +using Microsoft.CodeAnalysis; +using System; + +namespace PrimeFuncPack; + +partial class CodeAnalysisExtensions +{ + public static bool IsType(this ITypeSymbol typeSymbol, string @namespace, string typeName) + => + InnerIsType(typeSymbol, @namespace, typeName); + + private static bool InnerIsType(this ITypeSymbol? typeSymbol, string @namespace, string typeName) + => + typeSymbol is not null && + string.Equals(typeSymbol.ContainingNamespace?.ToString(), @namespace, CodeLineComparison) && + string.Equals(typeSymbol.Name, typeName, CodeLineComparison); } \ No newline at end of file diff --git a/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs b/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs index 2aa6b38..8dbed94 100644 --- a/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs +++ b/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs @@ -1,16 +1,16 @@ -using System.Collections.Generic; - -namespace PrimeFuncPack; - -public sealed class DisplayedTypeData -{ - public DisplayedTypeData(IReadOnlyCollection allNamespaces, string displayedTypeName) - { - AllNamespaces = allNamespaces ?? []; - DisplayedTypeName = displayedTypeName ?? string.Empty; - } - - public IReadOnlyCollection AllNamespaces { get; } - - public string DisplayedTypeName { get; } +using System.Collections.Generic; + +namespace PrimeFuncPack; + +public sealed class DisplayedTypeData +{ + public DisplayedTypeData(IReadOnlyCollection allNamespaces, string displayedTypeName) + { + AllNamespaces = allNamespaces ?? []; + DisplayedTypeName = displayedTypeName ?? ""; + } + + public IReadOnlyCollection AllNamespaces { get; } + + public string DisplayedTypeName { get; } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/CodeAnalysis.SourceBuilder.csproj b/src/CodeAnalysis.SourceBuilder/CodeAnalysis.SourceBuilder.csproj index 25c2362..c9b2278 100644 --- a/src/CodeAnalysis.SourceBuilder/CodeAnalysis.SourceBuilder.csproj +++ b/src/CodeAnalysis.SourceBuilder/CodeAnalysis.SourceBuilder.csproj @@ -1,41 +1,37 @@ - - - - netstandard2.0 - latest - true - disable - enable - true - true - $(NoWarn);IDE0130;IDE0290 - true - LICENSE - README.md - https://github.com/pfpack/early-codeanalysis - https://github.com/pfpack/early-codeanalysis - pfpack - Andrei Sergeev, Pavel Moskovoy - Copyright © 2025 Andrei Sergeev, Pavel Moskovoy - EarlyFuncPack CodeAnalysis is a library for .NET for use in building source generators. - PrimeFuncPack - EarlyFuncPack.CodeAnalysis.SourceBuilder - 0.0.1 - - - - - True - - - - True - - - - - - - - - \ No newline at end of file + + + + net10.0;netstandard2.0 + latest + true + disable + enable + true + true + $(NoWarn);IDE0130;IDE0290 + true + LICENSE + README.md + https://github.com/pfpack/early-codeanalysis + https://github.com/pfpack/early-codeanalysis + pfpack + Andrei Sergeev, Pavel Moskovoy + Copyright © 2024-2026 Andrei Sergeev, Pavel Moskovoy + PrimeFuncPack CodeAnalysis.SourceBuilder is a library for .NET with a source builder for use in building source generators. + PrimeFuncPack + EarlyFuncPack.CodeAnalysis.SourceBuilder + 0.1.0 + + + + + True + + + + True + + + + + diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs index bf41735..07beadb 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs @@ -1,27 +1,26 @@ -using System; -using System.Linq; - -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder AddAlias(string alias) - { - if (string.IsNullOrWhiteSpace(alias)) - { - return this; - } - - if (aliases.Any(AliasEquals)) - { - return this; - } - - aliases.Add(alias); - return this; - - bool AliasEquals(string aliasValue) - => - string.Equals(aliasValue, alias, StringComparison.InvariantCulture); - } +using System.Linq; + +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder AddAlias(string alias) + { + if (string.IsNullOrWhiteSpace(alias)) + { + return this; + } + + if (aliases.Exists(IsAliasMatch)) + { + return this; + } + + aliases.Add(alias); + return this; + + bool IsAliasMatch(string match) + => + string.Equals(alias, match, CodeLineComparison); + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs index 581e4fe..04920d5 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs @@ -1,52 +1,45 @@ -using System; -using System.Linq; - -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder AddUsing(params string[] usings) - { - if (usings?.Length is not > 0) - { - return this; - } - - foreach (var @using in usings) - { - _ = InnerAddUsing(@using); - } - - return this; - } - - private SourceBuilder InnerAddUsing(string @using) - { - if (string.IsNullOrWhiteSpace(@using)) - { - return this; - } - - if (string.Equals(@using, @namespace, StringComparison.InvariantCulture)) - { - return this; - } - - if (@namespace.StartsWith(@using + ".", StringComparison.InvariantCulture)) - { - return this; - } - - if (usings.Any(UsingEquals)) - { - return this; - } - - usings.Add(@using); - return this; - - bool UsingEquals(string usingValue) - => - string.Equals(usingValue, @using, StringComparison.InvariantCulture); - } +using System.Linq; + +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder AddUsing(params string[] usings) + { + foreach (var @using in usings ?? []) + { + InnerAddUsing(@using); + } + + return this; + } + + private void InnerAddUsing(string @using) + { + if (string.IsNullOrWhiteSpace(@using)) + { + return; + } + + if (string.Equals(@using, @namespace, CodeLineComparison)) + { + return; + } + + if (@namespace.StartsWith($"{@using}.", CodeLineComparison)) + { + return; + } + + if (usings.Exists(IsUsingMatch)) + { + return; + } + + usings.Add(@using); + + bool IsUsingMatch(string match) + => + string.Equals(@using, match, CodeLineComparison); + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs index 2727003..59a7016 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs @@ -1,21 +1,14 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder AppendCodeLine(params string[] codeLines) - { - if (codeLines?.Length is not > 0) - { - return this; - } - - var builder = this; - - foreach (var line in codeLines) - { - builder = InnerAppendLineWithTabulation(line); - } - - return builder; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder AppendCodeLines(params string[] codeLines) + { + foreach (var line in codeLines ?? []) + { + InnerAppendLineIndented(line); + } + + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs index f0fe1e5..565270e 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs @@ -1,20 +1,20 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder AppendDirective(string preprocessorDirective) - { - if (string.IsNullOrWhiteSpace(preprocessorDirective)) - { - return this; - } - - if (codeBuilder.Length > 0) - { - _ = codeBuilder.AppendLine(); - } - - _ = codeBuilder.Append(preprocessorDirective); - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder AppendDirective(string preprocessorDirective) + { + if (string.IsNullOrWhiteSpace(preprocessorDirective)) + { + return this; + } + + if (codeBuilder.Length > 0) + { + _ = codeBuilder.AppendLine(); + } + + _ = codeBuilder.Append(preprocessorDirective); + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs index 082f3c4..53d3f00 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs @@ -1,10 +1,10 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder AppendEmptyLine() - { - _ = codeBuilder.AppendLine(); - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder AppendEmptyLine() + { + _ = codeBuilder.AppendLine(); + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs index ad3ffcb..332c98d 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs @@ -1,10 +1,10 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder BeginArguments() - { - tabulationSize++; - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder BeginArguments() + { + currentIndentDepth++; + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs index 5fa07ad..9774e86 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs @@ -1,12 +1,12 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder BeginCodeBlock() - { - _ = InnerAppendLineWithTabulation("{"); - tabulationSize++; - - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder BeginCodeBlock() + { + InnerAppendLineIndented("{"); + currentIndentDepth++; + + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs index 58ff083..120e60f 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs @@ -1,12 +1,12 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder BeginCollectionExpression() - { - _ = InnerAppendLineWithTabulation("["); - tabulationSize++; - - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder BeginCollectionExpression() + { + InnerAppendLineIndented("["); + currentIndentDepth++; + + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs index 3ee022a..5cfd8fd 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs @@ -1,10 +1,11 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder BeginLambda() - { - tabulationSize++; - return InnerAppendLineWithTabulation("=>"); - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder BeginLambda() + { + currentIndentDepth++; + InnerAppendLineIndented("=>"); + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs index 147a93a..b5c4b05 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs @@ -1,46 +1,45 @@ -using System; -using System.Linq; -using System.Text; - -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public string Build() - { - var builder = new StringBuilder("// Auto-generated code by PrimeFuncPack").AppendLine().Append("#nullable enable"); - - if (usings.Count > 0) - { - builder = builder.AppendLine(); - } - - foreach (var @using in usings.OrderBy(GetNamespaceOrder)) - { - builder = builder.AppendLine().Append("using").Append(' ').Append(@using).Append(';'); - } - - builder = builder.AppendLine().AppendLine().Append("namespace").Append(' ').Append(@namespace).Append(';'); - - if (aliases.Count > 0) - { - builder = builder.AppendLine(); - } - - foreach (var alias in aliases) - { - builder = builder.AppendLine().Append("using").Append(' ').Append(alias).Append(';'); - } - - if (codeBuilder.Length is not > 0) - { - return builder.ToString(); - } - - return builder.AppendLine().AppendLine().Append(codeBuilder).ToString(); - - static string GetNamespaceOrder(string @namespace) - => - @namespace.StartsWith("System", StringComparison.InvariantCulture) ? "_" + @namespace : @namespace; - } +using System.Linq; +using System.Text; + +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public string Build() + { + var builder = new StringBuilder("// Auto-generated code by PrimeFuncPack").AppendLine().Append("#nullable enable"); + + if (usings.Count > 0) + { + builder = builder.AppendLine(); + } + + foreach (var @using in usings.OrderBy(NormalizeNamespaceOrder)) + { + builder = builder.AppendLine().Append("using").Append(InnerChars.Space).Append(@using).Append(InnerChars.Semicolon); + } + + builder = builder.AppendLine().AppendLine().Append("namespace").Append(InnerChars.Space).Append(@namespace).Append(InnerChars.Semicolon); + + if (aliases.Count > 0) + { + builder = builder.AppendLine(); + } + + foreach (var alias in aliases) + { + builder = builder.AppendLine().Append("using").Append(InnerChars.Space).Append(alias).Append(InnerChars.Semicolon); + } + + if (codeBuilder.Length is not > 0) + { + return builder.ToString(); + } + + return builder.AppendLine().AppendLine().Append(codeBuilder).ToString(); + + static string NormalizeNamespaceOrder(string @namespace) + => + @namespace.StartsWith("System", CodeLineComparison) ? $"_{@namespace}" : @namespace; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs index 28afe41..57f6377 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs @@ -1,10 +1,10 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder EndArguments() - { - tabulationSize--; - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder EndArguments() + { + currentIndentDepth--; + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs index 29e04a8..dc5ae45 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs @@ -1,17 +1,17 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder EndCodeBlock(string? finalSymbol = default) - { - tabulationSize--; - _ = InnerAppendLineWithTabulation("}"); - - if (string.IsNullOrWhiteSpace(finalSymbol) is false) - { - _ = codeBuilder.Append(finalSymbol); - } - - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder EndCodeBlock(string? finalSymbol = default) + { + currentIndentDepth--; + InnerAppendLineIndented("}"); + + if (string.IsNullOrWhiteSpace(finalSymbol) is false) + { + _ = codeBuilder.Append(finalSymbol); + } + + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs index 2481025..4f88c9f 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs @@ -1,17 +1,17 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder EndCollectionExpression(string? finalSymbol = default) - { - tabulationSize--; - _ = InnerAppendLineWithTabulation("]"); - - if (string.IsNullOrWhiteSpace(finalSymbol) is false) - { - _ = codeBuilder.Append(finalSymbol); - } - - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder EndCollectionExpression(string? finalSymbol = default) + { + currentIndentDepth--; + InnerAppendLineIndented("]"); + + if (string.IsNullOrWhiteSpace(finalSymbol) is false) + { + _ = codeBuilder.Append(finalSymbol); + } + + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs index b318c2b..105b7b7 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs @@ -1,10 +1,10 @@ -namespace PrimeFuncPack; - -partial class SourceBuilder -{ - public SourceBuilder EndLambda() - { - tabulationSize--; - return this; - } +namespace PrimeFuncPack; + +partial class SourceBuilder +{ + public SourceBuilder EndLambda() + { + currentIndentDepth--; + return this; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs index 5c846e1..e164489 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs @@ -1,40 +1,54 @@ -using System.Collections.Generic; -using System.Text; - -namespace PrimeFuncPack; - -public sealed partial class SourceBuilder -{ - private const int TabulationLength = 4; - - private readonly List usings = []; - - private readonly string @namespace; - - private readonly List aliases = []; - - private readonly StringBuilder codeBuilder = new(); - - private int tabulationSize = 0; - - public SourceBuilder(string? @namespace) - => - this.@namespace = string.IsNullOrWhiteSpace(@namespace) ? "PrimeFuncPack" : @namespace!; - - private SourceBuilder InnerAppendLineWithTabulation(string codeLine) - { - if (codeBuilder.Length > 0) - { - _ = codeBuilder.AppendLine(); - } - - if (tabulationSize > 0) - { - var tabulation = new string(' ', TabulationLength * tabulationSize); - _ = codeBuilder.Append(tabulation); - } - - _ = codeBuilder.Append(codeLine); - return this; - } +using System; +using System.Collections.Generic; +using System.Text; + +namespace PrimeFuncPack; + +public sealed partial class SourceBuilder +{ + private const StringComparison CodeLineComparison = StringComparison.InvariantCulture; + + private const int SingleIndentSize = 4; + + private readonly string @namespace; + + private readonly List usings = []; + + private readonly List aliases = []; + + private readonly StringBuilder codeBuilder = new(); + + private int currentIndentDepth; + + private int CurrentIndentSize => currentIndentDepth * SingleIndentSize; + + // TODO: Consider using global namespace instead of defaulting to the library namespace. + public SourceBuilder(string? @namespace = default) + => + this.@namespace = string.IsNullOrWhiteSpace(@namespace) ? $"{nameof(PrimeFuncPack)}" : @namespace!; + + private void InnerAppendLineIndented(string codeLine) + { + if (codeBuilder.Length > 0) + { + _ = codeBuilder.AppendLine(); + } + + if (currentIndentDepth > 0) + { + _ = codeBuilder.Append(InnerCurrentIndent()); + } + + _ = codeBuilder.Append(codeLine); + } + + private string InnerCurrentIndent() => new(InnerChars.Space, CurrentIndentSize); + + private static class InnerChars + { + // Use the escape sequence to avoid confusion with other whitespace characters. + internal const char Space = '\u0020'; + + internal const char Semicolon = ';'; + } } \ No newline at end of file diff --git a/src/CodeAnalysis.slnx b/src/CodeAnalysis.slnx new file mode 100644 index 0000000..c8098b1 --- /dev/null +++ b/src/CodeAnalysis.slnx @@ -0,0 +1,5 @@ + + + + + diff --git a/src/CodeAnalysis/CodeAnalysis.csproj b/src/CodeAnalysis/CodeAnalysis.csproj new file mode 100644 index 0000000..19090d5 --- /dev/null +++ b/src/CodeAnalysis/CodeAnalysis.csproj @@ -0,0 +1,42 @@ + + + + net10.0;netstandard2.0 + latest + true + disable + enable + true + true + $(NoWarn);IDE0130;IDE0290 + true + LICENSE + README.md + https://github.com/pfpack/early-codeanalysis + https://github.com/pfpack/early-codeanalysis + pfpack + Andrei Sergeev, Pavel Moskovoy + Copyright © 2024-2026 Andrei Sergeev, Pavel Moskovoy + PrimeFuncPack CodeAnalysis is a library pack for .NET for use in building source generators. + PrimeFuncPack + EarlyFuncPack.CodeAnalysis + 0.1.0 + + + + + True + + + + True + + + + + + + + + + From a63c4beb616d2474d85fa925771f2e3a1175d1ea Mon Sep 17 00:00:00 2001 From: Andrei Sergeev Date: Mon, 13 Apr 2026 22:53:06 +0400 Subject: [PATCH 2/3] Better diff --- .../Extensions/CodeAnalysisExtensions.cs | 2 +- .../Extensions/Ext.AsStringSourceCodeOr.cs | 2 +- .../Extensions/Ext.Attribute.GetConstructorArgumentValue.cs | 2 +- .../Extensions/Ext.Attribute.GetNamedArgumentValue.cs | 2 +- src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs | 2 +- src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs | 2 +- src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs | 2 +- .../Extensions/Ext.GetEnumUnderlyingType.cs | 2 +- src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs | 2 +- .../Extensions/Ext.GetJsonPropertyName.cs | 2 +- src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs | 2 +- src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs | 2 +- src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs | 2 +- .../SourceBuilder/Builder.AddAlias.cs | 2 +- .../SourceBuilder/Builder.AddUsing.cs | 2 +- .../SourceBuilder/Builder.AppendCodeLine.cs | 2 +- .../SourceBuilder/Builder.AppendDirective.cs | 2 +- .../SourceBuilder/Builder.AppendEmptyLine.cs | 2 +- .../SourceBuilder/Builder.BeginArguments.cs | 2 +- .../SourceBuilder/Builder.BeginCodeBlock.cs | 2 +- .../SourceBuilder/Builder.BeginCollectionExpression.cs | 2 +- .../SourceBuilder/Builder.BeginLambda.cs | 2 +- src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs | 2 +- .../SourceBuilder/Builder.EndArguments.cs | 2 +- .../SourceBuilder/Builder.EndCodeBlock.cs | 2 +- .../SourceBuilder/Builder.EndCollectionExpression.cs | 2 +- .../SourceBuilder/Builder.EndLambda.cs | 2 +- src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs b/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs index b421b71..abeff31 100644 --- a/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs +++ b/src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs @@ -26,4 +26,4 @@ private static class InnerNamespaces internal const string SystemTextJsonSerialization = "System.Text.Json.Serialization"; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs index c8e5a85..0666d80 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs @@ -15,4 +15,4 @@ private static string InnerWrapStringSourceCode(string source) var encodedString = source.Replace("\"", "\\\""); return $"\"{encodedString}\""; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs index 3f31215..6a169c6 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs @@ -17,4 +17,4 @@ partial class CodeAnalysisExtensions return attributeData?.ConstructorArguments[constructorOrder].Value; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs index 7bafc9c..5fd0eb1 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs @@ -18,4 +18,4 @@ bool IsNameMatched(KeyValuePair pair) => string.Equals(pair.Key, propertyName, CodeLineComparison); } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs index 42696f3..9c59d83 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs @@ -80,4 +80,4 @@ static bool IsCurrentProperty(IPropertySymbol propertySymbol) => string.Equals(propertySymbol.Name, "Current", CodeLineComparison); } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs index 0d8878a..b68d81b 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs @@ -95,4 +95,4 @@ static string GetName(DisplayedTypeData typeData) return null; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs index 66d06e0..003ad7d 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs @@ -23,4 +23,4 @@ static bool IsNameNotEmpty(IFieldSymbol fieldSymbol) => string.IsNullOrEmpty(fieldSymbol.Name) is false; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs index 8df736b..af546ea 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs @@ -7,4 +7,4 @@ partial class CodeAnalysisExtensions public static INamedTypeSymbol? GetEnumUnderlyingType(this ITypeSymbol typeSymbol) => typeSymbol is INamedTypeSymbol namedTypeSymbol ? namedTypeSymbol.EnumUnderlyingType : null; -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs index f908619..ad4cdac 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs @@ -33,4 +33,4 @@ static bool IsJsonIgnoreAttribute(AttributeData attributeData) return attributeData.InnerGetNamedArgumentValue("Condition") is null or 1; } } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs index 8bc81c3..6196330 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs @@ -26,4 +26,4 @@ static bool IsJsonPropertyNameAttribute(AttributeData attributeData) => InnerIsType(attributeData.AttributeClass, "System.Text.Json.Serialization", "JsonPropertyNameAttribute"); } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs index 2e12ba3..ea4f7f4 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs @@ -24,4 +24,4 @@ bool IsEqualToType(string type) => string.Equals(typeSymbol.Name, type, CodeLineComparison); } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs index be8e472..aca7a20 100644 --- a/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs +++ b/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs @@ -14,4 +14,4 @@ private static bool InnerIsType(this ITypeSymbol? typeSymbol, string @namespace, typeSymbol is not null && string.Equals(typeSymbol.ContainingNamespace?.ToString(), @namespace, CodeLineComparison) && string.Equals(typeSymbol.Name, typeName, CodeLineComparison); -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs b/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs index 8dbed94..2272ad8 100644 --- a/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs +++ b/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs @@ -13,4 +13,4 @@ public DisplayedTypeData(IReadOnlyCollection allNamespaces, string displ public IReadOnlyCollection AllNamespaces { get; } public string DisplayedTypeName { get; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs index 07beadb..34022fc 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddAlias.cs @@ -23,4 +23,4 @@ bool IsAliasMatch(string match) => string.Equals(alias, match, CodeLineComparison); } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs index 04920d5..18769cb 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs @@ -42,4 +42,4 @@ bool IsUsingMatch(string match) => string.Equals(@using, match, CodeLineComparison); } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs index 59a7016..cd91663 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs @@ -11,4 +11,4 @@ public SourceBuilder AppendCodeLines(params string[] codeLines) return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs index 565270e..4ce9e51 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs @@ -17,4 +17,4 @@ public SourceBuilder AppendDirective(string preprocessorDirective) _ = codeBuilder.Append(preprocessorDirective); return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs index 53d3f00..ca3b3cf 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs @@ -7,4 +7,4 @@ public SourceBuilder AppendEmptyLine() _ = codeBuilder.AppendLine(); return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs index 332c98d..7585163 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs @@ -7,4 +7,4 @@ public SourceBuilder BeginArguments() currentIndentDepth++; return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs index 9774e86..cf4cb68 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs @@ -9,4 +9,4 @@ public SourceBuilder BeginCodeBlock() return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs index 120e60f..6d78b99 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs @@ -9,4 +9,4 @@ public SourceBuilder BeginCollectionExpression() return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs index 5cfd8fd..f38975f 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs @@ -8,4 +8,4 @@ public SourceBuilder BeginLambda() InnerAppendLineIndented("=>"); return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs index b5c4b05..e8f25b8 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs @@ -42,4 +42,4 @@ static string NormalizeNamespaceOrder(string @namespace) => @namespace.StartsWith("System", CodeLineComparison) ? $"_{@namespace}" : @namespace; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs index 57f6377..260284b 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs @@ -7,4 +7,4 @@ public SourceBuilder EndArguments() currentIndentDepth--; return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs index dc5ae45..2c87af3 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs @@ -14,4 +14,4 @@ public SourceBuilder EndCodeBlock(string? finalSymbol = default) return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs index 4f88c9f..e2ff97a 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs @@ -14,4 +14,4 @@ public SourceBuilder EndCollectionExpression(string? finalSymbol = default) return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs index 105b7b7..d6acaef 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs @@ -7,4 +7,4 @@ public SourceBuilder EndLambda() currentIndentDepth--; return this; } -} \ No newline at end of file +} diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs index e164489..3a95c1d 100644 --- a/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs +++ b/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs @@ -51,4 +51,4 @@ private static class InnerChars internal const char Semicolon = ';'; } -} \ No newline at end of file +} From 5c4cf64717f18bbd16b40a4ed92e9c0694c52c61 Mon Sep 17 00:00:00 2001 From: Andrei Sergeev Date: Wed, 15 Apr 2026 23:36:39 +0400 Subject: [PATCH 3/3] Update github flow --- .github/workflows/dotnet.yml | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 6fecb38..c17c57e 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -1,12 +1,9 @@ -name: .NET +name: Setup CodeAnalysis .NET on: push: branches: [ main, dev, feature/*, fix/*, release/* ] - pull_request: - branches: [ main ] - release: types: [ published ] @@ -16,14 +13,15 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 + - name: Checkout repo + uses: actions/checkout@v6 + - name: Setup dotnet + uses: actions/setup-dotnet@v5 with: dotnet-version: | - 9.0.x + 10.0.x + # dotnet-quality: 'preview' # When using preview versions + dotnet-quality: 'ga' # General Availability # Create Local NuGet Source @@ -55,6 +53,17 @@ jobs: - name: Pack CodeAnalysis.SourceBuilder run: dotnet pack ./src/*/CodeAnalysis.SourceBuilder.csproj --no-restore -o ~/nuget -c Release + # CodeAnalysis + + - name: Restore CodeAnalysis + run: dotnet restore ./src/*/CodeAnalysis.csproj + + - name: Build CodeAnalysis + run: dotnet build ./src/*/CodeAnalysis.csproj --no-restore -c Release + + - name: Pack CodeAnalysis + run: dotnet pack ./src/*/CodeAnalysis.csproj --no-restore -o ~/nuget -c Release + # Push - name: Push Packages