Use io.StringWriter in ninjaWriter

ninjaWriter repeatedly called io.WriteString() on its writer, which
does a type assertion every time.  Replace its io.Writer with an
io.StringWriter and call WriteString on it directly.

Test: ninja_writer_test.go
Change-Id: Ie073d996a319190242bf6a00af07a13a60d078b5
This commit is contained in:
Colin Cross 2021-01-21 15:26:21 -08:00
parent bcd5686660
commit 0335e0900d
3 changed files with 83 additions and 24 deletions

View file

@ -186,7 +186,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri
}
const outFilePermissions = 0666
var out io.Writer
var out io.StringWriter
var f *os.File
var buf *bufio.Writer
@ -204,7 +204,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri
buf = bufio.NewWriter(f)
out = buf
} else {
out = ioutil.Discard
out = ioutil.Discard.(io.StringWriter)
}
if globFile != "" {

View file

@ -3489,7 +3489,7 @@ func (c *Context) SingletonName(singleton Singleton) string {
// WriteBuildFile writes the Ninja manifeset text for the generated build
// actions to w. If this is called before PrepareBuildActions successfully
// completes then ErrBuildActionsNotReady is returned.
func (c *Context) WriteBuildFile(w io.Writer) error {
func (c *Context) WriteBuildFile(w io.StringWriter) error {
var err error
pprof.Do(c.Context, pprof.Labels("blueprint", "WriteBuildFile"), func(ctx context.Context) {
if !c.buildActionsReady {

View file

@ -15,7 +15,6 @@
package blueprint
import (
"fmt"
"io"
"strings"
"unicode"
@ -29,13 +28,18 @@ const (
var indentString = strings.Repeat(" ", indentWidth*maxIndentDepth)
type StringWriterWriter interface {
io.StringWriter
io.Writer
}
type ninjaWriter struct {
writer io.Writer
writer io.StringWriter
justDidBlankLine bool // true if the last operation was a BlankLine
}
func newNinjaWriter(writer io.Writer) *ninjaWriter {
func newNinjaWriter(writer io.StringWriter) *ninjaWriter {
return &ninjaWriter{
writer: writer,
}
@ -72,7 +76,7 @@ func (n *ninjaWriter) Comment(comment string) error {
if writeLine {
line = strings.TrimSpace("# "+line) + "\n"
_, err := io.WriteString(n.writer, line)
_, err := n.writer.WriteString(line)
if err != nil {
return err
}
@ -82,7 +86,15 @@ func (n *ninjaWriter) Comment(comment string) error {
if lineStart != len(comment) {
line := strings.TrimSpace(comment[lineStart:])
_, err := fmt.Fprintf(n.writer, "# %s\n", line)
_, err := n.writer.WriteString("# ")
if err != nil {
return err
}
_, err = n.writer.WriteString(line)
if err != nil {
return err
}
_, err = n.writer.WriteString("\n")
if err != nil {
return err
}
@ -93,14 +105,12 @@ func (n *ninjaWriter) Comment(comment string) error {
func (n *ninjaWriter) Pool(name string) error {
n.justDidBlankLine = false
_, err := fmt.Fprintf(n.writer, "pool %s\n", name)
return err
return n.writeStatement("pool", name)
}
func (n *ninjaWriter) Rule(name string) error {
n.justDidBlankLine = false
_, err := fmt.Fprintf(n.writer, "rule %s\n", name)
return err
return n.writeStatement("rule", name)
}
func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
@ -174,14 +184,48 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
func (n *ninjaWriter) Assign(name, value string) error {
n.justDidBlankLine = false
_, err := fmt.Fprintf(n.writer, "%s = %s\n", name, value)
return err
_, err := n.writer.WriteString(name)
if err != nil {
return err
}
_, err = n.writer.WriteString(" = ")
if err != nil {
return err
}
_, err = n.writer.WriteString(value)
if err != nil {
return err
}
_, err = n.writer.WriteString("\n")
if err != nil {
return err
}
return nil
}
func (n *ninjaWriter) ScopedAssign(name, value string) error {
n.justDidBlankLine = false
_, err := fmt.Fprintf(n.writer, "%s%s = %s\n", indentString[:indentWidth], name, value)
return err
_, err := n.writer.WriteString(indentString[:indentWidth])
if err != nil {
return err
}
_, err = n.writer.WriteString(name)
if err != nil {
return err
}
_, err = n.writer.WriteString(" = ")
if err != nil {
return err
}
_, err = n.writer.WriteString(value)
if err != nil {
return err
}
_, err = n.writer.WriteString("\n")
if err != nil {
return err
}
return nil
}
func (n *ninjaWriter) Default(targets ...string) error {
@ -206,19 +250,34 @@ func (n *ninjaWriter) Default(targets ...string) error {
func (n *ninjaWriter) Subninja(file string) error {
n.justDidBlankLine = false
_, err := fmt.Fprintf(n.writer, "subninja %s\n", file)
return err
return n.writeStatement("subninja", file)
}
func (n *ninjaWriter) BlankLine() (err error) {
// We don't output multiple blank lines in a row.
if !n.justDidBlankLine {
n.justDidBlankLine = true
_, err = io.WriteString(n.writer, "\n")
_, err = n.writer.WriteString("\n")
}
return err
}
func (n *ninjaWriter) writeStatement(directive, name string) error {
_, err := n.writer.WriteString(directive + " ")
if err != nil {
return err
}
_, err = n.writer.WriteString(name)
if err != nil {
return err
}
_, err = n.writer.WriteString("\n")
if err != nil {
return err
}
return nil
}
type ninjaWriterWithWrap struct {
*ninjaWriter
maxLineLen int
@ -237,25 +296,25 @@ func (n *ninjaWriterWithWrap) writeString(s string, space bool) {
}
if n.writtenLen+len(s)+spaceLen > n.maxLineLen {
_, n.err = io.WriteString(n.writer, " $\n")
_, n.err = n.writer.WriteString(" $\n")
if n.err != nil {
return
}
_, n.err = io.WriteString(n.writer, indentString[:indentWidth*2])
_, n.err = n.writer.WriteString(indentString[:indentWidth*2])
if n.err != nil {
return
}
n.writtenLen = indentWidth * 2
s = strings.TrimLeftFunc(s, unicode.IsSpace)
} else if space {
_, n.err = io.WriteString(n.writer, " ")
_, n.err = n.writer.WriteString(" ")
if n.err != nil {
return
}
n.writtenLen++
}
_, n.err = io.WriteString(n.writer, s)
_, n.err = n.writer.WriteString(s)
n.writtenLen += len(s)
}
@ -271,6 +330,6 @@ func (n *ninjaWriterWithWrap) Flush() error {
if n.err != nil {
return n.err
}
_, err := io.WriteString(n.writer, "\n")
_, err := n.writer.WriteString("\n")
return err
}