๐Ÿš€ Grammar-Aware Code Formatter: Structure through separation (supports Go, JavaScript, TypeScript, JSX, and TSX)
go formatter code-formatter javascript typescript jsx tsx
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf: Reduce allocations and syscalls in formatting pipeline

Fuwn 77bbef01 9f39211f

+25 -20
+5 -4
adapter_go.go
··· 1 1 package main 2 2 3 3 import ( 4 + "bytes" 4 5 "github.com/Fuwn/iku/engine" 5 6 "go/format" 6 7 "go/parser" 7 8 "go/token" 8 - "strings" 9 9 ) 10 10 11 11 type GoAdapter struct{} ··· 26 26 27 27 formatter := &Formatter{} 28 28 lineInformationMap := formatter.buildLineInfo(tokenFileSet, parsedFile) 29 - sourceLines := strings.Split(string(formattedSource), "\n") 30 - events := make([]engine.LineEvent, len(sourceLines)) 29 + sourceByteLines := bytes.Split(formattedSource, []byte("\n")) 30 + events := make([]engine.LineEvent, len(sourceByteLines)) 31 31 insideRawString := false 32 32 33 - for lineIndex, currentLine := range sourceLines { 33 + for lineIndex, currentLineBytes := range sourceByteLines { 34 + currentLine := string(currentLineBytes) 34 35 backtickCount := countRawStringDelimiters(currentLine) 35 36 wasInsideRawString := insideRawString 36 37
+8 -5
engine/engine.go
··· 104 104 105 105 func (e *Engine) FormatToString(events []LineEvent) string { 106 106 lines := e.Format(events) 107 - output := strings.Join(lines, "\n") 107 + lines = append(lines, "") 108 + 109 + return strings.Join(lines, "\n") 110 + } 108 111 109 - if !strings.HasSuffix(output, "\n") { 110 - output += "\n" 111 - } 112 + func (e *Engine) FormatToBytes(events []LineEvent) []byte { 113 + lines := e.Format(events) 114 + lines = append(lines, "") 112 115 113 - return output 116 + return []byte(strings.Join(lines, "\n")) 114 117 } 115 118 116 119 func (e *Engine) findNextNonComment(events []LineEvent, startIndex int) int {
+1 -1
formatter.go
··· 33 33 34 34 formattingEngine := &engine.Engine{CommentMode: MapCommentMode(f.CommentMode)} 35 35 36 - return []byte(formattingEngine.FormatToString(events)), nil 36 + return formattingEngine.FormatToBytes(events), nil 37 37 } 38 38 39 39 func analyzeSource(source []byte, filename string) ([]byte, []engine.LineEvent, error) {
+2 -2
formatter_test.go
··· 1 1 package main 2 2 3 3 import ( 4 + "fmt" 4 5 "strings" 5 6 "testing" 6 7 ) ··· 448 449 sourceBuilder.WriteString("package main\n\n") 449 450 450 451 for functionIndex := range 100 { 451 - sourceBuilder.WriteString("func foo") 452 - sourceBuilder.WriteString(string(rune('A' + functionIndex%26))) 452 + fmt.Fprintf(&sourceBuilder, "func foo%d", functionIndex) 453 453 sourceBuilder.WriteString("() {\n") 454 454 sourceBuilder.WriteString("\tx := 1\n") 455 455 sourceBuilder.WriteString("\tif x > 0 {\n")
+6 -6
inspect.go
··· 1 1 package main 2 2 3 3 import ( 4 + "fmt" 4 5 "go/ast" 5 6 "go/token" 6 - "reflect" 7 7 ) 8 8 9 9 func isGeneralDeclarationScoped(generalDeclaration *ast.GenDecl) bool { ··· 20 20 } 21 21 22 22 func (f *Formatter) buildLineInfo(tokenFileSet *token.FileSet, parsedFile *ast.File) map[int]*lineInformation { 23 - lineInformationMap := make(map[int]*lineInformation) 23 + lineInformationMap := make(map[int]*lineInformation, 2*len(parsedFile.Decls)) 24 24 tokenFile := tokenFileSet.File(parsedFile.Pos()) 25 25 26 26 if tokenFile == nil { ··· 41 41 statementType = "func" 42 42 isScoped = true 43 43 default: 44 - statementType = reflect.TypeOf(declaration).String() 44 + statementType = fmt.Sprintf("%T", declaration) 45 45 } 46 46 47 47 lineInformationMap[startLine] = &lineInformation{statementType: statementType, isTopLevel: true, isScoped: isScoped, isStartLine: true} ··· 88 88 if generalDeclaration, isGeneralDeclaration := typedStatement.Decl.(*ast.GenDecl); isGeneralDeclaration { 89 89 statementType = generalDeclaration.Tok.String() 90 90 } else { 91 - statementType = reflect.TypeOf(statement).String() 91 + statementType = fmt.Sprintf("%T", statement) 92 92 } 93 93 case *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, 94 94 *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.BlockStmt: 95 - statementType = reflect.TypeOf(statement).String() 95 + statementType = fmt.Sprintf("%T", statement) 96 96 isScoped = true 97 97 default: 98 - statementType = reflect.TypeOf(statement).String() 98 + statementType = fmt.Sprintf("%T", statement) 99 99 } 100 100 101 101 existingStart := lineInformationMap[startLine]
+3 -2
main.go
··· 5 5 "flag" 6 6 "fmt" 7 7 "io" 8 + "io/fs" 8 9 "os" 9 10 "path/filepath" 10 11 "runtime" ··· 107 108 func processDirectory(formatter *Formatter, directoryPath string, exitCode *int) error { 108 109 var sourceFilePaths []string 109 110 110 - err := filepath.Walk(directoryPath, func(currentPath string, fileInfo os.FileInfo, err error) error { 111 + err := filepath.WalkDir(directoryPath, func(currentPath string, dirEntry fs.DirEntry, err error) error { 111 112 if err != nil { 112 113 return err 113 114 } 114 115 115 - if !fileInfo.IsDir() && supportedFileExtensions[filepath.Ext(currentPath)] { 116 + if !dirEntry.IsDir() && supportedFileExtensions[filepath.Ext(currentPath)] { 116 117 sourceFilePaths = append(sourceFilePaths, currentPath) 117 118 } 118 119