@@ -47,9 +47,7 @@ const (
47
47
embedFiles
48
48
)
49
49
50
- var numLocalEmbed int
51
-
52
- func varEmbed (p * noder , names []* Node , typ * Node , exprs []* Node , embeds []PragmaEmbed ) (newExprs []* Node ) {
50
+ func varEmbed (p * noder , names []* Node , typ * Node , exprs []* Node , embeds []PragmaEmbed ) {
53
51
haveEmbed := false
54
52
for _ , decl := range p .file .DeclList {
55
53
imp , ok := decl .(* syntax.ImportDecl )
@@ -67,44 +65,52 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma
67
65
pos := embeds [0 ].Pos
68
66
if ! haveEmbed {
69
67
p .yyerrorpos (pos , "invalid go:embed: missing import \" embed\" " )
70
- return exprs
68
+ return
71
69
}
72
70
if embedCfg .Patterns == nil {
73
71
p .yyerrorpos (pos , "invalid go:embed: build system did not supply embed configuration" )
74
- return exprs
72
+ return
75
73
}
76
74
if len (names ) > 1 {
77
75
p .yyerrorpos (pos , "go:embed cannot apply to multiple vars" )
78
- return exprs
76
+ return
79
77
}
80
78
if len (exprs ) > 0 {
81
79
p .yyerrorpos (pos , "go:embed cannot apply to var with initializer" )
82
- return exprs
80
+ return
83
81
}
84
82
if typ == nil {
85
83
// Should not happen, since len(exprs) == 0 now.
86
84
p .yyerrorpos (pos , "go:embed cannot apply to var without type" )
87
- return exprs
85
+ return
86
+ }
87
+ if dclcontext != PEXTERN {
88
+ p .yyerrorpos (pos , "go:embed cannot apply to var inside func" )
89
+ return
88
90
}
89
91
90
- kind := embedKindApprox (typ )
91
- if kind == embedUnknown {
92
- p .yyerrorpos (pos , "go:embed cannot apply to var of type %v" , typ )
93
- return exprs
92
+ var list []irEmbed
93
+ for _ , e := range embeds {
94
+ list = append (list , irEmbed {Pos : p .makeXPos (e .Pos ), Patterns : e .Patterns })
94
95
}
96
+ v := names [0 ]
97
+ v .Name .Param .SetEmbedList (list )
98
+ embedlist = append (embedlist , v )
99
+ }
95
100
101
+ func embedFileList (v * Node , kind int ) []string {
96
102
// Build list of files to store.
97
103
have := make (map [string ]bool )
98
104
var list []string
99
- for _ , e := range embeds {
105
+ for _ , e := range v . Name . Param . EmbedList () {
100
106
for _ , pattern := range e .Patterns {
101
107
files , ok := embedCfg .Patterns [pattern ]
102
108
if ! ok {
103
- p . yyerrorpos (e .Pos , "invalid go:embed: build system did not map pattern: %s" , pattern )
109
+ yyerrorl (e .Pos , "invalid go:embed: build system did not map pattern: %s" , pattern )
104
110
}
105
111
for _ , file := range files {
106
112
if embedCfg .Files [file ] == "" {
107
- p . yyerrorpos (e .Pos , "invalid go:embed: build system did not map file: %s" , file )
113
+ yyerrorl (e .Pos , "invalid go:embed: build system did not map file: %s" , file )
108
114
continue
109
115
}
110
116
if ! have [file ] {
@@ -126,52 +132,23 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma
126
132
127
133
if kind == embedString || kind == embedBytes {
128
134
if len (list ) > 1 {
129
- p . yyerrorpos ( pos , "invalid go:embed: multiple files for type %v" , typ )
130
- return exprs
135
+ yyerrorl ( v . Pos , "invalid go:embed: multiple files for type %v" , v . Type )
136
+ return nil
131
137
}
132
138
}
133
139
134
- v := names [0 ]
135
- if dclcontext != PEXTERN {
136
- p .yyerrorpos (pos , "go:embed cannot apply to var inside func" )
137
- return exprs
138
- }
139
-
140
- v .Name .Param .SetEmbedFiles (list )
141
- embedlist = append (embedlist , v )
142
- return exprs
143
- }
144
-
145
- // embedKindApprox determines the kind of embedding variable, approximately.
146
- // The match is approximate because we haven't done scope resolution yet and
147
- // can't tell whether "string" and "byte" really mean "string" and "byte".
148
- // The result must be confirmed later, after type checking, using embedKind.
149
- func embedKindApprox (typ * Node ) int {
150
- if typ .Sym != nil && typ .Sym .Name == "FS" && (typ .Sym .Pkg .Path == "embed" || (typ .Sym .Pkg == localpkg && myimportpath == "embed" )) {
151
- return embedFiles
152
- }
153
- // These are not guaranteed to match only string and []byte -
154
- // maybe the local package has redefined one of those words.
155
- // But it's the best we can do now during the noder.
156
- // The stricter check happens later, in initEmbed calling embedKind.
157
- if typ .Sym != nil && typ .Sym .Name == "string" && typ .Sym .Pkg == localpkg {
158
- return embedString
159
- }
160
- if typ .Op == OTARRAY && typ .Left == nil && typ .Right .Sym != nil && typ .Right .Sym .Name == "byte" && typ .Right .Sym .Pkg == localpkg {
161
- return embedBytes
162
- }
163
- return embedUnknown
140
+ return list
164
141
}
165
142
166
143
// embedKind determines the kind of embedding variable.
167
144
func embedKind (typ * types.Type ) int {
168
145
if typ .Sym != nil && typ .Sym .Name == "FS" && (typ .Sym .Pkg .Path == "embed" || (typ .Sym .Pkg == localpkg && myimportpath == "embed" )) {
169
146
return embedFiles
170
147
}
171
- if typ == types .Types [ TSTRING ] {
148
+ if typ . Etype == types .TSTRING {
172
149
return embedString
173
150
}
174
- if typ .Sym == nil && typ . IsSlice () && typ .Elem () == types .Bytetype {
151
+ if typ .Etype == types . TSLICE && typ .Elem (). Etype == types .TUINT8 {
175
152
return embedBytes
176
153
}
177
154
return embedUnknown
@@ -209,11 +186,14 @@ func dumpembeds() {
209
186
// initEmbed emits the init data for a //go:embed variable,
210
187
// which is either a string, a []byte, or an embed.FS.
211
188
func initEmbed (v * Node ) {
212
- files := v .Name .Param .EmbedFiles ()
213
- switch kind := embedKind (v .Type ); kind {
214
- case embedUnknown :
189
+ kind := embedKind (v .Type )
190
+ if kind == embedUnknown {
215
191
yyerrorl (v .Pos , "go:embed cannot apply to var of type %v" , v .Type )
192
+ return
193
+ }
216
194
195
+ files := embedFileList (v , kind )
196
+ switch kind {
217
197
case embedString , embedBytes :
218
198
file := files [0 ]
219
199
fsym , size , err := fileStringSym (v .Pos , embedCfg .Files [file ], kind == embedString , nil )
0 commit comments