diff --git a/builtins.go b/builtins.go index 2d939434..b25ec6a9 100644 --- a/builtins.go +++ b/builtins.go @@ -1301,6 +1301,15 @@ func builtinEqualsIgnoreCase(i *interpreter, sv1, sv2 value) (value, error) { return makeValueBoolean(strings.EqualFold(s1.getGoString(), s2.getGoString())), nil } +func builtinTrim(i *interpreter, strv value) (value, error) { + str, err := i.getString(strv) + if err != nil { + return nil, err + } + sStr := str.getGoString() + return makeValueString(strings.TrimSpace(sStr)), nil +} + func base64DecodeGoBytes(i *interpreter, str string) ([]byte, error) { strLen := len(str) if strLen%4 != 0 { @@ -2407,6 +2416,7 @@ var funcBuiltins = buildBuiltinMap([]builtin{ &ternaryBuiltin{name: "strReplace", function: builtinStrReplace, params: ast.Identifiers{"str", "from", "to"}}, &unaryBuiltin{name: "isEmpty", function: builtinIsEmpty, params: ast.Identifiers{"str"}}, &binaryBuiltin{name: "equalsIgnoreCase", function: builtinEqualsIgnoreCase, params: ast.Identifiers{"str1", "str2"}}, + &unaryBuiltin{name: "trim", function: builtinTrim, params: ast.Identifiers{"str"}}, &unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, params: ast.Identifiers{"str"}}, &unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, params: ast.Identifiers{"str"}}, &unaryBuiltin{name: "parseInt", function: builtinParseInt, params: ast.Identifiers{"str"}}, diff --git a/linter/internal/types/stdlib.go b/linter/internal/types/stdlib.go index 01c4ebbe..cb1f8357 100644 --- a/linter/internal/types/stdlib.go +++ b/linter/internal/types/stdlib.go @@ -91,6 +91,7 @@ func prepareStdlib(g *typeGraph) { "format": g.newSimpleFuncType(stringType, "str", "vals"), "isEmpty": g.newSimpleFuncType(boolType, "str"), "equalsIgnoreCase": g.newSimpleFuncType(boolType, "str1", "str2"), + "trim": g.newSimpleFuncType(stringType, "str"), // TODO(sbarzowski) Fix when they match the documentation "escapeStringBash": g.newSimpleFuncType(stringType, "str_"), "escapeStringDollars": g.newSimpleFuncType(stringType, "str_"), @@ -145,10 +146,10 @@ func prepareStdlib(g *typeGraph) { "maxArray": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}), "contains": g.newSimpleFuncType(boolType, "arr", "elem"), // TODO these need test cases written by someone who understands how to make them - "all": g.newSimpleFuncType(boolArrayType, "arr"), - "any": g.newSimpleFuncType(boolArrayType, "arr"), - "remove": g.newSimpleFuncType(anyArrayType, "arr", "elem"), - "removeAt": g.newSimpleFuncType(anyArrayType, "arr", "i"), + "all": g.newSimpleFuncType(boolArrayType, "arr"), + "any": g.newSimpleFuncType(boolArrayType, "arr"), + "remove": g.newSimpleFuncType(anyArrayType, "arr", "elem"), + "removeAt": g.newSimpleFuncType(anyArrayType, "arr", "i"), // Sets diff --git a/testdata/builtinTrim.golden b/testdata/builtinTrim.golden new file mode 100644 index 00000000..f387f89d --- /dev/null +++ b/testdata/builtinTrim.golden @@ -0,0 +1 @@ +"already trimmed string" diff --git a/testdata/builtinTrim.jsonnet b/testdata/builtinTrim.jsonnet new file mode 100644 index 00000000..fa394dc1 --- /dev/null +++ b/testdata/builtinTrim.jsonnet @@ -0,0 +1 @@ +std.trim("already trimmed string") diff --git a/testdata/builtinTrim.linter.golden b/testdata/builtinTrim.linter.golden new file mode 100644 index 00000000..e69de29b diff --git a/testdata/builtinTrim1.golden b/testdata/builtinTrim1.golden new file mode 100644 index 00000000..a1f0231e --- /dev/null +++ b/testdata/builtinTrim1.golden @@ -0,0 +1 @@ +"string with spaces on both ends" diff --git a/testdata/builtinTrim1.jsonnet b/testdata/builtinTrim1.jsonnet new file mode 100644 index 00000000..fc2dc8de --- /dev/null +++ b/testdata/builtinTrim1.jsonnet @@ -0,0 +1 @@ +std.trim(" string with spaces on both ends ") diff --git a/testdata/builtinTrim1.linter.golden b/testdata/builtinTrim1.linter.golden new file mode 100644 index 00000000..e69de29b diff --git a/testdata/builtinTrim2.golden b/testdata/builtinTrim2.golden new file mode 100644 index 00000000..858b6d6c --- /dev/null +++ b/testdata/builtinTrim2.golden @@ -0,0 +1 @@ +"string with newline character at end" diff --git a/testdata/builtinTrim2.jsonnet b/testdata/builtinTrim2.jsonnet new file mode 100644 index 00000000..6578c660 --- /dev/null +++ b/testdata/builtinTrim2.jsonnet @@ -0,0 +1 @@ +std.trim("string with newline character at end\n") diff --git a/testdata/builtinTrim2.linter.golden b/testdata/builtinTrim2.linter.golden new file mode 100644 index 00000000..e69de29b diff --git a/testdata/builtinTrim3.golden b/testdata/builtinTrim3.golden new file mode 100644 index 00000000..10cab94f --- /dev/null +++ b/testdata/builtinTrim3.golden @@ -0,0 +1 @@ +"string with tabs at end" diff --git a/testdata/builtinTrim3.jsonnet b/testdata/builtinTrim3.jsonnet new file mode 100644 index 00000000..ffc1ff35 --- /dev/null +++ b/testdata/builtinTrim3.jsonnet @@ -0,0 +1 @@ +std.trim("string with tabs at end\t\t") diff --git a/testdata/builtinTrim3.linter.golden b/testdata/builtinTrim3.linter.golden new file mode 100644 index 00000000..e69de29b diff --git a/testdata/builtinTrim4.golden b/testdata/builtinTrim4.golden new file mode 100644 index 00000000..8befa99e --- /dev/null +++ b/testdata/builtinTrim4.golden @@ -0,0 +1,10 @@ +RUNTIME ERROR: Unexpected type number, expected string +------------------------------------------------- + testdata/builtinTrim4:1:1-13 $ + +std.trim(10) + +------------------------------------------------- + During evaluation + + diff --git a/testdata/builtinTrim4.jsonnet b/testdata/builtinTrim4.jsonnet new file mode 100644 index 00000000..4bd9d068 --- /dev/null +++ b/testdata/builtinTrim4.jsonnet @@ -0,0 +1 @@ +std.trim(10) diff --git a/testdata/builtinTrim4.linter.golden b/testdata/builtinTrim4.linter.golden new file mode 100644 index 00000000..e69de29b