@@ -134,7 +134,50 @@ func BuildSSA(c *gin.Context) {
134
134
c .JSON (http .StatusOK , out )
135
135
}
136
136
137
+ /*
138
+ According to spec there are two cases we need to handle:
139
+
140
+ - Function declaration, in the form of 'func f() {...}' , see:
141
+ https://golang.org/ref/spec#Function_declarations
142
+
143
+ - Function literal/anonymous function, in the form of
144
+ 'myfunc := func() {...}' or 'go func() {...}', see:
145
+ https://golang.org/ref/spec#Function_literals
146
+
147
+ As users can use some tricks like raw string to bypass our check, we
148
+ only do check conservatively, which means it is mainly used for
149
+ preventing misspell and wrong format.
150
+
151
+ All cases:
152
+ // <i>,<j>,<k> means unique function index in the scope of outer function, see:
153
+ https://github.com/golang/go/blob/84162b88324aa7993fe4a8580a2b65c6a7055f88/src/cmd/compile/internal/typecheck/func.go#L182
154
+
155
+ - func foo() // most common case
156
+ - glob..func<i> // global function literal
157
+ + glob..func<i>.<j>.<k>... // inner anonymous function
158
+ - foo.func<i> // anonymous function inside function 'foo'
159
+ + foo.func<i>.<j>.<k>...
160
+ - (*T).foo() // method expression with explicit receiver, see
161
+ https://golang.org/ref/spec#Method_expressions
162
+
163
+ Note that non-ascii letters are unsupported, as our intention is to dig
164
+ into go ssa IR.
165
+ */
137
166
func findSSAFunc (code , funcname string ) bool {
167
+ // The dot character is not allowed to appear in function name.
168
+ // See https://golang.org/ref/spec#Identifiers
169
+ if strings .IndexByte (funcname , '.' ) != - 1 {
170
+ if funcname [0 ] == '(' {
171
+ methodReg := regexp .MustCompile (`^\([\w\*]+\)\.\w+$` )
172
+ return methodReg .MatchString (funcname )
173
+ } else if strings .HasPrefix (funcname , "glob" ) {
174
+ globReg := regexp .MustCompile (`^glob\.\.func\d+(\.\d)*$` )
175
+ return globReg .MatchString (funcname )
176
+ } else {
177
+ anonyReg := regexp .MustCompile (`^\w+\.func\d+(\.\d)*$` )
178
+ return anonyReg .MatchString (funcname )
179
+ }
180
+ }
138
181
// func Foo (
139
182
re := regexp .MustCompile (fmt .Sprintf (`func[ \t]+%s[ \t]*\(` , funcname ))
140
183
return re .FindString (code ) != ""
@@ -185,12 +228,23 @@ func initModules(path string) error {
185
228
}
186
229
187
230
func buildSSA (funcname , gcflags , outf , buildf string , isTest bool ) error {
188
- var cmd * exec.Cmd
231
+ var (
232
+ cmd * exec.Cmd
233
+ buildDir string
234
+ )
235
+
236
+ // Restrict the ssa.html target to the target ssa build folder.
237
+ // See https://github.com/golang-design/ssaplayground/issues/9
238
+ buildDir = filepath .Dir (buildf )
239
+ outf = filepath .Base (outf )
240
+ buildf = filepath .Base (buildf )
241
+
189
242
if ! isTest {
190
243
cmd = exec .Command ("go" , "build" , "-mod=readonly" , fmt .Sprintf (`-gcflags=%s` , gcflags ), "-o" , outf , buildf )
191
244
} else {
192
245
cmd = exec .Command ("go" , "test" , "-mod=readonly" , fmt .Sprintf (`-gcflags=%s` , gcflags ), buildf )
193
246
}
247
+ cmd .Dir = buildDir
194
248
cmd .Env = append (os .Environ (), fmt .Sprintf ("GOSSAFUNC=%s" , funcname ))
195
249
cmd .Stderr = & bytes.Buffer {}
196
250
err := cmd .Run ()
0 commit comments