From 8f8a393b40535b02f358196f5fbdb855c92bb0fa Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 15 Oct 2009 09:29:31 -0700 Subject: [PATCH] bug fix: do not modify (string) literals in any way even if they contain tabs or line breaks R=rsc DELTA=57 (19 added, 12 deleted, 26 changed) OCL=35749 CL=35770 --- src/pkg/go/printer/printer.go | 63 ++++++++++--------- src/pkg/go/printer/testdata/expressions.go | 10 +-- .../go/printer/testdata/expressions.golden | 10 +-- 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index a9ae51b51e..36400ca42d 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -50,6 +50,7 @@ const ( var ( + esc = []byte{tabwriter.Escape}; htab = []byte{'\t'}; htabs = [...]byte{'\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t'}; newlines = [...]byte{'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; // more than maxNewlines @@ -81,6 +82,7 @@ type printer struct { // Current state written int; // number of bytes written indent int; // current indentation + escape bool; // true if in escape sequence // Buffered whitespace buffer []whiteSpace; @@ -125,17 +127,11 @@ func (p *printer) write0(data []byte) { } -type writeMode uint; -const ( - writeRaw writeMode = 1< maxNewlines { n = maxNewlines; } - p.write(newlines[0 : n], 0); + p.write(newlines[0 : n]); } } @@ -214,11 +213,11 @@ func (p *printer) writeNewlines(n int) { // writeItem writes data at position pos. data is the text corresponding to // a single lexical token, but may also be comment text. pos is the actual // (or at least very accurately estimated) position of the data in the original -// source text. The data may be tagged, depending on p.mode and the mode +// source text. The data may be tagged, depending on p.mode and the setLineTag // parameter. writeItem updates p.last to the position immediately following // the data. // -func (p *printer) writeItem(pos token.Position, data []byte, mode writeMode) { +func (p *printer) writeItem(pos token.Position, data []byte, setLineTag bool) { p.pos = pos; if debug { // do not update p.pos - use write0 @@ -226,7 +225,7 @@ func (p *printer) writeItem(pos token.Position, data []byte, mode writeMode) { } if p.mode & GenHTML != 0 { // no html-escaping and no p.pos update for tags - use write0 - if mode & setLineTag != 0 && pos.Line > p.lastTaggedLine { + if setLineTag && pos.Line > p.lastTaggedLine { // id's must be unique within a document: set // line tag only if line number has increased // (note: for now write complete start and end @@ -240,14 +239,14 @@ func (p *printer) writeItem(pos token.Position, data []byte, mode writeMode) { p.write0(strings.Bytes(p.tag.start)); p.tag.start = ""; // tag consumed } - p.write(data, mode); + p.write(data); // write end tag, if any if p.tag.end != "" { p.write0(strings.Bytes(p.tag.end)); p.tag.end = ""; // tag consumed } } else { - p.write(data, mode); + p.write(data); } p.last = p.pos; } @@ -295,7 +294,7 @@ func (p *printer) writeCommentPrefix(line int, isFirst bool) { } // make sure there is at least one tab if !hasTab { - p.write(htab, 0); + p.write(htab); } } else { @@ -352,7 +351,7 @@ func (p *printer) writeComment(comment *ast.Comment) { } // write comment - p.writeItem(comment.Pos(), text, 0); + p.writeItem(comment.Pos(), text, false); } @@ -382,7 +381,7 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) { // make sure we have a line break if needsLinebreak { - p.write([]byte{'\n'}, 0); + p.write([]byte{'\n'}); } } @@ -441,7 +440,7 @@ func (p *printer) writeWhitespace(n int) { fallthrough; default: data[0] = byte(ch); - p.write(&data, 0); + p.write(&data); } } @@ -470,7 +469,7 @@ func (p *printer) writeWhitespace(n int) { // printed, followed by the actual token. // func (p *printer) print(args ...) { - var mode writeMode; + setLineTag := false; v := reflect.NewValue(args).(*reflect.StructValue); for i := 0; i < v.NumField(); i++ { f := v.Field(i); @@ -491,10 +490,6 @@ func (p *printer) print(args ...) { p.buffer[i] = x; case []byte: data = x; - // do not modify multi-line `` strings! - if len(x) > 0 && x[0] == '`' && x[len(x)-1] == '`' { - mode |= writeRaw; - } case string: data = strings.Bytes(x); case token.Token: @@ -507,7 +502,7 @@ func (p *printer) print(args ...) { pos := token.Position(x); if pos.IsValid() { next = pos; // accurate position of next item - mode |= setLineTag; + setLineTag = true; } case htmlTag: p.tag = x; // tag surrounding next item @@ -524,8 +519,8 @@ func (p *printer) print(args ...) { // at the end of a file) p.writeNewlines(next.Line - p.pos.Line); - p.writeItem(next, data, mode); - mode = 0; + p.writeItem(next, data, setLineTag); + setLineTag = false; } } } @@ -976,8 +971,16 @@ func (p *printer) expr1(expr ast.Expr, prec1 int) (optSemi bool) { } case *ast.BasicLit: - // TODO(gri): string contents must remain unchanged through tabwriter! - p.print(x.Value); + if p.mode & RawFormat == 0 { + // tabwriter is used: escape all literals + // so they pass through unchanged + // (note that a legal Go program cannot contain an '\xff' byte in + // literal source text since '\xff' is not a legal byte in correct + // UTF-8 encoded text) + p.print(esc, x.Value, esc); + } else { + p.print(x.Value); + } case *ast.StringList: p.stringList(x.Strings); diff --git a/src/pkg/go/printer/testdata/expressions.go b/src/pkg/go/printer/testdata/expressions.go index 29619f496d..f771bfcee8 100644 --- a/src/pkg/go/printer/testdata/expressions.go +++ b/src/pkg/go/printer/testdata/expressions.go @@ -105,10 +105,13 @@ func _() { func _() { - // do not modify `` strings + // do not modify literals + _ = "tab1 tab2 tab3 end"; // string contains 3 tabs + _ = "tab1 tab2 tab3 end"; // same string with 3 blanks - may be unaligned because editors see tabs in strings + _ = ""; // this comment should be aligned with the one on the previous line _ = ``; _ = ` -`; // TODO(gri): fix line breaks here +`; _ = `foo bar`; } @@ -138,8 +141,7 @@ func _() { b < a; _ = "1234567890" "1234567890"; - // TODO(gri): add more test cases - // TODO(gri): these comments should be indented + // this comment should be indented } diff --git a/src/pkg/go/printer/testdata/expressions.golden b/src/pkg/go/printer/testdata/expressions.golden index 259a5c31f4..1c92c4914e 100644 --- a/src/pkg/go/printer/testdata/expressions.golden +++ b/src/pkg/go/printer/testdata/expressions.golden @@ -105,10 +105,13 @@ func _() { func _() { - // do not modify `` strings + // do not modify literals + _ = "tab1 tab2 tab3 end"; // string contains 3 tabs + _ = "tab1 tab2 tab3 end"; // same string with 3 blanks - may be unaligned because editors see tabs in strings + _ = ""; // this comment should be aligned with the one on the previous line _ = ``; _ = ` -`; // TODO(gri): fix line breaks here +`; _ = `foo bar`; } @@ -138,8 +141,7 @@ func _() { b < a; _ = "1234567890" "1234567890"; - // TODO(gri): add more test cases - // TODO(gri): these comments should be indented + // this comment should be indented } -- 2.50.0