Skip to content

Commit

Permalink
Added converter convention updated source
Browse files Browse the repository at this point in the history
  • Loading branch information
jeppevammenkristensen committed Jul 24, 2023
1 parent ac06c22 commit a30418c
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ namespace Test
[AutoSpectreForm]
public class TestForm
{
[Ask(AskType = AskType.Selection, SelectionSource = nameof(ListOfOther))]
[Ask(AskType = AskType.Selection)]
public List<OtherTest.OtherClass> Other {get;set;}
public string OtherConverter(OtherTest.OtherClass other)
Expand All @@ -235,7 +235,7 @@ public string OtherConverter(OtherTest.OtherClass other)
}
public List<OtherTest.OtherClass> ListOfOther {get;set;} = new ();
public List<OtherTest.OtherClass> OtherSource {get;set;} = new ();
}
}
Expand Down
8 changes: 0 additions & 8 deletions AutoSpectre.SourceGeneration/AskBuilder.cs

This file was deleted.

72 changes: 0 additions & 72 deletions AutoSpectre.SourceGeneration/AttributeCode.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<IsRoslynComponent>true</IsRoslynComponent>
<Version>0.3.4.0</Version>
<Version>0.3.5.0</Version>


</PropertyGroup>
Expand All @@ -20,7 +20,7 @@
<PackageProjectUrl>https://github.com/jeppevammenkristensen/auto-spectre</PackageProjectUrl>
<RepositoryUrl>https://github.com/jeppevammenkristensen/auto-spectre</RepositoryUrl>
<PackageTags>C#;Source Generator</PackageTags>
<PackageReleaseNotes>Fixed issue with mapped typed used in List in other mapped type</PackageReleaseNotes>
<PackageReleaseNotes>Add conventions for Converter and SelectionSource</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
Expand Down
103 changes: 55 additions & 48 deletions AutoSpectre.SourceGeneration/PropertyContextBuilderOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,13 @@ public List<PropertyContext> GetPropertyContexts()

