diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d5e1936..b512cfb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Build BicepDocs run: dotnet build --configuration release src/BicepDocs.sln - name: Run tests - run: dotnet test --configuration release ./src/**/*Tests.csproj + run: dotnet test --configuration release src/BicepDocs.sln - id: get-version run: | parsedVersion=$(echo ${{ github.ref }} | cut -dv -f2) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 7734547..e8ed1b0 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -32,7 +32,7 @@ jobs: - name: Build BicepDocs run: dotnet build --configuration release src/BicepDocs.sln - name: Run tests - run: dotnet test --configuration release ./src/**/*Tests.csproj + run: dotnet test --configuration release src/BicepDocs.sln - name: Build binary run: dotnet publish --configuration release --self-contained true -p:PublishTrimmed=true -p:PublishSingleFile=true -p:TrimmerDefaultAction=copyused -p:SuppressTrimAnalysisWarnings=true -r ${{ matrix.rid }} ./src/BicepDocs.Cli/BicepDocs.Cli.csproj diff --git a/docs/formatters/examples/generated-output/docusaurus/resources/resource-groups.md b/docs/formatters/examples/generated-output/docusaurus/resources/resource-groups.md index 0b10ef3..5e18cef 100644 --- a/docs/formatters/examples/generated-output/docusaurus/resources/resource-groups.md +++ b/docs/formatters/examples/generated-output/docusaurus/resources/resource-groups.md @@ -46,7 +46,7 @@ module exampleInstance 'ts/IacModules:resources/resource-groups:2022-12-17' = { | `complexObject` | Object input | object | [complexObjectValue](#complexobjectvalue) | | `inputArray` | Complex array input | array | [inputArrayValue](#inputarrayvalue) | | `inputArraySimple` | Simple array input | array | [ 'one' 'two'] | -| `intInput` | int input | int | 124 | +| `intInput` | int input | int

Acceptable values range from 1 to 2333. | 124 | | `resourceGroupLocation` | Location of the resource group | [resourceGroupLocationAllow](#resourcegrouplocationallow) | | | `resourceGroupName` | Name of the resource group | string | | | `tags` | Tags to append to resource group | object | {} | diff --git a/docs/formatters/examples/generated-output/docusaurus/resources/versions/2022-12-17/resource-groups.md b/docs/formatters/examples/generated-output/docusaurus/resources/versions/2022-12-17/resource-groups.md index 0b10ef3..5e18cef 100644 --- a/docs/formatters/examples/generated-output/docusaurus/resources/versions/2022-12-17/resource-groups.md +++ b/docs/formatters/examples/generated-output/docusaurus/resources/versions/2022-12-17/resource-groups.md @@ -46,7 +46,7 @@ module exampleInstance 'ts/IacModules:resources/resource-groups:2022-12-17' = { | `complexObject` | Object input | object | [complexObjectValue](#complexobjectvalue) | | `inputArray` | Complex array input | array | [inputArrayValue](#inputarrayvalue) | | `inputArraySimple` | Simple array input | array | [ 'one' 'two'] | -| `intInput` | int input | int | 124 | +| `intInput` | int input | int

Acceptable values range from 1 to 2333. | 124 | | `resourceGroupLocation` | Location of the resource group | [resourceGroupLocationAllow](#resourcegrouplocationallow) | | | `resourceGroupName` | Name of the resource group | string | | | `tags` | Tags to append to resource group | object | {} | diff --git a/docs/formatters/examples/generated-output/markdown/resources/resource-groups.md b/docs/formatters/examples/generated-output/markdown/resources/resource-groups.md index 9fa3542..6ceb799 100644 --- a/docs/formatters/examples/generated-output/markdown/resources/resource-groups.md +++ b/docs/formatters/examples/generated-output/markdown/resources/resource-groups.md @@ -33,11 +33,11 @@ module exampleInstance 'ts/IacModules:resources/resource-groups:2022-12-17' = { | Parameter | Description | Type | Default | | --- | --- | --- | --- | | `boolInput` | Bool input | bool | false | -| `complexObject` | Object input | object | [complexObjectValue](#complexobjectvalue) | +| `complexObject` | Object input | object (secure) | [complexObjectValue](#complexobjectvalue) | | `inputArray` | Complex array input | array | [inputArrayValue](#inputarrayvalue) | | `inputArraySimple` | Simple array input | array | [ 'one' 'two'] | -| `intInput` | int input | int | 124 | -| `resourceGroupLocation` | Location of the resource group | [resourceGroupLocationAllow](#resourcegrouplocationallow) | | +| `intInput` | int input | int

Accepted values: from 1 to 2333. | 124 | +| `resourceGroupLocation` | Location of the resource group | [resourceGroupLocationAllow](#resourcegrouplocationallow) (secure)

Character limit: 3-24 | | | `resourceGroupName` | Name of the resource group | string | | | `tags` | Tags to append to resource group | object | {} | diff --git a/docs/formatters/examples/generated-output/markdown/resources/versions/2022-12-17/resource-groups.md b/docs/formatters/examples/generated-output/markdown/resources/versions/2022-12-17/resource-groups.md index 9fa3542..6ceb799 100644 --- a/docs/formatters/examples/generated-output/markdown/resources/versions/2022-12-17/resource-groups.md +++ b/docs/formatters/examples/generated-output/markdown/resources/versions/2022-12-17/resource-groups.md @@ -33,11 +33,11 @@ module exampleInstance 'ts/IacModules:resources/resource-groups:2022-12-17' = { | Parameter | Description | Type | Default | | --- | --- | --- | --- | | `boolInput` | Bool input | bool | false | -| `complexObject` | Object input | object | [complexObjectValue](#complexobjectvalue) | +| `complexObject` | Object input | object (secure) | [complexObjectValue](#complexobjectvalue) | | `inputArray` | Complex array input | array | [inputArrayValue](#inputarrayvalue) | | `inputArraySimple` | Simple array input | array | [ 'one' 'two'] | -| `intInput` | int input | int | 124 | -| `resourceGroupLocation` | Location of the resource group | [resourceGroupLocationAllow](#resourcegrouplocationallow) | | +| `intInput` | int input | int

Accepted values: from 1 to 2333. | 124 | +| `resourceGroupLocation` | Location of the resource group | [resourceGroupLocationAllow](#resourcegrouplocationallow) (secure)

Character limit: 3-24 | | | `resourceGroupName` | Name of the resource group | string | | | `tags` | Tags to append to resource group | object | {} | diff --git a/docs/formatters/examples/inputs/resources/resource-groups.bicep b/docs/formatters/examples/inputs/resources/resource-groups.bicep index 5306f89..3b365f2 100644 --- a/docs/formatters/examples/inputs/resources/resource-groups.bicep +++ b/docs/formatters/examples/inputs/resources/resource-groups.bicep @@ -22,6 +22,9 @@ param resourceGroupName string 'westeurope' ]) @description('Location of the resource group') +@minLength(3) +@maxLength(24) +@secure() param resourceGroupLocation string @description('Tags to append to resource group') @@ -31,6 +34,8 @@ param tags object = {} param boolInput bool = false @description('int input') +@minValue(1) +@maxValue(2333) param intInput int = 124 @description('Complex array input') @@ -45,6 +50,7 @@ param inputArraySimple array = [ ] @description('Object input') +@secure() param complexObject object = { prop: 'one' propTwo: 'two' diff --git a/src/BicepDocs.Cli.UnitTests/BicepDocs.Cli.UnitTests.csproj b/src/BicepDocs.Cli.UnitTests/BicepDocs.Cli.UnitTests.csproj deleted file mode 100644 index dfebff1..0000000 --- a/src/BicepDocs.Cli.UnitTests/BicepDocs.Cli.UnitTests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - LandingZones.Tools.BicepDocs.Cli.UnitTests - LandingZones.Tools.BicepDocs.Cli.UnitTests - net6.0 - enable - enable - false - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/src/BicepDocs.Cli.UnitTests/Usings.cs b/src/BicepDocs.Cli.UnitTests/Usings.cs deleted file mode 100644 index ab67c7e..0000000 --- a/src/BicepDocs.Cli.UnitTests/Usings.cs +++ /dev/null @@ -1 +0,0 @@ -global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/src/BicepDocs.Core.UnitTests/Parsers/ParameterParserTests.cs b/src/BicepDocs.Core.UnitTests/Parsers/ParameterParserTests.cs index 3180864..ef55006 100644 --- a/src/BicepDocs.Core.UnitTests/Parsers/ParameterParserTests.cs +++ b/src/BicepDocs.Core.UnitTests/Parsers/ParameterParserTests.cs @@ -37,6 +37,61 @@ param resourceGroupLocation string Assert.AreEqual("Tags to append to resource group", tags.Description); } + + [TestMethod] + public async Task Parameter_Constraints_Parses() + { + const string template = @"targetScope = 'subscription' + +@minLength(3) +@maxLength(24) +@description('Name of the resource group') +param resourceGroupName string + +@minLength(3) +@maxLength(24) +param someArr array = [] + +@maxValue(100) +@minValue(1) +param intVal int = 1 + +@secure() +param objectVal object = {} + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-01-01' = { + name: resourceGroupName +}"; + var semanticModel = await GetModel(template); + var parameters = ParameterParser.ParseParameters(semanticModel); + + var resourceGroupName = parameters.First(x => x.Name == "resourceGroupName"); + Assert.AreEqual("resourceGroupName", resourceGroupName.Name); + Assert.AreEqual("string", resourceGroupName.Type); + Assert.AreEqual("Name of the resource group", resourceGroupName.Description); + Assert.AreEqual(3, resourceGroupName.MinLength); + Assert.AreEqual(24, resourceGroupName.MaxLength); + + + var someArr = parameters.First(x => x.Name == "someArr"); + Assert.AreEqual("someArr", someArr.Name); + Assert.AreEqual("array", someArr.Type); + Assert.AreEqual(3, someArr.MinLength); + Assert.AreEqual(24, someArr.MaxLength); + + + var intVal = parameters.First(x => x.Name == "intVal"); + Assert.AreEqual("intVal", intVal.Name); + Assert.AreEqual("int", intVal.Type); + Assert.AreEqual(100, intVal.MaxValue); + Assert.AreEqual(1, intVal.MinValue); + + var objectVal = parameters.First(x => x.Name == "objectVal"); + Assert.AreEqual("objectVal", objectVal.Name); + Assert.AreEqual("object", objectVal.Type); + Assert.IsTrue(objectVal.Secure); + } + [TestMethod] public async Task Parameter_Interpolated_Parses() { diff --git a/src/BicepDocs.Core/Models/Parsing/ParsedParameter.cs b/src/BicepDocs.Core/Models/Parsing/ParsedParameter.cs index 7df6050..30680e1 100644 --- a/src/BicepDocs.Core/Models/Parsing/ParsedParameter.cs +++ b/src/BicepDocs.Core/Models/Parsing/ParsedParameter.cs @@ -10,4 +10,14 @@ public record ParsedParameter(string Name, string Type) public List? AllowedValues { get; set; } public bool IsComplexAllow { get; set; } public bool IsInterpolated { get; set; } + + public int? MinLength { get; set; } + + public int? MinValue { get; set; } + + public int? MaxLength { get; set; } + + public int? MaxValue { get; set; } + + public bool Secure { get; set; } } \ No newline at end of file diff --git a/src/BicepDocs.Core/Parsers/ParameterParser.cs b/src/BicepDocs.Core/Parsers/ParameterParser.cs index f69379e..bcf2fa8 100644 --- a/src/BicepDocs.Core/Parsers/ParameterParser.cs +++ b/src/BicepDocs.Core/Parsers/ParameterParser.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Bicep.Core; using Bicep.Core.Navigation; using Bicep.Core.Semantics; using Bicep.Core.Syntax; @@ -10,10 +11,6 @@ public static class ParameterParser { public static ImmutableList ParseParameters(SemanticModel model) { - var defaultValueSyntaxes = model.Root.ParameterDeclarations - .ToImmutableDictionary(x => x.Name, y => y.DeclaringParameter.Modifier as ParameterDefaultValueSyntax) - .ToDictionary(x => x.Key, y => y.Value); - var parameters = new List(); foreach (var templateParameter in model.Parameters.OrderBy(x => x.Key)) { @@ -25,10 +22,32 @@ public static ImmutableList ParseParameters(SemanticModel model { Description = templateParameter.Value.Description }; - if (defaultValueSyntaxes.TryGetValue(templateParameter.Key, out var syntaxBase) && syntaxBase != null) + + var paramType = templateParameter.Value.TypeReference.Type.Name; + var allowList = paramType.Split('\'').Select(x => x.Trim()).Where(x => x.Length > 1).ToArray(); + var allowValues = allowList.Select(x => x.Replace("'", "")).Where(x => !string.IsNullOrEmpty(x)).ToList(); + parameter.IsComplexAllow = allowList.Length > 2; + parameter.AllowedValues = allowValues; + + var symbol = GetParameterSymbol(model, templateParameter.Key); + if (symbol == null) { - parameter.DefaultValue = syntaxBase.DefaultValue.ToTextPreserveFormatting(); - parameter.IsComplexDefault = syntaxBase.DefaultValue switch + parameters.Add(parameter); + continue; + } + + parameter.MaxLength = GetDecorator(symbol, LanguageConstants.ParameterMaxLengthPropertyName); + parameter.MinLength = GetDecorator(symbol, LanguageConstants.ParameterMinLengthPropertyName); + parameter.Secure = HasDecorator(symbol, LanguageConstants.ParameterSecurePropertyName); + parameter.MinValue = GetDecorator(symbol, LanguageConstants.ParameterMinValuePropertyName); + parameter.MaxValue = GetDecorator(symbol, LanguageConstants.ParameterMaxValuePropertyName); + + + var defaultValueSyntaxBase = GetDefaultValue(symbol); + if (defaultValueSyntaxBase != null) + { + parameter.DefaultValue = defaultValueSyntaxBase.ToTextPreserveFormatting(); + parameter.IsComplexDefault = defaultValueSyntaxBase switch { ObjectSyntax objectSyntax when objectSyntax.ToNamedPropertyDictionary().IsEmpty => false, ObjectSyntax => true, @@ -36,7 +55,7 @@ ObjectSyntax objectSyntax when objectSyntax.ToNamedPropertyDictionary().IsEmpty _ => false }; - parameter.IsInterpolated = syntaxBase.DefaultValue switch + parameter.IsInterpolated = defaultValueSyntaxBase switch { StringSyntax stringSyntax when stringSyntax.IsInterpolated() => true, PropertyAccessSyntax => true, @@ -44,11 +63,6 @@ StringSyntax stringSyntax when stringSyntax.IsInterpolated() => true, }; } - var paramType = templateParameter.Value.TypeReference.Type.Name; - var allowList = paramType.Split('\'').Select(x => x.Trim()).Where(x => x.Length > 1).ToArray(); - var allowValues = allowList.Select(x => x.Replace("'", "")).Where(x => !string.IsNullOrEmpty(x)).ToList(); - parameter.IsComplexAllow = allowList.Length > 2; - parameter.AllowedValues = allowValues; parameters.Add(parameter); } @@ -56,6 +70,30 @@ StringSyntax stringSyntax when stringSyntax.IsInterpolated() => true, return parameters.ToImmutableList(); } + private static bool HasDecorator(ParameterSymbol parameterSymbol, string decoratorName) + { + var f = parameterSymbol.DeclaringParameter.Decorators; + var fcs = f.FirstOrDefault(x => (x.Expression as FunctionCallSyntax)?.Name?.IdentifierName == decoratorName); + return fcs != null; + } + + private static ParameterSymbol? GetParameterSymbol(SemanticModel model, string paramName) => + model.Root.ParameterDeclarations.FirstOrDefault(x => x.Name == paramName); + + private static SyntaxBase? GetDefaultValue(ParameterSymbol parameterSymbol) + { + var declaration = parameterSymbol.DeclaringParameter.Modifier as ParameterDefaultValueSyntax; + return declaration?.DefaultValue; + } + + private static int? GetDecorator(ParameterSymbol parameterSymbol, string decoratorName) + { + var f = parameterSymbol.DeclaringParameter.Decorators; + var fcs = f.FirstOrDefault(x => (x.Expression as FunctionCallSyntax)?.Name?.IdentifierName == decoratorName); + var literalText = (fcs?.Arguments.FirstOrDefault()?.Expression as IntegerLiteralSyntax)?.Literal?.Text; + return int.TryParse(literalText, out var value) ? value : default(int?); + } + private static bool IsComplexArray(ArraySyntax syntax) { if (!syntax.Items.Any()) diff --git a/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ParameterGeneratorTests.cs b/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ParameterGeneratorTests.cs index d8e3004..1c9f41d 100644 --- a/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ParameterGeneratorTests.cs +++ b/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ParameterGeneratorTests.cs @@ -42,6 +42,46 @@ public void BuildParameters_NoParameters_DoesNotGenerate() Assert.AreEqual(0, document.Count); } + [DataTestMethod] + [DataRow(1, null, null, null, false, "

Accepted values: from 1.")] + [DataRow(null, 1, null, null, false, "

Accepted values: to 1.")] + [DataRow(1, 10, null, null, false, "

Accepted values: from 1 to 10.")] + [DataRow(null, null, 1, null, false, "

Character limit: 1-X")] + [DataRow(null, null, null, 10, false, "

Character limit: X-10")] + [DataRow(null, null, 1, 10, false, "

Character limit: 1-10")] + [DataRow(null, null, null, null, true, "(secure)")] + public void BuildParameters_DecoratorSet_BuildsCorrectly(int? minValue, int? maxValue, int? minLength, + int? maxLength, bool secure, string expectedDesc) + { + string expected = $@"## Parameters + +| Parameter | Description | Type | Default | +| --- | --- | --- | --- | +| `location` | The location of the resource | string {expectedDesc} | |"; + + var parameters = new List + { + new("location", "string") + { + Description = "The location of the resource", + MinValue = minValue, + MaxValue = maxValue, + MinLength = minLength, + MaxLength = maxLength, + Secure = secure + } + }.ToImmutableList(); + var document = new MarkdownDocument(); + + ParameterGenerator.BuildParameters(document, new FormatterOptions(), parameters); + + Assert.AreEqual(2, document.Count); + + var md = document.ToMarkdown(); + + Assert.AreEqual(expected, md); + } + [TestMethod] public void BuildParameters_SimpleParameterType_BuildsCorrectly() { diff --git a/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ResourceGeneratorTests.cs b/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ResourceGeneratorTests.cs index 7a2d0fd..283bf93 100644 --- a/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ResourceGeneratorTests.cs +++ b/src/BicepDocs.Formatter.Markdown.UnitTests/Generators/ResourceGeneratorTests.cs @@ -152,7 +152,7 @@ public void BuildReferencedResources_Input_BuildsCorrectly() | Provider | Name | Scope | | --- | --- | --- | -| Microsoft.Web/sites/2022-12-18 | siteOne | `subscription()` |"; +| Microsoft.Web/sites/2022-12-18 | `siteOne` | `subscription()` |"; var resources = new List { new("Microsoft.Web/sites/2022-12-18", "Microsoft.Web", "sites") @@ -185,8 +185,8 @@ public void BuildReferencedResources_MultipleOfSame_BuildsAll() | Provider | Name | Scope | | --- | --- | --- | -| Microsoft.Web/sites/2022-12-18 | siteOne | `subscription()` | -| Microsoft.Web/sites/2022-12-18 | siteTwo | `subscription()` |"; +| Microsoft.Web/sites/2022-12-18 | `siteOne` | `subscription()` | +| Microsoft.Web/sites/2022-12-18 | `siteTwo` | `subscription()` |"; var resources = new List { new("Microsoft.Web/sites/2022-12-18", "Microsoft.Web", "sites") @@ -230,7 +230,7 @@ public async Task BuildReferencedResources_InputTemplate_BuildsSingle() | Provider | Name | Scope | | --- | --- | --- | -| Microsoft.Resources/resourceGroups@2021-01-01 | resourceGroupName | - |"; +| Microsoft.Resources/resourceGroups@2021-01-01 | `resourceGroupName` | - |"; const string template = @"resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-01-01' existing = { name: resourceGroupName diff --git a/src/BicepDocs.Formatter.Markdown/Elements/MkTable.cs b/src/BicepDocs.Formatter.Markdown/Elements/MkTable.cs index 5787c12..e85c35a 100644 --- a/src/BicepDocs.Formatter.Markdown/Elements/MkTable.cs +++ b/src/BicepDocs.Formatter.Markdown/Elements/MkTable.cs @@ -34,6 +34,6 @@ public override string ToMarkdown() sb.AppendLine($"| {string.Join(" | ", row)} |"); } - return sb.ToString().Replace("<", "\\<").Replace(">", "\\>"); + return sb.ToString().Replace("<", "\\<").Replace(">", "\\>").Replace("\\
", "
"); } } \ No newline at end of file diff --git a/src/BicepDocs.Formatter.Markdown/Generators/ParameterGenerator.cs b/src/BicepDocs.Formatter.Markdown/Generators/ParameterGenerator.cs index 1ce5db9..d772068 100644 --- a/src/BicepDocs.Formatter.Markdown/Generators/ParameterGenerator.cs +++ b/src/BicepDocs.Formatter.Markdown/Generators/ParameterGenerator.cs @@ -18,9 +18,7 @@ internal static void BuildParameters(MarkdownDocument document, FormatterOptions .AddColumn("Default"); foreach (var tp in parameters.OrderBy(x => x.Name)) { - var type = tp.IsComplexAllow - ? new MkAnchor($"{tp.Name}Allow", $"#{tp.Name}Allow".ToLower()).ToMarkdown() - : tp.Type.Replace("|", "\\|"); + var type = BuildType(tp); var dfValue = GetParameterDefault(tp); paramOverviewTable.AddRow(tp.Name.WrapInBackticks(), tp.Description ?? "", type, dfValue); @@ -37,7 +35,8 @@ private static string GetParameterDefault(ParsedParameter tp) if (tp.IsComplexDefault) return new MkAnchor($"{tp.Name}Value", $"#{tp.Name}Value".ToLower()).ToMarkdown(); - return (tp.IsInterpolated ? tp.DefaultValue.WrapInBackticks() : tp.DefaultValue).Replace(Environment.NewLine, ""); + return (tp.IsInterpolated ? tp.DefaultValue.WrapInBackticks() : tp.DefaultValue).Replace(Environment.NewLine, + ""); } internal static void BuildParameterReferences(MarkdownDocument document, FormatterOptions options, @@ -76,4 +75,89 @@ internal static void BuildParameterReferences(MarkdownDocument document, Formatt } } } + + private static string? BuildType(ParsedParameter parameter) + { + string type = string.Empty; + + if (parameter.IsComplexAllow) + { + type += new MkAnchor($"{parameter.Name}Allow", $"#{parameter.Name}Allow".ToLower()).ToMarkdown(); + if (parameter.Secure) + { + type += " (secure)"; + } + } + else + { + type += parameter.Type.Replace("|", "\\|"); + if (parameter.Secure) type += " (secure)"; + } + + + var minMax = GetCharacterLimit(parameter); + if (minMax != null) + { + type += "

"; + type += $"Character limit: {minMax}"; + } + + var value = GetAcceptedValues(parameter); + if (value != null) + { + type += "

"; + type += $"Accepted values: {value}";; + } + + return type; + } + + public static string? GetAcceptedValues(ParsedParameter parameter) + { + if (parameter.MinValue == null && parameter.MaxValue == null) + return null; + + if (parameter is { MinValue: { }, MaxValue: { } }) + { + return $"from {parameter.MinValue} to {parameter.MaxValue}."; + } + + if (parameter.MinValue != null) + { + return $"from {parameter.MinValue}."; + } + + if (parameter.MaxValue != null) + { + return $"to {parameter.MaxValue}."; + } + + return null; + } + + + private static string? GetCharacterLimit(ParsedParameter parameter) + { + if (parameter.MinLength == null && parameter.MaxLength == null) + { + return null; + } + + if (parameter is { MinLength: { }, MaxLength: { } }) + { + return $"{parameter.MinLength}-{parameter.MaxLength}"; + } + + if (parameter.MinLength != null) + { + return $"{parameter.MinLength}-X"; + } + + if (parameter.MaxLength != null) + { + return $"X-{parameter.MaxLength}"; + } + + return null; + } } \ No newline at end of file diff --git a/src/BicepDocs.sln b/src/BicepDocs.sln index aa19637..15f21eb 100644 --- a/src/BicepDocs.sln +++ b/src/BicepDocs.sln @@ -12,8 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E367F706 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BicepDocs.Core.UnitTests", "BicepDocs.Core.UnitTests\BicepDocs.Core.UnitTests.csproj", "{992E11FE-FD9A-4250-AB60-0EACAC444599}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BicepDocs.Cli.UnitTests", "BicepDocs.Cli.UnitTests\BicepDocs.Cli.UnitTests.csproj", "{AD274B94-C107-4693-9FD4-4749EC8039E5}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BicepDocs.Formatter.Docusaurus.UnitTests", "BicepDocs.Formatter.Docusaurus.UnitTests\BicepDocs.Formatter.Docusaurus.UnitTests.csproj", "{2185B91F-1224-4CF6-9B09-E0C98F392914}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Formatters", "Formatters", "{5F98E680-B7E6-49AE-9CA8-B99838AE9CBC}" @@ -64,10 +62,6 @@ Global {992E11FE-FD9A-4250-AB60-0EACAC444599}.Debug|Any CPU.Build.0 = Debug|Any CPU {992E11FE-FD9A-4250-AB60-0EACAC444599}.Release|Any CPU.ActiveCfg = Release|Any CPU {992E11FE-FD9A-4250-AB60-0EACAC444599}.Release|Any CPU.Build.0 = Release|Any CPU - {AD274B94-C107-4693-9FD4-4749EC8039E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AD274B94-C107-4693-9FD4-4749EC8039E5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD274B94-C107-4693-9FD4-4749EC8039E5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AD274B94-C107-4693-9FD4-4749EC8039E5}.Release|Any CPU.Build.0 = Release|Any CPU {2185B91F-1224-4CF6-9B09-E0C98F392914}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2185B91F-1224-4CF6-9B09-E0C98F392914}.Debug|Any CPU.Build.0 = Debug|Any CPU {2185B91F-1224-4CF6-9B09-E0C98F392914}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -95,7 +89,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {992E11FE-FD9A-4250-AB60-0EACAC444599} = {E367F706-9E68-4431-8FC4-BCC89B1211A9} - {AD274B94-C107-4693-9FD4-4749EC8039E5} = {E367F706-9E68-4431-8FC4-BCC89B1211A9} {68BB0CC8-DAEA-4EF1-8380-6597A4C2EE63} = {5F98E680-B7E6-49AE-9CA8-B99838AE9CBC} {4410595E-60F5-4C59-8149-334517556E43} = {5F98E680-B7E6-49AE-9CA8-B99838AE9CBC} {5430B82F-50B4-4FA2-9F5D-62619A22B52A} = {4C4A19D1-C386-41CB-A311-0EC767BD4459}