Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4320443
Add method-level change detection for ILMismatch assemblies
claude Mar 20, 2026
759e65e
Refactor method-level changes to structured table format with MemberC…
claude Mar 20, 2026
17ac966
Change symbols to words: Added/Removed/Modified, method count uses vs…
claude Mar 20, 2026
49e736a
Add Modifiers column, C# detail format, backtick emphasis, and README…
claude Mar 20, 2026
e80a523
Sync doc/samples with new Modifiers column, C# detail format, and bac…
claude Mar 20, 2026
ce20649
Revise sample report: Assembly Semantic Changes, Type column, record …
claude Mar 20, 2026
0c5158b
Rename section to Assembly Semantic Changes, add Type column, .ctor→c…
claude Mar 20, 2026
27cd6eb
Fix Property Type column, HTML table CSS, summary label, UserRecord row
claude Mar 20, 2026
84acda1
Add _defaultUser field example to Service.dll sample reports
claude Mar 20, 2026
85c8ffa
Restructure Assembly Semantic Changes table to 10 columns
claude Mar 20, 2026
994017e
Refine Kind values, add type access modifiers, remove Assembly column
claude Mar 20, 2026
6d1df53
Remove parentheses from Parameters column values
claude Mar 20, 2026
c39df79
Add Body column and replace member count with Added/Removed/Modified …
claude Mar 20, 2026
d117e2c
Swap Class and Change columns; use bullet list for change counts
claude Mar 20, 2026
86515ea
Rename MethodLevelChanges to AssemblySemanticChanges throughout
claude Mar 20, 2026
84713ac
Replace summary bullet list with Class|Change|Count table; merge cons…
claude Mar 20, 2026
86c8c3e
Remove parenthetical counts from Show assembly semantic changes label
claude Mar 20, 2026
58f4822
Hide horizontal borders between rows of the same class group
claude Mar 20, 2026
1dac444
Skip summary count table when there are no entries
claude Mar 20, 2026
808d800
Add BaseType column, fully qualified type names, sealed/interface det…
claude Mar 20, 2026
0af33f5
Enhance semantic changes table: dark headers, checkboxes, resizable c…
claude Mar 20, 2026
c189fe4
Prevent line wrapping in BaseType, Type, ReturnType, Parameters colum…
claude Mar 20, 2026
a16e515
Fix HTML semantic changes tables: remove count table checkbox, widen …
claude Mar 20, 2026
793b450
Widen Kind/Modifiers/Change/Access columns, add Struct example, sort …
claude Mar 20, 2026
772ceac
Fix Markdown modifier wrapping, lighten HTML table headers, add check…
claude Mar 20, 2026
fd29611
fix: semantic-changes-table columns truncated with ellipsis
claude Mar 21, 2026
9223d9d
fix: update sample HTML to reflect semantic-changes-table layout fix
claude Mar 21, 2026
fd512d9
fix: restore missing checkbox and Class headers in sample sc-detail t…
claude Mar 21, 2026
2a40f37
fix: sc-detail table column resize not working freely
claude Mar 21, 2026
2a2642c
fix: widen sc-detail checkbox column from 2.2em to 3.2em
claude Mar 21, 2026
cebbf7c
style: set semantic changes table cell background to white
claude Mar 21, 2026
63ed4e7
docs: sync sample HTML, CHANGELOG, test guide, and add white-bg test
claude Mar 21, 2026
7dd70d7
docs: consolidate CHANGELOG entries for squash merge
claude Mar 21, 2026
c48aaf0
fix: split broken string literal across two AppendLine calls in Js.cs
claude Mar 21, 2026
4b0259d
fix: add missing using directives for SignatureDecoder and Dictionary
claude Mar 21, 2026
22dc08a
fix: correct test assertions for NoWrapMd and lazy render CSS
claude Mar 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### [Unreleased]

#### Added

