From 7fbfbba8be6b80680f904f9158437dfac3d45492 Mon Sep 17 00:00:00 2001 From: kts982 Date: Mon, 23 Feb 2026 12:16:08 +0200 Subject: [PATCH] feat: add ignore_warnings parameter to EditSource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EditSource previously treated all syntax check results (errors, warnings, info) as fatal, blocking saves. This forced users to use syntax_check=false to work around pre-existing warnings like "Redundant conversion for type STRING", which feels unsafe. Now EditSource separates errors from warnings: - Errors (E) always block the save - Warnings (W) and info (I) block by default but can be allowed with ignore_warnings=true - Warnings are always returned in the response (syntaxWarnings field) Typical flow: Call 1: EditSource(...) → "2 warnings. Use ignore_warnings=true" Call 2: EditSource(..., ignore_warnings=true) → saves + activates Refs #33 --- internal/mcp/handlers_fileio.go | 6 ++++ internal/mcp/server.go | 3 ++ pkg/adt/workflows.go | 58 ++++++++++++++++++++++----------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/internal/mcp/handlers_fileio.go b/internal/mcp/handlers_fileio.go index 32cc14c..2700880 100644 --- a/internal/mcp/handlers_fileio.go +++ b/internal/mcp/handlers_fileio.go @@ -205,6 +205,11 @@ func (s *Server) handleEditSource(ctx context.Context, request mcp.CallToolReque method = m } + ignoreWarnings := false + if iw, ok := request.Params.Arguments["ignore_warnings"].(bool); ok { + ignoreWarnings = iw + } + transport := "" if t, ok := request.Params.Arguments["transport"].(string); ok { transport = t @@ -213,6 +218,7 @@ func (s *Server) handleEditSource(ctx context.Context, request mcp.CallToolReque opts := &adt.EditSourceOptions{ ReplaceAll: replaceAll, SyntaxCheck: syntaxCheck, + IgnoreWarnings: ignoreWarnings, CaseInsensitive: caseInsensitive, Method: method, Transport: transport, diff --git a/internal/mcp/server.go b/internal/mcp/server.go index 7d333ff..49d0428 100644 --- a/internal/mcp/server.go +++ b/internal/mcp/server.go @@ -1676,6 +1676,9 @@ func (s *Server) registerTools(mode string, disabledGroups string, toolsConfig m mcp.WithBoolean("syntax_check", mcp.Description("If true (default), validate syntax before saving. If syntax errors found, changes are NOT saved. Default: true"), ), + mcp.WithBoolean("ignore_warnings", + mcp.Description("If true, only block on syntax errors (E), allow warnings (W) and info (I) through. Warnings are still returned in the response. Default: false"), + ), mcp.WithBoolean("case_insensitive", mcp.Description("If true, ignore case when matching old_string. Useful for renaming variables regardless of case. Default: false"), ), diff --git a/pkg/adt/workflows.go b/pkg/adt/workflows.go index 9ff4292..c8c7c51 100755 --- a/pkg/adt/workflows.go +++ b/pkg/adt/workflows.go @@ -1157,22 +1157,24 @@ func (c *Client) SaveClassIncludeToFile(ctx context.Context, className string, i // EditSourceResult represents the result of editing source code. type EditSourceResult struct { - Success bool `json:"success"` - ObjectURL string `json:"objectUrl"` - ObjectName string `json:"objectName"` - MatchCount int `json:"matchCount"` - OldString string `json:"oldString,omitempty"` - NewString string `json:"newString,omitempty"` - SyntaxErrors []string `json:"syntaxErrors,omitempty"` - Activation *ActivationResult `json:"activation,omitempty"` - Message string `json:"message,omitempty"` - Method string `json:"method,omitempty"` // Method name if method-level edit + Success bool `json:"success"` + ObjectURL string `json:"objectUrl"` + ObjectName string `json:"objectName"` + MatchCount int `json:"matchCount"` + OldString string `json:"oldString,omitempty"` + NewString string `json:"newString,omitempty"` + SyntaxErrors []string `json:"syntaxErrors,omitempty"` + SyntaxWarnings []string `json:"syntaxWarnings,omitempty"` + Activation *ActivationResult `json:"activation,omitempty"` + Message string `json:"message,omitempty"` + Method string `json:"method,omitempty"` // Method name if method-level edit } // EditSourceOptions provides optional parameters for EditSource. type EditSourceOptions struct { ReplaceAll bool // If true, replace all occurrences; if false, require unique match SyntaxCheck bool // If true, validate syntax before saving (default: true if not set) + IgnoreWarnings bool // If true, only block on errors (E), allow warnings (W) and info (I) CaseInsensitive bool // If true, ignore case when matching Method string // For CLAS only: constrain search/replace to this method only Transport string // Transport request number (required for non-$TMP packages) @@ -1464,21 +1466,39 @@ func (c *Client) EditSourceWithOptions(ctx context.Context, objectURL, oldString // 4. Optional syntax check if opts.SyntaxCheck { // For class includes, pass the include URL directly - SyntaxCheck handles it - syntaxErrors, err := c.SyntaxCheck(ctx, objectURL, newSource) + syntaxResults, err := c.SyntaxCheck(ctx, objectURL, newSource) if err != nil { result.Message = fmt.Sprintf("Syntax check failed: %v", err) return result, nil } - if len(syntaxErrors) > 0 { - // Convert to string messages - errorMsgs := make([]string, len(syntaxErrors)) - for i, e := range syntaxErrors { - errorMsgs[i] = fmt.Sprintf("Line %d: %s", e.Line, e.Text) + if len(syntaxResults) > 0 { + // Separate errors from warnings/info + var errors, warnings []string + for _, e := range syntaxResults { + msg := fmt.Sprintf("Line %d: %s", e.Line, e.Text) + if e.Severity == "E" { + errors = append(errors, msg) + } else { + warnings = append(warnings, msg) + } + } + + result.SyntaxWarnings = warnings + + if len(errors) > 0 { + // Always block on actual errors + result.SyntaxErrors = errors + result.Message = fmt.Sprintf("Edit would introduce %d syntax error(s). Changes NOT saved.", len(errors)) + return result, nil + } + + if len(warnings) > 0 && !opts.IgnoreWarnings { + // Block on warnings unless ignore_warnings is set + result.SyntaxErrors = warnings + result.Message = fmt.Sprintf("Edit has %d syntax warning(s). Use ignore_warnings=true to proceed. Changes NOT saved.", len(warnings)) + return result, nil } - result.SyntaxErrors = errorMsgs - result.Message = fmt.Sprintf("Edit would introduce %d syntax errors. Changes NOT saved.", len(syntaxErrors)) - return result, nil } }