Skip to content

Commit 4ecb747

Browse files
committed
test comment formatting and newline handling
1 parent 7f06980 commit 4ecb747

File tree

4 files changed

+81
-6
lines changed

4 files changed

+81
-6
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
folder: test
2+
docString: Function with comment at end
3+
body: |-
4+
sourceTable
5+
| limit 100
6+
| where IsNotEmpty(EventId) // this is a comment at the end

KustoSchemaTools.Tests/YamlDatabaseParserTests.cs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public async Task GetDatabase()
2727

2828
Assert.NotNull(db);
2929
Assert.Equal(2, db.Tables.Count);
30-
Assert.Equal(4, db.Functions.Count);
3130
Assert.Equal(6, db.Functions["UP"].Body.RowLength());
3231
Assert.Equal("DemoDatabase", db.Name);
3332

@@ -140,9 +139,39 @@ void AssertMaterializedView(
140139
Assert.NotNull(mv_with_cleanup);
141140
Assert.NotNull(mv_without_cleanup);
142141
Assert.Equal(should_match, mv_without_cleanup.Query == mv_with_cleanup.Query);
142+
143+
Assert.DoesNotContain("Preformatted", mv_with_cleanup.Query);
144+
Assert.DoesNotContain("Preformatted", mv_without_cleanup.Query);
143145
}
144146
AssertMaterializedView("mv", false);
145147
AssertMaterializedView("mv_preformatted", true);
146148
}
149+
150+
[Fact]
151+
public async Task VerifyFunctionWithCommentAtEnd()
152+
{
153+
// This test verifies that functions with comments at the end without a newline
154+
// are handled correctly when scripts are generated
155+
156+
// Arrange - First load the database
157+
var factory = new YamlDatabaseHandlerFactory<Model.Database>()
158+
.WithPlugin(new TablePlugin())
159+
.WithPlugin(new FunctionPlugin())
160+
.WithPlugin(new DatabaseCleanup());
161+
var loader = factory.Create(Path.Combine(BasePath, Deployment), Database);
162+
163+
// Act - Load the database
164+
var db = await loader.LoadAsync();
165+
var commentEndFunction = db.Functions["COMMENT_END"];
166+
Assert.NotNull(commentEndFunction);
167+
168+
// Generate the script container for the function
169+
var scriptContainers = commentEndFunction.CreateScripts("COMMENT_END", false);
170+
Assert.Single(scriptContainers);
171+
172+
var script = scriptContainers[0].Script.Text;
173+
var expected = ".create-or-alter function with(SkipValidation=```False```, View=```False```, Folder=```test```, DocString=```Function with comment at end```) COMMENT_END () { sourceTable\n| limit 100\n| where IsNotEmpty(EventId) // this is a comment at the end\n }";
174+
Assert.Equal(expected, script);
175+
}
147176
}
148-
}
177+
}

KustoSchemaTools/Model/Function.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using KustoSchemaTools.Parser;
55
using System.Text;
66
using YamlDotNet.Serialization;
7+
using System.Xml.Schema;
78

89
namespace KustoSchemaTools.Model
910
{
@@ -16,14 +17,14 @@ public class Function : IKustoBaseEntity
1617
public string Parameters { get; set; } = "";
1718
[YamlMember(ScalarStyle = YamlDotNet.Core.ScalarStyle.Literal)]
1819
public bool Preformatted { get; set; } = false;
19-
2020
public string Body { get; set; }
2121

2222
public List<DatabaseScriptContainer> CreateScripts(string name, bool isNew)
2323
{
2424
// load the non-query parts of the yaml model
25+
var excludedProperties = new HashSet<string>(["Body", "Parameters", "Preformatted"]);
2526
var properties = GetType().GetProperties()
26-
.Where(p => p.GetValue(this) != null && p.Name != "Body" && p.Name != "Parameters")
27+
.Where(p => p.GetValue(this) != null && !excludedProperties.Contains(p.Name))
2728
.Select(p => $"{p.Name}=```{p.GetValue(this)}```");
2829
var propertiesString = string.Join(", ", properties);
2930

@@ -75,7 +76,37 @@ public List<DatabaseScriptContainer> CreateScripts(string name, bool isNew)
7576
parameters = replacedFunction[9..^15];
7677
}
7778

78-
return new List<DatabaseScriptContainer> { new DatabaseScriptContainer("CreateOrAlterFunction", 40, $".create-or-alter function with({propertiesString}) {name} ({parameters}) {{ {Body} }}") };
79+
// Normalize the body to ensure it ends with exactly one newline character
80+
// and remove trailing whitespace from each line
81+
string normalizedBody = Body;
82+
83+
if (string.IsNullOrEmpty(normalizedBody))
84+
{
85+
// Empty body case
86+
normalizedBody = string.Empty;
87+
}
88+
else
89+
{
90+
// Split the body into lines, trim each line, and rejoin
91+
string[] lines = normalizedBody.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n');
92+
93+
// Process all lines except the last one
94+
for (int i = 0; i < lines.Length - 1; i++)
95+
{
96+
lines[i] = lines[i].TrimEnd();
97+
}
98+
99+
// Handle the last line separately - no need to trim trailing newlines since we split on them
100+
if (lines.Length > 0)
101+
{
102+
lines[lines.Length - 1] = lines[lines.Length - 1].TrimEnd();
103+
}
104+
105+
// Rejoin the lines and add exactly one newline character at the end
106+
normalizedBody = string.Join(Environment.NewLine, lines) + Environment.NewLine;
107+
}
108+
109+
return new List<DatabaseScriptContainer> { new DatabaseScriptContainer("CreateOrAlterFunction", 40, $".create-or-alter function with({propertiesString}) {name} ({parameters}) {{ {normalizedBody} }}") };
79110
}
80111
}
81112

KustoSchemaTools/Model/MaterializedView.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,16 @@ public List<DatabaseScriptContainer> CreateScripts(string name, bool isNew)
2929
{
3030
var asyncSetup = isNew && Backfill == true;
3131

32-
var excludedProperties = new HashSet<string>(["Query", "Source", "Kind", "RetentionAndCachePolicy", "RowLevelSecurity", "Policies"]);
32+
var excludedProperties = new HashSet<string>([
33+
"Query",
34+
"Source",
35+
"Kind",
36+
"RetentionAndCachePolicy",
37+
"RowLevelSecurity",
38+
"Policies",
39+
"Preformatted"
40+
]);
41+
3342
if (!asyncSetup)
3443
{
3544
excludedProperties.Add("EffectiveDateTime");

0 commit comments

Comments
 (0)