dte test coverage


Directory: ./
File: src/filetype/signatures.c
Date: 2025-11-09 11:15:51
Coverage Exec Excl Total
Lines: 100.0% 49 0 49
Functions: 100.0% 4 0 4
Branches: 90.2% 46 0 51

Line Branch Exec Source
1 static const struct EmacsModeEntry {
2 char name[15];
3 uint8_t type; // FileTypeEnum
4 } emacs_modes[] = {
5 // Strings already in builtin_filetype_names[] need not be included here
6 {"autoconf", M4},
7 {"c++", CPLUSPLUS},
8 {"cperl", PERL},
9 {"latex", TEX},
10 {"makefile", MAKE},
11 {"muttrc", CONFIG},
12 {"nroff", ROFF},
13 {"nxml", XML},
14 {"shell-script", SH},
15 };
16
17 47 static ssize_t find_var_delim(const char *start, size_t len)
18 {
19 47 const char *delim = xmemmem(start, len, STRN("-*-"));
20
2/2
✓ Branch 2 → 3 taken 28 times.
✓ Branch 2 → 4 taken 19 times.
47 return delim ? delim - start : -1;
21 }
22
23 33 static FileTypeEnum filetype_from_emacs_var(const StringView line)
24 {
25 33 ssize_t delim_offset = find_var_delim(line.data, MIN(line.length, 128));
26
2/2
✓ Branch 2 → 3 taken 14 times.
✓ Branch 2 → 18 taken 19 times.
33 if (delim_offset < 0) {
27 return NONE;
28 }
29
30 14 StringView vars = line;
31 14 strview_remove_prefix(&vars, delim_offset + STRLEN("-*-"));
32 14 strview_trim_left(&vars);
33
34 14 delim_offset = find_var_delim(vars.data, MIN(vars.length, 128));
35
1/2
✓ Branch 5 → 6 taken 14 times.
✗ Branch 5 → 18 not taken.
14 if (delim_offset <= 0) {
36 return NONE;
37 }
38
39 14 vars.length = delim_offset;
40 14 strview_trim_right(&vars);
41 14 LOG_DEBUG("found emacs file-local vars: '%.*s'", (int)vars.length, vars.data);
42
43 // TODO: Handle multiple local vars like e.g. "mode: example; other: xyz;",
44 // in addition to a single major mode string (by searching for "[Mm]ode:")?
45
1/2
✓ Branch 8 → 9 taken 14 times.
✗ Branch 8 → 18 not taken.
14 if (vars.length > FILETYPE_NAME_MAX) {
46 return NONE;
47 }
48
49 // Write the extracted var string into a buffer, to null-terminate and
50 // convert to lowercase (making the lookup effectively case-insensitive)
51 14 char name[FILETYPE_NAME_MAX + 1];
52 14 name[vars.length] = '\0';
53
2/2
✓ Branch 11 → 10 taken 187 times.
✓ Branch 11 → 12 taken 14 times.
201 for (size_t i = 0; i < vars.length; i++) {
54 187 name[i] = ascii_tolower(vars.data[i]);
55 }
56
57 // TODO: Remove "-ts" (tree-sitter), "-base" and "-ts-base" suffixes
58 // from name, before lookup?
59 14 const struct EmacsModeEntry *entry = BSEARCH(name, emacs_modes, vstrcmp);
60
2/2
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 15 taken 12 times.
14 if (entry) {
61 2 return entry->type;
62 }
63
64 12 ssize_t ft = BSEARCH_IDX(name, builtin_filetype_names, vstrcmp);
65
2/2
✓ Branch 16 → 17 taken 6 times.
✓ Branch 16 → 18 taken 6 times.
12 return (ft >= 0) ? (FileTypeEnum)ft : NONE;
66 }
67
68 4 static bool is_gitlog_commit_line(StringView line)
69 {
70
2/4
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 12 not taken.
4 if (!strview_remove_matching_prefix(&line, "commit ") || line.length < 40) {
71 return false;
72 }
73
74 4 size_t ndigits = ascii_hex_prefix_length(line.data, line.length);
75
2/2
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 12 taken 1 time.
4 if (ndigits < 40) {
76 return false;
77 }
78
79 3 strview_remove_prefix(&line, ndigits);
80
4/4
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 11 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 1 time.
4 return line.length == 0 || strview_has_prefix_and_suffix(line, " (", ")");
81 }
82
83 176 static FileTypeEnum filetype_from_signature(const StringView line)
84 {
85
2/2
✓ Branch 2 → 3 taken 77 times.
✓ Branch 2 → 25 taken 99 times.
176 if (line.length < 5) {
86 return NONE;
87 }
88
89
9/9
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 8 taken 3 times.
✓ Branch 3 → 10 taken 18 times.
✓ Branch 3 → 12 taken 1 time.
✓ Branch 3 → 15 taken 4 times.
✓ Branch 3 → 18 taken 3 times.
✓ Branch 3 → 21 taken 2 times.
✓ Branch 3 → 24 taken 12 times.
✓ Branch 3 → 25 taken 25 times.
77 switch (line.data[0]) {
90 9 case '<':
91
2/2
✓ Branch 5 → 6 taken 7 times.
✓ Branch 5 → 25 taken 2 times.
9 if (strview_has_prefix_icase(line, "<!DOCTYPE HTML")) {
92 return HTML;
93
2/2
✓ Branch 7 → 24 taken 3 times.
✓ Branch 7 → 25 taken 4 times.
7 } else if (strview_has_either_prefix(line, "<!DOCTYPE", "<?xml")) {
94 return XML;
95 }
96 break;
97 3 case '%':
98
2/2
✓ Branch 9 → 24 taken 2 times.
✓ Branch 9 → 25 taken 1 time.
3 if (strview_has_prefix(line, "%YAML")) {
99 return YAML;
100 }
101 break;
102 18 case '#':
103
2/2
✓ Branch 11 → 24 taken 16 times.
✓ Branch 11 → 25 taken 2 times.
18 if (strview_has_either_prefix(line, "#compdef ", "#autoload")) {
104 return SH;
105 }
106 break;
107 1 case 'I':
108
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 25 taken 1 time.
1 return strview_has_prefix(line, "ISO-10303-21;") ? STEP : NONE;
109 4 case 'c':
110
2/2
✓ Branch 16 → 17 taken 2 times.
✓ Branch 16 → 25 taken 2 times.
4 return is_gitlog_commit_line(line) ? GITLOG : NONE;
111 3 case 'd':
112
2/2
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 25 taken 1 time.
3 return strview_has_prefix(line, "diff --git") ? DIFF : NONE;
113 2 case 's':
114
2/2
✓ Branch 22 → 23 taken 1 time.
✓ Branch 22 → 25 taken 1 time.
2 return strview_has_prefix(line, "stash@{") ? GITSTASH : NONE;
115 case '/':
116 case '.':
117 case ';':
118 case '-':
119 case '\\':
120 // See: "emacs style file-local variables" in test_find_ft_firstline()
121 break;
122 default:
123 return NONE;
124 }
125
126 33 return filetype_from_emacs_var(line);
127 }
128