Skip to content

Commit 95cb263

Browse files
Copilotalexec
andauthored
Fix parser failure on empty task content (#175)
* Initial plan * Fix task parsing error for empty content and improve error messages - Handle empty/whitespace-only task content gracefully in ParseTask - Add file path to "failed to parse task content" error message - Add unit tests for newline-only and whitespace-only inputs - Add integration tests for tasks with empty content Co-authored-by: alexec <1142830+alexec@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
1 parent 40b7c0a commit 95cb263

4 files changed

Lines changed: 107 additions & 1 deletion

File tree

integration_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,3 +1632,73 @@ This is a rule from a local directory without protocol.
16321632
}
16331633
}
16341634
}
1635+
1636+
// TestTaskWithEmptyContent verifies that tasks with only frontmatter
1637+
// and empty or whitespace-only content are handled gracefully.
1638+
func TestTaskWithEmptyContent(t *testing.T) {
1639+
tests := []struct {
1640+
name string
1641+
taskName string
1642+
taskContent string
1643+
}{
1644+
{
1645+
name: "empty content",
1646+
taskName: "empty-task",
1647+
taskContent: `---
1648+
task_name: empty-task
1649+
---
1650+
`,
1651+
},
1652+
{
1653+
name: "single newline",
1654+
taskName: "newline-task",
1655+
taskContent: `---
1656+
task_name: newline-task
1657+
---
1658+
1659+
`,
1660+
},
1661+
{
1662+
name: "multiple newlines",
1663+
taskName: "newlines-task",
1664+
taskContent: `---
1665+
task_name: newlines-task
1666+
---
1667+
1668+
1669+
`,
1670+
},
1671+
{
1672+
name: "whitespace only",
1673+
taskName: "whitespace-task",
1674+
taskContent: `---
1675+
task_name: whitespace-task
1676+
---
1677+
1678+
1679+
`,
1680+
},
1681+
}
1682+
1683+
for _, tt := range tests {
1684+
t.Run(tt.name, func(t *testing.T) {
1685+
dirs := setupTestDirs(t)
1686+
1687+
// Create task file with empty or whitespace content
1688+
// Use the task name in the filename
1689+
taskFile := filepath.Join(dirs.tasksDir, tt.taskName+".md")
1690+
if err := os.WriteFile(taskFile, []byte(tt.taskContent), 0o644); err != nil {
1691+
t.Fatalf("failed to write task file: %v", err)
1692+
}
1693+
1694+
// Run the program - should not error
1695+
output := runTool(t, "-C", dirs.tmpDir, tt.taskName)
1696+
1697+
// The output should contain the frontmatter but not fail
1698+
// (exact output format may vary, but it should succeed)
1699+
if output == "" {
1700+
t.Errorf("expected some output, got empty string")
1701+
}
1702+
})
1703+
}
1704+
}

pkg/codingcontext/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func (cc *Context) findTask(taskName string) error {
152152
// Parse the task content (including user_prompt) to separate text blocks from slash commands
153153
task, err := taskparser.ParseTask(taskContent)
154154
if err != nil {
155-
return fmt.Errorf("failed to parse task content: %w", err)
155+
return fmt.Errorf("failed to parse task content in file %s: %w", path, err)
156156
}
157157

158158
// Build the final content by processing each block

pkg/codingcontext/taskparser/taskparser.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ import (
110110
// task, _ := ParseTask("Introduction text\n/fix-bug 123\nSome text after")
111111
// // len(task) == 3 (text, command, text)
112112
func ParseTask(text string) (Task, error) {
113+
// Handle empty or whitespace-only content gracefully
114+
// TrimSpace returns empty string for whitespace-only input
115+
if strings.TrimSpace(text) == "" {
116+
return Task{}, nil
117+
}
118+
113119
input, err := parser().ParseString("", text)
114120
if err != nil {
115121
return nil, err

pkg/codingcontext/taskparser/taskparser_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,36 @@ func TestParseTask(t *testing.T) {
2222
}
2323
},
2424
},
25+
{
26+
name: "single newline",
27+
input: "\n",
28+
wantErr: false,
29+
check: func(t *testing.T, task Task) {
30+
if len(task) != 0 {
31+
t.Errorf("expected empty task, got %d blocks", len(task))
32+
}
33+
},
34+
},
35+
{
36+
name: "multiple newlines",
37+
input: "\n\n\n",
38+
wantErr: false,
39+
check: func(t *testing.T, task Task) {
40+
if len(task) != 0 {
41+
t.Errorf("expected empty task, got %d blocks", len(task))
42+
}
43+
},
44+
},
45+
{
46+
name: "whitespace only",
47+
input: " \t \n \n",
48+
wantErr: false,
49+
check: func(t *testing.T, task Task) {
50+
if len(task) != 0 {
51+
t.Errorf("expected empty task, got %d blocks", len(task))
52+
}
53+
},
54+
},
2555
{
2656
name: "simple text block",
2757
input: "This is a simple text block.",

0 commit comments

Comments
 (0)