Source file
src/go/printer/gobuild.go
1
2
3
4
5 package printer
6
7 import (
8 "go/build/constraint"
9 "slices"
10 "text/tabwriter"
11 )
12
13 func (p *printer) fixGoBuildLines() {
14 if len(p.goBuild)+len(p.plusBuild) == 0 {
15 return
16 }
17
18
19
20
21
22
23
24
25 insert := 0
26 for pos := 0; ; {
27
28 blank := true
29 for pos < len(p.output) && (p.output[pos] == ' ' || p.output[pos] == '\t') {
30 pos++
31 }
32
33 if pos+3 < len(p.output) && p.output[pos] == tabwriter.Escape && p.output[pos+1] == '/' && p.output[pos+2] == '/' {
34 blank = false
35 for pos < len(p.output) && !isNL(p.output[pos]) {
36 pos++
37 }
38 }
39
40 if pos >= len(p.output) || !isNL(p.output[pos]) {
41 break
42 }
43 pos++
44
45 if blank {
46 insert = pos
47 }
48 }
49
50
51
52 if len(p.goBuild) > 0 && p.goBuild[0] < insert {
53 insert = p.goBuild[0]
54 } else if len(p.plusBuild) > 0 && p.plusBuild[0] < insert {
55 insert = p.plusBuild[0]
56 }
57
58 var x constraint.Expr
59 switch len(p.goBuild) {
60 case 0:
61
62 for _, pos := range p.plusBuild {
63 y, err := constraint.Parse(p.commentTextAt(pos))
64 if err != nil {
65 x = nil
66 break
67 }
68 if x == nil {
69 x = y
70 } else {
71 x = &constraint.AndExpr{X: x, Y: y}
72 }
73 }
74 case 1:
75
76 x, _ = constraint.Parse(p.commentTextAt(p.goBuild[0]))
77 }
78
79 var block []byte
80 if x == nil {
81
82
83
84 for _, pos := range p.goBuild {
85 block = append(block, p.lineAt(pos)...)
86 }
87 for _, pos := range p.plusBuild {
88 block = append(block, p.lineAt(pos)...)
89 }
90 } else {
91 block = append(block, tabwriter.Escape)
92 block = append(block, "//go:build "...)
93 block = append(block, x.String()...)
94 block = append(block, tabwriter.Escape, '\n')
95 if len(p.plusBuild) > 0 {
96 lines, err := constraint.PlusBuildLines(x)
97 if err != nil {
98 lines = []string{"// +build error: " + err.Error()}
99 }
100 for _, line := range lines {
101 block = append(block, tabwriter.Escape)
102 block = append(block, line...)
103 block = append(block, tabwriter.Escape, '\n')
104 }
105 }
106 }
107 block = append(block, '\n')
108
109
110 toDelete := append(p.goBuild, p.plusBuild...)
111 slices.Sort(toDelete)
112
113
114 var after []byte
115 start := insert
116 for _, end := range toDelete {
117 if end < start {
118 continue
119 }
120 after = appendLines(after, p.output[start:end])
121 start = end + len(p.lineAt(end))
122 }
123 after = appendLines(after, p.output[start:])
124 if n := len(after); n >= 2 && isNL(after[n-1]) && isNL(after[n-2]) {
125 after = after[:n-1]
126 }
127
128 p.output = p.output[:insert]
129 p.output = append(p.output, block...)
130 p.output = append(p.output, after...)
131 }
132
133
134
135
136
137
138 func appendLines(x, y []byte) []byte {
139 if len(y) > 0 && isNL(y[0]) &&
140 (len(x) == 0 || len(x) >= 2 && isNL(x[len(x)-1]) && isNL(x[len(x)-2])) {
141 y = y[1:]
142 }
143 return append(x, y...)
144 }
145
146 func (p *printer) lineAt(start int) []byte {
147 pos := start
148 for pos < len(p.output) && !isNL(p.output[pos]) {
149 pos++
150 }
151 if pos < len(p.output) {
152 pos++
153 }
154 return p.output[start:pos]
155 }
156
157 func (p *printer) commentTextAt(start int) string {
158 if start < len(p.output) && p.output[start] == tabwriter.Escape {
159 start++
160 }
161 pos := start
162 for pos < len(p.output) && p.output[pos] != tabwriter.Escape && !isNL(p.output[pos]) {
163 pos++
164 }
165 return string(p.output[start:pos])
166 }
167
168 func isNL(b byte) bool {
169 return b == '\n' || b == '\f'
170 }
171
View as plain text