From d24c8218fd71304d5630304cb5e479734e619224 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sun, 21 Jun 2026 02:21:37 +0100 Subject: [PATCH] refactor: remove dead scaffolding from parser and edit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit edit.ValidateLanguage had zero callers (only its own godoc referenced it) — removed. yaml_json.go: contrary to the audit's claim, the file is NOT entirely dead — ParseYAML/ParseJSON are live via the Parse() dispatch (parser.go:198-200) and are kept with their tests. Removed only the genuinely unreachable scaffolding that nothing constructs or calls: the YAMLNode/JSONNode types, WalkYAML, GetYAMLNodeText, GetYAMLNodeLocation, QueryYAML, QueryJSON, ValidateYAML, ValidateJSON, and ToSitterTree, plus their now-orphaned tests. YAML/JSON parsing behavior is unchanged (TestParseYAML/TestParseJSON/TestRegistryParse_YAML_JSON still pass). --- internal/edit/edit.go | 11 --- internal/parser/yaml_json.go | 153 ++---------------------------- internal/parser/yaml_json_test.go | 81 ---------------- 3 files changed, 8 insertions(+), 237 deletions(-) diff --git a/internal/edit/edit.go b/internal/edit/edit.go index a9e7ee0..7989a80 100644 --- a/internal/edit/edit.go +++ b/internal/edit/edit.go @@ -881,14 +881,3 @@ func truncateString(s string, maxLen int) string { } return s[:util.RuneBoundary(s, maxLen-3)] + "..." } - -// ValidateLanguage checks if AST editing is supported for a file. -// Returns nil for supported languages, error for unsupported. -// Note: Text-based editing is always available regardless of this check. -func ValidateLanguage(filename string) error { - lang := protocol.DetectLanguage(filename) - if lang == protocol.LangUnknown { - return fmt.Errorf("unsupported file type for AST editing: %s (text-based editing is available)", filename) - } - return nil -} diff --git a/internal/parser/yaml_json.go b/internal/parser/yaml_json.go index 053a5f8..315076d 100644 --- a/internal/parser/yaml_json.go +++ b/internal/parser/yaml_json.go @@ -4,70 +4,45 @@ package parser import ( "context" "encoding/json" - "fmt" "gopkg.in/yaml.v3" "github.com/lukaszraczylo/mcp-filepuff/pkg/errors" "github.com/lukaszraczylo/mcp-filepuff/pkg/protocol" - sitter "github.com/smacker/go-tree-sitter" ) -// YAMLNode wraps yaml.Node to provide tree-sitter-like interface -type YAMLNode struct { - *yaml.Node - Content []byte -} - -// JSONNode represents a JSON AST node -type JSONNode struct { - Value any - Type string - Children []*JSONNode - Line int - Column int -} - -// ParseYAML parses YAML content and returns a tree-sitter-compatible result +// ParseYAML parses YAML content and returns a tree-sitter-compatible result. +// YAML does not use tree-sitter, so the returned ParseResult.Tree is nil. func (r *Registry) ParseYAML(ctx context.Context, filename string, content []byte) (*ParseResult, error) { - // Check file size if len(content) > maxFileSize { return nil, errors.NewFileTooLarge(filename, int64(len(content)), maxFileSize) } - // Parse YAML var root yaml.Node if err := yaml.Unmarshal(content, &root); err != nil { return nil, errors.NewParseError("yaml", filename, err) } - // Extract syntax errors from YAML parse - syntaxErrors := extractYAMLErrors() - - // Create a pseudo tree-sitter tree for compatibility - // We'll use nil for the tree since YAML doesn't use tree-sitter return &ParseResult{ - Tree: nil, // YAML uses yaml.Node instead + Tree: nil, // YAML uses yaml.Node instead of tree-sitter Language: protocol.LangYAML, - Errors: syntaxErrors, + Errors: extractYAMLErrors(), Content: content, }, nil } -// ParseJSON parses JSON content and returns a tree-sitter-compatible result +// ParseJSON parses JSON content and returns a tree-sitter-compatible result. +// JSON does not use tree-sitter, so the returned ParseResult.Tree is nil. func (r *Registry) ParseJSON(ctx context.Context, filename string, content []byte) (*ParseResult, error) { - // Check file size if len(content) > maxFileSize { return nil, errors.NewFileTooLarge(filename, int64(len(content)), maxFileSize) } - // Parse JSON to validate syntax var jsonData any if err := json.Unmarshal(content, &jsonData); err != nil { return nil, errors.NewParseError("json", filename, err) } - // JSON parsing succeeded, no syntax errors return &ParseResult{ Tree: nil, // JSON uses native Go structures Language: protocol.LangJSON, @@ -76,120 +51,8 @@ func (r *Registry) ParseJSON(ctx context.Context, filename string, content []byt }, nil } -// extractYAMLErrors extracts errors from YAML nodes +// extractYAMLErrors returns YAML syntax errors. yaml.Unmarshal already reports +// parse errors, so reaching here means the document was syntactically valid. func extractYAMLErrors() []SyntaxError { - // YAML parser already validates during unmarshal - // If we got here, there are no syntax errors - // However, we could add semantic validation here in the future return []SyntaxError{} } - -// WalkYAML walks a YAML AST and calls fn for each node -func WalkYAML(node *yaml.Node, fn func(*yaml.Node) bool) { - if node == nil || !fn(node) { - return - } - - for _, child := range node.Content { - WalkYAML(child, fn) - } -} - -// GetYAMLNodeText returns the text representation of a YAML node -func GetYAMLNodeText(node *yaml.Node) string { - if node == nil { - return "" - } - - switch node.Kind { - case yaml.DocumentNode: - if len(node.Content) > 0 { - return GetYAMLNodeText(node.Content[0]) - } - return "" - case yaml.MappingNode: - return node.Value - case yaml.SequenceNode: - return node.Value - case yaml.ScalarNode: - return node.Value - case yaml.AliasNode: - return node.Value - default: - return "" - } -} - -// GetYAMLNodeLocation returns the location of a YAML node -func GetYAMLNodeLocation(node *yaml.Node) protocol.Location { - if node == nil { - return protocol.Location{Line: 1, Column: 1} - } - - return protocol.Location{ - Line: node.Line, - Column: node.Column, - } -} - -// QueryYAML performs a simple query on YAML content -// Example: "$.metadata.name" to find the name field in metadata -func QueryYAML(content []byte, query string) ([]*yaml.Node, error) { - var root yaml.Node - if err := yaml.Unmarshal(content, &root); err != nil { - return nil, fmt.Errorf("failed to parse YAML: %w", err) - } - - // Simple path-based query implementation - // This is a basic implementation - can be extended with more sophisticated queries - var results []*yaml.Node - - WalkYAML(&root, func(node *yaml.Node) bool { - if node.Value == query || node.Tag == query { - results = append(results, node) - } - return true - }) - - return results, nil -} - -// QueryJSON performs a simple query on JSON content -func QueryJSON(content []byte, query string) ([]any, error) { - var data any - if err := json.Unmarshal(content, &data); err != nil { - return nil, fmt.Errorf("failed to parse JSON: %w", err) - } - - // Basic implementation - can be extended with JSONPath support - var results []any - - // For now, just validate that it's valid JSON - results = append(results, data) - - return results, nil -} - -// ValidateYAML validates YAML content without parsing to full AST -func ValidateYAML(content []byte) error { - var node yaml.Node - if err := yaml.Unmarshal(content, &node); err != nil { - return fmt.Errorf("YAML validation failed: %w", err) - } - return nil -} - -// ValidateJSON validates JSON content -func ValidateJSON(content []byte) error { - var data any - if err := json.Unmarshal(content, &data); err != nil { - return fmt.Errorf("JSON validation failed: %w", err) - } - return nil -} - -// ToSitterTree is a placeholder that returns nil for YAML/JSON -// These formats don't use tree-sitter, but we keep this for interface compatibility -func (yn *YAMLNode) ToSitterTree() *sitter.Tree { - return nil -} diff --git a/internal/parser/yaml_json_test.go b/internal/parser/yaml_json_test.go index 6ec220a..9a86b8b 100644 --- a/internal/parser/yaml_json_test.go +++ b/internal/parser/yaml_json_test.go @@ -4,8 +4,6 @@ import ( "context" "testing" - "gopkg.in/yaml.v3" - "github.com/lukaszraczylo/mcp-filepuff/pkg/protocol" ) @@ -202,82 +200,3 @@ version: 1.0.0`) t.Errorf("expected YAML language for .yml extension, got %s", ymlResult.Language) } } - -func TestWalkYAML(t *testing.T) { - content := []byte(`metadata: - name: test - labels: - app: myapp - env: prod`) - - var root yaml.Node - if err := yaml.Unmarshal(content, &root); err != nil { - t.Fatalf("failed to parse YAML: %v", err) - } - - nodeCount := 0 - WalkYAML(&root, func(node *yaml.Node) bool { - nodeCount++ - return true - }) - - if nodeCount == 0 { - t.Error("expected to visit nodes, but count is 0") - } -} - -func TestValidateYAML(t *testing.T) { - tests := []struct { - name string - content []byte - shouldError bool - }{ - { - name: "valid YAML", - content: []byte("name: test\nvalue: 100"), - shouldError: false, - }, - { - name: "invalid YAML", - content: []byte("name: test\n bad:\n[unclosed"), - shouldError: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateYAML(tt.content) - if (err != nil) != tt.shouldError { - t.Errorf("ValidateYAML() error = %v, shouldError = %v", err, tt.shouldError) - } - }) - } -} - -func TestValidateJSON(t *testing.T) { - tests := []struct { - name string - content []byte - shouldError bool - }{ - { - name: "valid JSON", - content: []byte(`{"name": "test", "value": 100}`), - shouldError: false, - }, - { - name: "invalid JSON", - content: []byte(`{"name": "test", "value": 100`), - shouldError: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateJSON(tt.content) - if (err != nil) != tt.shouldError { - t.Errorf("ValidateJSON() error = %v, shouldError = %v", err, tt.shouldError) - } - }) - } -}