Added an analyzer which keeps line breaks LF on every system (#1193)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-11 19:30:00 +01:00
1 parent b1c1f13993
commit 65d50de033
96 files changed
+741 -393

No files matched your search

@@ -618,7 +618,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
{
var markdown = new StringBuilder();
foreach (var item in items)
markdown.AppendLine($"- {item}");
markdown.AppendLineLF($"- {item}");
return markdown.ToString();
}
@@ -1090,7 +1090,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
if (outcome.Failures.Count > 0)
{
var message = string.Join(Environment.NewLine, outcome.Failures.Select(failure => $"{failure.FileName}: {failure.UserMessage}"));
var message = string.Join('\n',outcome.Failures.Select(failure => $"{failure.FileName}: {failure.UserMessage}"));
await this.MessageBus.SendError(new(AppIcons.VOICE_TRANSCRIPTION, message));
}
else if (outcome.Status is MediaImportStatus.FAILED)
@@ -1100,7 +1100,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
if (outcome.Warnings.Count > 0)
{
var message = string.Join(Environment.NewLine, outcome.Warnings.Select(warning => $"{warning.FileName}: {warning.UserMessage}"));
var message = string.Join('\n',outcome.Warnings.Select(warning => $"{warning.FileName}: {warning.UserMessage}"));
await this.MessageBus.SendWarning(new(AppIcons.VOICE_TRANSCRIPTION, message));
}
@@ -106,9 +106,9 @@ public partial class AssistantBatchProcessing
private async Task WriteLogAsync(string resolvedOutputDirectory)
{
var sb = new StringBuilder();
sb.AppendLine(CsvWriter.ToRow(LOG_SEPARATOR, T("File"), T("Time"), T("Model"), T("Status"), T("Details"), T("Tools used")));
sb.Append(CsvWriter.ToRow(LOG_SEPARATOR, T("File"), T("Time"), T("Model"), T("Status"), T("Details"), T("Tools used"))).Append(CsvWriter.ROW_END);
foreach (var fileResult in this.fileResults.Where(x => x.Status is not BatchProcessingFileStatus.QUEUED and not BatchProcessingFileStatus.PROCESSING))
sb.AppendLine(CsvWriter.ToRow(LOG_SEPARATOR, fileResult.RelativePath, fileResult.ProcessedAt.ToString(TIME_FORMAT, CultureInfo.InvariantCulture), fileResult.ModelName, fileResult.Status.ToString(), fileResult.Message, fileResult.UsedTools));
sb.Append(CsvWriter.ToRow(LOG_SEPARATOR, fileResult.RelativePath, fileResult.ProcessedAt.ToString(TIME_FORMAT, CultureInfo.InvariantCulture), fileResult.ModelName, fileResult.Status.ToString(), fileResult.Message, fileResult.UsedTools)).Append(CsvWriter.ROW_END);
await this.WriteCsvFileAsync(Path.Join(resolvedOutputDirectory, LOG_FILENAME), sb.ToString());
}
@@ -120,9 +120,9 @@ public partial class AssistantBatchProcessing
{
var separator = this.csvSeparator.Character(this.customCsvSeparator);
var sb = new StringBuilder();
sb.AppendLine(CsvWriter.ToRow(separator, T("File"), this.ResultColumnHeader));
sb.Append(CsvWriter.ToRow(separator, T("File"), this.ResultColumnHeader)).Append(CsvWriter.ROW_END);
foreach (var fileResult in this.fileResults.Where(x => x.Status is BatchProcessingFileStatus.DONE))
sb.AppendLine(CsvWriter.ToRow(separator, fileResult.RelativePath, fileResult.ResultText));
sb.Append(CsvWriter.ToRow(separator, fileResult.RelativePath, fileResult.ResultText)).Append(CsvWriter.ROW_END);
await this.WriteCsvFileAsync(Path.Join(resolvedOutputDirectory, this.ResolveResultsFileName()), sb.ToString());
}
@@ -2,8 +2,6 @@ using System.Text;
using AIStudio.Chat;
using SharedTools;
namespace AIStudio.Assistants.BeyondFactsLab;
/// <summary>
@@ -111,12 +111,12 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
var sb = new StringBuilder();
if (this.biasOfTheDay.Links.Count > 0)
{
sb.AppendLine();
sb.AppendLine("Please share the following sources with the user as a Markdown list:");
sb.AppendLineLF();
sb.AppendLineLF("Please share the following sources with the user as a Markdown list:");
foreach (var link in this.biasOfTheDay.Links)
sb.AppendLine($"- {link}");
sb.AppendLineLF($"- {link}");
sb.AppendLine();
sb.AppendLineLF();
}
return sb.ToString();
@@ -197,12 +197,12 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
var sbCompilerMessages = new StringBuilder();
if (this.provideCompilerMessages)
{
sbCompilerMessages.AppendLine("I have the following compiler messages:");
sbCompilerMessages.AppendLine();
sbCompilerMessages.AppendLine("```");
sbCompilerMessages.AppendLine(this.compilerMessages);
sbCompilerMessages.AppendLine("```");
sbCompilerMessages.AppendLine();
sbCompilerMessages.AppendLineLF("I have the following compiler messages:");
sbCompilerMessages.AppendLineLF();
sbCompilerMessages.AppendLineLF("```");
sbCompilerMessages.AppendLineLF(this.compilerMessages);
sbCompilerMessages.AppendLineLF("```");
sbCompilerMessages.AppendLineLF();
}
this.CreateChatThread();
@@ -897,7 +897,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
if (documents.Count > 0)
{
sb.AppendLine("""
sb.AppendLineLF("""
# DOCUMENTS:
""");
@@ -941,7 +941,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
}
var fileContent = extraction.Content;
sb.AppendLine($"""
sb.AppendLineLF($"""
## DOCUMENT {numDocuments}:
File path: {document.FilePath}
@@ -961,7 +961,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
{
if (documents.Count == 0)
{
sb.AppendLine($"""
sb.AppendLineLF($"""
There are {numImages} image file(s) attached as documents.
Please consider them as documents as well and use them to
@@ -971,7 +971,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
}
else
{
sb.AppendLine($"""
sb.AppendLineLF($"""
Additionally, there are {numImages} image file(s) attached.
Please consider them as documents as well and use them to
@@ -345,24 +345,24 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
var componentSummary = this.assistantPlugin.CreateAuditComponentSummary();
if (!string.IsNullOrWhiteSpace(componentSummary))
{
builder.AppendLine("Current component overview:");
builder.AppendLine(componentSummary);
builder.AppendLine();
builder.AppendLineLF("Current component overview:");
builder.AppendLineLF(componentSummary);
builder.AppendLineLF();
}
}
var promptPreview = await this.CollectUserPromptAsync();
if (!string.IsNullOrWhiteSpace(promptPreview))
{
builder.AppendLine("Current prompt preview from the assistant form:");
builder.AppendLine(promptPreview);
builder.AppendLine();
builder.AppendLineLF("Current prompt preview from the assistant form:");
builder.AppendLineLF(promptPreview);
builder.AppendLineLF();
}
if (this.ResultingContentBlock?.Content is ContentText text && !string.IsNullOrWhiteSpace(text.Text))
{
builder.AppendLine("Last assistant response visible in this session:");
builder.AppendLine(text.Text);
builder.AppendLineLF("Last assistant response visible in this session:");
builder.AppendLineLF(text.Text);
}
return builder.ToString().Trim();
@@ -740,6 +740,6 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
}
}
return prompt.Append(Environment.NewLine).ToString();
return prompt.AppendLineLF().ToString();
}
}
@@ -256,9 +256,9 @@ public partial class AssistantEMail : AssistantBaseCore<SettingsDialogWritingEMa
return string.Empty;
var sb = new StringBuilder();
sb.AppendLine("I want to amplify the following points:");
sb.AppendLineLF("I want to amplify the following points:");
foreach (var focus in this.selectedFoci)
sb.AppendLine($"- {focus}");
sb.AppendLineLF($"- {focus}");
return sb.ToString();
}
@@ -18,50 +18,50 @@ internal static class SwotAnalysisMarkdownFormatter
var markdown = new StringBuilder();
AppendHeading(markdown, result.MatrixHeading);
markdown.AppendLine($"| | {EscapeTableCell(result.PositiveLabel)} | {EscapeTableCell(result.NegativeLabel)} |");
markdown.AppendLine("|---|---|---|");
markdown.AppendLine($"| **{EscapeTableCell(result.InternalLabel)}** | {FormatCategoryCell(result.Strengths)} | {FormatCategoryCell(result.Weaknesses)} |");
markdown.AppendLine($"| **{EscapeTableCell(result.ExternalLabel)}** | {FormatCategoryCell(result.Opportunities)} | {FormatCategoryCell(result.Threats)} |");
markdown.AppendLine();
markdown.AppendLineLF($"| | {EscapeTableCell(result.PositiveLabel)} | {EscapeTableCell(result.NegativeLabel)} |");
markdown.AppendLineLF("|---|---|---|");
markdown.AppendLineLF($"| **{EscapeTableCell(result.InternalLabel)}** | {FormatCategoryCell(result.Strengths)} | {FormatCategoryCell(result.Weaknesses)} |");
markdown.AppendLineLF($"| **{EscapeTableCell(result.ExternalLabel)}** | {FormatCategoryCell(result.Opportunities)} | {FormatCategoryCell(result.Threats)} |");
markdown.AppendLineLF();
AppendHeading(markdown, result.OverallAssessment.Label);
foreach (var paragraph in result.OverallAssessment.Paragraphs)
{
markdown.AppendLine(Markdown.EscapeInlineText(paragraph));
markdown.AppendLine();
markdown.AppendLineLF(Markdown.EscapeInlineText(paragraph));
markdown.AppendLineLF();
}
AppendHeading(markdown, result.PrioritizedActions.Label);
if (result.PrioritizedActions.Items.Count == 0)
markdown.AppendLine(Markdown.EscapeInlineText(result.PrioritizedActions.EmptyMessage));
markdown.AppendLineLF(Markdown.EscapeInlineText(result.PrioritizedActions.EmptyMessage));
else
for (var index = 0; index < result.PrioritizedActions.Items.Count; index++)
{
var action = result.PrioritizedActions.Items[index];
var factors = string.Join("; ", action.AddressedFactors.Select(Markdown.EscapeInlineText));
markdown.AppendLine($"{index + 1}. **{Markdown.EscapeInlineText(action.Action)}** — {Markdown.EscapeInlineText(action.Rationale)} ");
markdown.AppendLine($" *{factors}*");
markdown.AppendLineLF($"{index + 1}. **{Markdown.EscapeInlineText(action.Action)}** — {Markdown.EscapeInlineText(action.Rationale)} ");
markdown.AppendLineLF($" *{factors}*");
}
markdown.AppendLine();
markdown.AppendLineLF();
foreach (var category in result.Categories)
{
AppendHeading(markdown, category.Label);
if (category.Findings.Count == 0)
markdown.AppendLine(Markdown.EscapeInlineText(category.EmptyMessage));
markdown.AppendLineLF(Markdown.EscapeInlineText(category.EmptyMessage));
else
foreach (var finding in category.Findings)
markdown.AppendLine($"- **{Markdown.EscapeInlineText(finding.Summary)}** — {Markdown.EscapeInlineText(finding.Explanation)}");
markdown.AppendLineLF($"- **{Markdown.EscapeInlineText(finding.Summary)}** — {Markdown.EscapeInlineText(finding.Explanation)}");
markdown.AppendLine();
markdown.AppendLineLF();
}
AppendHeading(markdown, result.ModerationNotes.Label);
if (result.ModerationNotes.Items.Count == 0)
markdown.AppendLine(Markdown.EscapeInlineText(result.ModerationNotes.EmptyMessage));
markdown.AppendLineLF(Markdown.EscapeInlineText(result.ModerationNotes.EmptyMessage));
else
foreach (var note in result.ModerationNotes.Items)
markdown.AppendLine($"- **{Markdown.EscapeInlineText(note.Change)}** — {Markdown.EscapeInlineText(note.Reason)}");
markdown.AppendLineLF($"- **{Markdown.EscapeInlineText(note.Change)}** — {Markdown.EscapeInlineText(note.Reason)}");
return markdown.ToString().TrimEnd();
}
@@ -69,7 +69,7 @@ internal static class SwotAnalysisMarkdownFormatter
private static void AppendHeading(StringBuilder markdown, string heading)
{
markdown.Append("## ");
markdown.AppendLine(Markdown.EscapeInlineText(heading));
markdown.AppendLineLF(Markdown.EscapeInlineText(heading));
}
private static string FormatCategoryCell(SwotCategory category)
@@ -227,7 +227,7 @@ public partial class SlideAssistant
if (library.Pictures.Count == 0)
return string.Empty;
var list = string.Join(Environment.NewLine, library.Pictures.Select((picture, index) => $"- Picture {firstNumber + index}: {picture.Name}{(picture.IsIcon ? " (icon)" : string.Empty)}"));
var list = string.Join('\n',library.Pictures.Select((picture, index) => $"- Picture {firstNumber + index}: {picture.Name}{(picture.IsIcon ? " (icon)" : string.Empty)}"));
var sanitizedList = await guardService.SanitizeAsync(list, PromptInjectionSource.FileContent(folderPath), promptInjectionScope);
return $"""
@@ -357,7 +357,7 @@ public partial class SlideAssistant
if (this.SourceImagesOfRequest().Count > 0)
rules.Add(" - Images attached as source material are for reading only. Never place them on a slide.");
return string.Join(Environment.NewLine, rules);
return string.Join('\n',rules);
}
/// <summary>
@@ -376,7 +376,7 @@ public partial class SlideAssistant
if (pictures.Count == 0)
return string.Empty;
var list = string.Join(Environment.NewLine, pictures.Select((picture, index) => $"- Picture {index + 1}: {picture.FileName}"));
var list = string.Join('\n',pictures.Select((picture, index) => $"- Picture {index + 1}: {picture.FileName}"));
var seeing = modelSeesPictures
? "The images attached to this request start with these pictures, in this order."
: "You cannot see these pictures. Place them by what their names say.";
@@ -516,7 +516,7 @@ public partial class SlideAssistant
private static string RepairPromptOf(IReadOnlyList<string> issues)
{
var listedIssues = string.Join(Environment.NewLine, issues.Take(MAX_REPORTED_ISSUES).Select(issue => $"- {issue}"));
var listedIssues = string.Join('\n',issues.Take(MAX_REPORTED_ISSUES).Select(issue => $"- {issue}"));
return $"""
Your JSON does not fit the layouts yet:
{listedIssues}
@@ -542,7 +542,7 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
if (prompts.Count == 0)
return " - Do not tailor the text to a specific audience.";
return string.Join(Environment.NewLine, prompts.Select(prompt => $" - {prompt}"));
return string.Join('\n',prompts.Select(prompt => $" - {prompt}"));
}
private string GetDocumentTaskDescription()
@@ -577,7 +577,7 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
if (documents.Count > 0)
{
sb.AppendLine("""
sb.AppendLineLF("""
# DOCUMENTS:
""");
@@ -614,7 +614,7 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
}
var fileContent = extraction.Content;
sb.AppendLine($"""
sb.AppendLineLF($"""
## DOCUMENT {numDocuments}:
File path: {document.FilePath}
@@ -634,7 +634,7 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
{
if (documents.Count == 0)
{
sb.AppendLine($"""
sb.AppendLineLF($"""
There are {numImages} image file(s) attached as source material.
Please consider them as documents as well and use them to
@@ -644,7 +644,7 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
}
else
{
sb.AppendLine($"""
sb.AppendLineLF($"""
Additionally, there are {numImages} image file(s) attached as source material.
Please consider them as documents as well and use them to
@@ -188,13 +188,13 @@ public partial class VisualBriefingAssistant
return;
if (outcome.Failures.Count > 0)
await this.MessageBus.SendError(new(AppIcons.VOICE_TRANSCRIPTION, string.Join(Environment.NewLine, outcome.Failures.Select(failure => $"{failure.FileName}: {failure.UserMessage}"))));
await this.MessageBus.SendError(new(AppIcons.VOICE_TRANSCRIPTION, string.Join('\n',outcome.Failures.Select(failure => $"{failure.FileName}: {failure.UserMessage}"))));
else if (outcome.Status is MediaImportStatus.FAILED)
await this.MessageBus.SendError(new(AppIcons.VOICE_TRANSCRIPTION, T("The media file could not be transcribed.")));
if (outcome.Warnings.Count > 0)
await this.MessageBus.SendWarning(new(AppIcons.VOICE_TRANSCRIPTION, string.Join(Environment.NewLine, outcome.Warnings.Select(warning => $"{warning.FileName}: {warning.UserMessage}"))));
await this.MessageBus.SendWarning(new(AppIcons.VOICE_TRANSCRIPTION, string.Join('\n',outcome.Warnings.Select(warning => $"{warning.FileName}: {warning.UserMessage}"))));
if (outcome.Status is MediaImportStatus.CANCELLED)
await this.MessageBus.SendWarning(new(AppIcons.VOICE_TRANSCRIPTION, T("The media transcription was canceled.")));
@@ -78,7 +78,7 @@ internal static partial class VisualBriefingStructuredResponseProcessor
var root = GetContract(typeof(T));
var shapes = EnumerateObjectShapes(root);
var builder = new StringBuilder();
builder.AppendLine("Strict JSON grammar generated from the active response contract:");
builder.AppendLineLF("Strict JSON grammar generated from the active response contract:");
foreach (var shape in shapes)
{
builder.Append(shape.Name);
@@ -98,7 +98,7 @@ internal static partial class VisualBriefingStructuredResponseProcessor
if (property.AllowsNull)
builder.Append(" | null");
}
builder.AppendLine("}");
builder.AppendLineLF("}");
}
builder.Append(
"Every object may contain only the properties shown above. Required properties must be present even when their value is null.");