release-request-051da47e-713f-4e09-8f6c-698fb4d4e92e-for-git_oc-dr1-release-3997165 snap-temp-L04400000062809322

Change-Id: I7b5380023fc17e85e9981a8b09e48decfcce6e34
diff --git a/live_tracker.go b/live_tracker.go
index 8348988..63bdf8a 100644
--- a/live_tracker.go
+++ b/live_tracker.go
@@ -68,6 +68,13 @@
 		return err
 	}
 
+	for _, value := range def.Variables {
+		err = l.addNinjaStringDeps(value)
+		if err != nil {
+			return err
+		}
+	}
+
 	for _, value := range def.Args {
 		err = l.addNinjaStringDeps(value)
 		if err != nil {
diff --git a/ninja_defs.go b/ninja_defs.go
index 8737ed2..64bab16 100644
--- a/ninja_defs.go
+++ b/ninja_defs.go
@@ -79,6 +79,7 @@
 	Comment         string            // The comment that will appear above the definition.
 	Depfile         string            // The dependency file name.
 	Deps            Deps              // The format of the dependency file.
+	Description     string            // The description that Ninja will print for the build.
 	Rule            Rule              // The rule to invoke.
 	Outputs         []string          // The list of explicit output targets.
 	ImplicitOutputs []string          // The list of implicit output targets.
@@ -265,6 +266,13 @@
 		Rule:    rule,
 	}
 
+	setVariable := func(name string, value *ninjaString) {
+		if b.Variables == nil {
+			b.Variables = make(map[string]*ninjaString)
+		}
+		b.Variables[name] = value
+	}
+
 	if !scope.IsRuleVisible(rule) {
 		return nil, fmt.Errorf("Rule %s is not visible in this scope", rule)
 	}
@@ -301,22 +309,24 @@
 
 	b.Optional = params.Optional
 
-	if params.Depfile != "" || params.Deps != DepsNone {
-		if b.Variables == nil {
-			b.Variables = make(map[string]*ninjaString)
-		}
-	}
-
 	if params.Depfile != "" {
 		value, err := parseNinjaString(scope, params.Depfile)
 		if err != nil {
 			return nil, fmt.Errorf("error parsing Depfile param: %s", err)
 		}
-		b.Variables["depfile"] = value
+		setVariable("depfile", value)
 	}
 
 	if params.Deps != DepsNone {
-		b.Variables["deps"] = simpleNinjaString(params.Deps.String())
+		setVariable("deps", simpleNinjaString(params.Deps.String()))
+	}
+
+	if params.Description != "" {
+		value, err := parseNinjaString(scope, params.Description)
+		if err != nil {
+			return nil, fmt.Errorf("error parsing Description param: %s", err)
+		}
+		setVariable("description", value)
 	}
 
 	argNameScope := rule.scope()
diff --git a/ninja_strings.go b/ninja_strings.go
index 5bdddea..a52f174 100644
--- a/ninja_strings.go
+++ b/ninja_strings.go
@@ -54,6 +54,7 @@
 type parseState struct {
 	scope       scope
 	str         string
+	pendingStr  string
 	stringStart int
 	varStart    int
 	result      *ninjaString
@@ -64,6 +65,9 @@
 		// Last push was a variable, we need a blank string separator
 		ps.result.strings = append(ps.result.strings, "")
 	}
+	if ps.pendingStr != "" {
+		panic("oops, pushed variable with pending string")
+	}
 	ps.result.variables = append(ps.result.variables, v)
 }
 
@@ -71,7 +75,8 @@
 	if len(ps.result.strings) != len(ps.result.variables) {
 		panic("oops, pushed string after string")
 	}
-	ps.result.strings = append(ps.result.strings, s)
+	ps.result.strings = append(ps.result.strings, ps.pendingStr+s)
+	ps.pendingStr = ""
 }
 
 type stateFunc func(*parseState, int, rune) (stateFunc, error)
@@ -93,7 +98,7 @@
 		result: result,
 	}
 
-	state := parseStringState
+	state := parseFirstRuneState
 	var err error
 	for i := 0; i < len(str); i++ {
 		r := rune(str[i])
@@ -111,6 +116,13 @@
 	return result, nil
 }
 
+func parseFirstRuneState(state *parseState, i int, r rune) (stateFunc, error) {
+	if r == ' ' {
+		state.pendingStr += "$"
+	}
+	return parseStringState(state, i, r)
+}
+
 func parseStringState(state *parseState, i int, r rune) (stateFunc, error) {
 	switch {
 	case r == '$':
diff --git a/ninja_strings_test.go b/ninja_strings_test.go
index b417335..6227ea6 100644
--- a/ninja_strings_test.go
+++ b/ninja_strings_test.go
@@ -71,6 +71,11 @@
 		strs:  []string{"foo bar"},
 	},
 	{
+		input: " foo ",
+		vars:  nil,
+		strs:  []string{"$ foo "},
+	},
+	{
 		input: "foo $ bar",
 		err:   "invalid character after '$' at byte offset 5",
 	},