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

PHPStanで始める継続的静的解析 #phperkaigi /php-static-analysis

PHPStanで始める継続的静的解析 #phperkaigi /php-static-analysis

PHPerKaigi 2018のトーク内容です。

Hiraku NAKANO

March 10, 2018
Tweet

More Decks by Hiraku NAKANO

Other Decks in Technology

Transcript

  1. PHPStanʹΑΔ
    ܧଓత੩తղੳ
    @hiraku

    View full-size slide

  2. ࣗݾ঺հ
    • த໺ ୓ (@Hiraku)
    • https://github.com/hirak
    • גࣜձࣾϝϧΧϦ → ϝϧϖΠ
    • PHPྺ10೥͙Β͍
    • Composerؔ࿈ͷൃදΛΑ͍ͯ͘͠·͢

    View full-size slide

  3. 2݄͔ΒϝϧϖΠࣾʹҟಈ͠·ͨ͠
    • ۚ༥ؔ࿈ͷ৽نࣄۀΛߦ͏

    ϝϧΧϦͷάϧʔϓձࣾ
    • શํ໘ɺϝϯόʔืूதʂ

    View full-size slide

  4. ʲએ఻ऴΘΓʳ

    View full-size slide

  5. ΋͘͡
    • dynamic ͱ static
    • PHPStanͷ঺հ ~ϝϧΧϦͰͷ׆༻ࣄྫ
    • staticͱͷڑ཭ײ
    • ࣮ફɾܕ஫ऍ

    View full-size slide

  6. ୈ1෦
    dynamic ͱ static
    PHPStanʹΑΔܧଓత੩తղੳ

    View full-size slide

  7. ྑ͍ίʔυ͔Ͳ͏͔
    ΛݟۃΊΔ2ͭͷΞϓϩʔν
    dynamic
    /
    static

    View full-size slide

  8. dynamic = ಈ͔ͯ͠ΈΔ
    • ςετ (ࣗಈ/खಈͲͪΒͰ΋)
    • ୅ද஋Λ༩࣮͑ͯߦˠ૝ఆ௨Γ͔൱͔
    • ࢓༷ͷ֬ೝʹ΋࢖͑Δ

    View full-size slide

  9. dynamicͷ೉఺
    • ຊ౰ʹ࣮ߦ͞ΕΔͱࠔΔ৔߹͕͋Δ

    (ϛαΠϧൃࣹͱ͔)
    • શ෦ςετ͢Δͷ͸ແཧ

    (64bit intͷҾ਺㲈1844ژύλʔϯ)
    • ϞοΫΛ༻ҙͯ͠ɺ୅ද஋ΛબΜͰ…

    ޻෉͕ඞཁ

    View full-size slide

  10. static = ಈ͔ͣ͞ʹಡΉ
    • ίʔυϨϏϡʔ / ੩తݕࠪ
    • ಈ͔͞ͳ͍ͷͰԿ΋ى͖ͳͯ҆͘৺
    • ςετίʔυ͕ͳͯ͘΋ݕࠪՄೳ

    View full-size slide

  11. staticͷ೉఺
    • ϓϩάϥϛϯάݴޠ, ίʔυͷελΠϧʹ

    ΑͬͯɺͰ͖ΔϨϕϧ͕มΘΔ
    • ཧ࿦্ɺܾఆͰ͖ͳ͍छྨͷ໰୊͕͋Δ
    • ແݶϧʔϓ/ఀࢭੑͳͲ
    • (ϥΠεͷఆཧͱ͔Ͱάάͬͯʂ)

    View full-size slide

  12. ͳͥ͜Μͳ࿩Λ
    ͍ͯ͠Δͷ͔

    View full-size slide

  13. ϝϧΧϦͷ
    PHPίʔυͷ࿩

    View full-size slide

  14. ~2016೥·Ͱ
    •!"#
    ͷશαʔόʔαΠυϩδοΫ͕

    1ͭͷrepositoryͩͬͨ
    • ifͰ෼ذଟ਺
    • ΤϯδχΞϦιʔεͷڞ༗Խ

    View full-size slide

  15. 2017೥ʹى͖ͨ͜ͱ
    •!ͱ"#
    ͷίʔυ͕෼཭ͨ͠
    • ݕূൣғΛڱͯ͘͠։ൃεϐʔυUP
    • ࢖ͬͯͳ͍ίʔυͷ࡟আ͕ඞཁʹͳͬͨ

    View full-size slide

  16. େྔͷίʔυ࡟আΛࢼΈΔ

    View full-size slide

  17. Өڹൣғͷେ͖ͳमਖ਼

    View full-size slide

  18. യવͱͨ͠ෆ҆

    View full-size slide

  19. ൃੜͨ͠໰୊
    • ϚχϡΞϧͰQA͢Δͱ͔͔࣌ؒΔ
    • ϦϑΝΫλϦϯά୲౰ऀ͕ϢχοτςετΛ
    ॻ͘ͱ͜Ζ͔Β࢝Ίͳ͍ͱ͍͚ͳ͍
    • ϦϦʔεʹ༐ؾ͕ඞཁ

    View full-size slide

  20. ༐ؾ͕΄͍͠ʂ

    View full-size slide

  21. ྑ͍ίʔυ͔Ͳ͏͔
    ΛݟۃΊΔ2ͭͷΞϓϩʔν
    dynamic
    /
    static

    View full-size slide

  22. staticํ໘͔Β΋߈Ί͍ͨ
    • ςετΛ૿΍͞ͳͯ͘΋࣮ߦͰ͖Δ
    • मਖ਼ྔ͕ଟͯ͘΋ػցͳΒશ෦ϨϏϡʔͯ͘͠ΕΔ
    • Ͳ͏ͤͳΒCIαʔόʔʹ૊ΈࠐΜͰɺக໋తͳ΋ͷ
    ͸CIΛࣦഊ͍ͤͨ͞
    • PHPStorm͸༏ल͚ͩͲɺCIʹ૊ΈࠐΉͷ͕

    ೉͍͠

    View full-size slide

  23. ୈ2෦
    PHPStanͷ঺հ
    PHPStanʹΑΔܧଓత੩తղੳ

    View full-size slide

  24. PHPStanͱ͸
    • https://github.com/phpstan/phpstan
    • PHP Static Analysis Tool ͷུ
    • ಈ࡞ʹ͸PHP 7.1Ҏ্͕ඞཁ
    • PHP5ͷίʔυ΋ղੳͯ͘͠ΕΔ
    • nikic/php-parserϕʔεͰͷղੳΛߦ͏ (ͷͰׂͱݡ͍)

    View full-size slide

  25. Phanͱͷҧ͍
    • https://github.com/phan/phan
    • ͲͪΒ΋ࣅͨ͜ͱ͕Մೳ
    • ͪΐͬͱઃܭࢥ૝͕ҧ͏(͋ͱͰղઆ͠·͢)

    View full-size slide

  26. ※ϝϧΧϦͰPhanΛ

    ࠾༻͠ͳ͔ͬͨཧ༝
    • PHPDocΛख͕͔Γʹ͢ΔͷͰɺPHPDoc Λ
    ͔ͬ͠Γॻ͍ͯͳ͍ͱπϥ͔ͬͨ
    • ext-ast Λඞཁͱ͢ΔͷͰऔΓճ͕͠ѱ͔ͬͨ
    • ʮͱΓ͋͑ͣɺ͜͜Ͱൃੜ͍ͯ͠Δ͜ͷΤϥʔ
    ͸ແࢹ͓ͯ͜͠͏ʯ͍ͬͯ͏ઃఆͷॊೈ͞

    View full-size slide

  27. ݕग़ͯ͘͠ΕΔ໰୊ͷྫ
    • ม਺ͷະఆٛ
    • nullͷՄೳੑ͕͋ΔͷʹϝιουݺΜͰΔ
    • PHPDocͷߏจෆඋ
    • ܕͷෆඋશൠ

    View full-size slide

  28. div() should return int but returns float.
    floatͳΒOK

    View full-size slide

  29. Install
    • composer require --dev phpstan/phpstan
    • phar൛΋͋Δ͠ɺglobal requireͯ͠΋୯ಠಈ
    ࡞͢Δ
    • docker hubʹ΋Πϝʔδ͕͋Δ
    • https://hub.docker.com/r/phpstan/phpstan/

    View full-size slide

  30. ※όʔδϣϯҧ͍ʹ஫ҙ
    • 2018೥3݄࣌఺ͷstable (0.9ܥ) ͱɺdev (1.0ܥ)͸
    ͔ͳΓΦϓγϣϯʹҧ͍͕͋Γ·͢
    • githubͷREADME.mdΛಡΉͱ͖͸஫ҙ
    • ͜͜Ͱ͸dev൛(1.0ܥ)Λϕʔεʹ࿩͠·͢
    • composer global require "phpstan/phpstan:@dev"
    ͳͲͰೖΓ·͢

    View full-size slide

  31. Run
    • ϓϩδΣΫτϩʔΧϧʹೖͬͯΕ͹

    $ vendor/bin/phpstan analyseͰىಈ
    • ղੳ͍ͨ͠σΟϨΫτϦʹͯɺphpstanίϚϯ
    υΛىಈ͢Ε͹ྑ͍

    View full-size slide

  32. ࣮ߦͨ͠ͱ͖ͷΠϝʔδ
    $ phpstan analyse
    Note: Using configuration file /Users/hiraku/src/github.com/hirak/
    prestissimo/phpstan.neon.dist.
    12/12 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
    ------ -------------------------------------------------------------------
    Line src/BaseRequest.php
    ------ -------------------------------------------------------------------
    23 PHPDoc tag @var has invalid value ([string => string]): Unexpected
    token "[", expected TOKEN_IDENTIFIER at offset 9
    120 PHPDoc tag @param has invalid value ($io): Unexpected token "$io",
    expected TOKEN_IDENTIFIER at offset 18
    120 PHPDoc tag @param has invalid value ($githubDomains): Unexpected
    token "$githubDomains", expected TOKEN_IDENTIFIER at offset 70
    120 PHPDoc tag @param has invalid value ($gitlabDomains): Unexpected
    token "$gitlabDomains", expected TOKEN_IDENTIFIER at offset 99
    ------ -------------------------------------------------------------------

    View full-size slide

  33. Configure
    • ઃఆϑΝΠϧ͕͋Ε͹ɺ phpstan analyse ͩ
    ͚ͰղੳͰ͖Δ(1.0ܥ)
    • .neonͱ͍͏ɺYAMLͷΑ͏ͳઃఆϑΝΠϧΛ࢖͏
    • stable൛(0.9ܥ)ͱɺdev൛(1.0ܥ)Ͱ͔ͳΓมߋ͕
    ೖ͍ͬͯΔɻdev൛ͷํ͕ศར͞ˢˢ

    View full-size slide

  34. 1.0ܥͷphpstan.neon.distྫ
    • phpstan.neon→~.distͷ
    ॱʹ୳ͯ͠ಡΉ
    • .neon͸.gitignore͠ͱ͘
    ͱڞಉ։ൃऀ͕޷͖ʹ֦
    ுͰ͖Δ

    View full-size slide

  35. CIͱͷ࿈ܞ
    • Τϥʔ͕͋ΔͱίϚϯυͷऴྃεςʔλε͕1ʹͳΔͷ
    Ͱɺࣦഊ൑ఆ͸༰қ
    • ϝϧΧϦͰ͸CircleCIΛ࢖ͬͯ2ஈ֊Ͱ࿈ܞ
    • ࠷௿ݶͷϧʔϧ͸CIࣗମΛམͱ͢
    • ݫ͠Ίͷϧʔϧ͸reviewdogͰPull Requestʹίϝϯ
    τͤ͞Δ(CI͸མͱ͞ͳ͍)

    View full-size slide

  36. reviewdogศར
    • http://haya14busa.com/reviewdog/

    View full-size slide

  37. ϧʔϧΛΏΔΊΔํ๏
    • levelΦϓγϣϯͰࡶʹࢦఆ
    • 0 ~ 7ɺmaxͱ͍͏ΤΠϦΞε΋͋Δ
    • https://github.com/phpstan/phpstan/tree/
    master/conf

    View full-size slide

  38. ஸೡʹϧʔϧΛΧελϜ
    • level͸ࢦఆͤͣʹ
    parameters

    .customRulesetUsed
    Λtrueʹ
    • rulesʹฒ΂Δ

    View full-size slide

  39. ࡶʹ཈੍
    • parameters

    .ignoreErrors

    Λ௥Ճ
    • ਖ਼نදݱͰΤϥʔ
    ϝο
    ηʔδΛϚον͞
    ͤͯແࢹͰ͖Δ(!)
    ͱ͔Λ௥Ճͨ͠Β
    શΤϥʔ཈ࢭʂ

    View full-size slide

  40. ୈ3෦
    staticͱͷڑ཭ײ
    PHPStanʹΑΔܧଓత੩తղੳ

    View full-size slide

  41. autoloadͷઃఆ͕͋Δ

    View full-size slide

  42. autoloadͱ͸
    • ಛఆͷؔ਺Λ࣮ߦͯ͠ϑΝΠϧΛ
    require_once͠ɺΫϥεΛϩʔυ͢Δ
    • ࠷ۙͷPHPϓϩδΣΫτͩͱී௨ʹ࢖ΘΕͯ
    ͍Δ

    View full-size slide

  43. ศར͚ͩͲ…ʁ

    View full-size slide

  44. autoloadͱ͸
    • ಛఆͷؔ਺Λ࣮ߦͯ͠ϑΝΠϧΛ
    require_once͠ɺΫϥεΛϩʔυ͢Δ
    • ࠷ۙͷPHPϓϩδΣΫτͩͱී௨ʹ࢖ΘΕͯ
    ͍Δ

    View full-size slide

  45. ίʔυΛ࣮ߦ͠ͳ͍ͱݴͬͨͳɻ
    ͋Ε͸ӕͩɻ
    • PHPStan͸Ұ෦ίʔυΛ࣮ߦ͢Δ
    • "੩త"ͪΌ͏Μ͔ʔ͍
    • Phan͸autoload͕ઃఆͰ͖ͳ͍͕ɺ੩తղੳ
    Ͱ͋Δ͜ͱʹ஧࣮

    View full-size slide

  46. "࣮ߦ"͢ΔͷͰ
    • autoloadϑΝΠϧࣗମ͕exit͢Δͱphpstan΋
    Ϋϥογϡ͢Δ
    • autoloadʹΑͬͯݺͼग़͞ΕͨϑΝΠϧ͸

    ࣮ߦ͞Εͯ͠·͏

    View full-size slide

  47. PHPͷ੩తղੳͮ͠Β͍ͱ͜Ζ
    • ίϯύΠϧͱϥϯλΠϜͷڥք͕͸͖ͬΓ͠ͳ͍
    ఆٛ ࣮ߦ
    ఆٛ ࣮ߦ
    ఆٛ ࣮ߦ
    ఆٛ ࣮ߦ
    autoload
    autoload
    autoload

    View full-size slide

  48. ৘੎ͷมԽ

    View full-size slide

  49. "ϞμϯͳελΠϧ"ͷཱ֬
    • autoload͕ී௨ɻcomposerͷඪ४ʹै͏
    • ن໿ͱͯ͠PSR-1Λक͍ͬͯΔ͔ΒɺΫϥεఆ
    ٛʹ͸ఆٛҎ֎ͷ෭࡞༻͕ͳ͍͸ͣ

    View full-size slide

  50. PHPStanͷཱͪҐஔ
    • Ϋϥεϩʔυ͚ͩϥϯλΠϜΛڐ͢
    • "ϞμϯͳελΠϧʹ࠷దԽ"
    ఆٛ

    ߦ
    autoload
    ఆٛ

    ߦ
    ఆٛ
    ఆٛ
    autoload
    autoload

    View full-size slide

  51. ಘΒΕͨ΋ͷ
    • ಋೖͷ͠қ͞
    • ղੳͷߴ଎ੑ
    • গ͠ͷةݥੑ

    View full-size slide

  52. ݸਓతҙݟ
    • 100%੩తʹؤுΔͷͰ͸ͳ͘ɺಈత΋ࠞͥΔ
    • PHPΒͯ͘͠ɺ͍͍མͱ͠ॴͷπʔϧ
    • ܕએݴͷه๏ͷॆ࣮΍ɺPSR-1ͳͲͷจԽ͕Ͱ
    ͖͔ͨΒͦ͜ɺ࡞Εͨπʔϧ

    View full-size slide

  53. ୈ4෦
    ࣮ફɾܕ஫ऍ
    PHPStanʹΑΔܧଓత੩తղੳ

    View full-size slide

  54. PHPStanͷجຊಈ࡞
    • ίʔυʹॻ͍ͯ͋Δܕ஫ऍΛ΋ͱʹɺ͋Γ͑
    ͳ͍ૢ࡞Λ͍ͯͨ͠ΒΤϥʔʹ͢Δ
    • ܕ஫ऍ͕ஸೡͩͱɺݕࠪ΋ஸೡʹͳΔ
    • ܕʹର͢Δ஌͕ࣝ͋Δͱ͸͔ͲΔ

    View full-size slide

  55. ܕએݴͱPHPDoc
    • PHPͷܕ஫ऍ͸ࣗ༝౓͕௿͍
    • ͳͷͰɺPHPDocΛࠞͥͯ࢖͏
    • PHPStan͸ͲͪΒ΋ղऍͯ͘͠ΕΔ

    View full-size slide

  56. PHP7ͷܕએݴ
    • int, float, bool, string, array, Ϋϥε/Πϯλʔϑ
    Σʔε໊, callable, iterable
    • ?Λઌ಄ʹ͚ͭΔ/σϑΥϧτҾ਺Λnullʹ͢Δ
    ͱnullable

    View full-size slide

  57. εΧϥܕʹ஫ҙ
    • double͡Όͳͯ͘float
    • integer, boolean͡Όͳͯ͘int, bool
    • ؒҧ͑ΔͱΫϥε໊ͱͯ͠ղऍ͞ΕΔ

    View full-size slide

  58. PHPDoc
    • PHPެࣜͷػೳͰ͸ͳ͍
    ͕ɺ΄΅ඪ४͕͋Δ
    • docBlock (/** ~ */) Λؔ਺
    ͷ௚લʹهೖ

    View full-size slide

  59. PHPDocͷߏจ
    • @param ܕ໊ $ม਺໊ આ໌
    • εϖʔε۠੾ΓͳͷͰɺܕ໊ʹεϖʔεΛೖΕ
    ͯ͸͍͚ͳ͍
    • ܕ͸লུෆՄ
    • JavaDocͷͭ΋ΓͰॻ͘ͱจ๏Τϥʔ

    View full-size slide

  60. PHPDocಠࣗͷܕه๏
    • \DateTime[] ͳͲͷܕݻఆ഑ྻ
    • string|null ͳͲͷunion෩ه๏
    • true/false ΋ॻ͚Δ
    • @return $this
    • ϝιουνΣʔϯͷ໌ࣔ

    View full-size slide

  61. PHPStanͰunionͷݕࠪ
    →hoge() should return string
    but returns bool|string.

    View full-size slide

  62. PHPStanͰunionͷݕࠪ
    →hoge() should return string
    but returns false|string.

    View full-size slide

  63. PHPStanͰunionͷݕࠪ
    ݁ߏ͔͍͜͠ʂ

    View full-size slide

  64. PHPStanͰnullableͷݕࠪ
    • ?string ΍ string|null ͲͪΒ΋ೝࣝ͢Δ
    • ifจͰݕ͔ࠪͯ͠Βࢀর͢Ε͹ݕࠪOK

    View full-size slide

  65. ݱঢ়Ͱ͖ͳ͍͜ͱ
    • ܧঝؔ܎Λ͏·͘ѻ͑ͳ͍͜ͱ͕͋Δ

    (൓มɾڞม)
    • هड़Ͱ͖ͳ͍ܕ͕͍ͬͺ͍
    • ࿈૝഑ྻͷৄ͍͠هड़

    View full-size slide

  66. Ϧείϑͷஔ׵ݪଇ(LSP)
    • ܕΛ೿ੜͨ͠ͱ͖ɺ

    ΋ͱͷೳྗ͕ݮͬͨΒμϝ
    • ຬͨͯ͠Ε͹ϝιουΛ

    ্ॻ͖ͯ͠΋OK
    جఈ

    View full-size slide

  67. LSPతʹOKͳ্ॻ͖
    • ϝιουΛΦʔόʔϥΠυͨ͠ͱ͖ɺPHPެ
    ࣜͰ͸ܕએݴΛมߋͰ͖ͳ͍
    • 7.2Ͱܕফڈ͚ͩڐՄ͞Εͨ
    • PHPDoc + PHPStanͩͱνΣοΫ͞Εͳ͍

    View full-size slide

  68. هड़ํ๏͕ͳ͍ܕͷྫ
    • ArrayObject
    • function (int): int
    • [int, float] (࿈૝഑ྻͰ)

    View full-size slide

  69. ΫϥεͰؤுΕͳ͘΋ͳ͍
    Ҏ߱͸IntArrayͰܕΛهड़
    ࣮૷ʹ΋IntArrayΛ࢖͏

    View full-size slide

  70. ΫϥεͰؤுΕͳ͘΋ͳ͍
    callableͰ͸ͳ͘
    ΠϯλʔϑΣʔε
    ΫϩʔδϟͰ͸ͳ͘
    ແ໊Ϋϥε

    View full-size slide

  71. ʘ໘౗͍͘͞ʗ

    View full-size slide

  72. ʘHackͳΒͰ͖Δͷʹʂʗ

    View full-size slide

  73. ແཧʹؤுΔඞཁ͸ͳ͍

    View full-size slide

  74. ςετ͢Ε͹͍͍ΜͰ͢
    • PHP͸ಈతܕ෇͖ݴޠ
    • ࠔͬͨΒܕ஫ऍΛফͯ͠mixedʹ໭Ζ͏
    • ෆ҆ͳΒϢχοτςετ

    View full-size slide

  75. ·ͱΊ
    • PHP΋੩తղੳ͕͠΍͘͢ͳͬͨ
    • staticํ໘Λॆ࣮ͤ͞Ε͹ɺയવͱͨ͠ෆ͕҆
    ݮΒͤΔ
    • ಈతͱ੩తͷΦΠγΠͱ͜ΖΛ࢖͍ͬͯ͜͏

    View full-size slide

  76. ࢀߟจݙ
    • https://ja.wikipedia.org/wiki/ແݶϧʔϓ
    • PHPDocͷߏจ͸PSR-5͕ಡΈ΍͍͢

    https://github.com/php-fig/fig-standards/blob/
    master/proposed/phpdoc.md
    • https://ja.wikipedia.org/wiki/ڞมੑͱ൓มੑ
    _(ܭࢉػՊֶ)

    View full-size slide