Support variables with dashes in their names

Bug: 221946551
Test: go test
Change-Id: I085fc35159c4f3afe53868fbc731fcaeac3a69a8
This commit is contained in:
Cole Faust
2022-02-28 16:05:01 -08:00
parent 812bfff3d8
commit 3c4fc99593
3 changed files with 26 additions and 12 deletions

View File

@@ -465,17 +465,17 @@ func newParseContext(ss *StarlarkScript, nodes []mkparser.Node) *parseContext {
return ctx return ctx
} }
func (ctx *parseContext) lastAssignment(name string) *assignmentNode { func (ctx *parseContext) lastAssignment(v variable) *assignmentNode {
for va := ctx.varAssignments; va != nil; va = va.outer { for va := ctx.varAssignments; va != nil; va = va.outer {
if v, ok := va.vars[name]; ok { if v, ok := va.vars[v.name()]; ok {
return v return v
} }
} }
return nil return nil
} }
func (ctx *parseContext) setLastAssignment(name string, asgn *assignmentNode) { func (ctx *parseContext) setLastAssignment(v variable, asgn *assignmentNode) {
ctx.varAssignments.vars[name] = asgn ctx.varAssignments.vars[v.name()] = asgn
} }
func (ctx *parseContext) pushVarAssignments() { func (ctx *parseContext) pushVarAssignments() {
@@ -532,7 +532,7 @@ func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) []starlarkNode
if lhs == nil { if lhs == nil {
return []starlarkNode{ctx.newBadNode(a, "unknown variable %s", name)} return []starlarkNode{ctx.newBadNode(a, "unknown variable %s", name)}
} }
_, isTraced := ctx.tracedVariables[name] _, isTraced := ctx.tracedVariables[lhs.name()]
asgn := &assignmentNode{lhs: lhs, mkValue: a.Value, isTraced: isTraced, location: ctx.errorLocation(a)} asgn := &assignmentNode{lhs: lhs, mkValue: a.Value, isTraced: isTraced, location: ctx.errorLocation(a)}
if lhs.valueType() == starlarkTypeUnknown { if lhs.valueType() == starlarkTypeUnknown {
// Try to divine variable type from the RHS // Try to divine variable type from the RHS
@@ -565,8 +565,8 @@ func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) []starlarkNode
} }
} }
asgn.previous = ctx.lastAssignment(name) asgn.previous = ctx.lastAssignment(lhs)
ctx.setLastAssignment(name, asgn) ctx.setLastAssignment(lhs, asgn)
switch a.Type { switch a.Type {
case "=", ":=": case "=", ":=":
asgn.flavor = asgnSet asgn.flavor = asgnSet
@@ -1268,12 +1268,12 @@ func (ctx *parseContext) parseReference(node mkparser.Node, ref *mkparser.MakeSt
args: []starlarkExpr{ args: []starlarkExpr{
&stringLiteralExpr{literal: substParts[0]}, &stringLiteralExpr{literal: substParts[0]},
&stringLiteralExpr{literal: substParts[1]}, &stringLiteralExpr{literal: substParts[1]},
NewVariableRefExpr(v, ctx.lastAssignment(v.name()) != nil), NewVariableRefExpr(v, ctx.lastAssignment(v) != nil),
}, },
} }
} }
if v := ctx.addVariable(refDump); v != nil { if v := ctx.addVariable(refDump); v != nil {
return NewVariableRefExpr(v, ctx.lastAssignment(v.name()) != nil) return NewVariableRefExpr(v, ctx.lastAssignment(v) != nil)
} }
return ctx.newBadExpr(node, "unknown variable %s", refDump) return ctx.newBadExpr(node, "unknown variable %s", refDump)
} }

View File

@@ -65,6 +65,10 @@ def init(g, handle):
PRODUCT_NAME := Pixel 3 PRODUCT_NAME := Pixel 3
PRODUCT_MODEL := PRODUCT_MODEL :=
local_var = foo local_var = foo
local-var-with-dashes := bar
$(warning local-var-with-dashes: $(local-var-with-dashes))
GLOBAL-VAR-WITH-DASHES := baz
$(warning GLOBAL-VAR-WITH-DASHES: $(GLOBAL-VAR-WITH-DASHES))
`, `,
expected: `load("//build/make/core:product_config.rbc", "rblf") expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -73,6 +77,10 @@ def init(g, handle):
cfg["PRODUCT_NAME"] = "Pixel 3" cfg["PRODUCT_NAME"] = "Pixel 3"
cfg["PRODUCT_MODEL"] = "" cfg["PRODUCT_MODEL"] = ""
_local_var = "foo" _local_var = "foo"
_local_var_with_dashes = "bar"
rblf.mkwarning("pixel3.mk", "local-var-with-dashes: %s" % _local_var_with_dashes)
g["GLOBAL-VAR-WITH-DASHES"] = "baz"
rblf.mkwarning("pixel3.mk", "GLOBAL-VAR-WITH-DASHES: %s" % g["GLOBAL-VAR-WITH-DASHES"])
`, `,
}, },
{ {

View File

@@ -278,6 +278,14 @@ var presetVariables = map[string]bool{
// addVariable returns a variable with a given name. A variable is // addVariable returns a variable with a given name. A variable is
// added if it does not exist yet. // added if it does not exist yet.
func (ctx *parseContext) addVariable(name string) variable { func (ctx *parseContext) addVariable(name string) variable {
// Heuristics: if variable's name is all lowercase, consider it local
// string variable.
isLocalVariable := name == strings.ToLower(name)
// Local variables can't have special characters in them, because they
// will be used as starlark identifiers
if isLocalVariable {
name = strings.ReplaceAll(strings.TrimSpace(name), "-", "_")
}
v, found := ctx.variables[name] v, found := ctx.variables[name]
if !found { if !found {
_, preset := presetVariables[name] _, preset := presetVariables[name]
@@ -288,9 +296,7 @@ func (ctx *parseContext) addVariable(name string) variable {
case VarClassSoong: case VarClassSoong:
v = &otherGlobalVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}} v = &otherGlobalVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}}
} }
} else if name == strings.ToLower(name) { } else if isLocalVariable {
// Heuristics: if variable's name is all lowercase, consider it local
// string variable.
v = &localVariable{baseVariable{nam: name, typ: starlarkTypeUnknown}} v = &localVariable{baseVariable{nam: name, typ: starlarkTypeUnknown}}
} else { } else {
vt := starlarkTypeUnknown vt := starlarkTypeUnknown