cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.71.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/diags/problems.go

116lines · modecode

1package diags
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/cloudflare/pint/internal/output"
8)
9
10func countDigits(n int) (c int) {
11 for n > 0 {
12 n /= 10
13 c++
14 }
15 return c
16}
17
18type Diagnostic struct {
19 Message string
20 Pos PositionRanges
21 FirstColumn int // 1-indexed
22 LastColumn int // 1-indexed
23}
24
25func InjectDiagnostics(content string, diags []Diagnostic, color output.Color, firstLine, lastLine int) string {
26 diagPositions := make([]PositionRanges, len(diags))
27 for i, diag := range diags {
28 dl := diag.Pos.Len()
29 diagPositions[i] = readRange(
30 min(diag.FirstColumn, dl),
31 min(diag.LastColumn, dl),
32 diag.Pos,
33 )
34 }
35
36 var buf strings.Builder
37 nextLine := make([]strings.Builder, len(diags))
38 needsNextLine := make([]bool, len(diags))
39
40 disablePoints := make([]bool, len(diags))
41 for i, a := range diags {
42 for j := range i {
43 b := diags[j]
44 if a.FirstColumn == b.FirstColumn && a.LastColumn == b.LastColumn {
45 disablePoints[i] = true
46 }
47 }
48 }
49
50 nrFmt := fmt.Sprintf("%%%dd", countDigits(lastLine))
51
52 for lineIndex, line := range strings.Split(content, "\n") {
53
54 if lineIndex+1 < firstLine {
55 continue
56 }
57 if lineIndex+1 > lastLine {
58 break
59 }
60
61 for i := range diags {
62 needsNextLine[i] = false
63 for _, pos := range diagPositions[i] {
64 if pos.Line == lineIndex+1 {
65 needsNextLine[i] = true
66 }
67 }
68 }
69
70 prefix := fmt.Sprintf(nrFmt+" | ", lineIndex+1)
71 buf.WriteString(output.MaybeColor(output.White, color == output.None, prefix))
72 for i, ok := range needsNextLine {
73 if ok {
74 nextLine[i].WriteString(strings.Repeat(" ", len(prefix)))
75 }
76 }
77
78 for columnIndex, r := range line {
79 buf.WriteRune(r)
80
81 for i, ok := range needsNextLine {
82 if !ok {
83 continue
84 }
85 for _, pos := range diagPositions[i] {
86 if pos.Line != lineIndex+1 {
87 continue
88 }
89 before := pos.FirstColumn > columnIndex+1
90 inside := pos.FirstColumn <= columnIndex+1 && pos.LastColumn >= columnIndex+1
91 switch {
92 case before:
93 nextLine[i].WriteRune(' ')
94 case inside && disablePoints[i]:
95 nextLine[i].WriteRune(' ')
96 case inside && !disablePoints[i]:
97 nextLine[i].WriteRune('^')
98 }
99 }
100 }
101 }
102 buf.WriteRune('\n')
103
104 for i, ok := range needsNextLine {
105 if ok {
106 buf.WriteString(output.MaybeColor(color, color == output.None, nextLine[i].String()))
107 buf.WriteRune(' ')
108 buf.WriteString(output.MaybeColor(color, color == output.None, diags[i].Message))
109 buf.WriteRune('\n')
110 nextLine[i].Reset()
111 }
112 }
113 }
114
115 return buf.String()
116}
117