• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / modo / 12828318641

17 Jan 2025 11:37AM CUT coverage: 48.228% (+11.7%) from 36.563%
12828318641

Pull #54

github

web-flow
Merge 519b6c6c2 into 41ff6f833
Pull Request #54: More unit tests

12 of 28 new or added lines in 3 files covered. (42.86%)

108 existing lines in 3 files now uncovered.

626 of 1298 relevant lines covered (48.23%)

3.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.9
/document/links.go
1
package document
2

3
import (
4
        "fmt"
5
        "log"
6
        "path"
7
        "regexp"
8
        "strings"
9
)
10

11
const regexString = `(?s)(?:(` + "```.*?```)|(`.*?`" + `))|(\[.*?\])`
12

13
func findLinks(text string) ([]int, error) {
24✔
14
        re, err := regexp.Compile(regexString)
24✔
15
        if err != nil {
24✔
16
                return nil, err
×
17
        }
×
18
        links := []int{}
24✔
19
        results := re.FindAllStringSubmatchIndex(text, -1)
24✔
20
        for _, r := range results {
34✔
21
                if r[6] >= 0 {
18✔
22
                        if len(text) > r[7] && string(text[r[7]]) == "(" {
9✔
23
                                continue
1✔
24
                        }
25
                        links = append(links, r[6], r[7])
7✔
26
                }
27
        }
28

29
        return links, nil
24✔
30
}
31

32
func (proc *Processor) processLinksPackage(p *Package, elems []string) error {
1✔
33
        newElems := AppendNew(elems, p.GetName())
1✔
34

1✔
35
        var err error
1✔
36
        p.Summary, err = proc.replaceRefs(p.Summary, newElems, len(newElems))
1✔
37
        if err != nil {
1✔
UNCOV
38
                return err
×
39
        }
×
40
        p.Description, err = proc.replaceRefs(p.Description, newElems, len(newElems))
1✔
41
        if err != nil {
1✔
42
                return err
×
43
        }
×
44

45
        for _, pkg := range p.Packages {
1✔
46
                proc.processLinksPackage(pkg, newElems)
×
47
        }
×
48
        for _, mod := range p.Modules {
3✔
49
                proc.processLinksModule(mod, newElems)
2✔
50
        }
2✔
51

52
        for _, f := range p.Functions {
1✔
53
                err := proc.processLinksFunction(f, newElems)
×
54
                if err != nil {
×
55
                        return err
×
56
                }
×
57
        }
58
        for _, s := range p.Structs {
1✔
59
                err := proc.processLinksStruct(s, newElems)
×
60
                if err != nil {
×
61
                        return err
×
62
                }
×
63
        }
64
        for _, tr := range p.Traits {
1✔
65
                err := proc.processLinksTrait(tr, newElems)
×
66
                if err != nil {
×
67
                        return err
×
68
                }
×
69
        }
70

71
        return nil
1✔
72
}
73

74
func (proc *Processor) processLinksModule(m *Module, elems []string) error {
2✔
75
        newElems := AppendNew(elems, m.GetName())
2✔
76

2✔
77
        var err error
2✔
78
        m.Summary, err = proc.replaceRefs(m.Summary, newElems, len(newElems))
2✔
79
        if err != nil {
2✔
80
                return err
×
81
        }
×
82
        m.Description, err = proc.replaceRefs(m.Description, newElems, len(newElems))
2✔
83
        if err != nil {
2✔
84
                return err
×
85
        }
×
86

87
        for _, a := range m.Aliases {
3✔
88
                err := proc.processLinksAlias(a, newElems)
1✔
89
                if err != nil {
1✔
90
                        return err
×
91
                }
×
92
        }
93
        for _, f := range m.Functions {
3✔
94
                err := proc.processLinksFunction(f, newElems)
1✔
95
                if err != nil {
1✔
96
                        return err
×
97
                }
×
98
        }
99
        for _, s := range m.Structs {
4✔
100
                err := proc.processLinksStruct(s, newElems)
2✔
101
                if err != nil {
2✔
102
                        return err
×
103
                }
×
104
        }
105
        for _, tr := range m.Traits {
3✔
106
                err := proc.processLinksTrait(tr, newElems)
1✔
107
                if err != nil {
1✔
108
                        return err
×
109
                }
×
110
        }
111

112
        return nil
2✔
113
}
114

115
func (proc *Processor) processLinksStruct(s *Struct, elems []string) error {
2✔
116
        newElems := AppendNew(elems, s.GetName())
2✔
117

2✔
118
        var err error
2✔
119
        s.Summary, err = proc.replaceRefs(s.Summary, newElems, len(elems))
2✔
120
        if err != nil {
2✔
121
                return err
×
UNCOV
122
        }
×
123
        s.Description, err = proc.replaceRefs(s.Description, newElems, len(elems))
2✔
124
        if err != nil {
2✔
125
                return err
×
126
        }
×
127

128
        for _, a := range s.Aliases {
2✔
129
                a.Description, err = proc.replaceRefs(a.Description, newElems, len(elems))
×
130
                if err != nil {
×
131
                        return err
×
132
                }
×
133
        }
134
        for _, p := range s.Parameters {
2✔
135
                p.Description, err = proc.replaceRefs(p.Description, newElems, len(elems))
×
UNCOV
136
                if err != nil {
×
UNCOV
137
                        return err
×
UNCOV
138
                }
×
139
        }
140
        for _, f := range s.Fields {
2✔
UNCOV
141
                f.Summary, err = proc.replaceRefs(f.Summary, newElems, len(elems))
×
UNCOV
142
                if err != nil {
×
UNCOV
143
                        return err
×
144
                }
×
145
                f.Description, err = proc.replaceRefs(f.Description, newElems, len(elems))
×
146
                if err != nil {
×
147
                        return err
×
148
                }
×
149
        }
150
        for _, f := range s.Functions {
2✔
151
                if err := proc.processLinksMethod(f, elems); err != nil {
×
152
                        return err
×
UNCOV
153
                }
×
154
        }
155

156
        return nil
2✔
157
}
158

159
func (proc *Processor) processLinksTrait(tr *Trait, elems []string) error {
1✔
160
        newElems := AppendNew(elems, tr.GetName())
1✔
161

1✔
162
        var err error
1✔
163
        tr.Summary, err = proc.replaceRefs(tr.Summary, newElems, len(elems))
1✔
164
        if err != nil {
1✔
165
                return err
×
166
        }
×
167
        tr.Description, err = proc.replaceRefs(tr.Description, newElems, len(elems))
1✔
168
        if err != nil {
1✔
169
                return err
×
170
        }
×
171

172
        // TODO: add when traits support parameters
173
        /*for _, p := range tr.Parameters {
174
                p.Description, err = replaceLinks(p.Description, newElems, len(elems), lookup, t)
175
                if err != nil {
176
                        return err
177
                }
178
        }*/
179
        for _, f := range tr.Fields {
1✔
180
                f.Summary, err = proc.replaceRefs(f.Summary, newElems, len(elems))
×
181
                if err != nil {
×
182
                        return err
×
UNCOV
183
                }
×
184
                f.Description, err = proc.replaceRefs(f.Description, newElems, len(elems))
×
185
                if err != nil {
×
186
                        return err
×
187
                }
×
188
        }
189
        for _, f := range tr.Functions {
1✔
190
                if err := proc.processLinksMethod(f, elems); err != nil {
×
191
                        return err
×
192
                }
×
193
        }
194

195
        return nil
1✔
196
}
197

198
func (proc *Processor) processLinksFunction(f *Function, elems []string) error {
2✔
199
        newElems := AppendNew(elems, f.GetName())
2✔
200

2✔
201
        var err error
2✔
202
        f.Summary, err = proc.replaceRefs(f.Summary, newElems, len(elems))
2✔
203
        if err != nil {
2✔
204
                return err
×
UNCOV
205
        }
×
206
        f.Description, err = proc.replaceRefs(f.Description, newElems, len(elems))
2✔
207
        if err != nil {
2✔
208
                return err
×
209
        }
×
210
        f.ReturnsDoc, err = proc.replaceRefs(f.ReturnsDoc, newElems, len(elems))
2✔
211
        if err != nil {
2✔
212
                return err
×
213
        }
×
214
        f.RaisesDoc, err = proc.replaceRefs(f.RaisesDoc, newElems, len(elems))
2✔
215
        if err != nil {
2✔
216
                return err
×
217
        }
×
218

219
        for _, a := range f.Args {
2✔
UNCOV
220
                a.Description, err = proc.replaceRefs(a.Description, newElems, len(elems))
×
UNCOV
221
                if err != nil {
×
222
                        return err
×
223
                }
×
224
        }
225
        for _, p := range f.Parameters {
2✔
226
                p.Description, err = proc.replaceRefs(p.Description, newElems, len(elems))
×
227
                if err != nil {
×
228
                        return err
×
229
                }
×
230
        }
231

232
        for _, o := range f.Overloads {
3✔
233
                err := proc.processLinksFunction(o, elems)
1✔
234
                if err != nil {
1✔
235
                        return err
×
236
                }
×
237
        }
238

239
        return nil
2✔
240
}
241

