From 9c3bf097c8acae50f4ff3659083fc0c84e81bf00 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 17 Apr 2015 11:21:02 -0700 Subject: [PATCH] cmd/go: add $GOLINE to generate Also use os.Expand for variable substitution so ${x}y works. Fixes #9960. Change-Id: Ic8239b2e737d1f41910dde8ee9524ac48907cb03 Reviewed-on: https://go-review.googlesource.com/9007 Reviewed-by: Russ Cox --- src/cmd/go/doc.go | 2 + src/cmd/go/generate.go | 58 ++++++++++----------------- src/cmd/go/test.bash | 8 ++-- src/cmd/go/testdata/generate/test3.go | 2 +- 4 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go index f327330e98..39eb7867c7 100644 --- a/src/cmd/go/doc.go +++ b/src/cmd/go/doc.go @@ -276,6 +276,8 @@ Go generate sets several variables when it runs the generator: The execution operating system (linux, windows, etc.) $GOFILE The base name of the file. + $GOLINE + The line number of the directive in the source file. $GOPACKAGE The name of the package of the file containing the directive. $DOLLAR diff --git a/src/cmd/go/generate.go b/src/cmd/go/generate.go index 1877acdeb6..a17f6e7747 100644 --- a/src/cmd/go/generate.go +++ b/src/cmd/go/generate.go @@ -18,7 +18,6 @@ import ( "strconv" "strings" "unicode" - "unicode/utf8" ) var cmdGenerate = &Command{ @@ -63,6 +62,8 @@ Go generate sets several variables when it runs the generator: The execution operating system (linux, windows, etc.) $GOFILE The base name of the file. + $GOLINE + The line number of the directive in the source file. $GOPACKAGE The name of the package of the file containing the directive. $DOLLAR @@ -177,7 +178,7 @@ type Generator struct { file string // base name of file. pkg string commands map[string][]string - lineNum int + lineNum int // current line number. } // run runs the generators in the current file. @@ -325,7 +326,7 @@ Words: } // Substitute environment variables. for i, word := range words { - words[i] = g.expandEnv(word) + words[i] = os.Expand(word, g.expandVar) } return words } @@ -341,40 +342,25 @@ func (g *Generator) errorf(format string, args ...interface{}) { panic(stop) } -// expandEnv expands any $XXX invocations in word. -func (g *Generator) expandEnv(word string) string { - if !strings.ContainsRune(word, '$') { - return word +// expandVar expands the $XXX invocation in word. It is called +// by os.Expand. +func (g *Generator) expandVar(word string) string { + switch word { + case "GOARCH": + return runtime.GOARCH + case "GOOS": + return runtime.GOOS + case "GOFILE": + return g.file + case "GOLINE": + return fmt.Sprint(g.lineNum) + case "GOPACKAGE": + return g.pkg + case "DOLLAR": + return "$" + default: + return os.Getenv(word) } - var buf bytes.Buffer - var w int - var r rune - for i := 0; i < len(word); i += w { - r, w = utf8.DecodeRuneInString(word[i:]) - if r != '$' { - buf.WriteRune(r) - continue - } - w += g.identLength(word[i+w:]) - envVar := word[i+1 : i+w] - var sub string - switch envVar { - case "GOARCH": - sub = runtime.GOARCH - case "GOOS": - sub = runtime.GOOS - case "GOFILE": - sub = g.file - case "GOPACKAGE": - sub = g.pkg - case "DOLLAR": - sub = "$" - default: - sub = os.Getenv(envVar) - } - buf.WriteString(sub) - } - return buf.String() } // identLength returns the length of the identifier beginning the string. diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash index ca3c9241da..e1809b4e65 100755 --- a/src/cmd/go/test.bash +++ b/src/cmd/go/test.bash @@ -1089,20 +1089,20 @@ TEST 'go generate variable substitution' if ! ./testgo generate ./testdata/generate/test3.go > testdata/std.out; then echo "go generate ./testdata/generate/test3.go failed to run" ok=false -elif ! grep "$GOARCH test3.go p xyzp/test3.go/123" testdata/std.out > /dev/null; then +elif ! grep "$GOARCH test3.go:7 pabc xyzp/test3.go/123" testdata/std.out > /dev/null; then echo "go generate ./testdata/generate/test3.go generated wrong output" ok=false fi TEST 'go generate run flag' if ! ./testgo generate -run y.s ./testdata/generate/test4.go > testdata/std.out; then - echo "go test -run y.s ./testdata/generate/test4.go failed to run" + echo "go test -run yes ./testdata/generate/test4.go failed to run" ok=false elif ! grep "yes" testdata/std.out > /dev/null; then - echo "go generate -run y.s ./testdata/generate/test4.go did not select yes" + echo "go generate -run yes ./testdata/generate/test4.go did not select yes" ok=false elif grep "no" testdata/std.out > /dev/null; then - echo "go generate -run y.s ./testdata/generate/test4.go selected no" + echo "go generate -run yes ./testdata/generate/test4.go selected no" ok=false fi diff --git a/src/cmd/go/testdata/generate/test3.go b/src/cmd/go/testdata/generate/test3.go index 41ffb7ea87..3d6a8a5c74 100644 --- a/src/cmd/go/testdata/generate/test3.go +++ b/src/cmd/go/testdata/generate/test3.go @@ -4,6 +4,6 @@ // Test go generate variable substitution. -//go:generate echo $GOARCH $GOFILE $GOPACKAGE xyz$GOPACKAGE/$GOFILE/123 +//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123 package p -- 2.48.1