Skip to content

Commit 46bf771

Browse files
committed
Enforce reproducible formatting baseline
1 parent 4f0a9c5 commit 46bf771

19 files changed

Lines changed: 194 additions & 90 deletions

.editorconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
root = true
22

3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
39
[*.cs]
10+
indent_style = space
11+
indent_size = 4
12+
tab_width = 4
413
dotnet_diagnostic.CA1031.severity = warning
514

615
[FolderDiffIL4DotNet.Tests/**/*.cs]
716
dotnet_diagnostic.CA1031.severity = none
17+
18+
[*.{g,g.i,generated,designer}.cs]
19+
generated_code = true
20+
21+
[**/Generated/**/*.cs]
22+
generated_code = true
23+
24+
[*.{bat,cmd}]
25+
end_of_line = crlf

.gitattributes

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
* text=auto eol=lf
2+
3+
*.bat text eol=crlf
4+
*.cmd text eol=crlf
5+
6+
*.gif binary
7+
*.ico binary
8+
*.jpg binary
9+
*.jpeg binary
10+
*.png binary
11+
*.zip binary

.github/workflows/dotnet.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ jobs:
6161
- name: Restore dependencies
6262
run: dotnet restore FolderDiffIL4DotNet.sln
6363

64+
- name: Verify formatting
65+
run: dotnet format FolderDiffIL4DotNet.sln --verify-no-changes --no-restore --verbosity minimal
66+
6467
- name: Test NuGet audit gate
6568
run: python3 -m unittest discover -s scripts/tests -p 'test_*.py'
6669

CONTRIBUTING.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ Before opening a pull request:
1616
If you are reporting a bug, include the exact command, OS, .NET SDK version, and sanitized output.
1717
Do not paste private paths, customer data, proprietary binaries, or exploit details into public issues.
1818

19+
### Formatting
20+
21+
[`global.json`](global.json) pins the .NET SDK used by developers and CI, and [`.editorconfig`](.editorconfig) is the formatting source of truth. Install the pinned SDK, then run:
22+
23+
```shell
24+
dotnet restore FolderDiffIL4DotNet.sln
25+
dotnet format FolderDiffIL4DotNet.sln --verify-no-changes --no-restore
26+
```
27+
28+
To fix formatting drift locally, replace the verification command with:
29+
30+
```shell
31+
dotnet format FolderDiffIL4DotNet.sln --no-restore
32+
```
33+
34+
Tracked text files use LF through [`.gitattributes`](.gitattributes), except Windows command scripts (`*.bat` and `*.cmd`), which use CRLF. Binary assets are marked as binary. Build output under `bin/` and `obj/`, files recognized by the SDK as generated, and conventional generated C# filenames are not part of the hand-maintained formatting baseline.
35+
1936
## 日本語
2037

2138
`FolderDiffIL4DotNet` の改善に協力していただきありがとうございます。
@@ -31,3 +48,20 @@ Do not paste private paths, customer data, proprietary binaries, or exploit deta
3148

3249
不具合報告には、実行したコマンド、OS、.NET SDK バージョン、匿名化した出力を含めてください。
3350
public issue に private なパス、顧客データ、プロプライエタリなバイナリ、攻撃詳細を貼らないでください。
51+
52+
### フォーマット
53+
54+
開発環境と CI で使う .NET SDK は [`global.json`](global.json) で固定し、フォーマット規則は [`.editorconfig`](.editorconfig) を正本とします。固定された SDK をインストールしてから、次を実行してください。
55+
56+
```shell
57+
dotnet restore FolderDiffIL4DotNet.sln
58+
dotnet format FolderDiffIL4DotNet.sln --verify-no-changes --no-restore
59+
```
60+
61+
手元でフォーマットのずれを修正するには、検証コマンドの代わりに次を実行します。
62+
63+
```shell
64+
dotnet format FolderDiffIL4DotNet.sln --no-restore
65+
```
66+
67+
追跡対象のテキストファイルは [`.gitattributes`](.gitattributes) により LF に統一します。ただし、Windows コマンドスクリプト(`*.bat``*.cmd`)は CRLF とします。バイナリアセットは binary として指定します。`bin/``obj/` 配下のビルド出力、SDK が生成済みと認識するファイル、および一般的な生成 C# ファイル名は、手作業で保守するフォーマット基準の対象外です。

