main semdiff_lang_test.go
Eric Bower  ·  2026-02-25
  1package patchbin
  2
  3import (
  4	"testing"
  5)
  6
  7const sampleJSDiff = `diff --git a/foo.js b/foo.js
  8index 1111111..2222222 100644
  9--- a/foo.js
 10+++ b/foo.js
 11@@ -1,5 +1,9 @@
 12 module.exports = {};
 13
 14-function add(a) {
 15-       return a
 16+function add(a, b) {
 17+       return a + b
 18+}
 19+
 20+function sub(a, b) {
 21+       return a - b
 22 }
 23`
 24
 25func TestSemanticChangesJavaScript(t *testing.T) {
 26	files, _, err := ParsePatch(sampleJSDiff)
 27	if err != nil {
 28		t.Fatalf("ParsePatch: %v", err)
 29	}
 30	if len(files) != 1 {
 31		t.Fatalf("expected 1 file, got %d", len(files))
 32	}
 33
 34	changes := AnalyzeSemanticChanges(files[0])
 35	if len(changes) == 0 {
 36		t.Fatalf("expected semantic changes, got none")
 37	}
 38
 39	var sawAdd, sawSub bool
 40	for _, c := range changes {
 41		t.Logf("change: kind=%s entity=%s name=%s oldSig=%q newSig=%q hunk=%d",
 42			c.Kind, c.EntityKind, c.Name, c.OldSig, c.NewSig, c.HunkIndex)
 43		if c.Name == "add" && c.Kind == SemanticSignatureChanged {
 44			sawAdd = true
 45		}
 46		if c.Name == "sub" && c.Kind == SemanticAdded {
 47			sawSub = true
 48		}
 49	}
 50
 51	if !sawAdd {
 52		t.Errorf("expected add to be reported as signature_changed")
 53	}
 54	if !sawSub {
 55		t.Errorf("expected sub to be reported as added")
 56	}
 57}
 58
 59const sampleTSDiff = `diff --git a/foo.ts b/foo.ts
 60index 1111111..2222222 100644
 61--- a/foo.ts
 62+++ b/foo.ts
 63@@ -1,5 +1,9 @@
 64 export {};
 65
 66-function add(a: number): number {
 67-       return a
 68+function add(a: number, b: number): number {
 69+       return a + b
 70+}
 71+
 72+function sub(a: number, b: number): number {
 73+       return a - b
 74 }
 75`
 76
 77func TestSemanticChangesTypeScript(t *testing.T) {
 78	files, _, err := ParsePatch(sampleTSDiff)
 79	if err != nil {
 80		t.Fatalf("ParsePatch: %v", err)
 81	}
 82	if len(files) != 1 {
 83		t.Fatalf("expected 1 file, got %d", len(files))
 84	}
 85
 86	changes := AnalyzeSemanticChanges(files[0])
 87	if len(changes) == 0 {
 88		t.Fatalf("expected semantic changes, got none")
 89	}
 90
 91	var sawAdd, sawSub bool
 92	for _, c := range changes {
 93		t.Logf("change: kind=%s entity=%s name=%s oldSig=%q newSig=%q hunk=%d",
 94			c.Kind, c.EntityKind, c.Name, c.OldSig, c.NewSig, c.HunkIndex)
 95		if c.Name == "add" && c.Kind == SemanticSignatureChanged {
 96			sawAdd = true
 97		}
 98		if c.Name == "sub" && c.Kind == SemanticAdded {
 99			sawSub = true
100		}
101	}
102
103	if !sawAdd {
104		t.Errorf("expected add to be reported as signature_changed")
105	}
106	if !sawSub {
107		t.Errorf("expected sub to be reported as added")
108	}
109}
110
111const samplePyDiff = `diff --git a/foo.py b/foo.py
112index 1111111..2222222 100644
113--- a/foo.py
114+++ b/foo.py
115@@ -1,4 +1,7 @@
116 import os
117
118-def add(a):
119-       return a
120+def add(a, b):
121+       return a + b
122+
123+def sub(a, b):
124+       return a - b
125`
126
127func TestSemanticChangesPython(t *testing.T) {
128	files, _, err := ParsePatch(samplePyDiff)
129	if err != nil {
130		t.Fatalf("ParsePatch: %v", err)
131	}
132	if len(files) != 1 {
133		t.Fatalf("expected 1 file, got %d", len(files))
134	}
135
136	changes := AnalyzeSemanticChanges(files[0])
137	if len(changes) == 0 {
138		t.Fatalf("expected semantic changes, got none")
139	}
140
141	var sawAdd, sawSub bool
142	for _, c := range changes {
143		t.Logf("change: kind=%s entity=%s name=%s oldSig=%q newSig=%q hunk=%d",
144			c.Kind, c.EntityKind, c.Name, c.OldSig, c.NewSig, c.HunkIndex)
145		if c.Name == "add" && c.Kind == SemanticSignatureChanged {
146			sawAdd = true
147		}
148		if c.Name == "sub" && c.Kind == SemanticAdded {
149			sawSub = true
150		}
151	}
152
153	if !sawAdd {
154		t.Errorf("expected add to be reported as signature_changed")
155	}
156	if !sawSub {
157		t.Errorf("expected sub to be reported as added")
158	}
159}
160
161const sampleRustDiff = `diff --git a/foo.rs b/foo.rs
162index 1111111..2222222 100644
163--- a/foo.rs
164+++ b/foo.rs
165@@ -1,5 +1,9 @@
166 mod foo;
167
168-fn add(a: i32) -> i32 {
169-       return a
170+fn add(a: i32, b: i32) -> i32 {
171+       return a + b
172+}
173+
174+fn sub(a: i32, b: i32) -> i32 {
175+       return a - b
176 }
177`
178
179func TestSemanticChangesRust(t *testing.T) {
180	files, _, err := ParsePatch(sampleRustDiff)
181	if err != nil {
182		t.Fatalf("ParsePatch: %v", err)
183	}
184	if len(files) != 1 {
185		t.Fatalf("expected 1 file, got %d", len(files))
186	}
187
188	changes := AnalyzeSemanticChanges(files[0])
189	if len(changes) == 0 {
190		t.Fatalf("expected semantic changes, got none")
191	}
192
193	var sawAdd, sawSub bool
194	for _, c := range changes {
195		t.Logf("change: kind=%s entity=%s name=%s oldSig=%q newSig=%q hunk=%d",
196			c.Kind, c.EntityKind, c.Name, c.OldSig, c.NewSig, c.HunkIndex)
197		if c.Name == "add" && c.Kind == SemanticSignatureChanged {
198			sawAdd = true
199		}
200		if c.Name == "sub" && c.Kind == SemanticAdded {
201			sawSub = true
202		}
203	}
204
205	if !sawAdd {
206		t.Errorf("expected add to be reported as signature_changed")
207	}
208	if !sawSub {
209		t.Errorf("expected sub to be reported as added")
210	}
211}