OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package formatter | 5 package formatter |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "mojom/mojom_parser/lexer" | 10 "mojom/mojom_parser/lexer" |
(...skipping 21 matching lines...) Expand all Loading... |
32 // buffer is the buffer to which the write.* methods write the pretty-pr
inted | 32 // buffer is the buffer to which the write.* methods write the pretty-pr
inted |
33 // mojom file element. | 33 // mojom file element. |
34 buffer bytes.Buffer | 34 buffer bytes.Buffer |
35 | 35 |
36 // indentSize is the current size of the indentation in number of space
runes. | 36 // indentSize is the current size of the indentation in number of space
runes. |
37 indentSize int | 37 indentSize int |
38 | 38 |
39 // eolComment is the comment to be printed at the end of the current lin
e. | 39 // eolComment is the comment to be printed at the end of the current lin
e. |
40 eolComment *lexer.Token | 40 eolComment *lexer.Token |
41 | 41 |
42 » // lineLength is the number of runes that have been written to the curre
nt line. | 42 » // linePos is the number of runes that have been written to the current
line. |
43 » lineLength int | 43 » linePos int |
| 44 |
| 45 » // maxLineLength is the maximum number of runes that should be printed o
n a line. |
| 46 » // A negative maxLineLength indicates no maximum line length should be e
nforced. |
| 47 » // This is currently only used to decide when to break up a method on di
fferent lines. |
| 48 » maxLineLength int |
44 } | 49 } |
45 | 50 |
46 // newPrinter is a constructor for printer. | 51 // newPrinter is a constructor for printer. |
47 func newPrinter() (p *printer) { | 52 func newPrinter() (p *printer) { |
48 p = new(printer) | 53 p = new(printer) |
| 54 p.maxLineLength = 100 |
49 return | 55 return |
50 } | 56 } |
51 | 57 |
52 // result returns the pretty-printed version of what was given to the printer. | 58 // result returns the pretty-printed version of what was given to the printer. |
53 // Usually, this is a pretty-printed MojomFile. | 59 // Usually, this is a pretty-printed MojomFile. |
54 func (p *printer) result() string { | 60 func (p *printer) result() string { |
55 return p.buffer.String() | 61 return p.buffer.String() |
56 } | 62 } |
57 | 63 |
58 // writeMojomFile is the entry point of the pretty printer. | 64 // writeMojomFile is the entry point of the pretty printer. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 p.write("enum ") | 173 p.write("enum ") |
168 p.writeDeclaredObjectsContainer(mojomEnum) | 174 p.writeDeclaredObjectsContainer(mojomEnum) |
169 } | 175 } |
170 | 176 |
171 func (p *printer) writeMojomInterface(mojomInterface *mojom.MojomInterface) { | 177 func (p *printer) writeMojomInterface(mojomInterface *mojom.MojomInterface) { |
172 p.write("interface ") | 178 p.write("interface ") |
173 p.writeDeclaredObjectsContainer(mojomInterface) | 179 p.writeDeclaredObjectsContainer(mojomInterface) |
174 } | 180 } |
175 | 181 |
176 func (p *printer) writeMojomMethod(mojomMethod *mojom.MojomMethod) { | 182 func (p *printer) writeMojomMethod(mojomMethod *mojom.MojomMethod) { |
| 183 splitResponse := false |
| 184 if p.maxLineLength > 0 { |
| 185 scratch := newPrinter() |
| 186 scratch.maxLineLength = -1 |
| 187 scratch.writeMojomMethod(mojomMethod) |
| 188 if len(scratch.result())+p.lineLength() > p.maxLineLength { |
| 189 splitResponse = true |
| 190 } |
| 191 } |
| 192 |
177 p.write(mojomMethod.NameToken().Text) | 193 p.write(mojomMethod.NameToken().Text) |
178 if mojomMethod.DeclaredOrdinal() >= 0 { | 194 if mojomMethod.DeclaredOrdinal() >= 0 { |
179 p.writef("@%v", mojomMethod.DeclaredOrdinal()) | 195 p.writef("@%v", mojomMethod.DeclaredOrdinal()) |
180 } | 196 } |
181 | 197 |
182 totalParams := len(mojomMethod.Parameters.Fields) | |
183 if mojomMethod.ResponseParameters != nil { | |
184 totalParams += len(mojomMethod.ResponseParameters.Fields) | |
185 } | |
186 | |
187 p.writeMethodParams(mojomMethod.Parameters) | 198 p.writeMethodParams(mojomMethod.Parameters) |
188 if mojomMethod.ResponseParameters != nil { | 199 if mojomMethod.ResponseParameters != nil { |
189 » » // TODO(azani): Actually enforce a line length limit instead. | 200 » » if splitResponse { |
190 » » if totalParams > 2 { | |
191 p.nl() | 201 p.nl() |
192 p.write(" ") | 202 p.write(" ") |
193 } | 203 } |
194 p.write(" => ") | 204 p.write(" => ") |
195 p.writeMethodParams(mojomMethod.ResponseParameters) | 205 p.writeMethodParams(mojomMethod.ResponseParameters) |
196 } | 206 } |
197 p.write(";") | 207 p.write(";") |
198 p.writeRightComments(mojomMethod) | 208 p.writeRightComments(mojomMethod) |
199 } | 209 } |
200 | 210 |
201 // writeMethodParams writes the pretty-printed method parameters represented by | 211 // writeMethodParams writes the pretty-printed method parameters represented by |
202 // a MojomStruct. | 212 // a MojomStruct. |
203 func (p *printer) writeMethodParams(params *mojom.MojomStruct) { | 213 func (p *printer) writeMethodParams(params *mojom.MojomStruct) { |
| 214 ownLine := false |
| 215 if p.maxLineLength > 0 { |
| 216 scratch := newPrinter() |
| 217 scratch.maxLineLength = -1 |
| 218 scratch.writeMethodParams(params) |
| 219 if len(scratch.result())+p.lineLength() > p.maxLineLength { |
| 220 ownLine = true |
| 221 } |
| 222 } |
204 p.write("(") | 223 p.write("(") |
205 declaredObjects := params.GetDeclaredObjects() | 224 declaredObjects := params.GetDeclaredObjects() |
206 | 225 |
207 » // TODO(azani): Actually enforce a line length limit instead. | 226 » extraIndent := p.lineLength() - p.indentSize |
208 » ownLine := len(declaredObjects) > 2 | |
209 » extraIndent := p.lineLength - p.indentSize | |
210 if ownLine { | 227 if ownLine { |
211 p.indentSize += extraIndent | 228 p.indentSize += extraIndent |
212 } | 229 } |
213 | 230 |
214 for i, param := range declaredObjects { | 231 for i, param := range declaredObjects { |
215 p.writeMethodParam(param.(*mojom.StructField)) | 232 p.writeMethodParam(param.(*mojom.StructField)) |
216 if i < len(declaredObjects)-1 { | 233 if i < len(declaredObjects)-1 { |
217 p.write(",") | 234 p.write(",") |
218 if ownLine { | 235 if ownLine { |
219 p.nl() | 236 p.nl() |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 | 627 |
611 // write writes the provided string to the buffer. | 628 // write writes the provided string to the buffer. |
612 // If nothing has been written yet on the current line write also writes the | 629 // If nothing has been written yet on the current line write also writes the |
613 // current indentation level. | 630 // current indentation level. |
614 func (p *printer) write(s string) { | 631 func (p *printer) write(s string) { |
615 if strings.ContainsRune(s, '\n') { | 632 if strings.ContainsRune(s, '\n') { |
616 panic(fmt.Sprintf("Only the nl method can write a new line: %q",
s)) | 633 panic(fmt.Sprintf("Only the nl method can write a new line: %q",
s)) |
617 } | 634 } |
618 | 635 |
619 // We only print the indentation if the line is not empty. | 636 // We only print the indentation if the line is not empty. |
620 » if p.lineLength == 0 { | 637 » if p.linePos == 0 { |
621 p.buffer.WriteString(strings.Repeat(" ", p.indentSize)) | 638 p.buffer.WriteString(strings.Repeat(" ", p.indentSize)) |
622 » » p.lineLength += p.indentSize | 639 » » p.linePos += p.indentSize |
623 } | 640 } |
624 » p.lineLength += len(s) | 641 » p.linePos += len(s) |
625 p.buffer.WriteString(s) | 642 p.buffer.WriteString(s) |
626 } | 643 } |
627 | 644 |
628 // nl writes a new line. Before writing the new line, nl writes the last | 645 // nl writes a new line. Before writing the new line, nl writes the last |
629 // comment on the line. | 646 // comment on the line. |
630 func (p *printer) nl() { | 647 func (p *printer) nl() { |
631 // Before going to the next line, print the last comment on the line. | 648 // Before going to the next line, print the last comment on the line. |
632 if p.eolComment != nil { | 649 if p.eolComment != nil { |
633 p.writef(" %s", p.eolComment.Text) | 650 p.writef(" %s", p.eolComment.Text) |
634 p.eolComment = nil | 651 p.eolComment = nil |
635 } | 652 } |
636 | 653 |
637 p.buffer.WriteString("\n") | 654 p.buffer.WriteString("\n") |
638 » p.lineLength = 0 | 655 » p.linePos = 0 |
639 } | 656 } |
640 | 657 |
641 func (p *printer) incIndent() { | 658 func (p *printer) incIndent() { |
642 p.indentSize += 2 | 659 p.indentSize += 2 |
643 } | 660 } |
644 | 661 |
645 func (p *printer) decIndent() { | 662 func (p *printer) decIndent() { |
646 p.indentSize -= 2 | 663 p.indentSize -= 2 |
647 if p.indentSize < 0 { | 664 if p.indentSize < 0 { |
648 panic("The printer is attempting to use negative indentation!") | 665 panic("The printer is attempting to use negative indentation!") |
649 } | 666 } |
650 } | 667 } |
651 | 668 |
652 // setEolComment sets the comment that is to be printed at the end of the curren
t line. | 669 // setEolComment sets the comment that is to be printed at the end of the curren
t line. |
653 // The last comment on the line is not necessarily associated with the last | 670 // The last comment on the line is not necessarily associated with the last |
654 // element on the line. So when the last comment is found, we record that | 671 // element on the line. So when the last comment is found, we record that |
655 // comment so we may print it right before going to the next line. | 672 // comment so we may print it right before going to the next line. |
656 func (p *printer) setEolComment(comment lexer.Token) { | 673 func (p *printer) setEolComment(comment lexer.Token) { |
657 if p.eolComment != nil { | 674 if p.eolComment != nil { |
658 panic("There is space for only one comment at the end of the lin
e!") | 675 panic("There is space for only one comment at the end of the lin
e!") |
659 } | 676 } |
660 | 677 |
661 if comment.Kind != lexer.SingleLineComment { | 678 if comment.Kind != lexer.SingleLineComment { |
662 panic("Only SingleLineComments need to be handled specially at t
he end of line.") | 679 panic("Only SingleLineComments need to be handled specially at t
he end of line.") |
663 } | 680 } |
664 | 681 |
665 p.eolComment = &comment | 682 p.eolComment = &comment |
666 } | 683 } |
667 | 684 |
| 685 // lineLength returns the length of the line so far. If nothing has been written |
| 686 // to the line yet, it returns the indent size. |
| 687 // The purpose of lineLenght is to answer the question: If I write something now |
| 688 // how far on the current line will it be written? |
| 689 func (p *printer) lineLength() int { |
| 690 if p.linePos == 0 { |
| 691 return p.indentSize |
| 692 } |
| 693 return p.linePos |
| 694 } |
| 695 |
668 // Standalone utilities that do not operate on the buffer. | 696 // Standalone utilities that do not operate on the buffer. |
669 | 697 |
670 // isNewBlock determines if an empty line should be printed above the element | 698 // isNewBlock determines if an empty line should be printed above the element |
671 // under consideration. The purpose is to respect user-intention to separate | 699 // under consideration. The purpose is to respect user-intention to separate |
672 // elements in a mojom file. | 700 // elements in a mojom file. |
673 // | 701 // |
674 // If the element has attributes, and the first "comment" attached above the | 702 // If the element has attributes, and the first "comment" attached above the |
675 // attributes is an empty line, the element is a new block. | 703 // attributes is an empty line, the element is a new block. |
676 // If the element has no attributes and the first "comment" attached above the | 704 // If the element has no attributes and the first "comment" attached above the |
677 // element itself is an empty line, the element is a new block. | 705 // element itself is an empty line, the element is a new block. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 | 768 |
741 // See sort.Interface. | 769 // See sort.Interface. |
742 func (ifs *importedFilesSorter) Less(i, j int) bool { | 770 func (ifs *importedFilesSorter) Less(i, j int) bool { |
743 return ifs.imports[i].SpecifiedName < ifs.imports[j].SpecifiedName | 771 return ifs.imports[i].SpecifiedName < ifs.imports[j].SpecifiedName |
744 } | 772 } |
745 | 773 |
746 // See sort.Interface. | 774 // See sort.Interface. |
747 func (ifs *importedFilesSorter) Swap(i, j int) { | 775 func (ifs *importedFilesSorter) Swap(i, j int) { |
748 ifs.imports[i], ifs.imports[j] = ifs.imports[j], ifs.imports[i] | 776 ifs.imports[i], ifs.imports[j] = ifs.imports[j], ifs.imports[i] |
749 } | 777 } |
OLD | NEW |