FolderDiffIL4DotNet.Core/Console/ConsoleBanner.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ public static void PrintGreeting(int hour)
6363
/// </summary>
6464
public static string GetGreeting(int hour) => hour switch
6565
{
66-
>= 0 and < 3 => "I hope you're enjoying hobby time, not working.",
67-
>= 3 and < 5 => "I hope tomorrow is a day you can sleep in...",
68-
>= 5 and < 7 => "You're up early! Did you sleep well?",
69-
>= 7 and < 8 => "Leave the diff to me and go have breakfast!",
70-
>= 8 and < 10 => "Good morning! Have you had breakfast?",
66+
>= 0 and < 3 => "I hope you're enjoying hobby time, not working.",
67+
>= 3 and < 5 => "I hope tomorrow is a day you can sleep in...",
68+
>= 5 and < 7 => "You're up early! Did you sleep well?",
69+
>= 7 and < 8 => "Leave the diff to me and go have breakfast!",
70+
>= 8 and < 10 => "Good morning! Have you had breakfast?",
7171
>= 10 and < 11 => "Breaks matter. How about a coffee?",
7272
>= 11 and < 12 => "Almost lunchtime!",
7373
>= 12 and < 13 => "Leave the diff to me and go have lunch!",
@@ -80,8 +80,8 @@ public static void PrintGreeting(int hour)
8080
>= 20 and < 21 => "Still have tasks left today? Thank you for your hard work.",
8181
>= 21 and < 22 => "Leave the diff to me and go take a shower!",
8282
>= 22 and < 23 => "Working late. Have you taken a shower?",
83-
>= 23 => "The day is almost over. Take care of your health!",
84-
_ => "Hello!",
83+
>= 23 => "The day is almost over. Take care of your health!",
84+
_ => "Hello!",
8585
};
8686
}
8787
}

FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,43 @@ public void DotNetWorkflow_DoesNotSkipDocumentationOnlyChanges()
4949
Assert.DoesNotContain("'**.md'", workflow, StringComparison.Ordinal);
5050
}
5151

52+
/// <summary>
53+
/// Verifies that developers and CI share an exact SDK, formatting rules, and a blocking format gate.
54+
/// 開発環境と CI が同一の SDK・フォーマット規則・ブロッキング形式検証を共有することを検証します。
55+
/// </summary>
56+
[Fact]
57+
[Trait("Category", "Unit")]
58+
public void FormattingBaseline_PinsSdkAndIsEnforcedByCi()
59+
{
60+
var workflow = File.ReadAllText(GetRepositoryFilePath(".github", "workflows", "dotnet.yml"));
61+
var editorConfig = File.ReadAllText(GetRepositoryFilePath(".editorconfig"));
62+
var gitAttributes = File.ReadAllText(GetRepositoryFilePath(".gitattributes"));
63+
var contributing = File.ReadAllText(GetRepositoryFilePath("CONTRIBUTING.md"));
64+
var globalJson = JsonDocument.Parse(File.ReadAllText(GetRepositoryFilePath("global.json"))).RootElement;
65+
var sdk = globalJson.GetProperty("sdk");
66+
67+
Assert.Equal("8.0.413", sdk.GetProperty("version").GetString());
68+
Assert.Equal("disable", sdk.GetProperty("rollForward").GetString());
69+
Assert.False(sdk.GetProperty("allowPrerelease").GetBoolean());
70+
Assert.Contains("global-json-file: global.json", workflow, StringComparison.Ordinal);
71+
Assert.Contains("name: Verify formatting", workflow, StringComparison.Ordinal);
72+
Assert.Contains(
73+
"dotnet format FolderDiffIL4DotNet.sln --verify-no-changes --no-restore --verbosity minimal",
74+
workflow,
75+
StringComparison.Ordinal);
76+
Assert.DoesNotContain("continue-on-error: true\n run: dotnet format", workflow, StringComparison.Ordinal);
77+
Assert.Contains("end_of_line = lf", editorConfig, StringComparison.Ordinal);
78+
Assert.Contains("indent_size = 4", editorConfig, StringComparison.Ordinal);
79+
Assert.Contains("generated_code = true", editorConfig, StringComparison.Ordinal);
80+
Assert.Contains("[*.{bat,cmd}]\nend_of_line = crlf", editorConfig, StringComparison.Ordinal);
81+
Assert.Contains("* text=auto eol=lf", gitAttributes, StringComparison.Ordinal);
82+
Assert.Contains("*.bat text eol=crlf", gitAttributes, StringComparison.Ordinal);
83+
Assert.Contains(
84+
"dotnet format FolderDiffIL4DotNet.sln --verify-no-changes --no-restore",
85+
contributing,
86+
StringComparison.Ordinal);
87+
}
88+
5289
/// <summary>
5390
/// Verifies that npm metadata used for JavaScript tests does not drift from repository metadata.
5491
/// JavaScript テスト用 npm メタデータがリポジトリメタデータからずれないことを検証します。

