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") {
continue
}
if proptools.IsConfigurable(field.Type) {
// Don't recurse into configurable properties, they're structs but not property structs
continue
}
fieldValue := structValue.Field(i)

View file

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

View file

@ -272,6 +272,21 @@ func getType(expr ast.Expr) (typ string, innerProps []Property, err error) {
if err != nil {
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:
typ = fmt.Sprintf("%T", expr)
}
@ -279,6 +294,20 @@ func getType(expr ast.Expr) (typ string, innerProps []Property, err error) {
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) {
filterPropsByTag(&ps.Properties, key, value, true)
}

View file

@ -25,6 +25,8 @@ import (
"runtime"
"strings"
"sync"
"github.com/google/blueprint/proptools"
)
// 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
// Base case: primitive type
if defaults.Kind() != reflect.Struct {
if defaults.Kind() != reflect.Struct || proptools.IsConfigurable(defaults.Type()) {
props = append(props, Property{Name: name,
Type: defaults.Type().String()})
return &PropertyStruct{Properties: props}, nil

View file

@ -22,6 +22,7 @@ import (
"testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
type factoryFn func() (blueprint.Module, []interface{})
@ -81,6 +82,8 @@ type complexProps struct {
List_of_ints []int
List_of_nested []structToNest
Configurable_bool proptools.Configurable[bool]
}
// 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
// property structs returned by the factory for that module type.
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 {
_, ret[moduleType] = factory()
}

View file

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