242
func (proc *Processor) processLinksAlias(a *Alias, elems []string) error {
1✔
243
        newElems := AppendNew(elems, a.GetName())
1✔
244

1✔
245
        var err error
1✔
246
        a.Summary, err = proc.replaceRefs(a.Summary, newElems, len(elems))
1✔
247
        if err != nil {
1✔
248
                return err
×
249
        }
×
250
        a.Description, err = proc.replaceRefs(a.Description, newElems, len(elems))
1✔
251
        if err != nil {
1✔
UNCOV
252
                return err
×
UNCOV
253
        }
×
254
        return nil
1✔
255
}
256

257
func (proc *Processor) processLinksMethod(f *Function, elems []string) error {
×
258
        var err error
×
UNCOV
259
        f.Summary, err = proc.replaceRefs(f.Summary, elems, len(elems))
×
UNCOV
260
        if err != nil {
×
261
                return err
×
UNCOV
262
        }
×
UNCOV
263
        f.Description, err = proc.replaceRefs(f.Description, elems, len(elems))
×
UNCOV
264
        if err != nil {
×
UNCOV
265
                return err
×
UNCOV
266
        }
×
267
        f.ReturnsDoc, err = proc.replaceRefs(f.ReturnsDoc, elems, len(elems))
×
268
        if err != nil {
×
UNCOV
269
                return err
×
270
        }
×
271
        f.RaisesDoc, err = proc.replaceRefs(f.RaisesDoc, elems, len(elems))
×
UNCOV
272
        if err != nil {
×
UNCOV
273
                return err
×
UNCOV
274
        }
×
275

UNCOV
276
        for _, a := range f.Args {
×
UNCOV
277
                a.Description, err = proc.replaceRefs(a.Description, elems, len(elems))
×
UNCOV
278
                if err != nil {
×
UNCOV
279
                        return err
×
280
                }
×
281
        }
UNCOV
282
        for _, p := range f.Parameters {
×
UNCOV
283
                p.Description, err = proc.replaceRefs(p.Description, elems, len(elems))
×
UNCOV
284
                if err != nil {
×
285
                        return err
×
286
                }
×
287
        }
288

289
        for _, o := range f.Overloads {
×
290
                err := proc.processLinksMethod(o, elems)
×
291
                if err != nil {
×
292
                        return err
×
293
                }
×
294
        }
295

296
        return nil
×
297
}
298

299
func (proc *Processor) replaceRefs(text string, elems []string, modElems int) (string, error) {
23✔
300
        indices, err := findLinks(text)
23✔
301
        if err != nil {
23✔
302
                return "", err
×
303
        }
×
304
        if len(indices) == 0 {
45✔
305
                return text, nil
22✔
306
        }
22✔
307
        for i := len(indices) - 2; i >= 0; i -= 2 {
6✔
308
                start, end := indices[i], indices[i+1]
5✔
309
                link := text[start+1 : end-1]
5✔
310

5✔
311
                content, ok := proc.refToPlaceholder(link, elems, modElems)
5✔
312
                if !ok {
10✔
313
                        continue
5✔
314
                }
315
                text = fmt.Sprintf("%s[%s]%s", text[:start], content, text[end:])
×
316
        }
317
        return text, nil
1✔
318
}
319

UNCOV
320
func (proc *Processor) ReplacePlaceholders(text string, elems []string, modElems int) (string, error) {
×
321
        indices, err := findLinks(text)
×
322
        if err != nil {
×
323
                return "", err
×
324
        }
×
325
        if len(indices) == 0 {
×
326
                return text, nil
×
327
        }
×
328
        for i := len(indices) - 2; i >= 0; i -= 2 {
×
329
                start, end := indices[i], indices[i+1]
×
330
                link := text[start+1 : end-1]
×
331

×
332
                entry, linkText, parts, ok := proc.placeholderToLink(link, elems, modElems, proc.ShortLinks)
×
333
                if !ok {
×
334
                        continue
×
335
                }
336

UNCOV
337
                var basePath string
×
338
                if entry.IsSection {
×
UNCOV
339
                        basePath = path.Join(parts[:len(parts)-1]...)
×
340
                } else {
×
UNCOV
341
                        basePath = path.Join(parts...)
×
UNCOV
342
                }
×
343

344
                pathStr, err := proc.Formatter.ToLinkPath(basePath, entry.Kind)
×
345
                if err != nil {
×
346
                        return "", err
×
347
                }
×
348
                if entry.IsSection {
×
349
                        pathStr += parts[len(parts)-1]
×
350
                }
×
351
                text = fmt.Sprintf("%s[%s](%s)%s", text[:start], linkText, pathStr, text[end:])
×
352
        }
UNCOV
353
        return text, nil
×
354
}
355

