Skip to content

Commit

Permalink
Create first version
Browse files Browse the repository at this point in the history
  • Loading branch information
pmosk committed Jun 19, 2024
1 parent 52b2ff5 commit bfab785
Show file tree
Hide file tree
Showing 32 changed files with 916 additions and 0 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: .NET

on:
push:
branches: [ main, dev, feature/*, fix/*, release/* ]

pull_request:
branches: [ main ]

release:
types: [ published ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
# Create Local NuGet Source

- name: Create Local NuGet Directory
run: mkdir ~/nuget

- name: Add Local Nuget Source
run: dotnet nuget add source ~/nuget

# CodeAnalysis.Extensions

- name: Restore CodeAnalysis.Extensions
run: dotnet restore ./src/*/CodeAnalysis.Extensions.csproj

- name: Build CodeAnalysis.Extensions
run: dotnet build ./src/*/CodeAnalysis.Extensions.csproj --no-restore -c Release

- name: Pack CodeAnalysis.Extensions
run: dotnet pack ./src/*/CodeAnalysis.Extensions.csproj --no-restore -o ~/nuget -c Release

# CodeAnalysis.SourceBuilder

- name: Restore CodeAnalysis.SourceBuilder
run: dotnet restore ./src/*/CodeAnalysis.SourceBuilder.csproj

- name: Build CodeAnalysis.SourceBuilder
run: dotnet build ./src/*/CodeAnalysis.SourceBuilder.csproj --no-restore -c Release

- name: Pack CodeAnalysis.SourceBuilder
run: dotnet pack ./src/*/CodeAnalysis.SourceBuilder.csproj --no-restore -o ~/nuget -c Release

# Push

- name: Push Packages
if: ${{ github.event_name == 'release' }}
run: >
dotnet nuget push "../../../nuget/*.nupkg"
-s https://api.nuget.org/v3/index.json
-k ${{ secrets.NuGetSourcePassword }}
--skip-duplicate
28 changes: 28 additions & 0 deletions CodeAnalysis.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

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
45 changes: 45 additions & 0 deletions src/CodeAnalysis.Extensions/CodeAnalysis.Extensions.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<InvariantGlobalization>true</InvariantGlobalization>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);IDE0130;IDE0290</NoWarn>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageProjectUrl>https://github.com/pfpack/early-codeanalysis</PackageProjectUrl>
<RepositoryUrl>https://github.com/pfpack/early-codeanalysis</RepositoryUrl>
<Company>pfpack</Company>
<Authors>Andrei Sergeev, Pavel Moskovoy</Authors>
<Copyright>Copyright © 2024 Andrei Sergeev, Pavel Moskovoy</Copyright>
<Description>EarlyFuncPack CodeAnalysis is a library for .NET for use in building source generators.</Description>
<RootNamespace>PrimeFuncPack</RootNamespace>
<AssemblyName>EarlyFuncPack.CodeAnalysis.Extensions</AssemblyName>
<Version>0.0.1-build.1</Version>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
<None Include="..\..\README.md">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.10.0" />
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions src/CodeAnalysis.Extensions/Extensions/CodeAnalysisExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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);
}
}
18 changes: 18 additions & 0 deletions src/CodeAnalysis.Extensions/Extensions/Ext.AsStringSourceCodeOr.cs
Original file line number Diff line number Diff line change
@@ -0,0 +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}\"";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.CodeAnalysis;

namespace PrimeFuncPack;

partial class CodeAnalysisExtensions
{
public static T? GetConstructorArgumentValue<T>(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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;

namespace PrimeFuncPack;

partial class CodeAnalysisExtensions
{
public static T? GetNamedArgumentValue<T>(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<string, TypedConstant> pair)
=>
string.Equals(pair.Key, propertyName, StringComparison.InvariantCulture);
}
}
83 changes: 83 additions & 0 deletions src/CodeAnalysis.Extensions/Extensions/Ext.GetCollectionType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +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<IMethodSymbol>().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");

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<IMethodSymbol>().Any(IsMoveNextMethod) is false)
{
return null;
}

return namedTypeSymbol.GetMembers().OfType<IPropertySymbol>().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");

static bool IsCurrentProperty(IPropertySymbol propertySymbol)
=>
string.Equals(propertySymbol.Name, "Current", StringComparison.InvariantCulture);
}
}
Loading

0 comments on commit bfab785

Please sign in to comment.