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

mlange-42 / modo / 12810176069

16 Jan 2025 01:43PM CUT coverage: 36.569% (+1.8%) from 34.803%
12810176069

push

github

web-flow
Implement re-exports on package level (#42)

235 of 505 new or added lines in 11 files covered. (46.53%)

41 existing lines in 4 files now uncovered.

437 of 1195 relevant lines covered (36.57%)

2.65 hits per line

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

18.03
/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) {
2✔
14
        re, err := regexp.Compile(regexString)
2✔
15
        if err != nil {
2✔
16
                return nil, err
×
17
        }
×
18
        links := []int{}
2✔
19
        results := re.FindAllStringSubmatchIndex(text, -1)
2✔
20
        for _, r := range results {
12✔
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
2✔
30
}
31

NEW
32
func (proc *Processor) ProcessLinks() error {
×
NEW
33
        proc.filterPackages()
×
NEW
34
        proc.collectPaths()
×
NEW
35

×
NEW
36
        if !proc.UseExports {
×
NEW
37
                for k := range proc.linkTargets {
×
NEW
38
                        proc.linkExports[k] = k
×
NEW
39
                }
×
40
        }
NEW
41
        if err := proc.processLinksPackage(proc.Docs.Decl, []string{}, true); err != nil {
×
NEW
42
                return err
×
NEW
43
        }
×
NEW
44
        if err := proc.processLinksPackage(proc.ExportDocs.Decl, []string{}, false); err != nil {
×
NEW
45
                return err
×
NEW
46
        }
×
NEW
47
        return nil
×
48
}
49

NEW
50
func (proc *Processor) processLinksPackage(p *Package, elems []string, firstPass bool) error {
×
51
        newElems := appendNew(elems, p.GetName())
×
52

×
53
        var err error
×
NEW
54
        p.Summary, err = proc.replaceLinks(p.Summary, newElems, len(newElems), firstPass)
×
55
        if err != nil {
×
56
                return err
×
57
        }
×
NEW
58
        p.Description, err = proc.replaceLinks(p.Description, newElems, len(newElems), firstPass)
×
59
        if err != nil {
×
60
                return err
×
61
        }
×
62

63
        for _, pkg := range p.Packages {
×
NEW
64
                proc.processLinksPackage(pkg, newElems, firstPass)
×
65
        }
×
66
        for _, mod := range p.Modules {
×
NEW
67
                proc.processLinksModule(mod, newElems, firstPass)
×
NEW
68
        }
×
69

NEW
70
        for _, f := range p.Functions {
×
NEW
71
                err := proc.processLinksFunction(f, newElems, firstPass)
×
NEW
72
                if err != nil {
×
NEW
73
                        return err
×
NEW
74
                }
×
75
        }
NEW
76
        for _, s := range p.Structs {
×
NEW
77
                err := proc.processLinksStruct(s, newElems, firstPass)
×
NEW
78
                if err != nil {
×
NEW
79
                        return err
×
NEW
80
                }
×
81
        }
NEW
82
        for _, tr := range p.Traits {
×
NEW
83
                err := proc.processLinksTrait(tr, newElems, firstPass)
×
NEW
84
                if err != nil {
×
NEW
85
                        return err
×
NEW
86
                }
×
87
        }
88

89
        return nil
×
90
}
91

NEW
92
func (proc *Processor) processLinksModule(m *Module, elems []string, firstPass bool) error {
×
93
        newElems := appendNew(elems, m.GetName())
×
94

×
95
        var err error
×
NEW
96
        m.Summary, err = proc.replaceLinks(m.Summary, newElems, len(newElems), firstPass)
×
97
        if err != nil {
×
98
                return err
×
99
        }
×
NEW
100
        m.Description, err = proc.replaceLinks(m.Description, newElems, len(newElems), firstPass)
×
101
        if err != nil {
×
102
                return err
×
103
        }
×
104

105
        for _, f := range m.Functions {
×
NEW
106
                err := proc.processLinksFunction(f, newElems, firstPass)
×
107
                if err != nil {
×
108
                        return err
×
109
                }
×
110
        }
111
        for _, s := range m.Structs {
×
NEW
112
                err := proc.processLinksStruct(s, newElems, firstPass)
×
113
                if err != nil {
×
114
                        return err
×
115
                }
×
116
        }
117
        for _, tr := range m.Traits {
×
NEW
118
                err := proc.processLinksTrait(tr, newElems, firstPass)
×
119
                if err != nil {
×
120
                        return err
×
121
                }
×
122
        }
123

124
        return nil
×
125
}
126

NEW
127
func (proc *Processor) processLinksStruct(s *Struct, elems []string, firstPass bool) error {
×
128
        newElems := appendNew(elems, s.GetName())
×
129

×
130
        var err error
×
NEW
131
        s.Summary, err = proc.replaceLinks(s.Summary, newElems, len(elems), firstPass)
×
132
        if err != nil {
×
133
                return err
×
134
        }
×
NEW
135
        s.Description, err = proc.replaceLinks(s.Description, newElems, len(elems), firstPass)
×
136
        if err != nil {
×
137
                return err
×
138
        }
×
139

140
        for _, p := range s.Parameters {
×
NEW
141
                p.Description, err = proc.replaceLinks(p.Description, newElems, len(elems), firstPass)
×
142
                if err != nil {
×
143
                        return err
×
144
                }
×
145
        }
146
        for _, f := range s.Fields {
×
NEW
147
                f.Summary, err = proc.replaceLinks(f.Summary, newElems, len(elems), firstPass)
×
148
                if err != nil {
×
149
                        return err
×
150
                }
×
NEW
151
                f.Description, err = proc.replaceLinks(f.Description, newElems, len(elems), firstPass)
×
152
                if err != nil {
×
153
                        return err
×
154
                }
×
155
        }
156
        for _, f := range s.Functions {
×
NEW
157
                if err := proc.processLinksMethod(f, elems, firstPass); err != nil {
×
158
                        return err
×
159
                }
×
160
        }
161

162
        return nil
×
163
}
164

NEW
165
func (proc *Processor) processLinksTrait(tr *Trait, elems []string, firstPass bool) error {
×
166
        newElems := appendNew(elems, tr.GetName())
×
167

×
168
        var err error
×
NEW
169
        tr.Summary, err = proc.replaceLinks(tr.Summary, newElems, len(elems), firstPass)
×
170
        if err != nil {
×
171
                return err
×
172
        }
×
NEW
173
        tr.Description, err = proc.replaceLinks(tr.Description, newElems, len(elems), firstPass)
×
174
        if err != nil {
×
175
                return err
×
176
        }
×
177

178
        // TODO: add when traits support parameters
179
        /*for _, p := range tr.Parameters {
180
                p.Description, err = replaceLinks(p.Description, newElems, len(elems), lookup, t)
181
                if err != nil {
182
                        return err
183
                }
184
        }*/
185
        for _, f := range tr.Fields {
×
NEW
186
                f.Summary, err = proc.replaceLinks(f.Summary, newElems, len(elems), firstPass)
×
187
                if err != nil {
×
188
                        return err
×
189
                }
×
NEW
190
                f.Description, err = proc.replaceLinks(f.Description, newElems, len(elems), firstPass)
×
191
                if err != nil {
×
192
                        return err
×
193
                }
×
194
        }
195
        for _, f := range tr.Functions {
×
NEW
196
                if err := proc.processLinksMethod(f, elems, firstPass); err != nil {
×
197
                        return err
×
198
                }
×
199
        }
200

201
        return nil
×
202
}
203

NEW
204
func (proc *Processor) processLinksFunction(f *Function, elems []string, firstPass bool) error {
×
205
        newElems := appendNew(elems, f.GetName())
×
206

×
207
        var err error
×
NEW
208
        f.Summary, err = proc.replaceLinks(f.Summary, newElems, len(elems), firstPass)
×
209
        if err != nil {
×
210
                return err
×
211
        }
×
NEW
212
        f.Description, err = proc.replaceLinks(f.Description, newElems, len(elems), firstPass)
×
213
        if err != nil {
×
214
                return err
×
215
        }
×
NEW
216
        f.ReturnsDoc, err = proc.replaceLinks(f.ReturnsDoc, newElems, len(elems), firstPass)
×
217
        if err != nil {
×
218
                return err
×
219
        }
×
NEW
220
        f.RaisesDoc, err = proc.replaceLinks(f.RaisesDoc, newElems, len(elems), firstPass)
×
221
        if err != nil {
×
222
                return err
×
223
        }
×
224

225
        for _, a := range f.Args {
×
NEW
226
                a.Description, err = proc.replaceLinks(a.Description, newElems, len(elems), firstPass)
×
227
                if err != nil {
×
228
                        return err
×
229
                }
×
230
        }
231
        for _, p := range f.Parameters {
×
NEW
232
                p.Description, err = proc.replaceLinks(p.Description, newElems, len(elems), firstPass)
×
233
                if err != nil {
×
234
                        return err
×
235
                }
×
236
        }
237

238
        for _, o := range f.Overloads {
×
NEW
239
                err := proc.processLinksFunction(o, elems, firstPass)
×
240
                if err != nil {
×
241
                        return err
×
242
                }
×
243
        }
244

245
        return nil
×
246
}
247

NEW
248
func (proc *Processor) processLinksMethod(f *Function, elems []string, firstPass bool) error {
×
249
        var err error
×
NEW
250
        f.Summary, err = proc.replaceLinks(f.Summary, elems, len(elems), firstPass)
×
251
        if err != nil {
×
252
                return err
×
253
        }
×
NEW
254
        f.Description, err = proc.replaceLinks(f.Description, elems, len(elems), firstPass)
×
255
        if err != nil {
×
256
                return err
×
257
        }
×
NEW
258
        f.ReturnsDoc, err = proc.replaceLinks(f.ReturnsDoc, elems, len(elems), firstPass)
×
259
        if err != nil {
×
260
                return err
×
261
        }
×
NEW
262
        f.RaisesDoc, err = proc.replaceLinks(f.RaisesDoc, elems, len(elems), firstPass)
×
263
        if err != nil {
×
264
                return err
×
265
        }
×
266

267
        for _, a := range f.Args {
×
NEW
268
                a.Description, err = proc.replaceLinks(a.Description, elems, len(elems), firstPass)
×
269
                if err != nil {
×
270
                        return err
×
271
                }
×
272
        }
273
        for _, p := range f.Parameters {
×
NEW
274
                p.Description, err = proc.replaceLinks(p.Description, elems, len(elems), firstPass)
×
275
                if err != nil {
×
276
                        return err
×
277
                }
×
278
        }
279

280
        for _, o := range f.Overloads {
×
NEW
281
                err := proc.processLinksMethod(o, elems, firstPass)
×
282
                if err != nil {
×
283
                        return err
×
284
                }
×
285
        }
286

287
        return nil
×
288
}
289

290
func (proc *Processor) replaceLinks(text string, elems []string, modElems int, firstPass bool) (string, error) {
1✔
291
        if firstPass {
2✔
292
                return proc.replaceLinksFirstPass(text, elems, modElems)
1✔
293
        }
1✔
NEW
294
        return proc.replaceLinksSecondPass(text, elems, modElems)
×
295
}
296

NEW
297
func (proc *Processor) replaceLinksSecondPass(text string, elems []string, modElems int) (string, error) {
×
UNCOV
298
        indices, err := findLinks(text)
×
UNCOV
299
        if err != nil {
×
300
                return "", err
×
301
        }
×
UNCOV
302
        if len(indices) == 0 {
×
303
                return text, nil
×
304
        }
×
UNCOV
305
        for i := len(indices) - 2; i >= 0; i -= 2 {
×
UNCOV
306
                start, end := indices[i], indices[i+1]
×
UNCOV
307
                link := text[start+1 : end-1]
×
UNCOV
308

×
NEW
309
                entry, linkText, parts, ok := placeholderToLink(link, elems, modElems, proc.linkTargets, proc.ShortLinks)
×
UNCOV
310
                if !ok {
×
311
                        continue
×
312
                }
313

UNCOV
314
                var basePath string
×
UNCOV
315
                if entry.IsSection {
×
UNCOV
316
                        basePath = path.Join(parts[:len(parts)-1]...)
×
UNCOV
317
                } else {
×
UNCOV
318
                        basePath = path.Join(parts...)
×
UNCOV
319
                }
×
320

UNCOV
321
                pathStr, err := proc.Formatter.ToLinkPath(basePath, entry.Kind)
×
UNCOV
322
                if err != nil {
×
323
                        return "", err
×
324
                }
×
UNCOV
325
                if entry.IsSection {
×
UNCOV
326
                        pathStr += parts[len(parts)-1]
×
UNCOV
327
                }
×
UNCOV
328
                text = fmt.Sprintf("%s[%s](%s)%s", text[:start], linkText, pathStr, text[end:])
×
329
        }
UNCOV
330
        return text, nil
×
331
}
332

333
func (proc *Processor) replaceLinksFirstPass(text string, elems []string, modElems int) (string, error) {
1✔
334
        indices, err := findLinks(text)
1✔
335
        if err != nil {
1✔
NEW
336
                return "", err
×
NEW
337
        }
×
338
        if len(indices) == 0 {
1✔
NEW
339
                return text, nil
×
NEW
340
        }
×
341
        for i := len(indices) - 2; i >= 0; i -= 2 {
6✔
342
                start, end := indices[i], indices[i+1]
5✔
343
                link := text[start+1 : end-1]
5✔
344

5✔
345
                content, ok := linkToPlaceholder(link, elems, modElems, proc.linkExports)
5✔
346
                if !ok {
10✔
347
                        continue
5✔
348
                }
NEW
349
                text = fmt.Sprintf("%s[%s]%s", text[:start], content, text[end:])
×
350
        }
351
        return text, nil
1✔
352
}
353

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

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

401
func linkToPlaceholder(link string, elems []string, modElems int, lookup map[string]string) (string, bool) {
5✔
402
        linkParts := strings.SplitN(link, " ", 2)
5✔
403

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

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

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

447
func linkToPlaceholderAbs(link string, elems []string, lookup map[string]string) (string, bool) {
1✔
448
        placeholder, ok := lookup[link]
1✔
449
        if !ok {
2✔
450
                log.Printf("WARNING: Can't resolve cross ref '%s' in %s", link, strings.Join(elems, "."))
1✔
451
                return "", false
1✔
452
        }
1✔
NEW
453
        return placeholder, true
×
454
}
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