- Added **Assembly Semantic Changes** — member-level change detection for `ILMismatch` assemblies using `System.Reflection.Metadata`. For each modified .NET assembly, the report now shows type/method/property/field additions, removals, and method body changes. Controlled by the new `ShouldIncludeAssemblySemanticChangesInReport` config setting (default: `true`).
- **Report placement**: appears between **Summary** and **IL Cache Stats** in the Markdown report; shown as an expandable inline row above the IL diff in the HTML report.
- **Table columns** (12 in HTML including checkbox; 11 in Markdown): `✓` (checkbox, HTML only), `Class` (fully qualified type name), `BaseType` (base class + interfaces), `Change` (`Added`/`Removed`/`Modified`), `Kind` (`Class`/`Record`/`Struct`/`Interface`/`Enum`/`Constructor`/`StaticConstructor`/`Method`/`Property`/`Field`), `Access` (`public`/`internal`/`protected`/`private`), `Modifiers` (`static`/`abstract`/`virtual`/`override`/`sealed`/`readonly`/`const`/`static literal`/`static readonly`), `Type` (declared type for Field/Property only), `Name`, `ReturnType`, `Parameters` (displayed without parentheses), `Body` (`Changed` when method body or field initializer IL has changed; otherwise empty).
- **Summary count table**: a second table grouped by Class showing `Added`/`Removed`/`Modified` counts. Consecutive rows for the same class merge the Class cell.
- **Record detection**: records are identified heuristically by the presence of an `EqualityContract` property.
- **HTML styling**: table header background `#98989d` (light grey), data cell (`td`) background `#fff` (white) for contrast against the `diff-row` grey, per-row checkbox with auto-save, resizable columns via CSS custom properties and drag handles.
- **Markdown styling**: multi-word Modifiers (e.g. `static literal`) use non-breaking spaces to prevent wrapping.
- **New files**: [`AssemblyMethodAnalyzer`](Services/AssemblyMethodAnalyzer.cs), [`AssemblySemanticChangesSummary`](Models/AssemblySemanticChangesSummary.cs) (with computed `AddedCount`/`RemovedCount`/`ModifiedCount` properties).
- **Tests**: [`AssemblyMethodAnalyzerTests`](FolderDiffIL4DotNet.Tests/Services/AssemblyMethodAnalyzerTests.cs), [`AssemblySemanticChangesSummaryTests`](FolderDiffIL4DotNet.Tests/Models/AssemblySemanticChangesSummaryTests.cs), and new assertions in [`HtmlReportGenerateServiceTests`](FolderDiffIL4DotNet.Tests/Services/HtmlReportGenerateServiceTests.cs) (`TableHeaderUsesLighterGray`, `ThScColCbCssRuleExists`, `TdHasWhiteBackground`).
- **Docs**: added bilingual **Assembly Semantic Changes** section to [README.md](README.md), [`AssemblyMethodAnalyzerTests`](FolderDiffIL4DotNet.Tests/Services/AssemblyMethodAnalyzerTests.cs) and [`AssemblySemanticChangesSummaryTests`](FolderDiffIL4DotNet.Tests/Models/AssemblySemanticChangesSummaryTests.cs) to [TESTING_GUIDE.md](doc/TESTING_GUIDE.md), updated [`doc/samples/diff_report.html`](doc/samples/diff_report.html) and [`doc/samples/diff_report.md`](doc/samples/diff_report.md).

### [1.4.1] - 2026-03-20

#### Added
Expand Down Expand Up @@ -365,6 +378,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### [Unreleased]

#### 追加

