Allow $(filter ...) with arbitrary args if its result is compared to the empty string
Bug: 172923994 Test: internal Change-Id: Iea36ecaa8940cf4e495ad63125f10d733c3eb2ee
This commit is contained in:
@@ -240,22 +240,21 @@ func (eq *eqExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (eq *eqExpr) emit(gctx *generationContext) {
|
func (eq *eqExpr) emit(gctx *generationContext) {
|
||||||
// Are we checking that a variable is empty?
|
emitSimple := func(expr starlarkExpr) {
|
||||||
var varRef *variableRefExpr
|
|
||||||
if s, ok := maybeString(eq.left); ok && s == "" {
|
|
||||||
varRef, ok = eq.right.(*variableRefExpr)
|
|
||||||
} else if s, ok := maybeString(eq.right); ok && s == "" {
|
|
||||||
varRef, ok = eq.left.(*variableRefExpr)
|
|
||||||
}
|
|
||||||
if varRef != nil {
|
|
||||||
// Yes.
|
|
||||||
if eq.isEq {
|
if eq.isEq {
|
||||||
gctx.write("not ")
|
gctx.write("not ")
|
||||||
}
|
}
|
||||||
varRef.emit(gctx)
|
expr.emit(gctx)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// Are we checking that a variable is empty?
|
||||||
|
if isEmptyString(eq.left) {
|
||||||
|
emitSimple(eq.right)
|
||||||
|
return
|
||||||
|
} else if isEmptyString(eq.right) {
|
||||||
|
emitSimple(eq.left)
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
// General case
|
// General case
|
||||||
eq.left.emit(gctx)
|
eq.left.emit(gctx)
|
||||||
if eq.isEq {
|
if eq.isEq {
|
||||||
@@ -578,3 +577,8 @@ func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
|
|||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isEmptyString(expr starlarkExpr) bool {
|
||||||
|
x, ok := expr.(*stringLiteralExpr)
|
||||||
|
return ok && x.literal == ""
|
||||||
|
}
|
||||||
|
@@ -938,14 +938,14 @@ func (ctx *parseContext) parseCheckFunctionCallResult(directive *mkparser.Direct
|
|||||||
func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
|
func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
|
||||||
filterFuncCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
|
filterFuncCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
|
||||||
// We handle:
|
// We handle:
|
||||||
// * ifeq/ifneq (,$(filter v1 v2 ..., $(VAR)) becomes if VAR not in/in ["v1", "v2", ...]
|
// * ifeq/ifneq (,$(filter v1 v2 ..., EXPR) becomes if EXPR not in/in ["v1", "v2", ...]
|
||||||
// * ifeq/ifneq (,$(filter $(VAR), v1 v2 ...) becomes if VAR not in/in ["v1", "v2", ...]
|
// * ifeq/ifneq (,$(filter EXPR, v1 v2 ...) becomes if EXPR not in/in ["v1", "v2", ...]
|
||||||
// * ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...) becomes if VAR in/not in ["v1", "v2"]
|
// * ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...) becomes if VAR in/not in ["v1", "v2"]
|
||||||
// TODO(Asmundak): check the last case works for filter-out, too.
|
// TODO(Asmundak): check the last case works for filter-out, too.
|
||||||
xPattern := filterFuncCall.args[0]
|
xPattern := filterFuncCall.args[0]
|
||||||
xText := filterFuncCall.args[1]
|
xText := filterFuncCall.args[1]
|
||||||
var xInList *stringLiteralExpr
|
var xInList *stringLiteralExpr
|
||||||
var xVar starlarkExpr
|
var expr starlarkExpr
|
||||||
var ok bool
|
var ok bool
|
||||||
switch x := xValue.(type) {
|
switch x := xValue.(type) {
|
||||||
case *stringLiteralExpr:
|
case *stringLiteralExpr:
|
||||||
@@ -955,34 +955,42 @@ func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
|
|||||||
// Either pattern or text should be const, and the
|
// Either pattern or text should be const, and the
|
||||||
// non-const one should be varRefExpr
|
// non-const one should be varRefExpr
|
||||||
if xInList, ok = xPattern.(*stringLiteralExpr); ok {
|
if xInList, ok = xPattern.(*stringLiteralExpr); ok {
|
||||||
xVar = xText
|
expr = xText
|
||||||
} else if xInList, ok = xText.(*stringLiteralExpr); ok {
|
} else if xInList, ok = xText.(*stringLiteralExpr); ok {
|
||||||
xVar = xPattern
|
expr = xPattern
|
||||||
|
} else {
|
||||||
|
return &callExpr{
|
||||||
|
object: nil,
|
||||||
|
name: filterFuncCall.name,
|
||||||
|
args: filterFuncCall.args,
|
||||||
|
returnType: starlarkTypeBool,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *variableRefExpr:
|
case *variableRefExpr:
|
||||||
if v, ok := xPattern.(*variableRefExpr); ok {
|
if v, ok := xPattern.(*variableRefExpr); ok {
|
||||||
if xInList, ok = xText.(*stringLiteralExpr); ok && v.ref.name() == x.ref.name() {
|
if xInList, ok = xText.(*stringLiteralExpr); ok && v.ref.name() == x.ref.name() {
|
||||||
// ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...), flip negate,
|
// ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...), flip negate,
|
||||||
// it's the opposite to what is done when comparing to empty.
|
// it's the opposite to what is done when comparing to empty.
|
||||||
xVar = xPattern
|
expr = xPattern
|
||||||
negate = !negate
|
negate = !negate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if xVar != nil && xInList != nil {
|
if expr != nil && xInList != nil {
|
||||||
if _, ok := xVar.(*variableRefExpr); ok {
|
slExpr := newStringListExpr(strings.Fields(xInList.literal))
|
||||||
slExpr := newStringListExpr(strings.Fields(xInList.literal))
|
// Generate simpler code for the common cases:
|
||||||
// Generate simpler code for the common cases:
|
if expr.typ() == starlarkTypeList {
|
||||||
if xVar.typ() == starlarkTypeList {
|
if len(slExpr.items) == 1 {
|
||||||
if len(slExpr.items) == 1 {
|
// Checking that a string belongs to list
|
||||||
// Checking that a string belongs to list
|
return &inExpr{isNot: negate, list: expr, expr: slExpr.items[0]}
|
||||||
return &inExpr{isNot: negate, list: xVar, expr: slExpr.items[0]}
|
} else {
|
||||||
} else {
|
// TODO(asmundak):
|
||||||
// TODO(asmundak):
|
panic("TBD")
|
||||||
panic("TBD")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &inExpr{isNot: negate, list: newStringListExpr(strings.Fields(xInList.literal)), expr: xVar}
|
} else if len(slExpr.items) == 1 {
|
||||||
|
return &eqExpr{left: expr, right: slExpr.items[0], isEq: !negate}
|
||||||
|
} else {
|
||||||
|
return &inExpr{isNot: negate, list: newStringListExpr(strings.Fields(xInList.literal)), expr: expr}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ctx.newBadExpr(cond, "filter arguments are too complex: %s", cond.Dump())
|
return ctx.newBadExpr(cond, "filter arguments are too complex: %s", cond.Dump())
|
||||||
@@ -990,7 +998,7 @@ func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
|
|||||||
|
|
||||||
func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Directive,
|
func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Directive,
|
||||||
xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
|
xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
|
||||||
if x, ok := xValue.(*stringLiteralExpr); !ok || x.literal != "" {
|
if !isEmptyString(xValue) {
|
||||||
return ctx.newBadExpr(directive, "wildcard result can be compared only to empty: %s", xValue)
|
return ctx.newBadExpr(directive, "wildcard result can be compared only to empty: %s", xValue)
|
||||||
}
|
}
|
||||||
callFunc := wildcardExistsPhony
|
callFunc := wildcardExistsPhony
|
||||||
@@ -1006,19 +1014,19 @@ func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Dire
|
|||||||
|
|
||||||
func (ctx *parseContext) parseCheckFindstringFuncResult(directive *mkparser.Directive,
|
func (ctx *parseContext) parseCheckFindstringFuncResult(directive *mkparser.Directive,
|
||||||
xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
|
xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
|
||||||
if x, ok := xValue.(*stringLiteralExpr); !ok || x.literal != "" {
|
if isEmptyString(xValue) {
|
||||||
return ctx.newBadExpr(directive, "findstring result can be compared only to empty: %s", xValue)
|
return &eqExpr{
|
||||||
}
|
left: &callExpr{
|
||||||
return &eqExpr{
|
object: xCall.args[1],
|
||||||
left: &callExpr{
|
name: "find",
|
||||||
object: xCall.args[1],
|
args: []starlarkExpr{xCall.args[0]},
|
||||||
name: "find",
|
returnType: starlarkTypeInt,
|
||||||
args: []starlarkExpr{xCall.args[0]},
|
},
|
||||||
returnType: starlarkTypeInt,
|
right: &intLiteralExpr{-1},
|
||||||
},
|
isEq: !negate,
|
||||||
right: &intLiteralExpr{-1},
|
}
|
||||||
isEq: !negate,
|
|
||||||
}
|
}
|
||||||
|
return ctx.newBadExpr(directive, "findstring result can be compared only to empty: %s", xValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *parseContext) parseCompareStripFuncResult(directive *mkparser.Directive,
|
func (ctx *parseContext) parseCompareStripFuncResult(directive *mkparser.Directive,
|
||||||
|
@@ -342,6 +342,8 @@ ifneq (,$(filter plaf,$(PLATFORM_LIST)))
|
|||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_BUILD_VARIANT), $(filter $(TARGET_BUILD_VARIANT), userdebug eng))
|
ifeq ($(TARGET_BUILD_VARIANT), $(filter $(TARGET_BUILD_VARIANT), userdebug eng))
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter true, $(v1)$(v2)))
|
||||||
|
endif
|
||||||
`,
|
`,
|
||||||
expected: `load("//build/make/core:product_config.rbc", "rblf")
|
expected: `load("//build/make/core:product_config.rbc", "rblf")
|
||||||
|
|
||||||
@@ -349,12 +351,14 @@ def init(g, handle):
|
|||||||
cfg = rblf.cfg(handle)
|
cfg = rblf.cfg(handle)
|
||||||
if g["TARGET_BUILD_VARIANT"] not in ["userdebug", "eng"]:
|
if g["TARGET_BUILD_VARIANT"] not in ["userdebug", "eng"]:
|
||||||
pass
|
pass
|
||||||
if g["TARGET_BUILD_VARIANT"] in ["userdebug"]:
|
if g["TARGET_BUILD_VARIANT"] == "userdebug":
|
||||||
pass
|
pass
|
||||||
if "plaf" in g.get("PLATFORM_LIST", []):
|
if "plaf" in g.get("PLATFORM_LIST", []):
|
||||||
pass
|
pass
|
||||||
if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]:
|
if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]:
|
||||||
pass
|
pass
|
||||||
|
if "%s%s" % (_v1, _v2) == "true":
|
||||||
|
pass
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -385,8 +389,23 @@ endif
|
|||||||
def init(g, handle):
|
def init(g, handle):
|
||||||
cfg = rblf.cfg(handle)
|
cfg = rblf.cfg(handle)
|
||||||
if g["TARGET_PRODUCT"] not in ["yukawa_gms", "yukawa_sei510_gms"]:
|
if g["TARGET_PRODUCT"] not in ["yukawa_gms", "yukawa_sei510_gms"]:
|
||||||
if g["TARGET_PRODUCT"] in ["yukawa_gms"]:
|
if g["TARGET_PRODUCT"] == "yukawa_gms":
|
||||||
pass
|
pass
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "filter $(V1), $(V2)",
|
||||||
|
mkname: "product.mk",
|
||||||
|
in: `
|
||||||
|
ifneq (, $(filter $(PRODUCT_LIST), $(TARGET_PRODUCT)))
|
||||||
|
endif
|
||||||
|
`,
|
||||||
|
expected: `load("//build/make/core:product_config.rbc", "rblf")
|
||||||
|
|
||||||
|
def init(g, handle):
|
||||||
|
cfg = rblf.cfg(handle)
|
||||||
|
if rblf.filter(g.get("PRODUCT_LIST", ""), g["TARGET_PRODUCT"]):
|
||||||
|
pass
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -779,7 +798,7 @@ endif
|
|||||||
|
|
||||||
def init(g, handle):
|
def init(g, handle):
|
||||||
cfg = rblf.cfg(handle)
|
cfg = rblf.cfg(handle)
|
||||||
if rblf.mkstrip(g.get("TARGET_VENDOR", "")) != "":
|
if rblf.mkstrip(g.get("TARGET_VENDOR", "")):
|
||||||
pass
|
pass
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user