Skip to content

Commit 2dceacb

Browse files
neboozclaude
andcommitted
fix: avoid false positive error/warning detection from echoed source code
The `grepWarningsAndErrors` regex matched any line containing `error:` or `warning:`, which produced false positives when xcodebuild echoes Swift source lines during compilation (e.g. `var authError: Error?`, `private(set) var error: WalletError?`). Tighten the regex to require `error:`/`warning:` at the start of the line or after a file:line:col location prefix (`:<digits>: `), matching only real xcodebuild diagnostic output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c14c159 commit 2dceacb

File tree

2 files changed

+99
-2
lines changed

2 files changed

+99
-2
lines changed

src/utils/__tests__/build-utils-suppress-warnings.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,96 @@ describe('executeXcodeBuildCommand - suppressWarnings', () => {
7575
expect(textContent).not.toContain('⚠️ Warning:');
7676
expect(textContent).toContain('❌ Error:');
7777
});
78+
79+
it('should not flag source code lines containing "error" or "warning" as diagnostics', async () => {
80+
sessionStore.setDefaults({ suppressWarnings: false });
81+
82+
// Swift source lines echoed during compilation that contain "error"/"warning" as substrings
83+
const buildOutput = [
84+
' var authError: Error?',
85+
' private(set) var error: WalletError?',
86+
' private(set) var lastError: Error?',
87+
' var loadError: Error?',
88+
' private(set) var error: String?',
89+
' var warningCount: Int = 0',
90+
' let isWarning: Bool',
91+
' fatalError("unexpected state")',
92+
].join('\n');
93+
94+
const mockExecutor = createMockExecutor({
95+
success: true,
96+
output: buildOutput,
97+
error: '',
98+
exitCode: 0,
99+
});
100+
101+
const result = await executeXcodeBuildCommand(
102+
{
103+
projectPath: '/test/project.xcodeproj',
104+
scheme: 'TestScheme',
105+
configuration: 'Debug',
106+
},
107+
{
108+
platform: XcodePlatform.macOS,
109+
logPrefix: 'Test',
110+
},
111+
false,
112+
'build',
113+
mockExecutor,
114+
);
115+
116+
expect(result.content).toBeDefined();
117+
const textContent = result.content
118+
?.filter((c) => c.type === 'text')
119+
.map((c) => (c as { text: string }).text)
120+
.join('\n');
121+
expect(textContent).not.toContain('❌ Error:');
122+
expect(textContent).not.toContain('⚠️ Warning:');
123+
});
124+
125+
it('should match real xcodebuild diagnostic lines', async () => {
126+
sessionStore.setDefaults({ suppressWarnings: false });
127+
128+
const buildOutput = [
129+
"/path/to/File.swift:42:10: error: cannot find 'foo' in scope",
130+
"/path/to/File.swift:15:5: warning: unused variable 'bar'",
131+
'error: build failed',
132+
'warning: deprecated API usage',
133+
'ld: warning: directory not found for option',
134+
'clang: error: linker command failed',
135+
'xcode-select: error: tool xcodebuild requires Xcode',
136+
'fatal error: too many errors emitted',
137+
"/path/to/header.h:1:9: fatal error: 'Header.h' file not found",
138+
].join('\n');
139+
140+
const mockExecutor = createMockExecutor({
141+
success: true,
142+
output: buildOutput,
143+
error: '',
144+
exitCode: 0,
145+
});
146+
147+
const result = await executeXcodeBuildCommand(
148+
{
149+
projectPath: '/test/project.xcodeproj',
150+
scheme: 'TestScheme',
151+
configuration: 'Debug',
152+
},
153+
{
154+
platform: XcodePlatform.macOS,
155+
logPrefix: 'Test',
156+
},
157+
false,
158+
'build',
159+
mockExecutor,
160+
);
161+
162+
expect(result.content).toBeDefined();
163+
const textContent = result.content
164+
?.filter((c) => c.type === 'text')
165+
.map((c) => (c as { text: string }).text)
166+
.join('\n');
167+
expect(textContent).toContain('❌ Error:');
168+
expect(textContent).toContain('⚠️ Warning:');
169+
});
78170
});

src/utils/build-utils.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,16 @@ export async function executeXcodeBuildCommand(
6060
// Collect warnings, errors, and stderr messages from the build output
6161
const buildMessages: { type: 'text'; text: string }[] = [];
6262
function grepWarningsAndErrors(text: string): { type: 'warning' | 'error'; content: string }[] {
63+
// Require "error:"/"warning:" at line start (with optional tool prefix like "ld: ")
64+
// or after a file:line:col location prefix, to avoid false positives from source
65+
// code like "var authError: Error?" echoed during compilation.
6366
return text
6467
.split('\n')
6568
.map((content) => {
66-
if (/warning:/i.test(content)) return { type: 'warning', content };
67-
if (/error:/i.test(content)) return { type: 'error', content };
69+
if (/(?:^(?:[\w-]+:\s+)?|:\d+:\s+)warning:\s/i.test(content))
70+
return { type: 'warning', content };
71+
if (/(?:^(?:[\w-]+:\s+)?|:\d+:\s+)(?:fatal )?error:\s/i.test(content))
72+
return { type: 'error', content };
6873
return null;
6974
})
7075
.filter(Boolean) as { type: 'warning' | 'error'; content: string }[];

0 commit comments

Comments
 (0)