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

mlange-42 / modo / 12813458655

16 Jan 2025 04:38PM CUT coverage: 37.068% (+0.2%) from 36.851%
12813458655

push

github

web-flow
Improve code structure (#44)

* rename methods
* convert functions to methods, simplify signature
* add a method for adding link targets

26 of 94 new or added lines in 5 files covered. (27.66%)

12 existing lines in 2 files now uncovered.

450 of 1214 relevant lines covered (37.07%)

2.7 hits per line

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

18.82
/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

32
func (proc *Processor) processLinksPackage(p *Package, elems []string, firstPass bool) error {
×
33
        newElems := appendNew(elems, p.GetName())
×
34

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

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

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

71
        return nil
×
72
}
73

74
func (proc *Processor) processLinksModule(m *Module, elems []string, firstPass bool) error {
×
75
        newElems := appendNew(elems, m.GetName())
×
76

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

87
        for _, f := range m.Functions {
×
88
                err := proc.processLinksFunction(f, newElems, firstPass)
×
89
                if err != nil {
×
90
                        return err
×
91
                }
×
92
        }
93
        for _, s := range m.Structs {
×
94
                err := proc.processLinksStruct(s, newElems, firstPass)
×
95
                if err != nil {
×
96
                        return err
×
97
                }
×
98
        }
99
        for _, tr := range m.Traits {
×
100
                err := proc.processLinksTrait(tr, newElems, firstPass)
×
101
                if err != nil {
×
102
                        return err
×
103
                }
×
104
        }
105

106
        return nil
×
107
}
108

109
func (proc *Processor) processLinksStruct(s *Struct, elems []string, firstPass bool) error {
×
110
        newElems := appendNew(elems, s.GetName())
×
111

×
112
        var err error
×
NEW
113
        s.Summary, err = proc.replaceRefs(s.Summary, newElems, len(elems), firstPass)
×
114
        if err != nil {
×
115
                return err
×
116
        }
×
NEW
117
        s.Description, err = proc.replaceRefs(s.Description, newElems, len(elems), firstPass)
×
118
        if err != nil {
×
119
                return err
×
120
        }
×
121

122
        for _, p := range s.Parameters {
×
NEW
123
                p.Description, err = proc.replaceRefs(p.Description, newElems, len(elems), firstPass)
×
124
                if err != nil {
×
125
                        return err
×
126
                }
×
127
        }
128
        for _, f := range s.Fields {
×
NEW
129
                f.Summary, err = proc.replaceRefs(f.Summary, newElems, len(elems), firstPass)
×
130
                if err != nil {
×
131
                        return err
×
132
                }
×
NEW
133
                f.Description, err = proc.replaceRefs(f.Description, newElems, len(elems), firstPass)
×
134
                if err != nil {
×
135
                        return err
×
136
                }
×
137
        }
138
        for _, f := range s.Functions {
×
139
                if err := proc.processLinksMethod(f, elems, firstPass); err != nil {
×
140
                        return err
×
141
                }
×
142
        }
143

144
        return nil
×
145
}
146

147
func (proc *Processor) processLinksTrait(tr *Trait, elems []string, firstPass bool) error {
×
148
        newElems := appendNew(elems, tr.GetName())
×
149

×
150
        var err error
×
NEW
151
        tr.Summary, err = proc.replaceRefs(tr.Summary, newElems, len(elems), firstPass)
×
152
        if err != nil {
×
153
                return err
×
154
        }
×
NEW
155
        tr.Description, err = proc.replaceRefs(tr.Description, newElems, len(elems), firstPass)
×
156
        if err != nil {
×
157
                return err
×
158
        }
×
159

160
        // TODO: add when traits support parameters
161
        /*for _, p := range tr.Parameters {
162
                p.Description, err = replaceLinks(p.Description, newElems, len(elems), lookup, t)
163
                if err != nil {
164
                        return err
165
                }
166
        }*/
167
        for _, f := range tr.Fields {
×
NEW
168
                f.Summary, err = proc.replaceRefs(f.Summary, newElems, len(elems), firstPass)
×
169
                if err != nil {
×
170
                        return err
×
171
                }
×
NEW
172
                f.Description, err = proc.replaceRefs(f.Description, newElems, len(elems), firstPass)
×
173
                if err != nil {
×
174
                        return err
×
175
                }
×
176
        }
177
        for _, f := range tr.Functions {
×
178
                if err := proc.processLinksMethod(f, elems, firstPass); err != nil {
×
179
                        return err
×
180
                }
×
181
        }
182

183
        return nil
×
184
}
185

186
func (proc *Processor) processLinksFunction(f *Function, elems []string, firstPass bool) error {
×
187
        newElems := appendNew(elems, f.GetName())
×
188

×
189
        var err error
×
NEW
190
        f.Summary, err = proc.replaceRefs(f.Summary, newElems, len(elems), firstPass)
×
191
        if err != nil {
×
192
                return err
×
193
        }
×
NEW
194
        f.Description, err = proc.replaceRefs(f.Description, newElems, len(elems), firstPass)
×
195
        if err != nil {
×
196
                return err
×
197
        }
×
NEW
198
        f.ReturnsDoc, err = proc.replaceRefs(f.ReturnsDoc, newElems, len(elems), firstPass)
×
199
        if err != nil {
×
200
                return err
×
201
        }
×
NEW
202
        f.RaisesDoc, err = proc.replaceRefs(f.RaisesDoc, newElems, len(elems), firstPass)
×
203
        if err != nil {
×
204
                return err
×
205
        }
×
206

207
        for _, a := range f.Args {
×
NEW
208
                a.Description, err = proc.replaceRefs(a.Description, newElems, len(elems), firstPass)
×
209
                if err != nil {
×
210
                        return err
×
211
                }
×
212
        }
213
        for _, p := range f.Parameters {
×
NEW
214
                p.Description, err = proc.replaceRefs(p.Description, newElems, len(elems), firstPass)
×
215
                if err != nil {
×
216
                        return err
×
217
                }
×
218
        }
219

220
        for _, o := range f.Overloads {
×
221
                err := proc.processLinksFunction(o, elems, firstPass)
×
222
                if err != nil {
×
223
                        return err
×
224
                }
×
225
        }
226

227
        return nil
×
228
}
229

230
func (proc *Processor) processLinksMethod(f *Function, elems []string, firstPass bool) error {
×
231
        var err error
×
NEW
232
        f.Summary, err = proc.replaceRefs(f.Summary, elems, len(elems), firstPass)
×
233
        if err != nil {
×
234
                return err
×
235
        }
×
NEW
236
        f.Description, err = proc.replaceRefs(f.Description, elems, len(elems), firstPass)
×
237
        if err != nil {
×
238
                return err
×
239
        }
×
NEW
240
        f.ReturnsDoc, err = proc.replaceRefs(f.ReturnsDoc, elems, len(elems), firstPass)
×
241
        if err != nil {
×
242
                return err
×
243
        }
×
NEW
244
        f.RaisesDoc, err = proc.replaceRefs(f.RaisesDoc, elems, len(elems), firstPass)
×
245
        if err != nil {
×
246
                return err
×
247
        }
×
248

249
        for _, a := range f.Args {
×
NEW
250
                a.Description, err = proc.replaceRefs(a.Description, elems, len(elems), firstPass)
×
251
                if err != nil {
×
252
                        return err
×
253
                }
×
254
        }
255
        for _, p := range f.Parameters {
×
NEW
256
                p.Description, err = proc.replaceRefs(p.Description, elems, len(elems), firstPass)
×
257
                if err != nil {
×
258
                        return err
×
259
                }
×
260
        }
261

262
        for _, o := range f.Overloads {
×
263
                err := proc.processLinksMethod(o, elems, firstPass)
×
264
                if err != nil {
×
265
                        return err
×
266
                }
×
267
        }
268

269
        return nil
×
270
}
271

272
func (proc *Processor) replaceRefs(text string, elems []string, modElems int, firstPass bool) (string, error) {
1✔
273
        if firstPass {
2✔
274
                return proc.replaceRefsByPlaceholders(text, elems, modElems)
1✔
275
        }
1✔
NEW
276
        return proc.replacePlaceholdersByLinks(text, elems, modElems)
×
277
}
278

279
func (proc *Processor) replaceRefsByPlaceholders(text string, elems []string, modElems int) (string, error) {
1✔
280
        indices, err := findLinks(text)
1✔
281
        if err != nil {
1✔
282
                return "", err
×
283
        }
×
284
        if len(indices) == 0 {
1✔
285
                return text, nil
×
286
        }
×
287
        for i := len(indices) - 2; i >= 0; i -= 2 {
6✔
288
                start, end := indices[i], indices[i+1]
5✔
289
                link := text[start+1 : end-1]
5✔
290

5✔
291
                content, ok := proc.refToPlaceholder(link, elems, modElems)
5✔
292
                if !ok {
10✔
293
                        continue
5✔
294
                }
NEW
295
                text = fmt.Sprintf("%s[%s]%s", text[:start], content, text[end:])
×
296
        }
297
        return text, nil
1✔
298
}
299

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

×
NEW
312
                entry, linkText, parts, ok := proc.placeholderToLink(link, elems, modElems, proc.ShortLinks)
×
UNCOV
313
                if !ok {
×
UNCOV
314
                        continue
×
315
                }
316

NEW
317
                var basePath string
×
NEW
318
                if entry.IsSection {
×
NEW
319
                        basePath = path.Join(parts[:len(parts)-1]...)
×
NEW
320
                } else {
×
NEW
321
                        basePath = path.Join(parts...)
×
NEW
322
                }
×
323

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

NEW
336
func (proc *Processor) placeholderToLink(link string, elems []string, modElems int, shorten bool) (entry *elemPath, text string, parts []string, ok bool) {
×
337
        linkParts := strings.SplitN(link, " ", 2)
×
NEW
338
        entry, text, parts, ok = proc.placeholderToAbsLink(linkParts[0], elems, modElems)
×
339
        if !ok {
×
340
                return
×
341
        }
×
342
        if len(linkParts) > 1 {
×
343
                text = linkParts[1]
×
344
        } else {
×
345
                if shorten {
×
346
                        textParts := strings.Split(text, ".")
×
347
                        if entry.IsSection {
×
348
                                text = strings.Join(textParts[len(textParts)-2:], ".")
×
349
                        } else {
×
350
                                text = textParts[len(textParts)-1]
×
351
                        }
×
352
                }
353
                text = fmt.Sprintf("`%s`", text)
×
354
        }
355
        return
×
356
}
357

NEW
358
func (proc *Processor) placeholderToAbsLink(link string, elems []string, modElems int) (*elemPath, string, []string, bool) {
×
NEW
359
        elemPath, ok := proc.linkTargets[link]
×
360
        if !ok {
×
361
                log.Printf("WARNING: Can't resolve cross ref '%s' in %s", link, strings.Join(elems, "."))
×
362
                return nil, "", nil, false
×
363
        }
×
364
        skip := 0
×
365
        for range modElems {
×
366
                if len(elemPath.Elements) <= skip {
×
367
                        break
×
368
                }
369
                if elemPath.Elements[skip] == elems[skip] {
×
370
                        skip++
×
371
                } else {
×
372
                        break
×
373
                }
374
        }
375
        fullPath := []string{}
×
376
        for range modElems - skip {
×
377
                fullPath = append(fullPath, "..")
×
378
        }
×
379
        fullPath = append(fullPath, elemPath.Elements[skip:]...)
×
380
        return &elemPath, link, fullPath, true
×
381
}
382

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

5✔
386
        var placeholder string
5✔
387
        var ok bool
5✔
388
        if strings.HasPrefix(link, ".") {
9✔
389
                placeholder, ok = proc.refToPlaceholderRel(linkParts[0], elems, modElems)
4✔
390
        } else {
5✔
391
                placeholder, ok = proc.refToPlaceholderAbs(linkParts[0], elems)
1✔
392
        }
1✔
393
        if !ok {
10✔
394
                return "", false
5✔
395
        }
5✔
396
        if len(linkParts) > 1 {
×
397
                return fmt.Sprintf("%s %s", placeholder, linkParts[1]), true
×
398
        } else {
×
399
                return placeholder, true
×
400
        }
×
401
}
402

