Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/utils/__tests__/build-utils-suppress-warnings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,96 @@ describe('executeXcodeBuildCommand - suppressWarnings', () => {
expect(textContent).not.toContain('⚠️ Warning:');
expect(textContent).toContain('❌ Error:');
});

it('should not flag source code lines containing "error" or "warning" as diagnostics', async () => {
sessionStore.setDefaults({ suppressWarnings: false });

// Swift source lines echoed during compilation that contain "error"/"warning" as substrings
const buildOutput = [
' var authError: Error?',
' private(set) var error: WalletError?',
' private(set) var lastError: Error?',
' var loadError: Error?',
' private(set) var error: String?',
' var warningCount: Int = 0',
' let isWarning: Bool',
' fatalError("unexpected state")',
].join('\n');

const mockExecutor = createMockExecutor({
success: true,
output: buildOutput,
error: '',
exitCode: 0,
});

const result = await executeXcodeBuildCommand(
{
projectPath: '/test/project.xcodeproj',
scheme: 'TestScheme',
configuration: 'Debug',
},
{
platform: XcodePlatform.macOS,
logPrefix: 'Test',
},
false,
'build',
mockExecutor,
);

expect(result.content).toBeDefined();
const textContent = result.content
?.filter((c) => c.type === 'text')
.map((c) => (c as { text: string }).text)
.join('\n');
expect(textContent).not.toContain('❌ Error:');
expect(textContent).not.toContain('⚠️ Warning:');
});

it('should match real xcodebuild diagnostic lines', async () => {
sessionStore.setDefaults({ suppressWarnings: false });

const buildOutput = [
"/path/to/File.swift:42:10: error: cannot find 'foo' in scope",
"/path/to/File.swift:15:5: warning: unused variable 'bar'",
'error: build failed',
'warning: deprecated API usage',
'ld: warning: directory not found for option',
'clang: error: linker command failed',
'xcode-select: error: tool xcodebuild requires Xcode',
'fatal error: too many errors emitted',
"/path/to/header.h:1:9: fatal error: 'Header.h' file not found",
].join('\n');

const mockExecutor = createMockExecutor({
success: true,
output: buildOutput,
error: '',
exitCode: 0,
});

const result = await executeXcodeBuildCommand(
{
projectPath: '/test/project.xcodeproj',
scheme: 'TestScheme',
configuration: 'Debug',
},
{
platform: XcodePlatform.macOS,
logPrefix: 'Test',
},
false,
'build',
mockExecutor,
);

expect(result.content).toBeDefined();
const textContent = result.content
?.filter((c) => c.type === 'text')
.map((c) => (c as { text: string }).text)
.join('\n');
expect(textContent).toContain('❌ Error:');
expect(textContent).toContain('⚠️ Warning:');
});
});
9 changes: 7 additions & 2 deletions src/utils/build-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,16 @@ export async function executeXcodeBuildCommand(
// Collect warnings, errors, and stderr messages from the build output
const buildMessages: { type: 'text'; text: string }[] = [];
function grepWarningsAndErrors(text: string): { type: 'warning' | 'error'; content: string }[] {
// Require "error:"/"warning:" at line start (with optional tool prefix like "ld: ")
// or after a file:line:col location prefix, to avoid false positives from source
// code like "var authError: Error?" echoed during compilation.
return text
.split('\n')
.map((content) => {
if (/warning:/i.test(content)) return { type: 'warning', content };
if (/error:/i.test(content)) return { type: 'error', content };
if (/(?:^(?:[\w-]+:\s+)?|:\d+:\s+)warning:\s/i.test(content))
return { type: 'warning', content };
if (/(?:^(?:[\w-]+:\s+)?|:\d+:\s+)(?:fatal )?error:\s/i.test(content))
return { type: 'error', content };
return null;
})
.filter(Boolean) as { type: 'warning' | 'error'; content: string }[];
Expand Down