FolderDiffIL4DotNet.Tests/Core/Text/TextDifferTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public void Compute_VeryLargeFilesWithTinyDiff_ProducesInlineDiff()
233233
var result = TextDiffer.Compute(old, @new, contextLines: 0);
234234

235235
Assert.Contains(result, l => l.Kind == TextDiffer.Removed && l.Text == "old-changed");
236-
Assert.Contains(result, l => l.Kind == TextDiffer.Added && l.Text == "new-changed");
236+
Assert.Contains(result, l => l.Kind == TextDiffer.Added && l.Text == "new-changed");
237237
// Should produce a proper diff, not a single Truncated entry
238238
// 単独の Truncated で返すのではなく、正しく差分が得られること
239239
Assert.False(result.Count == 1 && result[0].Kind == TextDiffer.Truncated);
@@ -302,7 +302,7 @@ public void Compute_HunkHeaderLine_HasZeroLineNumbers()
302302
public void Compute_ContextLines_BothLineNumbersSet()
303303
{
304304
var old = new[] { "ctx", "changed", "ctx2" };
305-
var @new = new[] { "ctx", "new", "ctx2" };
305+
var @new = new[] { "ctx", "new", "ctx2" };
306306

307307
var result = TextDiffer.Compute(old, @new, contextLines: 1);
308308

FolderDiffIL4DotNet.Tests/Services/DotNetDisassembleServiceTests.UnitAndPrefetch.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public async Task DisassembleAsync_WhenVersionLookupFails_UsesFingerprintAndAvoi
6262
Assert.True(countAfterFirstRun > 0);
6363

6464
// Simulate tool binary update by touching mtime to change fingerprint
65-
// ツールバイナリの更新をシミュレートし、mtime 変更でフィンガープリントを変える
65+
// ツールバイナリの更新をシミュレートし、mtime 変更でフィンガープリントを変える
6666
await Task.Delay(1100);
6767
var binaryPath = GetInstalledFakeBinaryPath(binDir, "dotnet-ildasm");
6868
File.SetLastWriteTimeUtc(binaryPath, DateTime.UtcNow);

FolderDiffIL4DotNet.Tests/Services/FolderDiffServiceTests.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -312,20 +312,20 @@ private static ConfigSettings CreateConfig(
312312
int maxParallelism,
313313
List<string> textFileExtensions = null,
314314
bool shouldWarnWhenNewFileTimestampIsOlderThanOldFileTimestamp = true) => new ConfigSettingsBuilder()
315-
{
316-
IgnoredExtensions = new List<string> { ".pdb" },
317-
TextFileExtensions = textFileExtensions ?? new List<string> { ".txt" },
318-
ShouldIncludeUnchangedFiles = true,
319-
ShouldIncludeIgnoredFiles = true,
320-
ShouldOutputILText = false,
321-
ShouldIgnoreILLinesContainingConfiguredStrings = false,
322-
ILIgnoreLineContainingStrings = new List<string>(),
323-
ShouldOutputFileTimestamps = false,
324-
ShouldWarnWhenNewFileTimestampIsOlderThanOldFileTimestamp = shouldWarnWhenNewFileTimestampIsOlderThanOldFileTimestamp,
325-
MaxParallelism = maxParallelism,
326-
OptimizeForNetworkShares = false,
327-
AutoDetectNetworkShares = false
328-
}.Build();
315+
{
316+
IgnoredExtensions = new List<string> { ".pdb" },
317+
TextFileExtensions = textFileExtensions ?? new List<string> { ".txt" },
318+
ShouldIncludeUnchangedFiles = true,
319+
ShouldIncludeIgnoredFiles = true,
320+
ShouldOutputILText = false,
321+
ShouldIgnoreILLinesContainingConfiguredStrings = false,
322+
ILIgnoreLineContainingStrings = new List<string>(),
323+
ShouldOutputFileTimestamps = false,
324+
ShouldWarnWhenNewFileTimestampIsOlderThanOldFileTimestamp = shouldWarnWhenNewFileTimestampIsOlderThanOldFileTimestamp,
325+
MaxParallelism = maxParallelism,
326+
OptimizeForNetworkShares = false,
327+
AutoDetectNetworkShares = false
328+
}.Build();
329329

330330
private FolderDiffService CreateService(ConfigSettings config, ProgressReportService progressReporter, string oldDir, string newDir, string reportDir)
331331
{

ProgramRunner.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ public async Task<int> RunAsync(string[] args)
108108
{
109109
Console.Beep();
110110
}
111-
#pragma warning disable CA1031 // Beep may throw on platforms without audio support
111+
#pragma warning disable CA1031 // Beep may throw on platforms without audio support
112112
catch (PlatformNotSupportedException)
113113
{
114114
// Console.Beep() is not supported on some platforms (e.g. macOS, some Linux)
115115
// BEL character fallback above should still work
116116
}
117-
#pragma warning restore CA1031
117+
#pragma warning restore CA1031
118118
}
119119

120120
PromptForExitKeyIfNeeded(opts);
@@ -127,7 +127,7 @@ public async Task<int> RunAsync(string[] args)
127127
/// </summary>
128128
private async Task<ProgramRunResult> RunWithResultAsync(CliOptions opts)
129129
{
130-
#pragma warning disable CA1031 // Top-level application boundary classifies unexpected failures after logging.
130+
#pragma warning disable CA1031 // Top-level application boundary classifies unexpected failures after logging.
131131
try
132132
{
133133
var appVersion = InitializeLoggerAndGetAppVersion();
@@ -191,7 +191,7 @@ private async Task<ProgramRunResult> RunWithResultAsync(CliOptions opts)
191191
{
192192
return CreateFailureResult(ProgramExitCode.UnexpectedError, ex);
193193
}
194-
#pragma warning restore CA1031
194+
#pragma warning restore CA1031
195195
}
196196

197197
private string InitializeLoggerAndGetAppVersion()
@@ -240,9 +240,9 @@ private static void OutputCompletionSummaryChart(RunCompletionState state)
240240

241241
Console.WriteLine();
242242
OutputSummaryBar("Unchanged", state.UnchangedCount, total, null);
243-
OutputSummaryBar("Added", state.AddedCount, total, ConsoleColor.Green);
244-
OutputSummaryBar("Removed", state.RemovedCount, total, ConsoleColor.Red);
245-
OutputSummaryBar("Modified", state.ModifiedCount, total, ConsoleColor.Cyan);
243+
OutputSummaryBar("Added", state.AddedCount, total, ConsoleColor.Green);
244+
OutputSummaryBar("Removed", state.RemovedCount, total, ConsoleColor.Red);
245+
OutputSummaryBar("Modified", state.ModifiedCount, total, ConsoleColor.Cyan);
246246
Console.WriteLine();
247247
}
248248

0 commit comments

Comments
 (0)