foreach (var (property, attributeData) in PropertyCandidates)
{
var (nullable, originalType) = property.Type.GetTypeWithNullableInformation();
var (enumerable, underlying) = property.Type.IsEnumerableOfTypeButNotString();

var propertyEvaluationContext =
new SinglePropertyEvaluationContext(property: property,isNullable: nullable, type: originalType, isEnumerable: enumerable, underlyingType: underlying);
var propertyContext = GenerateSinglePropertyEvaluationContext(property);

if (attributeData.AskType == AskTypeCopy.Normal)
{
if (!propertyEvaluationContext.IsEnumerable)
if (!propertyContext.IsEnumerable)
{
if (GetNormalPromptBuildContext(attributeData.Title, propertyEvaluationContext) is
if (GetNormalPromptBuildContext(attributeData.Title, propertyContext) is
{ } promptBuildContext)
{
propertyContexts.Add(new(property.Name, property,
Expand All @@ -96,67 +92,78 @@ public List<PropertyContext> GetPropertyContexts()
}
else
{
if (GetNormalPromptBuildContext(attributeData.Title, propertyEvaluationContext) is
if (GetNormalPromptBuildContext(attributeData.Title, propertyContext) is
{ } promptBuildContext)
{
propertyContexts.Add(new(property.Name, property, new MultiAddBuildContext(propertyEvaluationContext.Type, propertyEvaluationContext.UnderlyingType, types, promptBuildContext)));
propertyContexts.Add(new(property.Name, property, new MultiAddBuildContext(propertyContext.Type, propertyContext.UnderlyingType, types, promptBuildContext)));
}
}
}

if (attributeData.AskType == AskTypeCopy.Selection)
{
EvaluateSelectionConverter(attributeData, propertyEvaluationContext);

if (attributeData.SelectionSource is { })
{
var match = TargetType
.GetMembers()
.Where(x => x.Name == attributeData.SelectionSource)
.FirstOrDefault(x => x is IMethodSymbol
{
Parameters.Length: 0
} or IPropertySymbol {GetMethod: { }});
EvaluateSelectionConverter(attributeData, propertyContext);

var selectionSource = attributeData.SelectionSource ?? $"{propertyContext.Property.Name}Source";

if (match is { })
var match = TargetType
.GetMembers()
.Where(x => x.Name == selectionSource)
.FirstOrDefault(x => x is IMethodSymbol
{
SelectionPromptSelectionType selectionType = match switch
{
IMethodSymbol => SelectionPromptSelectionType.Method,
IPropertySymbol => SelectionPromptSelectionType.Property,
_ => throw new NotSupportedException(),
};
if (!propertyEvaluationContext.IsEnumerable)
{
propertyContexts.Add(new(property.Name, property,
new SelectionPromptBuildContext(attributeData.Title, propertyEvaluationContext,
attributeData.SelectionSource, selectionType)));
}
else
{
propertyContexts.Add(new(property.Name, property,
new MultiSelectionBuildContext(title: attributeData.Title,
propertyEvaluationContext,
selectionTypeName: attributeData.SelectionSource,
selectionType: selectionType, types)));
}
Parameters.Length: 0
} or IPropertySymbol { GetMethod: { } });

if (match is { })
{
SelectionPromptSelectionType selectionType = match switch
{
IMethodSymbol => SelectionPromptSelectionType.Method,
IPropertySymbol => SelectionPromptSelectionType.Property,
_ => throw new NotSupportedException(),
};
if (!propertyContext.IsEnumerable)
{
propertyContexts.Add(new(property.Name, property,
new SelectionPromptBuildContext(attributeData.Title, propertyContext,
selectionSource, selectionType)));
}
else
else
{
ProductionContext.ReportDiagnostic(Diagnostic.Create(
new("AutoSpectre_JJK0005",
"Not a valid selection source",
$"The selectionsource {attributeData.SelectionSource} was not found on type",
"General", DiagnosticSeverity.Warning, true),
property.Locations.FirstOrDefault()));
propertyContexts.Add(new(property.Name, property,
new MultiSelectionBuildContext(title: attributeData.Title,
propertyContext,
selectionTypeName: selectionSource,
selectionType: selectionType, types)));
}
}
else
{
ProductionContext.ReportDiagnostic(Diagnostic.Create(
new("AutoSpectre_JJK0005",
"Not a valid selection source",
$"The selectionsource {attributeData.SelectionSource} was not found on type",
"General", DiagnosticSeverity.Warning, true),
property.Locations.FirstOrDefault()));
}

}
}

return propertyContexts;
}

private static SinglePropertyEvaluationContext GenerateSinglePropertyEvaluationContext(IPropertySymbol property)
{
var (nullable, originalType) = property.Type.GetTypeWithNullableInformation();
var (enumerable, underlying) = property.Type.IsEnumerableOfTypeButNotString();

var propertyEvaluationContext =
new SinglePropertyEvaluationContext(property: property, isNullable: nullable, type: originalType,
isEnumerable: enumerable, underlyingType: underlying);
return propertyEvaluationContext;
}

/// <summary>
/// Evalutes the Converter set on the attributeData. If it's correct a valid converter is set on the context.
/// if it is set but not valid a warning is reported.
Expand Down
35 changes: 25 additions & 10 deletions AutoSpectre/AskAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

namespace AutoSpectre
{
/// <summary>
/// Apply this attribute to a property to tell that a prompt should take place
/// <example>
///[Ask()]
/// public string Name {get;set;}
/// </example>
/// </summary>
public class AskAttribute : Attribute
{
public AskAttribute()
Expand All @@ -14,32 +21,40 @@ public AskAttribute(string? title = null)
{

}

//public AskAttribute(string? title = null, AskType askType = AutoSpectre.AskType.Normal, string? selectionSource = null)
//{
// Title = title;
// AskType = askType;
// SelectionSource = selectionSource;
//}


/// <summary>
/// The title displayed. If nothing is defined a text including property name is displayed
/// </summary>
public string? Title { get; set; }

/// <summary>
/// The type used to ask with
/// The type of prompting
/// </summary>
public AskType AskType { get; set; }

/// <summary>
/// The source to get a list of items to present to the user.
/// Only relevant if the AskType is <see cref="AutoSpectre.AskType.Selection"/>
/// The source pointed to must be either a property or method (with no input parameters)
/// that returns a list of the same type as defined on the property.
/// NOTE: If you define a source as {NameOfProperty}Source by convention that will be used
/// as source and you don't have to define a selection source
/// </summary>
public string? SelectionSource { get; set; }

/// <summary>
/// The method that can create a string representation of the given property. The method must
/// take the type of the property as input parameter and return a string.
/// NOTE: If you define a converter method as {NameOfProperty}Converter you don't have to define
/// Converter
/// </summary>
public string? Converter { get; set; }
}

public enum AskType
{
/// <summary>
/// Default.
/// Default. The user will input the values
/// </summary>
Normal,
/// <summary>
Expand Down
8 changes: 6 additions & 2 deletions AutoSpectre/AutoSpectre.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Version>0.2.1.0</Version>
<Version>0.2.2.0</Version>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Description>Classes used by the AutoSpectre.SourceGeneration package</Description>
<Authors>Jeppe Roi Kristensen</Authors>
<RepositoryUrl>https://github.com/jeppevammenkristensen/auto-spectre</RepositoryUrl>
<PackageReleaseNotes>Added Converter property to attribute</PackageReleaseNotes>
<PackageReleaseNotes>Added better summaries for classes</PackageReleaseNotes>

</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\AutoSpectre.xml</DocumentationFile>
</PropertyGroup>

</Project>
3 changes: 2 additions & 1 deletion AutoSpectre/AutoSpectreForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
namespace AutoSpectre;

/// <summary>
/// Marker interface. Apply this to a class and a factory will
/// Marker interface. Apply this to a class and a factory will be generated
/// based on the properties in decorated with the <see cref="AskAttribute"/>
/// </summary>
public class AutoSpectreForm : Attribute
{
Expand Down
Loading

0 comments on commit a30418c

Please sign in to comment.