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
4.2k
fmt
ktr
January 25, 2018
Tweet
Share
More Decks by ktr
See All by ktr
あまり知られていない MCP 仕様たち / MCP specifications that aren’t widely known
ktr_0731
0
380
CLI ツールを Go ライブラリ として再実装する理由 / Why reimplement a CLI tool as a Go library
ktr_0731
3
1.3k
激動の一年を通じて見えてきた「技術でリードする」ということ
ktr_0731
8
10k
Monorepo における Go テストの差分実行 / Running Differential Go Tests in a Monorepo
ktr_0731
1
310
Designing libraries in Go way
ktr_0731
7
1.6k
Go Modules and Proxy Walkthrough
ktr_0731
8
27k
ソフトウェアの複雑さに立ち向かう技術 / Tackling software complexity
ktr_0731
0
220
Fuzzy finder as a Go library
ktr_0731
3
6.1k
つよくてニューゲーム / NewGame++
ktr_0731
0
1k
Other Decks in Technology
See All in Technology
GoでもGUIアプリを作りたい!
kworkdev
PRO
0
160
WEBサービスを成り立たせるAWSサービス
takano0131
1
200
HR Force における DWH の併用事例 ~ サービス基盤としての BigQuery / 分析基盤としての Snowflake ~@Cross Data Platforms Meetup #2「BigQueryと愉快な仲間たち」
ryo_suzuki
0
250
Copilot Studio ハンズオン - 生成オーケストレーションモード
tomoyasasakimskk
0
190
Digitization部 紹介資料
sansan33
PRO
1
5.6k
事業開発におけるDify活用事例
kentarofujii
4
1.2k
AIフル活用で挑む!空間アプリ開発のリアル
taat
0
120
[OCI Skill Mapping] AWSユーザーのためのOCI – IaaS編(Compute/Storage/Networking) (2025年10月8日開催)
oracle4engineer
PRO
1
140
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
20k
Findy Team+ QAチーム これからのチャレンジ!
findy_eventslides
0
490
初めてのDatabricks Apps開発
taka_aki
1
230
Databricks AI/BI Genie の「値ディクショナリー」をAmazonの奥地(S3)まで見に行く
kameitomohiro
1
370
Featured
See All Featured
Building an army of robots
kneath
306
46k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
30
2.9k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.5k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Java REST API Framework Comparison - PWX 2021
mraible
34
8.9k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.2k
GraphQLとの向き合い方2022年版
quramy
49
14k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
657
61k
Thoughts on Productivity
jonyablonski
70
4.9k
Fireside Chat
paigeccino
40
3.7k
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