356
func (proc *Processor) placeholderToLink(link string, elems []string, modElems int, shorten bool) (entry *elemPath, text string, parts []string, ok bool) {
×
357
        linkParts := strings.SplitN(link, " ", 2)
×
UNCOV
358
        entry, text, parts, ok = proc.placeholderToAbsLink(linkParts[0], elems, modElems)
×
UNCOV
359
        if !ok {
×
360
                return
×
361
        }
×
362
        if len(linkParts) > 1 {
×
363
                text = linkParts[1]
×
364
        } else {
×
365
                if shorten {
×
UNCOV
366
                        textParts := strings.Split(text, ".")
×
UNCOV
367
                        if entry.IsSection {
×
UNCOV
368
                                text = strings.Join(textParts[len(textParts)-2:], ".")
×
UNCOV
369
                        } else {
×
UNCOV
370
                                text = textParts[len(textParts)-1]
×
UNCOV
371
                        }
×
372
                }
UNCOV
373
                text = fmt.Sprintf("`%s`", text)
×
374
        }
UNCOV
375
        return
×
376
}
377

UNCOV
378
func (proc *Processor) placeholderToAbsLink(link string, elems []string, modElems int) (*elemPath, string, []string, bool) {
×
UNCOV
379
        elemPath, ok := proc.linkTargets[link]
×
UNCOV
380
        if !ok {
×
381
                log.Printf("WARNING: Can't resolve cross ref '%s' in %s", link, strings.Join(elems, "."))
×
382
                return nil, "", nil, false
×
383
        }
×
384
        skip := 0
×
385
        for range modElems {
×
UNCOV
386
                if len(elemPath.Elements) <= skip {
×
UNCOV
387
                        break
×
388
                }
UNCOV
389
                if elemPath.Elements[skip] == elems[skip] {
×
UNCOV
390
                        skip++
×
UNCOV
391
                } else {
×
UNCOV
392
                        break
×
393
                }
394
        }
395
        fullPath := []string{}
×
396
        for range modElems - skip {
×
UNCOV
397
                fullPath = append(fullPath, "..")
×
UNCOV
398
        }
×
UNCOV
399
        fullPath = append(fullPath, elemPath.Elements[skip:]...)
×
UNCOV
400
        return &elemPath, link, fullPath, true
×
401
}
402

403
func (proc *Processor) refToPlaceholder(link string, elems []string, modElems int) (string, bool) {
5✔
404
        linkParts := strings.SplitN(link, " ", 2)
5✔
405

5✔
406
        var placeholder string
5✔
407
        var ok bool
5✔
408
        if strings.HasPrefix(link, ".") {
9✔
409
                placeholder, ok = proc.refToPlaceholderRel(linkParts[0], elems, modElems)
4✔
410
        } else {
5✔
411
                placeholder, ok = proc.refToPlaceholderAbs(linkParts[0], elems)
1✔
412
        }
1✔
413
        if !ok {
10✔
414
                return "", false
5✔
415
        }
5✔
UNCOV
416
        if len(linkParts) > 1 {
×
UNCOV
417
                return fmt.Sprintf("%s %s", placeholder, linkParts[1]), true
×
UNCOV
418
        } else {
×
UNCOV
419
                return placeholder, true
×
420
        }
×
421
}
422

423
func (proc *Processor) refToPlaceholderRel(link string, elems []string, modElems int) (string, bool) {
4✔
424
        dots := 0
4✔
425
        for strings.HasPrefix(link[dots:], ".") {
9✔
426
                dots++
5✔
427
        }
5✔
428
        if dots > modElems {
4✔
429
                log.Printf("WARNING: Too many leading dots in cross ref '%s' in %s", link, strings.Join(elems, "."))
×
430
                return "", false
×
431
        }
×
432
        linkText := link[dots:]
4✔
433
        subElems := elems[:modElems-(dots-1)]
4✔
434
        var fullLink string
4✔
435
        if len(subElems) == 0 {
4✔
436
                fullLink = linkText
×
437
        } else {
4✔
438
                fullLink = strings.Join(subElems, ".") + "." + linkText
4✔
439
        }
4✔
440

441
        placeholder, ok := proc.linkExports[fullLink]
4✔
442
        if !ok {
8✔
443
                log.Printf("WARNING: Can't resolve cross ref '%s' (%s) in %s", link, fullLink, strings.Join(elems, "."))
4✔
444
                return "", false
4✔
445
        }
4✔
UNCOV
446
        return placeholder, true
×
447
}
448

449
func (proc *Processor) refToPlaceholderAbs(link string, elems []string) (string, bool) {
1✔
450
        placeholder, ok := proc.linkExports[link]
1✔
451
        if !ok {
2✔
452
                log.Printf("WARNING: Can't resolve cross ref '%s' in %s", link, strings.Join(elems, "."))
1✔
453
                return "", false
1✔
454
        }
1✔
UNCOV
455
        return placeholder, true
×
456
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc