Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(744)

Side by Side Diff: src/pkg/go/printer/printer.go

Issue 3050041: code review 3050041: go/ast: use token.Pos instead of token.Position; adjus... (Closed)
Patch Set: code review 3050041: go/ast: use token.Pos instead of token.Position; adjus... Created 14 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/go/printer/nodes.go ('k') | src/pkg/go/printer/printer_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // The printer package implements printing of AST nodes. 5 // The printer package implements printing of AST nodes.
6 package printer 6 package printer
7 7
8 import ( 8 import (
9 "bytes" 9 "bytes"
10 "fmt" 10 "fmt"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 56
57 // Use ignoreMultiLine if the multiLine information is not important. 57 // Use ignoreMultiLine if the multiLine information is not important.
58 var ignoreMultiLine = new(bool) 58 var ignoreMultiLine = new(bool)
59 59
60 60
61 type printer struct { 61 type printer struct {
62 // Configuration (does not change after initialization) 62 // Configuration (does not change after initialization)
63 output io.Writer 63 output io.Writer
64 Config 64 Config
65 fset *token.FileSet
65 errors chan os.Error 66 errors chan os.Error
66 67
67 // Current state 68 // Current state
68 nesting int // nesting level (0: top-level (package scope), >0: functions/decls.) 69 nesting int // nesting level (0: top-level (package scope), >0: functions/decls.)
69 written int // number of bytes written 70 written int // number of bytes written
70 indent int // current indentation 71 indent int // current indentation
71 escape bool // true if in escape sequence 72 escape bool // true if in escape sequence
72 lastTok token.Token // the last token printed (token.ILLEGAL if it's whi tespace) 73 lastTok token.Token // the last token printed (token.ILLEGAL if it's whi tespace)
73 74
74 // Buffered whitespace 75 // Buffered whitespace
(...skipping 12 matching lines...) Expand all
87 // HTML support 88 // HTML support
88 lastTaggedLine int // last line for which a line tag was written 89 lastTaggedLine int // last line for which a line tag was written
89 90
90 // The list of all source comments, in order of appearance. 91 // The list of all source comments, in order of appearance.
91 comments []*ast.CommentGroup // may be nil 92 comments []*ast.CommentGroup // may be nil
92 cindex int // current comment index 93 cindex int // current comment index
93 useNodeComments bool // if not set, ignore lead and line comments of nodes 94 useNodeComments bool // if not set, ignore lead and line comments of nodes
94 } 95 }
95 96
96 97
97 func (p *printer) init(output io.Writer, cfg *Config) { 98 func (p *printer) init(output io.Writer, cfg *Config, fset *token.FileSet) {
98 p.output = output 99 p.output = output
99 p.Config = *cfg 100 p.Config = *cfg
101 p.fset = fset
100 p.errors = make(chan os.Error) 102 p.errors = make(chan os.Error)
101 p.buffer = make([]whiteSpace, 0, 16) // whitespace sequences are short 103 p.buffer = make([]whiteSpace, 0, 16) // whitespace sequences are short
102 } 104 }
103 105
104 106
105 func (p *printer) internalError(msg ...interface{}) { 107 func (p *printer) internalError(msg ...interface{}) {
106 if debug { 108 if debug {
107 fmt.Print(p.pos.String() + ": ") 109 fmt.Print(p.pos.String() + ": ")
108 fmt.Println(msg...) 110 fmt.Println(msg...)
109 panic("go/printer") 111 panic("go/printer")
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 } 591 }
590 } 592 }
591 } 593 }
592 594
593 595
594 func (p *printer) writeComment(comment *ast.Comment) { 596 func (p *printer) writeComment(comment *ast.Comment) {
595 text := comment.Text 597 text := comment.Text
596 598
597 // shortcut common case of //-style comments 599 // shortcut common case of //-style comments
598 if text[1] == '/' { 600 if text[1] == '/' {
599 » » p.writeCommentLine(comment, comment.Pos(), text) 601 » » p.writeCommentLine(comment, p.fset.Position(comment.Pos()), text )
600 return 602 return
601 } 603 }
602 604
603 // for /*-style comments, print line by line and let the 605 // for /*-style comments, print line by line and let the
604 // write function take care of the proper indentation 606 // write function take care of the proper indentation
605 lines := split(text) 607 lines := split(text)
606 stripCommonPrefix(lines) 608 stripCommonPrefix(lines)
607 609
608 // write comment lines, separated by formfeed, 610 // write comment lines, separated by formfeed,
609 // without a line break after the last line 611 // without a line break after the last line
610 linebreak := formfeeds[0:1] 612 linebreak := formfeeds[0:1]
611 » pos := comment.Pos() 613 » pos := p.fset.Position(comment.Pos())
612 for i, line := range lines { 614 for i, line := range lines {
613 if i > 0 { 615 if i > 0 {
614 p.write(linebreak) 616 p.write(linebreak)
615 pos = p.pos 617 pos = p.pos
616 } 618 }
617 if len(line) > 0 { 619 if len(line) > 0 {
618 p.writeCommentLine(comment, pos, line) 620 p.writeCommentLine(comment, pos, line)
619 } 621 }
620 } 622 }
621 } 623 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 // intersperseComments consumes all comments that appear before the next token 664 // intersperseComments consumes all comments that appear before the next token
663 // tok and prints it together with the buffered whitespace (i.e., the whitespace 665 // tok and prints it together with the buffered whitespace (i.e., the whitespace
664 // that needs to be written before the next token). A heuristic is used to mix 666 // that needs to be written before the next token). A heuristic is used to mix
665 // the comments and whitespace. intersperseComments returns true if a pending 667 // the comments and whitespace. intersperseComments returns true if a pending
666 // formfeed was dropped from the whitespace buffer. 668 // formfeed was dropped from the whitespace buffer.
667 // 669 //
668 func (p *printer) intersperseComments(next token.Position, tok token.Token) (dro ppedFF bool) { 670 func (p *printer) intersperseComments(next token.Position, tok token.Token) (dro ppedFF bool) {
669 var last *ast.Comment 671 var last *ast.Comment
670 for ; p.commentBefore(next); p.cindex++ { 672 for ; p.commentBefore(next); p.cindex++ {
671 for _, c := range p.comments[p.cindex].List { 673 for _, c := range p.comments[p.cindex].List {
672 » » » p.writeCommentPrefix(c.Pos(), next, last == nil, tok.IsK eyword()) 674 » » » p.writeCommentPrefix(p.fset.Position(c.Pos()), next, las t == nil, tok.IsKeyword())
673 p.writeComment(c) 675 p.writeComment(c)
674 last = c 676 last = c
675 } 677 }
676 } 678 }
677 679
678 if last != nil { 680 if last != nil {
679 » » if last.Text[1] == '*' && last.Pos().Line == next.Line { 681 » » if last.Text[1] == '*' && p.fset.Position(last.Pos()).Line == ne xt.Line {
680 // the last comment is a /*-style comment and the next i tem 682 // the last comment is a /*-style comment and the next i tem
681 // follows on the same line: separate with an extra blan k 683 // follows on the same line: separate with an extra blan k
682 p.write([]byte{' '}) 684 p.write([]byte{' '})
683 } 685 }
684 // ensure that there is a newline after a //-style comment 686 // ensure that there is a newline after a //-style comment
685 // or if we are before a closing '}' or at the end of a file 687 // or if we are before a closing '}' or at the end of a file
686 return p.writeCommentSuffix(last.Text[1] == '/' || tok == token. RBRACE || tok == token.EOF) 688 return p.writeCommentSuffix(last.Text[1] == '/' || tok == token. RBRACE || tok == token.EOF)
687 } 689 }
688 690
689 // no comment was written - we should never reach here since 691 // no comment was written - we should never reach here since
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 } 837 }
836 p.buffer = p.buffer[0:1] 838 p.buffer = p.buffer[0:1]
837 p.buffer[0] = ' ' 839 p.buffer[0] = ' '
838 } 840 }
839 if p.Styler != nil { 841 if p.Styler != nil {
840 data, tag = p.Styler.Token(x) 842 data, tag = p.Styler.Token(x)
841 } else { 843 } else {
842 data = []byte(s) 844 data = []byte(s)
843 } 845 }
844 tok = x 846 tok = x
845 » » case token.Position: 847 » » case token.Pos:
846 if x.IsValid() { 848 if x.IsValid() {
847 » » » » next = x // accurate position of next item 849 » » » » next = p.fset.Position(x) // accurate position o f next item
848 } 850 }
849 tok = p.lastTok 851 tok = p.lastTok
850 default: 852 default:
851 fmt.Fprintf(os.Stderr, "print: unsupported argument type %T\n", f) 853 fmt.Fprintf(os.Stderr, "print: unsupported argument type %T\n", f)
852 panic("go/printer type") 854 panic("go/printer type")
853 } 855 }
854 p.lastTok = tok 856 p.lastTok = tok
855 p.pos = next 857 p.pos = next
856 858
857 if data != nil { 859 if data != nil {
858 droppedFF := p.flush(next, tok) 860 droppedFF := p.flush(next, tok)
859 861
860 // intersperse extra newlines if present in the source 862 // intersperse extra newlines if present in the source
861 // (don't do this in flush as it will cause extra newlin es 863 // (don't do this in flush as it will cause extra newlin es
862 // at the end of a file) - use formfeeds if we dropped o ne 864 // at the end of a file) - use formfeeds if we dropped o ne
863 // before 865 // before
864 p.writeNewlines(next.Line-p.pos.Line, droppedFF) 866 p.writeNewlines(next.Line-p.pos.Line, droppedFF)
865 867
866 p.writeItem(next, data, tag) 868 p.writeItem(next, data, tag)
867 } 869 }
868 } 870 }
869 } 871 }
870 872
871 873
872 // commentBefore returns true iff the current comment occurs 874 // commentBefore returns true iff the current comment occurs
873 // before the next position in the source code. 875 // before the next position in the source code.
874 // 876 //
875 func (p *printer) commentBefore(next token.Position) bool { 877 func (p *printer) commentBefore(next token.Position) bool {
876 » return p.cindex < len(p.comments) && p.comments[p.cindex].List[0].Pos(). Offset < next.Offset 878 » return p.cindex < len(p.comments) && p.fset.Position(p.comments[p.cindex ].List[0].Pos()).Offset < next.Offset
877 } 879 }
878 880
879 881
880 // Flush prints any pending comments and whitespace occuring 882 // Flush prints any pending comments and whitespace occuring
881 // textually before the position of the next token tok. Flush 883 // textually before the position of the next token tok. Flush
882 // returns true if a pending formfeed character was dropped 884 // returns true if a pending formfeed character was dropped
883 // from the whitespace buffer as a result of interspersing 885 // from the whitespace buffer as a result of interspersing
884 // comments. 886 // comments.
885 // 887 //
886 func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) { 888 func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 // A Config node controls the output of Fprint. 1021 // A Config node controls the output of Fprint.
1020 type Config struct { 1022 type Config struct {
1021 Mode uint // default: 0 1023 Mode uint // default: 0
1022 Tabwidth int // default: 8 1024 Tabwidth int // default: 8
1023 Styler Styler // default: nil 1025 Styler Styler // default: nil
1024 } 1026 }
1025 1027
1026 1028
1027 // Fprint "pretty-prints" an AST node to output and returns the number 1029 // Fprint "pretty-prints" an AST node to output and returns the number
1028 // of bytes written and an error (if any) for a given configuration cfg. 1030 // of bytes written and an error (if any) for a given configuration cfg.
1031 // Position information is interpreted relative to the file set fset.
1029 // The node type must be *ast.File, or assignment-compatible to ast.Expr, 1032 // The node type must be *ast.File, or assignment-compatible to ast.Expr,
1030 // ast.Decl, ast.Spec, or ast.Stmt. 1033 // ast.Decl, ast.Spec, or ast.Stmt.
1031 // 1034 //
1032 func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { 1035 func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{ }) (int, os.Error) {
1033 // redirect output through a trimmer to eliminate trailing whitespace 1036 // redirect output through a trimmer to eliminate trailing whitespace
1034 // (Input to a tabwriter must be untrimmed since trailing tabs provide 1037 // (Input to a tabwriter must be untrimmed since trailing tabs provide
1035 // formatting information. The tabwriter could provide trimming 1038 // formatting information. The tabwriter could provide trimming
1036 // functionality but no tabwriter is used when RawFormat is set.) 1039 // functionality but no tabwriter is used when RawFormat is set.)
1037 output = &trimmer{output: output} 1040 output = &trimmer{output: output}
1038 1041
1039 // setup tabwriter if needed and redirect output 1042 // setup tabwriter if needed and redirect output
1040 var tw *tabwriter.Writer 1043 var tw *tabwriter.Writer
1041 if cfg.Mode&RawFormat == 0 { 1044 if cfg.Mode&RawFormat == 0 {
1042 minwidth := cfg.Tabwidth 1045 minwidth := cfg.Tabwidth
(...skipping 11 matching lines...) Expand all
1054 minwidth = 0 1057 minwidth = 0
1055 twmode |= tabwriter.TabIndent 1058 twmode |= tabwriter.TabIndent
1056 } 1059 }
1057 1060
1058 tw = tabwriter.NewWriter(output, minwidth, cfg.Tabwidth, 1, padc har, twmode) 1061 tw = tabwriter.NewWriter(output, minwidth, cfg.Tabwidth, 1, padc har, twmode)
1059 output = tw 1062 output = tw
1060 } 1063 }
1061 1064
1062 // setup printer and print node 1065 // setup printer and print node
1063 var p printer 1066 var p printer
1064 » p.init(output, cfg) 1067 » p.init(output, cfg, fset)
1065 go func() { 1068 go func() {
1066 switch n := node.(type) { 1069 switch n := node.(type) {
1067 case ast.Expr: 1070 case ast.Expr:
1068 p.nesting = 1 1071 p.nesting = 1
1069 p.useNodeComments = true 1072 p.useNodeComments = true
1070 p.expr(n, ignoreMultiLine) 1073 p.expr(n, ignoreMultiLine)
1071 case ast.Stmt: 1074 case ast.Stmt:
1072 p.nesting = 1 1075 p.nesting = 1
1073 p.useNodeComments = true 1076 p.useNodeComments = true
1074 // A labeled statement will un-indent to position the 1077 // A labeled statement will un-indent to position the
(...skipping 29 matching lines...) Expand all
1104 tw.Flush() // ignore errors 1107 tw.Flush() // ignore errors
1105 } 1108 }
1106 1109
1107 return p.written, err 1110 return p.written, err
1108 } 1111 }
1109 1112
1110 1113
1111 // Fprint "pretty-prints" an AST node to output. 1114 // Fprint "pretty-prints" an AST node to output.
1112 // It calls Config.Fprint with default settings. 1115 // It calls Config.Fprint with default settings.
1113 // 1116 //
1114 func Fprint(output io.Writer, node interface{}) os.Error { 1117 func Fprint(output io.Writer, fset *token.FileSet, node interface{}) os.Error {
1115 » _, err := (&Config{Tabwidth: 8}).Fprint(output, node) // don't care abou t number of bytes written 1118 » _, err := (&Config{Tabwidth: 8}).Fprint(output, fset, node) // don't car e about number of bytes written
1116 return err 1119 return err
1117 } 1120 }
OLDNEW
« no previous file with comments | « src/pkg/go/printer/nodes.go ('k') | src/pkg/go/printer/printer_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b