Skip to content

Commit

Permalink
Use object instead of string for Scriban variable values Fixes #30 (#31)
Browse files Browse the repository at this point in the history
* Use object instead of string for default values so the Scriban script engine can check for `true` instead of `!= "false"`

* Update readme.
  • Loading branch information
mrpmorris authored Aug 23, 2023
1 parent f28f8fe commit e6d2421
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
1 change: 1 addition & 0 deletions Docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## New in 1.6
* Honour Roslyn `ProductionContext.Cancellation.IsCancellationRequested` to improve performance
* Do not output `typeof()` in generated source when user has specified a type name as a mixin argument [Fixes #28](https://github.com/mrpmorris/Morris.Moxy/issues/28)
* Use object instead of string for variable values [Fixes #30](https://github.com/mrpmorris/Morris.Moxy/issues/30)

## New in 1.5
* Fixed IndexOutOfBoundsException when using attribute optional inputs [Fixes #19](https://github.com/mrpmorris/Morris.Moxy/issues/19)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
Expand All @@ -8,19 +9,21 @@ namespace Morris.Moxy.Extensions;
internal static class AttributeSyntaxGetArgumentKeyValuePairsExtension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ImmutableArray<KeyValuePair<string, string>> GetArgumentKeyValuePairs(
public static ImmutableArray<KeyValuePair<string, object?>> GetArgumentKeyValuePairs(
this AttributeSyntax attributeSyntax,
SemanticModel semanticModel,
ImmutableArray<Metas.Templates.TemplateInput> requiredInputs,
ImmutableArray<Metas.Templates.TemplateInput> optionalInputs)
{
SeparatedSyntaxList<AttributeArgumentSyntax>? arguments = attributeSyntax.ArgumentList?.Arguments;
if (arguments is null)
return ImmutableArray<KeyValuePair<string, string>>.Empty;
return ImmutableArray<KeyValuePair<string, object?>>.Empty;

ImmutableArray<Metas.Templates.TemplateInput> allInputs = requiredInputs.AddRange(optionalInputs);

var resultBuilder = ImmutableArray.CreateBuilder<KeyValuePair<string, string>>();
var nameToValueLookup = new Dictionary<string, object?>();
foreach (var item in optionalInputs.Union(requiredInputs).Where(x => x.DefaultValue is not null))
nameToValueLookup[item.Name] = GetValueFromStringRepresentation(item.DefaultValue!);

for(int argumentIndex = 0; argumentIndex < arguments.Value.Count; argumentIndex++)
{
Expand All @@ -33,21 +36,37 @@ argument.NameEquals is not null
? argument.NameColon.Name.Identifier.ValueText
: allInputs[argumentIndex].Name;

string value = argument.Expression switch {
TypeOfExpressionSyntax x => x.Type.ToFullString(),
_ => TrimQuotes(argument)
};

resultBuilder.Add(new KeyValuePair<string, string>(argumentName, value));
object? value = GetValueFromStringRepresentation(argument.ToString());
nameToValueLookup[argumentName] = value;

}
return nameToValueLookup.ToImmutableArray();
}


return resultBuilder.ToImmutableArray();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static object? GetValueFromStringRepresentation(string expressionStr)
{
var expression = SyntaxFactory.ParseExpression(expressionStr);
return GetValueFromArgument(expression);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static object? GetValueFromArgument(ExpressionSyntax expression)
{
return expression switch {
TypeOfExpressionSyntax x => x.Type.ToFullString(),
LiteralExpressionSyntax lit when lit.Token.IsKind(SyntaxKind.TrueKeyword) => true,
LiteralExpressionSyntax lit when lit.Token.IsKind(SyntaxKind.FalseKeyword) => false,
LiteralExpressionSyntax lit when lit.Token.IsKind(SyntaxKind.NullKeyword) => null,
_ => TrimQuotes(expression)
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string TrimQuotes(AttributeArgumentSyntax argument) =>
argument.Expression.ToFullString() switch {
private static string TrimQuotes(ExpressionSyntax expression) =>
expression.ToFullString() switch {
string x when x.StartsWith("\"") => x.Substring(1, x.Length - 2),
string x => x,
_ => throw new NotImplementedException()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ namespace Morris.Moxy.Extensions;
internal static class ScriptObjectAddVariablesForAttributeInstanceArgumentsExtension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddVariablesForAttributeInstanceArguments(this ScriptObject scriptObject, AttributeInstance attributeInstance)
public static void AddVariablesForAttributeInstanceArguments(
this ScriptObject scriptObject,
AttributeInstance attributeInstance)
{
for (int i = 0; i < attributeInstance.Arguments.Length; i++)
{
KeyValuePair<string, string> argument = attributeInstance.Arguments[i];
KeyValuePair<string, object?> argument = attributeInstance.Arguments[i];
scriptObject.Add(argument.Key, argument.Value);
}
}
Expand Down
6 changes: 3 additions & 3 deletions Source/Lib/Morris.Moxy/Metas/Classes/AttributeInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ namespace Morris.Moxy.Metas.Classes;
internal class AttributeInstance : IEquatable<AttributeInstance>
{
public readonly string Name;
public readonly ImmutableArray<KeyValuePair<string, string>> Arguments;
public readonly ImmutableArray<KeyValuePair<string, object?>> Arguments;

private readonly Lazy<int> CachedHashCode;

public AttributeInstance()
{
Name = "";
Arguments = ImmutableArray<KeyValuePair<string, string>>.Empty;
Arguments = ImmutableArray<KeyValuePair<string, object?>>.Empty;
CachedHashCode = new Lazy<int>(() => typeof(AttributeInstance).GetHashCode());
}

public AttributeInstance(
string name,
ImmutableArray<KeyValuePair<string, string>> arguments)
ImmutableArray<KeyValuePair<string, object?>> arguments)
{
if (name.EndsWith("Attribute"))
name = name.Substring(0, name.Length - 10);
Expand Down

0 comments on commit e6d2421

Please sign in to comment.