403
func (proc *Processor) refToPlaceholderRel(link string, elems []string, modElems int) (string, bool) {
4✔
404
        dots := 0
4✔
405
        for strings.HasPrefix(link[dots:], ".") {
9✔
406
                dots++
5✔
407
        }
5✔
408
        if dots > modElems {
4✔
409
                log.Printf("WARNING: Too many leading dots in cross ref '%s' in %s", link, strings.Join(elems, "."))
×
410
                return "", false
×
411
        }
×
412
        linkText := link[dots:]
4✔
413
        subElems := elems[:modElems-(dots-1)]
4✔
414
        var fullLink string
4✔
415
        if len(subElems) == 0 {
4✔
416
                fullLink = linkText
×
417
        } else {
4✔
418
                fullLink = strings.Join(subElems, ".") + "." + linkText
4✔
419
        }
4✔
420

421
        placeholder, ok := proc.linkExports[fullLink]
4✔
422
        if !ok {
8✔
423
                log.Printf("WARNING: Can't resolve cross ref '%s' (%s) in %s", link, fullLink, strings.Join(elems, "."))
4✔
424
                return "", false
4✔
425
        }
4✔
426
        return placeholder, true
×
427
}
428

429
func (proc *Processor) refToPlaceholderAbs(link string, elems []string) (string, bool) {
1✔
430
        placeholder, ok := proc.linkExports[link]
1✔
431
        if !ok {
2✔
432
                log.Printf("WARNING: Can't resolve cross ref '%s' in %s", link, strings.Join(elems, "."))
1✔
433
                return "", false
1✔
434
        }
1✔
435
        return placeholder, true
×
436
}
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