Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ function BuildWith([string]$configuration)
exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.4 --verbosity $verbosity}
exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.6 --verbosity $verbosity}
exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.8 --verbosity $verbosity}
exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.11 --verbosity $verbosity}
exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.12 --verbosity $verbosity}

exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.4 --verbosity $verbosity}
exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.6 --verbosity $verbosity}
exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.8 --verbosity $verbosity}
exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.11 --verbosity $verbosity}
exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.12 --verbosity $verbosity}
}

function Get999VersionWithUniquePatch()
Expand Down Expand Up @@ -157,4 +161,3 @@ WriteStage("Finally, packing the release version into " + $artifacts)
exec { & dotnet pack src/Vogen.Pack/Vogen.Pack.csproj -c Release -o $artifacts --no-build --verbosity $verbosity }

WriteStage("Done! Package generated at " + $artifacts)

25 changes: 19 additions & 6 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@

<PropertyGroup>
<RoslynVersion></RoslynVersion>
</PropertyGroup>
</PropertyGroup>

<ItemGroup>
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
</ItemGroup>

<Choose>
<When Condition="$(RoslynVersion) == 'roslyn4.4'">
<ItemGroup>
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageReference Update="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.4.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.4.0" />
Expand All @@ -32,7 +35,6 @@

<When Condition="$(RoslynVersion) == 'roslyn4.6'">
<ItemGroup>
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
<PackageReference Update="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.6.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.6.0" />
Expand All @@ -46,7 +48,6 @@

<When Condition="$(RoslynVersion) == 'roslyn4.8'">
<ItemGroup>
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageReference Update="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.8.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.8.0" />
Expand All @@ -58,9 +59,8 @@
</PropertyGroup>
</When>

<Otherwise>
<When Condition="$(RoslynVersion) == 'roslyn4.11'">
<ItemGroup>
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
<PackageReference Update="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.11.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" />
Expand All @@ -70,6 +70,19 @@
<DefineConstants>$(DefineConstants);CSHARP9_OR_GREATER;CSHARP10_OR_GREATER;CSHARP11_OR_GREATER;CSHARP12_OR_GREATER;CSHARP13_OR_GREATER</DefineConstants>
<NoWarn>$(NoWarn);CS0618</NoWarn>
</PropertyGroup>
</When>

<Otherwise>
<ItemGroup>
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageReference Update="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.12.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
</ItemGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);ROSLYN4_12;ROSLYN_4_2_OR_GREATER;ROSLYN_4_4_OR_GREATER;ROSLYN_4_5_OR_GREATER;ROSLYN_4_6_OR_GREATER;ROSLYN_4_8_OR_GREATER;ROSLYN_4_10_OR_GREATER;ROSLYN_4_12_OR_GREATER</DefineConstants>
<DefineConstants>$(DefineConstants);CSHARP9_OR_GREATER;CSHARP10_OR_GREATER;CSHARP11_OR_GREATER;CSHARP12_OR_GREATER;CSHARP13_OR_GREATER</DefineConstants>
<NoWarn>$(NoWarn);CS0618</NoWarn>
</PropertyGroup>
</Otherwise>
</Choose>

Expand Down
15 changes: 10 additions & 5 deletions src/Vogen.Pack/Vogen.Pack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,17 @@
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.8\$(Configuration)\netstandard2.0\Vogen.dll" Pack="true" PackagePath="analyzers/dotnet/roslyn4.8/cs/" Visible="false" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen.CodeFixers\bin\roslyn4.8\$(Configuration)\netstandard2.0\Vogen.CodeFixers.dll" Pack="true" PackagePath="analyzers/dotnet/roslyn4.8/cs" Visible="false" />

<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.8\$(Configuration)\netstandard2.0\Vogen.SharedTypes.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.11\$(Configuration)\netstandard2.0\Vogen.dll" Pack="true" PackagePath="analyzers/dotnet/roslyn4.11/cs/" Visible="false" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen.CodeFixers\bin\roslyn4.11\$(Configuration)\netstandard2.0\Vogen.CodeFixers.dll" Pack="true" PackagePath="analyzers/dotnet/roslyn4.11/cs" Visible="false" />

<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.8\$(Configuration)\netstandard2.0\Vogen.SharedTypes.dll" Pack="true" PackagePath="lib\netstandard2.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.8\$(Configuration)\net9.0\Vogen.SharedTypes.dll" Pack="true" PackagePath="lib\net9.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.8\$(Configuration)\net9.0\Vogen.SharedTypes.xml" Pack="true" PackagePath="lib\net9.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.8\$(Configuration)\net9.0\Vogen.SharedTypes.xml" Pack="true" PackagePath="lib\netstandard2.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.12\$(Configuration)\netstandard2.0\Vogen.dll" Pack="true" PackagePath="analyzers/dotnet/roslyn4.12/cs/" Visible="false" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen.CodeFixers\bin\roslyn4.12\$(Configuration)\netstandard2.0\Vogen.CodeFixers.dll" Pack="true" PackagePath="analyzers/dotnet/roslyn4.12/cs" Visible="false" />

<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.12\$(Configuration)\netstandard2.0\Vogen.SharedTypes.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.12\$(Configuration)\netstandard2.0\Vogen.SharedTypes.dll" Pack="true" PackagePath="lib\netstandard2.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.12\$(Configuration)\net9.0\Vogen.SharedTypes.dll" Pack="true" PackagePath="lib\net9.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.12\$(Configuration)\net9.0\Vogen.SharedTypes.xml" Pack="true" PackagePath="lib\net9.0" Visible="true" />
<None Include="$(MSBuildThisFileDirectory)\..\Vogen\bin\roslyn4.12\$(Configuration)\net9.0\Vogen.SharedTypes.xml" Pack="true" PackagePath="lib\netstandard2.0" Visible="true" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 4 additions & 0 deletions src/Vogen/BuildWorkItems.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ internal static class BuildWorkItems
UserProvidedOverloads userProvidedOverloads =
DiscoverUserProvidedOverloads.Discover(voSymbolInformation, underlyingType);

UserProvidedPartials userProvidedPartials =
DiscoverUserProvidedPartials.Discover(voSymbolInformation, underlyingType);

ThrowIfAnyToStringOverrideOnRecordIsUnsealed(target, context, userProvidedOverloads.ToStringOverloads);

MethodDeclarationSyntax? validateMethod = null;
Expand Down Expand Up @@ -150,6 +153,7 @@ RecordDeclarationSyntax rds when rds.IsKind(SyntaxKind.RecordStructDeclaration)
Config = config,

UserProvidedOverloads = userProvidedOverloads,
UserProvidedPartials = userProvidedPartials,

UnderlyingType = underlyingType,
ValidateMethod = validateMethod,
Expand Down
47 changes: 47 additions & 0 deletions src/Vogen/DiscoverUserProvidedPartials.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Microsoft.CodeAnalysis;
using System.Linq;

namespace Vogen;

internal class DiscoverUserProvidedPartials
{
public static UserProvidedPartials Discover(INamedTypeSymbol vo, INamedTypeSymbol underlyingType) =>
new()
{
PartialValue = TryGetPartialProperty(vo, "Value"),
PartialFrom = TryGetPartialMethod(vo, "From", [underlyingType]),
PartialBoolTryFrom = TryGetPartialMethod(vo, "TryFrom", [underlyingType, vo]),
PartialErrorTryFrom = TryGetPartialMethod(vo, "TryFrom", [underlyingType]),
};

private static UserProvidedPartial? TryGetPartialProperty(ITypeSymbol vo, string propertyName)
{
#if ROSLYN_4_12_OR_GREATER
var property = vo.GetMembers(propertyName)
.OfType<IPropertySymbol>()
.SingleOrDefault(x => x.IsPartialDefinition);

if (property is null)
return null;

return new(property.DeclaredAccessibility);
#else
return null;
#endif
}

private static UserProvidedPartial? TryGetPartialMethod(ITypeSymbol vo, string methodName, ITypeSymbol[] parameterTypes)
{
var method = vo.GetMembers(methodName)
.OfType<IMethodSymbol>()
.Where(x => x.IsPartialDefinition)
.SingleOrDefault(x =>
x.Parameters.Select(y => y.Type).SequenceEqual(parameterTypes, SymbolEqualityComparer.Default)
);

if (method is null)
return null;

return new(method.DeclaredAccessibility);
}
}
4 changes: 2 additions & 2 deletions src/Vogen/GenerateCodeForTryFrom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private static string Generate(VoWorkItem item, SyntaxToken className, string it
/// <param name="vo">An instance of the value object.</param>
/// <returns>True if the value object can be built, otherwise false.</returns>
#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes.
public static bool TryFrom({{Util.GenerateNotNullWhenTrueAttribute()}} {{itemUnderlyingType}}{{underlyingNullable}} value, {{Util.GenerateMaybeNullWhenFalse()}} out {{className}} vo)
{{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialBoolTryFrom)}} bool TryFrom({{Util.GenerateNotNullWhenTrueAttribute()}} {{itemUnderlyingType}}{{underlyingNullable}} value, {{Util.GenerateMaybeNullWhenFalse()}} out {{className}} vo)
#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes.
{
{{GenerateNullCheckAndReturnFalseIfNeeded(item)}}
Expand All @@ -59,7 +59,7 @@ public static bool TryFrom({{Util.GenerateNotNullWhenTrueAttribute()}} {{itemUnd
/// </summary>
/// <param name="value">The primitive value.</param>
/// <returns>A <see cref="Vogen.ValueObjectOrError{T}"/> containing either the value object, or an error.</returns>
public static Vogen.ValueObjectOrError<{{className}}> TryFrom({{itemUnderlyingType}} value)
{{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialErrorTryFrom)}} Vogen.ValueObjectOrError<{{className}}> TryFrom({{itemUnderlyingType}} value)
{
{{GenerateNullCheckAndReturnErrorIfNeeded(className, item)}}

Expand Down
4 changes: 2 additions & 2 deletions src/Vogen/Generators/ClassGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ string GenerateCode() => $@"
private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value;

{Util.GenerateCommentForValueProperty(item)}
public {itemUnderlyingType} Value
{Util.GenerateMethodModifiers(Accessibility.Public, [], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value
{{
[global::System.Diagnostics.DebuggerStepThroughAttribute]
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -90,7 +90,7 @@ string GenerateCode() => $@"
/// <param name=""value"">The underlying type.</param>
/// <returns>An instance of this type.</returns>
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static {wrapperName} From({itemUnderlyingType} value)
{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value)
{{
{Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)}

Expand Down
4 changes: 2 additions & 2 deletions src/Vogen/Generators/RecordClassGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ string GenerateCode() => $@"
private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value;

{Util.GenerateCommentForValueProperty(item)}
public {itemUnderlyingType} Value
{Util.GenerateMethodModifiers(Accessibility.Public, [], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value
{{
[global::System.Diagnostics.DebuggerStepThroughAttribute]
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -100,7 +100,7 @@ string GenerateCode() => $@"
/// <param name=""value"">The underlying type.</param>
/// <returns>An instance of this type.</returns>
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static {wrapperName} From({itemUnderlyingType} value)
{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value)
{{
{Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)}

Expand Down
4 changes: 2 additions & 2 deletions src/Vogen/Generators/RecordStructGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ string GenerateCode() => $@"
private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value;

{Util.GenerateCommentForValueProperty(item)}
public readonly {itemUnderlyingType} Value
{Util.GenerateMethodModifiers(Accessibility.Public, ["readonly"], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value
{{
[global::System.Diagnostics.DebuggerStepThroughAttribute]
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -88,7 +88,7 @@ public readonly {itemUnderlyingType} Value
/// <param name=""value"">The underlying type.</param>
/// <returns>An instance of this type.</returns>
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static {wrapperName} From({itemUnderlyingType} value)
{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value)
{{
{Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)}

Expand Down
4 changes: 2 additions & 2 deletions src/Vogen/Generators/StructGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ string GenerateCode() => $@"
private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value;

{Util.GenerateCommentForValueProperty(item)}
public readonly {itemUnderlyingType} Value
{Util.GenerateMethodModifiers(Accessibility.Public, ["readonly"], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value
{{
[global::System.Diagnostics.DebuggerStepThroughAttribute]
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -81,7 +81,7 @@ public readonly {itemUnderlyingType} Value
/// <param name=""value"">The underlying type.</param>
/// <returns>An instance of this type.</returns>
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static {wrapperName} From({itemUnderlyingType} value)
{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value)
{{
{Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)}

Expand Down
32 changes: 32 additions & 0 deletions src/Vogen/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic;
using Vogen.Generators.Conversions;
using Vogen.Types;

Expand All @@ -29,6 +30,37 @@ public static string GenerateNullCheckAndThrowIfNeeded(VoWorkItem voWorkItem, bo
""";
}

public static string GenerateMethodModifiers(
Accessibility defaultAccessibility,
IEnumerable<string> otherModifers,
UserProvidedPartial? userProvidedPartial
)
{
#pragma warning disable CS8524 // A switch on enum handles all the values
var accessModifiers = (userProvidedPartial?.DeclaredAccessibility ?? defaultAccessibility) switch
#pragma warning restore CS8524
{
Accessibility.NotApplicable => string.Empty,
Accessibility.Private => "private",
Accessibility.ProtectedAndInternal => "private protected",
Accessibility.Protected => "protected",
Accessibility.Internal => "internal",
Accessibility.ProtectedOrInternal => "protected internal",
Accessibility.Public => "public",
};

var modifiers = new List<string> { accessModifiers };

modifiers.AddRange(otherModifers);

if (userProvidedPartial is not null)
{
modifiers.Add("partial");
}

return string.Join(" ", modifiers);
}

public static string EscapeTypeNameForTripleSlashComment(string typeName) =>
typeName.Replace("<", "{").Replace(">", "}");

Expand Down
Loading