Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: mojom/mojom_parser/formatter/printer.go

Issue 1766463002: Implement formatting exclusion. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 28 matching lines...) Expand all
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 // linePos is the number of runes that have been written to the current line. 42 // linePos is the number of runes that have been written to the current line.
43 linePos int 43 linePos int
44 44
45 // maxLineLength is the maximum number of runes that should be printed o n a line. 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. 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. 47 // This is currently only used to decide when to break up a method on di fferent lines.
48 maxLineLength int 48 maxLineLength int
49
50 // mojomFile is the file being printed.
51 mojomFile *mojom.MojomFile
52
53 // noFormat indicates we are in a block where formatting has been disabl ed.
54 noFormat bool
55
56 // token that begins a block where formatting has been disabled.
57 noFormatStart lexer.Token
58
59 // indentSize at the time noFormat is set.
60 noFormatStartIndent int
49 } 61 }
50 62
51 // newPrinter is a constructor for printer. 63 // newPrinter is a constructor for printer.
52 func newPrinter() (p *printer) { 64 func newPrinter() (p *printer) {
53 p = new(printer) 65 p = new(printer)
54 p.maxLineLength = 100 66 p.maxLineLength = 100
55 return 67 return
56 } 68 }
57 69
58 // result returns the pretty-printed version of what was given to the printer. 70 // result returns the pretty-printed version of what was given to the printer.
59 // Usually, this is a pretty-printed MojomFile. 71 // Usually, this is a pretty-printed MojomFile.
60 func (p *printer) result() string { 72 func (p *printer) result() string {
61 return p.buffer.String() 73 return p.buffer.String()
62 } 74 }
63 75
64 // writeMojomFile is the entry point of the pretty printer. 76 // writeMojomFile is the entry point of the pretty printer.
65 // It takes a mojom file with attached comments and creates a pretty-printed 77 // It takes a mojom file with attached comments and creates a pretty-printed
66 // representation. 78 // representation.
67 func (p *printer) writeMojomFile(mojomFile *mojom.MojomFile) { 79 func (p *printer) writeMojomFile(mojomFile *mojom.MojomFile) {
68 if p.used { 80 if p.used {
69 panic("A printer can only be used once!") 81 panic("A printer can only be used once!")
70 } 82 }
71 p.used = true 83 p.used = true
84 p.mojomFile = mojomFile
72 85
73 p.writeAttributes(mojomFile.Attributes) 86 p.writeAttributes(mojomFile.Attributes)
74 p.writeModuleNamespace(mojomFile.ModuleNamespace) 87 p.writeModuleNamespace(mojomFile.ModuleNamespace)
75 88
76 if len(mojomFile.Imports) > 0 { 89 if len(mojomFile.Imports) > 0 {
77 p.writeImportedFiles(mojomFile.Imports) 90 p.writeImportedFiles(mojomFile.Imports)
78 } 91 }
79 92
80 for _, declaredObject := range mojomFile.DeclaredObjects { 93 for _, declaredObject := range mojomFile.DeclaredObjects {
81 p.writeDeclaredObject(declaredObject) 94 p.writeDeclaredObject(declaredObject)
82 p.nl() 95 p.nl()
83 } 96 }
84 97
85 if mojomFile.FinalComments != nil { 98 if mojomFile.FinalComments != nil {
86 finalComments := trimEmptyLines(mojomFile.FinalComments) 99 finalComments := trimEmptyLines(mojomFile.FinalComments)
87 if len(finalComments) > 0 { 100 if len(finalComments) > 0 {
88 p.nl() 101 p.nl()
89 p.writeCommentBlocks(finalComments, true) 102 p.writeCommentBlocks(finalComments, true)
90 } 103 }
91 } 104 }
105
106 p.eofNoFormat()
92 } 107 }
93 108
94 // writeModuleNamespace writes a mojom file's module statement and associated 109 // writeModuleNamespace writes a mojom file's module statement and associated
95 // comments. 110 // comments.
96 func (p *printer) writeModuleNamespace(module *mojom.ModuleNamespace) { 111 func (p *printer) writeModuleNamespace(module *mojom.ModuleNamespace) {
97 if module == nil || module.Identifier == "" { 112 if module == nil || module.Identifier == "" {
98 return 113 return
99 } 114 }
100 p.writeBeforeComments(module) 115 p.writeBeforeComments(module)
101 p.writef("module %s;", module.Identifier) 116 p.writef("module %s;", module.Identifier)
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 p.writef(" %s", comment.Text) 579 p.writef(" %s", comment.Text)
565 } 580 }
566 } 581 }
567 582
568 // writeCommentBlocks writes a slice of comments. If finalEol is true, a new 583 // writeCommentBlocks writes a slice of comments. If finalEol is true, a new
569 // line is written after all the comments are written. 584 // line is written after all the comments are written.
570 func (p *printer) writeCommentBlocks(comments []lexer.Token, finalEol bool) { 585 func (p *printer) writeCommentBlocks(comments []lexer.Token, finalEol bool) {
571 for i, comment := range comments { 586 for i, comment := range comments {
572 switch comment.Kind { 587 switch comment.Kind {
573 case lexer.SingleLineComment: 588 case lexer.SingleLineComment:
589 if comment.Text == "// no-format" {
590 p.startNoFormat(comment)
591 } else if comment.Text == "// end-no-format" {
592 p.endNoFormat(comment)
593 }
574 p.write(comment.Text) 594 p.write(comment.Text)
575 if finalEol || i < len(comments)-1 { 595 if finalEol || i < len(comments)-1 {
576 p.nl() 596 p.nl()
577 } 597 }
578 case lexer.MultiLineComment: 598 case lexer.MultiLineComment:
579 p.writeMultiLineComment(comment) 599 p.writeMultiLineComment(comment)
580 if finalEol || i < len(comments)-1 { 600 if finalEol || i < len(comments)-1 {
581 p.nl() 601 p.nl()
582 } 602 }
583 case lexer.EmptyLine: 603 case lexer.EmptyLine:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 // write writes the provided string to the buffer. 648 // write writes the provided string to the buffer.
629 // If nothing has been written yet on the current line write also writes the 649 // If nothing has been written yet on the current line write also writes the
630 // current indentation level. 650 // current indentation level.
631 func (p *printer) write(s string) { 651 func (p *printer) write(s string) {
632 if strings.ContainsRune(s, '\n') { 652 if strings.ContainsRune(s, '\n') {
633 panic(fmt.Sprintf("Only the nl method can write a new line: %q", s)) 653 panic(fmt.Sprintf("Only the nl method can write a new line: %q", s))
634 } 654 }
635 655
636 // We only print the indentation if the line is not empty. 656 // We only print the indentation if the line is not empty.
637 if p.linePos == 0 { 657 if p.linePos == 0 {
638 » » p.buffer.WriteString(strings.Repeat(" ", p.indentSize)) 658 » » if !p.noFormat {
659 » » » p.buffer.WriteString(strings.Repeat(" ", p.indentSize))
660 » » }
639 p.linePos += p.indentSize 661 p.linePos += p.indentSize
640 } 662 }
641 p.linePos += len(s) 663 p.linePos += len(s)
642 » p.buffer.WriteString(s) 664 » if !p.noFormat {
665 » » p.buffer.WriteString(s)
666 » }
643 } 667 }
644 668
645 // nl writes a new line. Before writing the new line, nl writes the last 669 // nl writes a new line. Before writing the new line, nl writes the last
646 // comment on the line. 670 // comment on the line.
647 func (p *printer) nl() { 671 func (p *printer) nl() {
648 // Before going to the next line, print the last comment on the line. 672 // Before going to the next line, print the last comment on the line.
649 if p.eolComment != nil { 673 if p.eolComment != nil {
650 » » p.writef(" %s", p.eolComment.Text) 674 » » if !p.noFormat {
675 » » » p.writef(" %s", p.eolComment.Text)
676 » » }
651 p.eolComment = nil 677 p.eolComment = nil
652 } 678 }
653 679
654 » p.buffer.WriteString("\n") 680 » if !p.noFormat {
681 » » p.buffer.WriteString("\n")
682 » }
655 p.linePos = 0 683 p.linePos = 0
656 } 684 }
657 685
658 func (p *printer) incIndent() { 686 func (p *printer) incIndent() {
659 p.indentSize += 2 687 p.indentSize += 2
660 } 688 }
661 689
662 func (p *printer) decIndent() { 690 func (p *printer) decIndent() {
663 p.indentSize -= 2 691 p.indentSize -= 2
664 if p.indentSize < 0 { 692 if p.indentSize < 0 {
(...skipping 21 matching lines...) Expand all
686 // to the line yet, it returns the indent size. 714 // to the line yet, it returns the indent size.
687 // The purpose of lineLenght is to answer the question: If I write something now 715 // 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? 716 // how far on the current line will it be written?
689 func (p *printer) lineLength() int { 717 func (p *printer) lineLength() int {
690 if p.linePos == 0 { 718 if p.linePos == 0 {
691 return p.indentSize 719 return p.indentSize
692 } 720 }
693 return p.linePos 721 return p.linePos
694 } 722 }
695 723
724 // startNoFormat disables writes to the buffer (future writes are discarded).
725 func (p *printer) startNoFormat(startToken lexer.Token) {
726 if p.noFormat {
727 return
728 }
729
730 p.noFormat = true
731 p.noFormatStart = startToken
732 p.noFormatStartIndent = p.indentSize
733 }
734
735 // endNoFormat re-enables writes to the buffer and writes the source starting
736 // at the beginning of p.startToken and ending right before endToken.
737 func (p *printer) endNoFormat(endToken lexer.Token) {
738 if !p.noFormat {
739 return
740 }
741
742 fileContents := p.mojomFile.FileContents()
743 notFormatted := fileContents[p.noFormatStart.SourcePosBytes:endToken.Sou rcePosBytes]
744
745 // Remove any unformatted indentation right before the end of the unform atted block.
746 notFormatted = strings.TrimRight(notFormatted, " \t")
747 p.buffer.WriteString(strings.Repeat(" ", p.noFormatStartIndent))
748 p.buffer.WriteString(notFormatted)
749 p.noFormat = false
750 }
751
752 // eofNoFormat handles the case where formatting had been disabled but not
753 // re-enabled. It writes everything after the formatting was ended.
754 func (p *printer) eofNoFormat() {
755 if !p.noFormat {
756 return
757 }
758
759 fileContents := p.mojomFile.FileContents()
760 p.endNoFormat(lexer.Token{SourcePosBytes: len(fileContents)})
761 }
762
696 // Standalone utilities that do not operate on the buffer. 763 // Standalone utilities that do not operate on the buffer.
697 764
698 // isNewBlock determines if an empty line should be printed above the element 765 // isNewBlock determines if an empty line should be printed above the element
699 // under consideration. The purpose is to respect user-intention to separate 766 // under consideration. The purpose is to respect user-intention to separate
700 // elements in a mojom file. 767 // elements in a mojom file.
701 // 768 //
702 // If the element has attributes, and the first "comment" attached above the 769 // If the element has attributes, and the first "comment" attached above the
703 // attributes is an empty line, the element is a new block. 770 // attributes is an empty line, the element is a new block.
704 // If the element has no attributes and the first "comment" attached above the 771 // If the element has no attributes and the first "comment" attached above the
705 // element itself is an empty line, the element is a new block. 772 // element itself is an empty line, the element is a new block.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 835
769 // See sort.Interface. 836 // See sort.Interface.
770 func (ifs *importedFilesSorter) Less(i, j int) bool { 837 func (ifs *importedFilesSorter) Less(i, j int) bool {
771 return ifs.imports[i].SpecifiedName < ifs.imports[j].SpecifiedName 838 return ifs.imports[i].SpecifiedName < ifs.imports[j].SpecifiedName
772 } 839 }
773 840
774 // See sort.Interface. 841 // See sort.Interface.
775 func (ifs *importedFilesSorter) Swap(i, j int) { 842 func (ifs *importedFilesSorter) Swap(i, j int) {
776 ifs.imports[i], ifs.imports[j] = ifs.imports[j], ifs.imports[i] 843 ifs.imports[i], ifs.imports[j] = ifs.imports[j], ifs.imports[i]
777 } 844 }
OLDNEW
« no previous file with comments | « mojom/mojom_parser/formatter/formatter_test.go ('k') | mojom/mojom_parser/mojom/mojom_descriptor.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698