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
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..abeff31 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);
- }
-}
\ No newline at end of file
+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";
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs
index bcff3b7..0666d80 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}\"";
- }
-}
\ No newline at end of file
+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}\"";
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetConstructorArgumentValue.cs
index a558255..6a169c6 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;
- }
-}
\ No newline at end of file
+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;
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.Attribute.GetNamedArgumentValue.cs
index 914561d..5fd0eb1 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);
- }
-}
\ No newline at end of file
+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);
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs
index 1f91144..9c59d83 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);
- }
-}
\ No newline at end of file
+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);
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetDisplayedData.cs
index c6ab7a9..b68d81b 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;
- }
-}
\ No newline at end of file
+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;
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumFields.cs
index edab470..003ad7d 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;
- }
-}
\ No newline at end of file
+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;
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetEnumUnderlyingType.cs
index 75de027..af546ea 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;
-}
\ No newline at end of file
+using Microsoft.CodeAnalysis;
+
+namespace PrimeFuncPack;
+
+partial class CodeAnalysisExtensions
+{
+ public static INamedTypeSymbol? GetEnumUnderlyingType(this ITypeSymbol typeSymbol)
+ =>
+ typeSymbol is INamedTypeSymbol namedTypeSymbol ? namedTypeSymbol.EnumUnderlyingType : null;
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonProperties.cs
index 77ce25e..ad4cdac 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;
- }
- }
-}
\ No newline at end of file
+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;
+ }
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.GetJsonPropertyName.cs
index f3d9198..6196330 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");
- }
-}
\ No newline at end of file
+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");
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.IsAnyType.cs
index 8cb7abd..ea4f7f4 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);
- }
-}
\ No newline at end of file
+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);
+ }
+}
diff --git a/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs b/src/CodeAnalysis.Extensions/Extensions/Ext.IsType.cs
index 867a211..aca7a20 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);
-}
\ No newline at end of file
+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);
+}
diff --git a/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs b/src/CodeAnalysis.Extensions/TypeData/DisplayedTypeData.cs
index 2aa6b38..2272ad8 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; }
-}
\ No newline at end of file
+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; }
+}
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..34022fc 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);
- }
-}
\ No newline at end of file
+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);
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AddUsing.cs
index 581e4fe..18769cb 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);
- }
-}
\ No newline at end of file
+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);
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendCodeLine.cs
index 2727003..cd91663 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder AppendCodeLines(params string[] codeLines)
+ {
+ foreach (var line in codeLines ?? [])
+ {
+ InnerAppendLineIndented(line);
+ }
+
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendDirective.cs
index f0fe1e5..4ce9e51 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;
- }
-}
\ No newline at end of file
+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;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.AppendEmptyLine.cs
index 082f3c4..ca3b3cf 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder AppendEmptyLine()
+ {
+ _ = codeBuilder.AppendLine();
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginArguments.cs
index ad3ffcb..7585163 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder BeginArguments()
+ {
+ currentIndentDepth++;
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCodeBlock.cs
index 5fa07ad..cf4cb68 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder BeginCodeBlock()
+ {
+ InnerAppendLineIndented("{");
+ currentIndentDepth++;
+
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginCollectionExpression.cs
index 58ff083..6d78b99 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder BeginCollectionExpression()
+ {
+ InnerAppendLineIndented("[");
+ currentIndentDepth++;
+
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.BeginLambda.cs
index 3ee022a..f38975f 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("=>");
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder BeginLambda()
+ {
+ currentIndentDepth++;
+ InnerAppendLineIndented("=>");
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.Build.cs
index 147a93a..e8f25b8 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;
- }
-}
\ No newline at end of file
+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;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndArguments.cs
index 28afe41..260284b 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder EndArguments()
+ {
+ currentIndentDepth--;
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCodeBlock.cs
index 29e04a8..2c87af3 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder EndCodeBlock(string? finalSymbol = default)
+ {
+ currentIndentDepth--;
+ InnerAppendLineIndented("}");
+
+ if (string.IsNullOrWhiteSpace(finalSymbol) is false)
+ {
+ _ = codeBuilder.Append(finalSymbol);
+ }
+
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndCollectionExpression.cs
index 2481025..e2ff97a 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder EndCollectionExpression(string? finalSymbol = default)
+ {
+ currentIndentDepth--;
+ InnerAppendLineIndented("]");
+
+ if (string.IsNullOrWhiteSpace(finalSymbol) is false)
+ {
+ _ = codeBuilder.Append(finalSymbol);
+ }
+
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/Builder.EndLambda.cs
index b318c2b..d6acaef 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;
- }
-}
\ No newline at end of file
+namespace PrimeFuncPack;
+
+partial class SourceBuilder
+{
+ public SourceBuilder EndLambda()
+ {
+ currentIndentDepth--;
+ return this;
+ }
+}
diff --git a/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs b/src/CodeAnalysis.SourceBuilder/SourceBuilder/SourceBuilder.cs
index 5c846e1..3a95c1d 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;
- }
-}
\ No newline at end of file
+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 = ';';
+ }
+}
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
+
+
+
+
+
+
+
+
+
+