diff options
| author | David Czihak <git@dcz.at> | 2026-05-07 14:33:19 +0200 |
|---|---|---|
| committer | David Czihak <git@dcz.at> | 2026-05-07 14:33:19 +0200 |
| commit | ddf2de739068b5ff0866ccb1d067f3cb53a4fc55 (patch) | |
| tree | 1a77efe9d73a6172be3c37d29b321eadd4efe379 /Scripts/normalize-zig-issues.pl | |
Initial commitv0.1.7
Diffstat (limited to 'Scripts/normalize-zig-issues.pl')
| -rw-r--r-- | Scripts/normalize-zig-issues.pl | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/Scripts/normalize-zig-issues.pl b/Scripts/normalize-zig-issues.pl new file mode 100644 index 0000000..b6ff328 --- /dev/null +++ b/Scripts/normalize-zig-issues.pl @@ -0,0 +1,93 @@ +use strict; +use warnings; +$| = 1; + +my $base = $ENV{NOVA_ZIG_TASK_CWD} || $ENV{PWD} || ""; +my %file_cache = (); + +sub normalize_path { + my ($path) = @_; + return $path if $path =~ m{^/} || $path =~ m{^[A-Za-z]:[\/\\]}; + + # The Zig compiler occasionally emits paths without a leading slash (e.g. + # "Users/..." instead of "/Users/...") when traversing relative directories. + # Detect known top-level directory names and restore the leading slash. + if ($path =~ m{^(?:Users|private|opt|Library|System|usr|var|tmp|etc|home)/}) { + return "/$path"; + } + + return $base eq "" ? $path : "$base/$path"; +} + +sub source_line_for_path { + my ($path, $line_number) = @_; + return undef if $line_number < 1; + + if (!exists $file_cache{$path}) { + if (open my $fh, "<", $path) { + my @lines = <$fh>; + close $fh; + $file_cache{$path} = \@lines; + } else { + $file_cache{$path} = undef; + } + } + + my $lines = $file_cache{$path}; + return undef if !defined $lines; + return undef if $line_number > scalar(@$lines); + + my $line = $lines->[$line_number - 1]; + $line =~ s/\r?\n$//; + return $line; +} + +# Zig reports argument-count errors at the column of the opening parenthesis, +# which causes Nova to underline the entire argument list. For method-call +# expressions (receiver.method(...)), shift the column back to the start of +# the callee identifier so only the call site itself is highlighted. +sub adjusted_call_column { + my ($source_line, $column) = @_; + return $column if !defined $source_line || $column < 1; + + my $column_index = $column - 1; + my $open_paren = index($source_line, "(", $column_index); + return $column if $open_paren < 0; + + my $prefix = substr($source_line, 0, $open_paren); + return $column if $prefix !~ /([A-Za-z_][A-Za-z0-9_]*)\s*$/; + + my $callee = $1; + my $callee_index = rindex($prefix, $callee); + return $column if $callee_index < 0; + + my $target_column = $callee_index + 1; + return $column if $target_column <= $column; + + my $between = substr($source_line, $column_index, $target_column - $column); + return $column if $between !~ /\./; + + return $target_column; +} + +while (my $line = <STDIN>) { + my $newline = $line =~ s/\r?\n$// ? "\n" : ""; + + if ($line =~ m{^([^:\n]+\.zig):(\d+):(\d+):\s*(error|warning|note):\s*(.*)$}) { + my ($path, $line_number, $column, $severity, $message) = ($1, $2, $3, $4, $5); + my $normalized = normalize_path($path); + + if ($message =~ /\bexpected\b.*argument\(s\).*\bfound\b/i) { + my $source_line = source_line_for_path($normalized, $line_number); + $column = adjusted_call_column($source_line, $column); + } + + $line = "$normalized:$line_number:$column: $severity: $message"; + } elsif ($line =~ m{^([^:\n]+\.zig):(\d+):(\d+):}) { + my ($path, $line_number, $column) = ($1, $2, $3); + my $normalized = normalize_path($path); + $line =~ s{^[^:\n]+\.zig:\d+:\d+:}{$normalized:$line_number:$column:}; + } + + print $line, $newline; +} |
