aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-28 20:58:53 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-28 20:58:53 +0000
commitcd79e4faa673990adf99c19d111defc18ca8d5bb (patch)
tree7dfb9196f54634505e83e32dff32af47145e9771
parent4023fb658d90f07d1d4bfa0b5b96cf0e6dc986e6 (diff)
parent89e90b4c60ab2d8f9c953bfcdf7876ab7da44545 (diff)
downloadblueprint-simpleperf-release.tar.gz
Snap for 11510257 from 89e90b4c60ab2d8f9c953bfcdf7876ab7da44545 to simpleperf-releasesimpleperf-release
Change-Id: I5fd812f07d5cae32efb2acd5a1e05d79088da6b7
-rw-r--r--context.go160
1 files changed, 147 insertions, 13 deletions
diff --git a/context.go b/context.go
index d682e55..4661055 100644
--- a/context.go
+++ b/context.go
@@ -4955,15 +4955,17 @@ func funcName(f interface{}) string {
// json representation of a dependency
type depJson struct {
- Name string `json:"name"`
- Variant string `json:"variant"`
- TagType string `json:"tag_type"`
+ Name string `json:"name"`
+ Variant string `json:"variant"`
+ TagType string `json:"tag_type"`
+ TagData interface{} `json:"tag_data"`
}
// json representation of a provider
type providerJson struct {
- Type string `json:"type"`
- Debug string `json:"debug"` // from GetDebugString on the provider data
+ Type string `json:"type"`
+ Debug string `json:"debug"` // from GetDebugString on the provider data
+ Fields interface{} `json:"fields"`
}
// interface for getting debug info from various data.
@@ -4972,18 +4974,136 @@ type Debuggable interface {
GetDebugString() string
}
+// Convert a slice in a reflect.Value to a value suitable for outputting to json
+func debugSlice(value reflect.Value) interface{} {
+ size := value.Len()
+ if size == 0 {
+ return nil
+ }
+ result := make([]interface{}, size)
+ for i := 0; i < size; i++ {
+ result[i] = debugValue(value.Index(i))
+ }
+ return result
+}
+
+// Convert a map in a reflect.Value to a value suitable for outputting to json
+func debugMap(value reflect.Value) interface{} {
+ if value.IsNil() {
+ return nil
+ }
+ result := make(map[string]interface{})
+ iter := value.MapRange()
+ for iter.Next() {
+ // In the (hopefully) rare case of a key collision (which will happen when multiple
+ // go-typed keys have the same string representation, we'll just overwrite the last
+ // value.
+ result[debugKey(iter.Key())] = debugValue(iter.Value())
+ }
+ return result
+}
+
+// Convert a value into a string, suitable for being a json map key.
+func debugKey(value reflect.Value) string {
+ return fmt.Sprintf("%v", value)
+}
+
+// Convert a single value (possibly a map or slice too) in a reflect.Value to a value suitable for outputting to json
+func debugValue(value reflect.Value) interface{} {
+ // Remember if we originally received a reflect.Interface.
+ wasInterface := value.Kind() == reflect.Interface
+ // Dereference pointers down to the real type
+ for value.Kind() == reflect.Ptr || value.Kind() == reflect.Interface {
+ // If it's nil, return nil
+ if value.IsNil() {
+ return nil
+ }
+ value = value.Elem()
+ }
+
+ // Skip private fields, maybe other weird corner cases of go's bizarre type system.
+ if !value.CanInterface() {
+ return nil
+ }
+
+ switch kind := value.Kind(); kind {
+ case reflect.Bool, reflect.String, reflect.Int, reflect.Uint:
+ return value.Interface()
+ case reflect.Slice:
+ return debugSlice(value)
+ case reflect.Struct:
+ // If we originally received an interface, and there is a String() method, call that.
+ // TODO: figure out why Path doesn't work correctly otherwise (in aconfigPropagatingDeclarationsInfo)
+ if s, ok := value.Interface().(interface{ String() string }); wasInterface && ok {
+ return s.String()
+ }
+ return debugStruct(value)
+ case reflect.Map:
+ return debugMap(value)
+ default:
+ // TODO: add cases as we find them.
+ return fmt.Sprintf("debugValue(Kind=%v, wasInterface=%v)", kind, wasInterface)
+ }
+
+ return nil
+}
+
+// Convert an object in a reflect.Value to a value suitable for outputting to json
+func debugStruct(value reflect.Value) interface{} {
+ result := make(map[string]interface{})
+ debugStructAppend(value, &result)
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// Convert an object to a value suiable for outputting to json
+func debugStructAppend(value reflect.Value, result *map[string]interface{}) {
+ for value.Kind() == reflect.Ptr {
+ if value.IsNil() {
+ return
+ }
+ value = value.Elem()
+ }
+ if value.IsZero() {
+ return
+ }
+
+ if value.Kind() != reflect.Struct {
+ // TODO: could maybe support other types
+ return
+ }
+
+ structType := value.Type()
+ for i := 0; i < value.NumField(); i++ {
+ v := debugValue(value.Field(i))
+ if v != nil {
+ (*result)[structType.Field(i).Name] = v
+ }
+ }
+}
+
+func debugPropertyStruct(props interface{}, result *map[string]interface{}) {
+ if props == nil {
+ return
+ }
+ debugStructAppend(reflect.ValueOf(props), result)
+}
+
// Get the debug json for a single module. Returns thae data as
// flattened json text for easy concatenation by GenerateModuleDebugInfo.
func getModuleDebugJson(module *moduleInfo) []byte {
info := struct {
- Name string `json:"name"`
- SourceFile string `json:"source_file"`
- SourceLine int `json:"source_line"`
- Type string `json:"type"`
- Variant string `json:"variant"`
- Deps []depJson `json:"deps"`
- Providers []providerJson `json:"providers"`
- Debug string `json:"debug"` // from GetDebugString on the module
+ Name string `json:"name"`
+ SourceFile string `json:"source_file"`
+ SourceLine int `json:"source_line"`
+ Type string `json:"type"`
+ Variant string `json:"variant"`
+ Deps []depJson `json:"deps"`
+ Providers []providerJson `json:"providers"`
+ Debug string `json:"debug"` // from GetDebugString on the module
+ Properties map[string]interface{} `json:"properties"`
}{
Name: module.logicModule.Name(),
SourceFile: module.pos.Filename,
@@ -5000,6 +5120,7 @@ func getModuleDebugJson(module *moduleInfo) []byte {
t := reflect.TypeOf(dep.tag)
if t != nil {
result[i].TagType = t.PkgPath() + "." + t.Name()
+ result[i].TagData = debugStruct(reflect.ValueOf(dep.tag))
}
}
return result
@@ -5022,6 +5143,12 @@ func getModuleDebugJson(module *moduleInfo) []byte {
include = true
}
}
+
+ if p != nil {
+ pj.Fields = debugValue(reflect.ValueOf(p))
+ include = true
+ }
+
if include {
result = append(result, pj)
}
@@ -5035,6 +5162,13 @@ func getModuleDebugJson(module *moduleInfo) []byte {
return ""
}
}(),
+ Properties: func() map[string]interface{} {
+ result := make(map[string]interface{})
+ for _, props := range module.properties {
+ debugPropertyStruct(props, &result)
+ }
+ return result
+ }(),
}
buf, _ := json.Marshal(info)
return buf