Upgrade to Pro — share decks privately, control downloads, hide ads and more …

package名と変数名がかぶっているのをとにかく検出したい / I need detect to conflicts of identifier for Go

mackee
June 18, 2019

package名と変数名がかぶっているのをとにかく検出したい / I need detect to conflicts of identifier for Go

mackee

June 18, 2019
Tweet

More Decks by mackee

Other Decks in Programming

Transcript

  1. package໊ͱม਺໊͕
    ͔Ϳ͍ͬͯΔͷΛ
    ͱʹ͔͘ݕग़͍ͨ͠
    golang.tokyo #25 2019-06-18
    @mackee_w a.k.a macopy
    1

    View full-size slide

  2. Ͳ͏͍͏͜ͱ͔
    package main
    import (
    "os"
    "errors"
    )
    func main() {
    // Ҿ਺͔Β࣮ߦ͢Δ܅ΛऔΓग़͢
    runner := NewRunners(os.Args[1:])
    2

    View full-size slide

  3. errors := make([]error, 0, len(runner))
    for _, r := range runners {
    result, err := runner.Run()
    if err != nil {
    errors = append(errors, err)
    }
    if result == nil {
    errors = append(
    errors,
    errors.New("result is nil"),
    )
    }
    3

    View full-size slide

  4. 1ߦา͍ͨΒ๨ΕͯΔ
    errors = append(
    errors,
    errors.New("result is nil"),
    )
    • ౰વ͜Ε͸ίϯύΠϧ͕௨Βͳ͍
    • errorsύοέʔδ͸طʹ࢖͑ͳ͘ͳ͍ͬͯΔͨΊ
    4

    View full-size slide

  5. ͜ͷίʔυ͕ੜ·ΕΔࢥߟͷաఔ
    • errors ࢖͍͍ͨͳΝ(github.com/pkg/errorsͰ΋Մ)
    • ͦΕ͸͓͖ͯ͞errorΛ·ͱΊ͓͖͍͔ͯͨΒerrorsͱ͍͏
    ม਺Λએݴ͢Δͧ
    • ΞϨϨɺerrors.Newͱ͔errors.Wrapͱ͔ͷิ׬͕ޮ͔ͳ
    ͍ͧ
    • ͔ͿͬͯΔʂʂʂ
    5

    View full-size slide

  6. Έͳ͞Μ͸ͦΜͳܦݧ͸͋Γ·ͤΜ͔ʁ
    • ʮ໋໊͕ྑ͘ͳ͍͔ΒͰ͸ʁʯ
    • ͜͜·Ͱ͔͋Β͞·ͳ͜ͱ͸ͳͯ͘΋ɺύοέʔδ໊ͱม਺໊
    ͕͔Ϳͬͯࠞཚ͢Δ͜ͱ͕͋Γ·͢
    • ͪͳΈʹࢲ͸্هͷΑ͏ͳerrorsΛimport͍ͯ͠Δͷʹ
    errorsΛ࡞Γग़͢͜ͱ͕͋Γ·͢(ຊ౰ʹ)
    • ݪҼ͕ίϯύΠϧΤϥʔͱ͸ҧ͏Օॴʹ͋ΔͨΊΘ͔Γʹ͍͘
    6

    View full-size slide

  7. ͦͷଞղܾ͍ͨ͠έʔεstruct໊ͱม਺໊͕͔ͿΔ
    type sheet struct {
    // ...
    }
    func NewSheet() *sheet {
    return &sheet{}
    }
    func (s *sheet) String() string {
    // ...
    }
    7

    View full-size slide

  8. ͦͷଞղܾ͍ͨ͠έʔεstruct໊ͱม਺໊͕͔ͿΔ
    ಉ͡ύοέʔδͷҧ͏ϑΝΠϧͰ
    func DoSomething() {
    sheet := NewSheet()
    // ...
    }
    8

    View full-size slide

  9. ͜͏ॻ͔ΕΔͱԿ͕ى͜Δ͔
    • ίϯύΠϧ͸௨Δ
    • DoSomethingͷ಺ͰsheetΛࣗ෼Ͱnew͸ग़དྷͳ͍
    9

    View full-size slide

  10. ύοέʔδͷ໊લͱԾҾ਺͕͔ͿΔ
    import "path"
    func ReadFromFile(path string) error {
    //...
    }
    10

    View full-size slide

  11. ͜͏ॻ͔ΕΔͱԿ͕ى͜Δ͔
    • ίϯύΠϧ͸௨Δ
    • ReadFromFileͷதͰpathύοέʔδͷؔ਺͕ݺ΂ͳ͘ͳΔ
    11

    View full-size slide

  12. ศརͳέʔε΋͋Δ
    Ұ෦ͷείʔϓ͚ͩlogΛผͷ΋ͷʹஔ͖׵͑Δͱ͔(ͦͦ͜͜अѱ
    import "log"
    // ͜ͷϝιουͷத͚ͩϑΝΠϧʹॻ͘
    func Do() {
    log := log.New(logfile, "Do(): ", log.LstdFlags)
    // ্ͷ1ߦΛՃ͑Δ͚ͩͰଞͷߦ͸ॻ͖׵͑ͳ͍͍ͯ͘
    log.Println("print something")
    }
    12

    View full-size slide

  13. ݴޠ࢓༷͕ѱ͍ͱݴ͍͍ͨΘ͚Ͱ͸ͳ͘...
    ਓؒ͸ϛεΛ͢ΔͷͰ...
    13

    View full-size slide

  14. ҙਤ͔ͤͣͿͬͯΔ
    έʔεΛݕ஌͍ͨ͠
    14

    View full-size slide

  15. github.com/mackee/conflic1dent
    15

    View full-size slide


  16. pathύοέʔδͱmainؔ਺είʔϓͷpathม਺͕͔ͿͬͯΔ
    import "path"
    func main() {
    path := "example.txt"
    }
    16

    View full-size slide

  17. ࣮ߦྫ
    ίϚϯυ࣮ߦ͢Δͱ
    $ conflictident .
    ग़ྗ͸͜Μͳײ͡
    pkgident.go:12:2:
    conflict identifier name of 'path' by pkgident.go:4:2.
    17

    View full-size slide

  18. ରԠ͍ͯ͠Δ͔Ϳ͍ͬͯΔྫ
    • ύοέʔδ໊ͱม਺໊
    • ύοέʔδ໊ͱԾҾ਺໊
    • ಉ͡ύοέʔδ಺ͷܕͱม਺໊/ԾҾ਺໊
    • ಉ͡ύοέʔδ಺ͷconstͷ໊લͱม਺໊/ԾҾ਺໊
    18

    View full-size slide

  19. ͱʹ͔͘ศར...
    19

    View full-size slide

  20. ྨࣅ඼
    • golang.org/x/tools/go/analysis/passes/shadow/
    cmd/shadow
    • ม਺ͷshadowingΛݕ஌ͯ͘͠ΕΔ
    func BadRead(f *os.File, buf []byte) error {
    var err error
    for {
    n, err := f.Read(buf) // shadows the function variable 'err'
    if err != nil {
    break // causes return of wrong value
    }
    foo(buf)
    }
    return err
    }
    20

    View full-size slide

  21. ຊ೔ݴ͍͍ͨͷ͸
    golang.org/x/tools/analysis ͕ศར...
    21

    View full-size slide

  22. 3ߦͰΘ͔Δx/tools/analysis
    • ੩తղੳνΣοΧʔΛ࡞ΔϑϨʔϜϫʔΫతͳϥΠϒϥϦ
    • ੩తղੳʹඞཁͳ ಡΉ, ղੳ͢Δ, ग़ྗ͢Δ ͷ͏ͪ ಡΉ, ग़ྗ͢
    Δ ΛΑ͠ͳʹ΍ͬͯ͘ΕΔ
    • ੩తղੳνΣοΧʔͷςετέʔεهड़͕௒ઈָ
    22

    View full-size slide

  23. x/tools/analysisΛ࢖͍ͬͯΔίʔυ
    package conflictident
    import (
    "golang.org/x/tools/go/analysis"
    "golang.org/x/tools/go/analysis/passes/inspect"
    "golang.org/x/tools/go/ast/inspector"
    )
    var Analyzer = &analysis.Analyzer{
    Name: "conflictident",
    Doc: Doc,
    Run: run,
    Requires: []*analysis.Analyzer{
    inspect.Analyzer,
    },
    }
    23

    View full-size slide

  24. x/tools/analysisΛ࢖͍ͬͯΔίʔυ
    func run(pass *analysis.Pass) (interface{}, error) {
    ins := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
    nodeFilter := []ast.Node{
    // ͜͜ʹཉ͍͠ASTͷϊʔυೖΕΑ͏
    }
    ins.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) bool {
    // ϑΟϧλʹઃఆͨ͠ASTͷϊʔυ͕΍ͬͯ͘Δͧ ͦΕΛݟ͍͍ͯײ͡ʹग़ྗ͠Α͏
    })
    }
    24

    View full-size slide

  25. x/tools/analysisΛ࢖͍ͬͯΔίʔυ
    pass.Reportf(
    ident.Pos(), // ؒҧ͍ͬͯΔίʔυͷϙδγϣϯ
    "conflict identifier name of '%s' by %s.",
    name,
    pos,
    )
    25

    View full-size slide

  26. x/tools/analysisΛ࢖͍ͬͯΔίʔυ
    package main
    import (
    "github.com/mackee/conflictident"
    "golang.org/x/tools/go/analysis/singlechecker"
    )
    func main() { singlechecker.Main(conflictident.Analyzer) }
    26

    View full-size slide

  27. conflic&dent͕΍͍ͬͯΔ͜ͱ
    • ύοέʔδείʔϓͷܕఆٛΛௐ΂Δ
    • ϑΝΠϧείʔϓͷimportએݴΛௐ΂Δ
    • ͦΕͧΕͷؔ਺είʔϓ಺Ͱએݴ͞ΕͯΔม਺໊΍ԾҾ਺໊͕
    ্ه2ͭͱ͔ͿͬͯͨΒग़ྗΛग़͢
    27

    View full-size slide

  28. ͜ΕͰ͍͍ײ͡ʹίϚϯυΛ࡞ΕΔʂʂ
    28

    View full-size slide

  29. ςετ͕ΊͬͪΌָͳͷΛओு͍ͨ͠
    29

    View full-size slide

  30. ͜͏͍͏ίϚϯυͷςετͷ೉͠͞
    • ϑΝΠϧΛ৯ͬͯඪ४ग़ྗʹ݁ՌΛग़͢λΠϓͷίϚϯυ
    • ࣮௚ʹ΍Δͱςετ༻ͷϑΝΠϧΛ࡞ͬͯඪ४ग़ྗΛಡΜͰ
    จࣈྻύʔεͯ͠...
    • ͪΌΜͱೖྗͱग़ྗΛ෼͚ͯɺςετͰ͸ೖग़ྗΛϞοΫ͢Δ
    • ↑ x/tools/analysisͰॻ͘ͱࣗવʹ͜Ε͕ग़དྷΔʂʂʂ
    30

    View full-size slide

  31. testdataͷ࡞੒
    • testdata/src ҎԼʹ੩తղੳνΣοΧʔͷςετσʔλͷ
    ίʔυΛॻ͘
    • ςετσʔλͷதʹίϝϯτͰظ଴͢Δग़ྗΛॻ͘
    • ςετଆ͸ x/tools/go/analysis/analysistest Λ࢖ͬ
    ͯهड़͢Δ
    31

    View full-size slide

  32. testdata/src/pkgident/pkgident.go
    package pkgident
    import (
    "path"
    )
    func hoge() {
    _ = path.ErrBadPattern
    }
    func main() {
    path, fuga := 1, 1
    // want "conflict identifier name of 'path' by testdata/src/pkgident/pkgident.go:4:2."
    _, _ = path, fuga
    }
    func p(path string) {
    // want "conflict identifier name of 'path' by testdata/src/pkgident/pkgident.go:4:2."
    }
    32

    View full-size slide

  33. conflic&dent_test.go
    package conflictident_test
    import (
    "testing"
    "github.com/mackee/conflictident"
    "golang.org/x/tools/go/analysis/analysistest"
    )
    func Test(t *testing.T) {
    testdata := analysistest.TestData()
    analysistest.Run(t, testdata, conflictident.Analyzer, "varspec", "funcarg")
    }
    33

    View full-size slide

  34. ͦͷଞ͓ಘϙΠϯτ
    • go vetͳͲͰݴ͏ ./... Έ͍ͨͳͷ΋ͦͷ··࢖͑Δ
    • ϞδϡʔϧԽ͍ͯ͠ΔͷͰଞͷLinterͱҰॹʹ࣮ߦ͢ΔίϚϯυ
    Λ࡞ΕΔ
    • go modulesରԠࡁΈ
    34

    View full-size slide

  35. ·ͱΊ
    • ࢲ͕ϛεΛ͠·͘ΔͷͰɺਖ਼͍͠ίʔυ͕ॻ͚ΔΑ͏ʹ੩తղ
    ੳνΣοΧʔΛ࡞Γ·ͨ͠
    • golang.org/x/tools/analysis Λ࢖͏ͱLinter͕͔ͳΓ؆
    ୯ʹॻ͚Δͧʂ
    • ղੳʹ͕͔͔࣌ؒΔͷͰνϡʔχϯά͍ͨ͠
    • ੩తղੳೖ໳ʹ࠷దͳͷͰΈΜͳ΍ͬͨΒ͍͍
    35

    View full-size slide

  36. Ͱɺ୭ʁ
    • mackee_w a.k.a @macopy
    • ໘ന๏ਓΧϠοΫ, 3DϓϦϯλ, ࣗ࡞
    ΩʔϘʔυ
    • ←ࠓि౔༵೔ʹח૔Ͱ΍ΔͷͰདྷͯ͘
    Εʂʂʂ
    36

    View full-size slide