Support generating docs for Configurable properties

Bug: 323382414
Test: m nothing --no-skip-soong-tests
Change-Id: I6e8a03c5785dbc3a90f458155dc4b9cd6ce7700b
This commit is contained in:
Cole Faust 2024-05-06 15:14:17 -07:00
parent 1c48101091
commit b9ff002303
7 changed files with 48 additions and 2 deletions

View file

@ -204,6 +204,10 @@ func nestedPropertyStructs(s reflect.Value) []nestedProperty {
if proptools.HasTag(field, "blueprint", "mutated") { if proptools.HasTag(field, "blueprint", "mutated") {
continue continue
} }
if proptools.IsConfigurable(field.Type) {
// Don't recurse into configurable properties, they're structs but not property structs
continue
}
fieldValue := structValue.Field(i) fieldValue := structValue.Field(i)

View file

@ -112,6 +112,10 @@ func TestAllPackages(t *testing.T) {
name: "list_of_nested", name: "list_of_nested",
typ: "list of structToNest", typ: "list of structToNest",
}, },
propInfo{
name: "configurable_bool",
typ: "configurable bool",
},
propInfo{ propInfo{
name: "nested_in_other_embedded", name: "nested_in_other_embedded",
typ: "otherStructToNest", typ: "otherStructToNest",

View file

@ -272,6 +272,21 @@ func getType(expr ast.Expr) (typ string, innerProps []Property, err error) {
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
case *ast.IndexExpr:
// IndexExpr is used to represent generic type arguments
if !isConfigurableAst(a.X) {
var writer strings.Builder
if err := ast.Fprint(&writer, nil, expr, nil); err != nil {
return "", nil, err
}
return "", nil, fmt.Errorf("unknown type %s", writer.String())
}
var innerType string
innerType, innerProps, err = getType(a.Index)
if err != nil {
return "", nil, err
}
typ = "configurable " + innerType
default: default:
typ = fmt.Sprintf("%T", expr) typ = fmt.Sprintf("%T", expr)
} }
@ -279,6 +294,20 @@ func getType(expr ast.Expr) (typ string, innerProps []Property, err error) {
return typ, innerProps, nil return typ, innerProps, nil
} }
func isConfigurableAst(expr ast.Expr) bool {
switch e := expr.(type) {
case *ast.Ident:
return e.Name == "Configurable"
case *ast.SelectorExpr:
if l, ok := e.X.(*ast.Ident); ok && l.Name == "proptools" {
if e.Sel.Name == "Configurable" {
return true
}
}
}
return false
}
func (ps *PropertyStruct) ExcludeByTag(key, value string) { func (ps *PropertyStruct) ExcludeByTag(key, value string) {
filterPropsByTag(&ps.Properties, key, value, true) filterPropsByTag(&ps.Properties, key, value, true)
} }

View file

@ -25,6 +25,8 @@ import (
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"github.com/google/blueprint/proptools"
) )
// Handles parsing and low-level processing of Blueprint module source files. Note that most getter // Handles parsing and low-level processing of Blueprint module source files. Note that most getter
@ -119,7 +121,7 @@ func (r *Reader) PropertyStruct(pkgPath, name string, defaults reflect.Value) (*
var props []Property var props []Property
// Base case: primitive type // Base case: primitive type
if defaults.Kind() != reflect.Struct { if defaults.Kind() != reflect.Struct || proptools.IsConfigurable(defaults.Type()) {
props = append(props, Property{Name: name, props = append(props, Property{Name: name,
Type: defaults.Type().String()}) Type: defaults.Type().String()})
return &PropertyStruct{Properties: props}, nil return &PropertyStruct{Properties: props}, nil

View file

@ -22,6 +22,7 @@ import (
"testing" "testing"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
) )
type factoryFn func() (blueprint.Module, []interface{}) type factoryFn func() (blueprint.Module, []interface{})
@ -81,6 +82,8 @@ type complexProps struct {
List_of_ints []int List_of_ints []int
List_of_nested []structToNest List_of_nested []structToNest
Configurable_bool proptools.Configurable[bool]
} }
// props docs. // props docs.

View file

@ -3883,7 +3883,7 @@ func (c *Context) OutDir() (string, error) {
// ModuleTypePropertyStructs returns a mapping from module type name to a list of pointers to // ModuleTypePropertyStructs returns a mapping from module type name to a list of pointers to
// property structs returned by the factory for that module type. // property structs returned by the factory for that module type.
func (c *Context) ModuleTypePropertyStructs() map[string][]interface{} { func (c *Context) ModuleTypePropertyStructs() map[string][]interface{} {
ret := make(map[string][]interface{}) ret := make(map[string][]interface{}, len(c.moduleFactories))
for moduleType, factory := range c.moduleFactories { for moduleType, factory := range c.moduleFactories {
_, ret[moduleType] = factory() _, ret[moduleType] = factory()
} }

View file

@ -156,3 +156,7 @@ func isMapOfStruct(t reflect.Type) bool {
func isConfigurable(t reflect.Type) bool { func isConfigurable(t reflect.Type) bool {
return isStruct(t) && t.NumField() > 0 && typeFields(t)[0].Type == configurableMarkerType return isStruct(t) && t.NumField() > 0 && typeFields(t)[0].Type == configurableMarkerType
} }
func IsConfigurable(t reflect.Type) bool {
return isConfigurable(t)
}