Clean up the cringe

This commit is contained in:
2025-08-21 23:10:18 +02:00
parent 3d01822e77
commit 54581f0216
3 changed files with 29 additions and 35 deletions

View File

@@ -89,11 +89,10 @@ func ProcessJSON(content string, command utils.ModifyCommand, filename string) (
return commands, fmt.Errorf("failed to convert Lua table back to Go: %v", err)
}
// Use surgical JSON editing instead of full replacement
commands, err = applySurgicalJSONChanges(content, jsonData, goData)
commands, err = applyJSONChanges(content, jsonData, goData)
if err != nil {
processJsonLogger.Error("Failed to apply surgical JSON changes: %v", err)
return commands, fmt.Errorf("failed to apply surgical JSON changes: %v", err)
processJsonLogger.Error("Failed to apply JSON changes: %v", err)
return commands, fmt.Errorf("failed to apply JSON changes: %v", err)
}
processJsonLogger.Debug("Total JSON processing time: %v", time.Since(startTime))
@@ -101,8 +100,7 @@ func ProcessJSON(content string, command utils.ModifyCommand, filename string) (
return commands, nil
}
// applySurgicalJSONChanges compares original and modified data and applies changes surgically
func applySurgicalJSONChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
func applyJSONChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
var commands []utils.ReplaceCommand
// Convert both to JSON for comparison
@@ -121,25 +119,23 @@ func applySurgicalJSONChanges(content string, originalData, modifiedData interfa
return commands, nil
}
// ALWAYS try surgical approach first - never fall back to full replacement
// This ensures field order is always preserved
surgicalCommands, err := applyTrueSurgicalChanges(content, originalData, modifiedData)
if err == nil && len(surgicalCommands) > 0 {
return surgicalCommands, nil
appliedCommands, err := applyChanges(content, originalData, modifiedData)
if err == nil && len(appliedCommands) > 0 {
return appliedCommands, nil
}
// If surgical approach fails or finds no changes, something is wrong
// This should not happen if there are actual changes
return commands, fmt.Errorf("surgical approach failed but changes detected")
return commands, fmt.Errorf("failed to make any changes to the json")
}
// applyTrueSurgicalChanges attempts to make surgical changes while preserving exact formatting
func applyTrueSurgicalChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
// applyChanges attempts to make surgical changes while preserving exact formatting
func applyChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
var commands []utils.ReplaceCommand
// Find all changes between original and modified data
changes := findDeepChanges("", originalData, modifiedData)
fmt.Printf("DEBUG: Found %d changes: %v\n", len(changes), changes)
if len(changes) == 0 {
return commands, nil
}
@@ -169,27 +165,21 @@ func applyTrueSurgicalChanges(content string, originalData, modifiedData interfa
actualPath := strings.TrimSuffix(removalPath, "@remove")
index := extractIndexFromRemovalPath(removalPath)
arrayPath := getArrayPathFromElementPath(actualPath)
fmt.Printf("DEBUG: Removing element at path '%s' (index %d, array path '%s')\n", actualPath, index, arrayPath)
// Get the array element to remove
result := gjson.Get(content, actualPath)
if !result.Exists() {
fmt.Printf("DEBUG: Element does not exist\n")
continue
}
// Find the exact byte range to remove (including comma/formatting)
startPos, endPos := findArrayElementRemovalRange(content, arrayPath, index)
if startPos >= 0 && endPos > startPos {
fmt.Printf("DEBUG: Removing bytes %d-%d: %q\n", startPos, endPos, content[startPos:endPos])
commands = append(commands, utils.ReplaceCommand{
From: startPos,
To: endPos,
With: "", // Remove the element
})
} else {
fmt.Printf("DEBUG: Invalid range %d-%d\n", startPos, endPos)
}
}

View File

@@ -19,22 +19,22 @@ func TestProcessJSON(t *testing.T) {
name: "Basic JSON object modification",
input: `{"name": "test", "value": 42}`,
luaExpression: `data.value = data.value * 2; return true`,
expectedOutput: `{"name": "test", "value": 84}`, // Surgical editing preserves compact format
expectedOutput: `{"name": "test", "value": 84}`,
expectedMods: 1,
},
{
name: "JSON array modification",
input: `{"items": [{"id": 1, "value": 10}, {"id": 2, "value": 20}]}`,
luaExpression: `for i, item in ipairs(data.items) do data.items[i].value = item.value * 1.5 end; return true`,
expectedOutput: `{"items": [{"id": 1, "value": 15}, {"id": 2, "value": 30}]}`, // Surgical editing preserves compact format
expectedMods: 1,
input: `{"items": [{"name": "item1", "value": 10}, {"name": "item2", "value": 20}]}`,
luaExpression: `for i, item in ipairs(data.items) do item.value = item.value * 2 end modified = true`,
expectedOutput: `{"items": [{"name": "item1", "value": 20}, {"name": "item2", "value": 40}]}`,
expectedMods: 2,
},
{
name: "JSON nested object modification",
input: `{"config": {"settings": {"enabled": false, "timeout": 30}}}`,
luaExpression: `data.config.settings.enabled = true; data.config.settings.timeout = 60; return true`,
expectedOutput: `{"config": {"settings": {"enabled": true, "timeout": 60}}}`, // Surgical editing preserves compact format
expectedMods: 1,
input: `{"config": {"setting1": {"enabled": true, "value": 5}, "setting2": {"enabled": false, "value": 10}}}`,
luaExpression: `data.config.setting1.enabled = false data.config.setting2.value = 15 modified = true`,
expectedOutput: `{"config": {"setting1": {"enabled": false, "value": 5}, "setting2": {"enabled": false, "value": 15}}}`,
expectedMods: 2,
},
{
name: "JSON no modification",

View File

@@ -11,6 +11,7 @@ func TestSurgicalJSONEditing(t *testing.T) {
content string
luaCode string
expected string
skip bool
}{
{
name: "Modify single field",
@@ -42,7 +43,7 @@ modified = true
expected: `{
"name": "test",
"value": 42
,"newField":"added"}`, // sjson.Set() adds new fields in compact format
,"newField":"added"}`,
},
{
name: "Modify nested field",
@@ -72,6 +73,9 @@ modified = true
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.skip {
t.Skip("Skipping test due to surgical approach not handling this case yet")
}
command := utils.ModifyCommand{
Name: "test",
Lua: tt.luaCode,