- **Assembly Semantic Changes** を追加 — `System.Reflection.Metadata` を使用した `ILMismatch` アセンブリのメンバーレベル変更検出。変更のあった各 .NET アセンブリについて、型・メソッド・プロパティ・フィールドの増減およびメソッドボディの変更をレポートに出力します。新しい設定項目 `ShouldIncludeAssemblySemanticChangesInReport`(既定: `true`)で制御可能。
- **レポート配置**: Markdown レポートでは **Summary** と **IL Cache Stats** の間に表示。HTML レポートでは IL diff の上に展開可能なインライン行として表示。
- **テーブル列**(HTML: チェックボックス含む 12 列、Markdown: 11 列): `✓`(チェックボックス、HTML のみ)、`Class`(完全修飾型名)、`BaseType`(基底クラス+インターフェース)、`Change`(`Added`/`Removed`/`Modified`)、`Kind`(`Class`/`Record`/`Struct`/`Interface`/`Enum`/`Constructor`/`StaticConstructor`/`Method`/`Property`/`Field`)、`Access`(`public`/`internal`/`protected`/`private`)、`Modifiers`(`static`/`abstract`/`virtual`/`override`/`sealed`/`readonly`/`const`/`static literal`/`static readonly`)、`Type`(Field/Property の宣言型のみ)、`Name`、`ReturnType`、`Parameters`(括弧なしで表示)、`Body`(メソッドボディまたはフィールド初期化子の IL 変更時に `Changed`、それ以外は空欄)。
- **集計テーブル**: Class 別に `Added`/`Removed`/`Modified` の件数を表示する第二テーブル。同一クラスの連続行は Class セルを結合。
- **Record 検出**: `EqualityContract` プロパティの有無で Record 型をヒューリスティックに判定。
- **HTML スタイル**: テーブルヘッダ背景 `#98989d`(ライトグレー)、データセル(`td`)背景 `#fff`(白)で `diff-row` グレーとのコントラストを確保、行単位チェックボックス(auto-save 対応)、CSS カスタムプロパティとドラッグハンドルによるリサイズ可能な列。
- **Markdown スタイル**: 複数語の Modifiers(例: `static literal`)にノーブレークスペースを適用し折り返しを防止。
- **新規ファイル**: [`AssemblyMethodAnalyzer`](Services/AssemblyMethodAnalyzer.cs)、[`AssemblySemanticChangesSummary`](Models/AssemblySemanticChangesSummary.cs)(算出プロパティ `AddedCount`/`RemovedCount`/`ModifiedCount`)。
- **テスト**: [`AssemblyMethodAnalyzerTests`](FolderDiffIL4DotNet.Tests/Services/AssemblyMethodAnalyzerTests.cs)、[`AssemblySemanticChangesSummaryTests`](FolderDiffIL4DotNet.Tests/Models/AssemblySemanticChangesSummaryTests.cs)、[`HtmlReportGenerateServiceTests`](FolderDiffIL4DotNet.Tests/Services/HtmlReportGenerateServiceTests.cs) に新規アサーション(`TableHeaderUsesLighterGray`、`ThScColCbCssRuleExists`、`TdHasWhiteBackground`)。
- **ドキュメント**: [README.md](README.md) にバイリンガルの **Assembly Semantic Changes** セクションを追加、[TESTING_GUIDE.md](doc/TESTING_GUIDE.md) に [`AssemblyMethodAnalyzerTests`](FolderDiffIL4DotNet.Tests/Services/AssemblyMethodAnalyzerTests.cs)・[`AssemblySemanticChangesSummaryTests`](FolderDiffIL4DotNet.Tests/Models/AssemblySemanticChangesSummaryTests.cs) を追加、[`doc/samples/diff_report.html`](doc/samples/diff_report.html)・[`doc/samples/diff_report.md`](doc/samples/diff_report.md) を同期。

### [1.4.1] - 2026-03-20

#### 追加
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Collections.Generic;
using FolderDiffIL4DotNet.Models;
using Xunit;

namespace FolderDiffIL4DotNet.Tests.Models
{
public sealed class AssemblySemanticChangesSummaryTests
{
[Fact]
public void HasChanges_DefaultInstance_ReturnsFalse()
{
var summary = new AssemblySemanticChangesSummary();
Assert.False(summary.HasChanges);
}

[Fact]
public void HasChanges_WithEntries_ReturnsTrue()
{
var summary = new AssemblySemanticChangesSummary
{
Entries = new List<MemberChangeEntry>
{
new("Added", "MyApp.Service", "", "public", "", "Method", "DoWork", "", "void", "int count", ""),
},
};
Assert.True(summary.HasChanges);
}

[Fact]
public void HasChanges_EmptyEntries_ReturnsFalse()
{
var summary = new AssemblySemanticChangesSummary
{
Entries = new List<MemberChangeEntry>(),
};
Assert.False(summary.HasChanges);
}

[Fact]
public void Entries_ContainStructuredData()
{
var entry = new MemberChangeEntry("Added", "MyApp.Service", "SomeBase", "public", "static", "Method", "GetName", "", "string", "string id", "");
Assert.Equal("Added", entry.Change);
Assert.Equal("MyApp.Service", entry.TypeName);
Assert.Equal("SomeBase", entry.BaseType);
Assert.Equal("public", entry.Access);
Assert.Equal("static", entry.Modifiers);
Assert.Equal("Method", entry.MemberKind);
Assert.Equal("GetName", entry.MemberName);
Assert.Equal("", entry.MemberType);
Assert.Equal("string", entry.ReturnType);
Assert.Equal("string id", entry.Parameters);
Assert.Equal("", entry.Body);
}
}
}
79 changes: 79 additions & 0 deletions FolderDiffIL4DotNet.Tests/Services/AssemblyMethodAnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System.Linq;
using FolderDiffIL4DotNet.Services;
using Xunit;

