Commit 9c3bf097 authored by Rob Pike's avatar Rob Pike

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/9007Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 13cb62c7
...@@ -276,6 +276,8 @@ Go generate sets several variables when it runs the generator: ...@@ -276,6 +276,8 @@ Go generate sets several variables when it runs the generator:
The execution operating system (linux, windows, etc.) The execution operating system (linux, windows, etc.)
$GOFILE $GOFILE
The base name of the file. The base name of the file.
$GOLINE
The line number of the directive in the source file.
$GOPACKAGE $GOPACKAGE
The name of the package of the file containing the directive. The name of the package of the file containing the directive.
$DOLLAR $DOLLAR
......
...@@ -18,7 +18,6 @@ import ( ...@@ -18,7 +18,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8"
) )
var cmdGenerate = &Command{ var cmdGenerate = &Command{
...@@ -63,6 +62,8 @@ Go generate sets several variables when it runs the generator: ...@@ -63,6 +62,8 @@ Go generate sets several variables when it runs the generator:
The execution operating system (linux, windows, etc.) The execution operating system (linux, windows, etc.)
$GOFILE $GOFILE
The base name of the file. The base name of the file.
$GOLINE
The line number of the directive in the source file.
$GOPACKAGE $GOPACKAGE
The name of the package of the file containing the directive. The name of the package of the file containing the directive.
$DOLLAR $DOLLAR
...@@ -177,7 +178,7 @@ type Generator struct { ...@@ -177,7 +178,7 @@ type Generator struct {
file string // base name of file. file string // base name of file.
pkg string pkg string
commands map[string][]string commands map[string][]string
lineNum int lineNum int // current line number.
} }
// run runs the generators in the current file. // run runs the generators in the current file.
...@@ -325,7 +326,7 @@ Words: ...@@ -325,7 +326,7 @@ Words:
} }
// Substitute environment variables. // Substitute environment variables.
for i, word := range words { for i, word := range words {
words[i] = g.expandEnv(word) words[i] = os.Expand(word, g.expandVar)
} }
return words return words
} }
...@@ -341,40 +342,25 @@ func (g *Generator) errorf(format string, args ...interface{}) { ...@@ -341,40 +342,25 @@ func (g *Generator) errorf(format string, args ...interface{}) {
panic(stop) panic(stop)
} }
// expandEnv expands any $XXX invocations in word. // expandVar expands the $XXX invocation in word. It is called
func (g *Generator) expandEnv(word string) string { // by os.Expand.
if !strings.ContainsRune(word, '$') { func (g *Generator) expandVar(word string) string {
return word 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. // identLength returns the length of the identifier beginning the string.
......
...@@ -1089,20 +1089,20 @@ TEST 'go generate variable substitution' ...@@ -1089,20 +1089,20 @@ TEST 'go generate variable substitution'
if ! ./testgo generate ./testdata/generate/test3.go > testdata/std.out; then if ! ./testgo generate ./testdata/generate/test3.go > testdata/std.out; then
echo "go generate ./testdata/generate/test3.go failed to run" echo "go generate ./testdata/generate/test3.go failed to run"
ok=false 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" echo "go generate ./testdata/generate/test3.go generated wrong output"
ok=false ok=false
fi fi
TEST 'go generate run flag' TEST 'go generate run flag'
if ! ./testgo generate -run y.s ./testdata/generate/test4.go > testdata/std.out; then 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 ok=false
elif ! grep "yes" testdata/std.out > /dev/null; then 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 ok=false
elif grep "no" testdata/std.out > /dev/null; then 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 ok=false
fi fi
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
// Test go generate variable substitution. // 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 package p
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment