interp: API change for Symbols method

Often enough when debugging, one does not know exactly what argument
should be given to Symbols, as it's not always clear in which
scope/namespace the symbol one is looking for is stored in.

Therefore, this change enables the Symbols method to now take the empty
string as an argument, which results in all the known symbols to be
returned (keyed by import path).

As a consequence, when an non-empty argument is given, the returned
result should be similar to what we had before, except it is now
returned as the sole entry of an encompassing map.

In addition, the "binary" symbols (i.e. the ones ingested through a
Use call), are now also taken into account.
This commit is contained in:
mpl
2020-10-15 10:02:04 +02:00
committed by GitHub
parent 57b49f40d6
commit 8916618a81
2 changed files with 53 additions and 23 deletions

View File

@@ -1,6 +1,7 @@
package main
import (
"errors"
"flag"
"fmt"
"go/build"
@@ -117,7 +118,11 @@ func test(arg []string) (err error) {
benchmarks := []testing.InternalBenchmark{}
tests := []testing.InternalTest{}
for name, sym := range i.Symbols(path) {
syms, ok := i.Symbols(path)[path]
if !ok {
return errors.New("No tests found")
}
for name, sym := range syms {
switch fun := sym.Interface().(type) {
case func(*testing.B):
benchmarks = append(benchmarks, testing.InternalBenchmark{name, fun})

View File

@@ -403,34 +403,59 @@ func (interp *Interpreter) EvalTest(path string) error {
return err
}
// Symbols returns a map of interpreter exported symbol values for the given path.
func (interp *Interpreter) Symbols(path string) map[string]reflect.Value {
m := map[string]reflect.Value{}
// Symbols returns a map of interpreter exported symbol values for the given
// import path. If the argument is the empty string, all known symbols are
// returned.
func (interp *Interpreter) Symbols(importPath string) Exports {
m := map[string]map[string]reflect.Value{}
interp.mutex.RLock()
if interp.scopes[path] == nil {
interp.mutex.RUnlock()
return m
}
sym := interp.scopes[path].sym
interp.mutex.RUnlock()
defer interp.mutex.RUnlock()
for n, s := range sym {
if !canExport(n) {
// Skip private non-exported symbols.
for k, v := range interp.srcPkg {
if importPath != "" && k != importPath {
continue
}
switch s.kind {
case constSym:
m[n] = s.rval
case funcSym:
m[n] = genFunctionWrapper(s.node)(interp.frame)
case varSym:
m[n] = interp.frame.data[s.index]
case typeSym:
m[n] = reflect.New(s.typ.TypeOf())
syms := map[string]reflect.Value{}
for n, s := range v {
if !canExport(n) {
// Skip private non-exported symbols.
continue
}
switch s.kind {
case constSym:
syms[n] = s.rval
case funcSym:
syms[n] = genFunctionWrapper(s.node)(interp.frame)
case varSym:
syms[n] = interp.frame.data[s.index]
case typeSym:
syms[n] = reflect.New(s.typ.TypeOf())
}
}
if len(syms) > 0 {
m[k] = syms
}
if importPath != "" {
return m
}
}
if importPath != "" && len(m) > 0 {
return m
}
for k, v := range interp.binPkg {
if importPath != "" && k != importPath {
continue
}
m[k] = v
if importPath != "" {
return m
}
}
return m
}