WokML compiler code coverage report (LCOV)
Current view: top level - c - wok_shape.c (source / functions) Coverage Total Hit
Test: 084deda Lines: 100.0 % 56 56
Test Date: 2026-08-10 11:39:41 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #include "wok_shape.h"
       2              : 
       3              : #include <string.h>
       4              : 
       5              : #include "wok_token.h"
       6              : 
       7              : typedef struct {
       8              :   u32 off, len;
       9              :   bool first_on_line;
      10              :   bool cont_lead;  // this item is a token the layout filter reads as a
      11              :                    // CONTINUATION lead, so its line is a wrapped one
      12              : } Item;
      13              : 
      14              : typedef struct {
      15              :   char *buf;
      16              :   usize len, cap;
      17              : } Out;
      18              : 
      19        33645 : static void put(Out *o, const char *p, usize n) {
      20        33645 :   if (o->len + n >= o->cap) return;  // cap is a proved bound; see wok_shape
      21        33645 :   memcpy(o->buf + o->len, p, n);
      22        33645 :   o->len += n;
      23              : }
      24              : 
      25        16892 : static void put_c(Out *o, char c) { put(o, &c, 1); }
      26              : 
      27              : // A comment's column, and whether it opens its line. WokComment carries only a
      28              : // span, so both are recovered from the source. Tabs cannot appear in
      29              : // indentation (the scanner rejects them), so counting bytes back to the
      30              : // newline gives the exact column.
      31         3027 : static u32 line_col(const char *src, u32 off, bool *first) {
      32         3027 :   u32 col = 1;
      33         3027 :   u32 i = off;
      34         3027 :   bool only_space = true;
      35         3079 :   while (i > 0 && src[i - 1] != '\n') {
      36           52 :     i--;
      37           52 :     col++;
      38           52 :     if (src[i] != ' ' && src[i] != '\t') only_space = false;
      39              :   }
      40         3027 :   *first = only_space;
      41         3027 :   return col;
      42              : }
      43              : 
      44          258 : char *wok_shape(const char *restrict src, usize src_len, WokArena *arena,
      45              :                 WokDiagSink *diag) {
      46          258 :   WokScanResult sr = wok_scan(src, src_len, arena, diag);
      47              : 
      48              :   // Every emitted byte is either a source byte, one clamped space, or one
      49              :   // newline per line, so twice the source plus a small constant is a bound.
      50          258 :   Out o = {.cap = src_len * 2 + 64, .len = 0};
      51          258 :   o.buf = WOK_NEW_N(arena, char, o.cap);
      52              : 
      53          258 :   usize ti = 0, ci = 0;
      54          258 :   const WokToken *prev = nullptr;
      55          258 :   u32 prev_end = 0;
      56          258 :   bool wrote_anything = false;
      57              : 
      58        33764 :   for (;;) {
      59              :     // Merge the token stream and the comment list by source position. A
      60              :     // comment is a first-class item here: a formatter that dropped one must
      61              :     // not be reported as canonical.
      62        17011 :     bool have_tok = ti < sr.tokens.n &&
      63        17011 :                     (WokKind)sr.tokens.tok[ti].kind != WT_EOF;
      64        17011 :     bool have_com = ci < sr.ncomments;
      65        17011 :     if (!have_tok && !have_com) break;
      66              : 
      67        16753 :     Item it;
      68        16753 :     if (have_tok && (!have_com || sr.tokens.tok[ti].off < sr.comments[ci].off)) {
      69        15237 :       const WokToken *t = &sr.tokens.tok[ti++];
      70        15237 :       it = (Item){.off = t->off,
      71        15237 :                   .len = t->len,
      72        15237 :                   .first_on_line = (t->flags & WOK_TF_FIRST_ON_LINE) != 0,
      73        15237 :                   .cont_lead = wok_token_is_continuation_lead(t)};
      74        15237 :       prev = t;
      75              :     } else {
      76         1516 :       const WokComment *c = &sr.comments[ci++];
      77         1516 :       bool first = false;
      78         1516 :       (void)line_col(src, c->off, &first);
      79         1516 :       it = (Item){.off = c->off, .len = c->len, .first_on_line = first,
      80              :                   .cont_lead = false};
      81         1516 :       prev = nullptr;
      82              :     }
      83              : 
      84        16753 :     if (it.first_on_line) {
      85         4375 :       if (wrote_anything) put_c(&o, '\n');
      86         4375 :       if (it.cont_lead) {
      87              :         // A WRAPPED line, and the one place indentation is not local: the
      88              :         // filler aligns a capability row under its `with`, so renaming the
      89              :         // function moves that column and reflows every continuation line
      90              :         // under it. Comparing those columns exactly would fail --check on a
      91              :         // rename, which is the churn arrow alignment was already exempted to
      92              :         // avoid. WHERE the break falls is still compared -- that is line
      93              :         // structure, and this line begins where it began.
      94          210 :         put_c(&o, ' ');
      95              :       } else {
      96         4165 :         bool ignored = false;
      97         2654 :         u32 col = prev && prev->off == it.off
      98              :                            ? prev->col
      99         4165 :                            : line_col(src, it.off, &ignored);
     100         6623 :         for (u32 k = 1; k < col; k++) put_c(&o, ' ');  // exactly
     101              :       }
     102        12378 :     } else if (wrote_anything) {
     103              :       // Interior gap, clamped: this is the whole trick.
     104        12378 :       if (it.off > prev_end) put_c(&o, ' ');
     105              :     }
     106              : 
     107              :     // A block comment may span lines; its interior is copied verbatim, since
     108              :     // reflowing it would be a change the formatter is not allowed to make.
     109        16753 :     put(&o, src + it.off, it.len);
     110        16753 :     prev_end = it.off + it.len;
     111        16753 :     wrote_anything = true;
     112              :   }
     113              : 
     114          258 :   o.buf[o.len < o.cap ? o.len : o.cap - 1] = '\0';
     115          258 :   return o.buf;
     116              : }
        

Generated by: LCOV version 2.4-1


Machine-readable coverage data

This page is generated. If you are a tool, a script, or an LLM, read the JSON instead of scraping this HTML — it is the same measurement, exact, and it names the individual uncovered lines.

Every artifact here is stamped with the commit it measured and the run that produced it: commit 084deda, dated 2026-08-10T11:39:41Z, built by Github CI run. The totals in coverage.json are checked against lcov’s own summary before publishing, so the JSON and this page cannot disagree.