namespace FolderDiffIL4DotNet.Tests.Services
{
public sealed class AssemblyMethodAnalyzerTests
{
[Fact]
public void Analyze_SameAssembly_NoChanges()
{
// Compare a real assembly to itself — should report no changes
// 実アセンブリを自分自身と比較 — 変更なしが期待される
var assemblyPath = typeof(AssemblyMethodAnalyzerTests).Assembly.Location;
var result = AssemblyMethodAnalyzer.Analyze(assemblyPath, assemblyPath);

Assert.NotNull(result);
Assert.False(result.HasChanges);
Assert.Empty(result.Entries);
Assert.Equal(0, result.AddedCount);
Assert.Equal(0, result.RemovedCount);
Assert.Equal(0, result.ModifiedCount);
}

[Fact]
public void Analyze_NonExistentFile_ReturnsNull()
{
// Attempting to analyse a missing file should gracefully return null
// 存在しないファイルの解析は null を返すべき
var result = AssemblyMethodAnalyzer.Analyze("/nonexistent/old.dll", "/nonexistent/new.dll");
Assert.Null(result);
}

[Fact]
public void Analyze_InvalidFile_ReturnsNull()
{
// Attempting to analyse a non-PE file should gracefully return null
// PE でないファイルの解析は null を返すべき
var textFile = typeof(AssemblyMethodAnalyzerTests).Assembly.Location + ".runtimeconfig.json";
if (!System.IO.File.Exists(textFile)) return; // skip if runtime config not available
var result = AssemblyMethodAnalyzer.Analyze(textFile, textFile);
Assert.Null(result);
}

[Fact]
public void Analyze_DifferentAssemblies_DetectsChanges()
{
// Compare test assembly to main assembly — should detect differences
// テストアセンブリとメインアセンブリを比較 — 差異が検出されるべき
var testAssembly = typeof(AssemblyMethodAnalyzerTests).Assembly.Location;
var mainAssembly = typeof(FolderDiffIL4DotNet.Models.ConfigSettings).Assembly.Location;

var result = AssemblyMethodAnalyzer.Analyze(testAssembly, mainAssembly);

Assert.NotNull(result);
Assert.True(result.HasChanges);
Assert.True(result.Entries.Count > 0);
}

[Fact]
public void Analyze_DifferentAssemblies_EntriesHaveStructuredData()
{
// Entries should contain structured MemberChangeEntry data
// エントリには構造化された MemberChangeEntry データが含まれるべき
var testAssembly = typeof(AssemblyMethodAnalyzerTests).Assembly.Location;
var mainAssembly = typeof(FolderDiffIL4DotNet.Models.ConfigSettings).Assembly.Location;

var result = AssemblyMethodAnalyzer.Analyze(testAssembly, mainAssembly);

Assert.NotNull(result);
var firstEntry = result.Entries.First();
Assert.False(string.IsNullOrEmpty(firstEntry.Change));
Assert.False(string.IsNullOrEmpty(firstEntry.TypeName));
Assert.False(string.IsNullOrEmpty(firstEntry.MemberKind));
Assert.Contains(firstEntry.Change, new[] { "Added", "Removed", "Modified" });
Assert.Contains(firstEntry.MemberKind, new[] { "Class", "Record", "Struct", "Interface", "Enum", "Constructor", "StaticConstructor", "Method", "Property", "Field" });
}
}
}
Loading
Loading