Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
fmt
Search
ktr
January 25, 2018
Technology
0
3.9k
fmt
ktr
January 25, 2018
Tweet
Share
More Decks by ktr
See All by ktr
Monorepo における Go テストの差分実行 / Running Differential Go Tests in a Monorepo
ktr_0731
0
110
Designing libraries in Go way
ktr_0731
6
1.5k
Go Modules and Proxy Walkthrough
ktr_0731
8
27k
ソフトウェアの複雑さに立ち向かう技術 / Tackling software complexity
ktr_0731
0
180
Fuzzy finder as a Go library
ktr_0731
3
5.8k
つよくてニューゲーム / NewGame++
ktr_0731
0
970
やはり俺の Go アプリケーション設計はまちがっている。 / My Go Application Design Is Wrong, As I Expected
ktr_0731
13
3.5k
GopherCon2018
ktr_0731
2
1.8k
Evans: more expressive gRPC client
ktr_0731
2
470
Other Decks in Technology
See All in Technology
CZII - CryoET Object Identification 参加振り返り・解法共有
tattaka
0
360
現場で役立つAPIデザイン
nagix
33
12k
あれは良かった、あれは苦労したB2B2C型SaaSの新規開発におけるCloud Spanner
hirohito1108
2
590
現場の種を事業の芽にする - エンジニア主導のイノベーションを事業戦略に装着する方法 -
kzkmaeda
2
2.1k
管理者しか知らないOutlookの裏側のAIを覗く#AzureTravelers
hirotomotaguchi
2
400
Classmethod AI Talks(CATs) #16 司会進行スライド(2025.02.12) / classmethod-ai-talks-aka-cats_moderator-slides_vol16_2025-02-12
shinyaa31
0
110
TAMとre:Capセキュリティ編 〜拡張脅威検出デモを添えて〜
fujiihda
2
240
インフラをつくるとはどういうことなのか、 あるいはPlatform Engineeringについて
nwiizo
5
2.6k
組織貢献をするフリーランスエンジニアという生き方
n_takehata
1
1.3k
トラシューアニマルになろう ~開発者だからこそできる、安定したサービス作りの秘訣~
jacopen
2
2k
偶然 × 行動で人生の可能性を広げよう / Serendipity × Action: Discover Your Possibilities
ar_tama
1
1.1k
「海外登壇」という 選択肢を与えるために 〜Gophers EX
logica0419
0
700
Featured
See All Featured
Embracing the Ebb and Flow
colly
84
4.6k
The Pragmatic Product Professional
lauravandoore
32
6.4k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
Designing for humans not robots
tammielis
250
25k
Agile that works and the tools we love
rasmusluckow
328
21k
Documentation Writing (for coders)
carmenintech
67
4.6k
KATA
mclloyd
29
14k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
40
2k
Git: the NoSQL Database
bkeepers
PRO
427
64k
Transcript
fmt fmt 1
$ whoami $ whoami (id:|@)ktr_0731 サーバサイドエンジニ ア STEINS;GATE / 響け!ユーフォニア
ム 2
3
ktr0731/evans ktr0731/evans more expressive gRPC client more expressive gRPC client
4
fmt? fmt? コードフォーマッタ ソースコードを 強制的 に整形してくれ る 5
gofmt YAPF Prettier scalafmt etc. 6
gofmt を読む gofmt を読む golang/go/src/cmd/gofmt 7
前提環境 前提環境 golang/go master (157d8cfbc13fbc4c849075e905b0001fb248b5e6) 8
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go gofmtMain() gofmtMain() for i := 0; i <
flag.NArg(); i++ { path := flag.Arg(i) switch dir, err := os.Stat(path); { case err != nil: report(err) case dir.IsDir(): walkDir(path) // NOTE; call processFil default: if err := processFile(path, nil, os.St report(err) } } } 9
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go processFile() processFile() file, sourceAdj, indentAdj, err := parse(fileSet,
filename, sr if err != nil { return err } 10
cmd/gofmt/internal.go cmd/gofmt/internal.go parse() parse() parser.ParseFile file, err = parser.ParseFile(fset, filename,
psrc, parserMode) if err == nil { sourceAdj = func(src []byte, indent int) []byte { src = src[indent+len("package p\n"):] return bytes.TrimSpace(src) } 11
go/parser go/parser ParseFile() ParseFile() go/parser: 構文解析用パッケージ Go ソースコードから AST (
抽象構文木) を生 成 12
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go processFile() processFile() ast.SortImports(fileSet, file) if *simplifyAST { simplify(file)
} res, err := format(fileSet, file, sourceAdj, indentAdj, src, p if err != nil { return err } 13
cmd/gofmt/internal.go cmd/gofmt/internal.go format format var buf bytes.Buffer err := cfg.Fprint(&buf,
fset, file) if err != nil { return nil, err } return buf.Bytes(), nil 14
go/printer/printer.go go/printer/printer.go Fprint() → Fprint() → fprint() fprint() AST ノードを整形・出力するパッケージ
var p printer p.init(cfg, fset, nodeSizes) if err = p.printNode(node); err != nil { return } 15
go/printer/printer.go go/printer/printer.go printNode() printNode() switch n := node.(type) { case
ast.Expr: p.expr(n) case ast.Stmt: if _, ok := n.(*ast.LabeledStmt); ok { p.indent = 1 } p.stmt(n, false) case ast.Decl: p.decl(n) case ast.Spec: p.spec(n, 1, false) case []ast.Stmt: for _, s := range n { if _, ok := s.(*ast.LabeledStmt); ok { 16
printNode printNode AST を再帰的に辿り、 各ノードの持つ内容を整 形・出力する 17
例: 二項演算子のスペース 例: 二項演算子のスペース fmt.Println("Hello, "+"World") fmt.Println("Hello, " + "World")
18
AST AST の構造 の構造 0 *ast.CallExpr { 1 . Fun:
*ast.SelectorExpr { 2 . . X: *ast.Ident { 3 . . . NamePos: 1 4 . . . Name: "fmt" 5 . . . Obj: *ast.Object { 6 . . . . Kind: bad 7 . . . . Name: "" 8 . . . } 9 . . } 10 . . Sel: *ast.Ident { 11 . . . NamePos: 5 12 . . . Name: "Println" 13 . . } 14 . } 19
20
go/printer/printer.go go/printer/printer.go printNode() printNode() switch n := node.(type) { case
ast.Expr: p.expr(n) func (p *printer) expr(x ast.Expr) { const depth = 1 p.expr1(x, token.LowestPrec, depth) } 21
go/printer/nodes.go go/printer/nodes.go expr1() expr1() switch x := expr.(type) { case
*ast.BinaryExpr: if depth < 1 { p.internalError("depth < 1:", depth) depth = 1 } p.binaryExpr(x, prec1, cutoff(x, depth), depth) 22
go/printer/nodes.go go/printer/nodes.go binaryExpr() binaryExpr() ( 一部略) ( 一部略) // X
評価 p.expr1(x.X, prec, depth+diffPrec(x.X, prec)) if printBlank { // 追加 p.print(blank) } // "+" p.print(x.OpPos, x.Op) if printBlank { // 追加 p.print(blank) } // Y 評価 p.expr1(x.Y, prec+1, depth+1) 23
gofmt のフォーマットルール gofmt のフォーマットルール AST 生成までの過程で取り除かれるも の go/printer によって整形されるもの 24
AST AST 生成までの過程で取り除かれるもの 生成までの過程で取り除かれるもの 改行 スペー ス etc. 25
go/printer によって整形されるもの go/printer によって整形されるもの 二項演算子のスペース ( 前 述) 配列の最後の要素のカンマ etc.
[]string{"foo", "bar",} []string{"foo", "bar"} 26
似たようなのを実装してみる 似たようなのを実装してみる 27
ktr0731/markdownfmt ktr0731/markdownfmt 28
29
30
31
整形ルール 整形ルール 余計な改行・空白は取り除く テキストの最大長を 80 文字 に 32
整形ルール 整形ルール テキストの単語間のスペースは1つ に this is a text! this is
a text! 33
整形ルール 整形ルール 水平線 (hr) の上下に空 行 horizontal --- line horizontal
--- line 34
demo demo 35
これはデモ用のテキストです これはデモ用のテキストです this text is an example text for demonstration.
current version of markdownfmt accepts 80 charactors as the max width. so, maybe this text will be splitted to some lines. 36
まとめ まとめ AST なんでもできてすごい 特に Go は取得できる情報が多い AST を作れれば、フォーマットはそこまで難しく ない
意外と gofmt は読みやすい 37
参考 参考 printer - The Go Programming Language parser -
The Go Programming Language Go のための Go GitHub Flavored Markdown Spec 38