Slide 1

Slide 1 text

© DMM.com !LHNZTIJO ,PUMJO'FTU LPUMJOMJOUFS

Slide 2

Slide 2 text

© DMM.com X w LHNZTIJOఝٶ ͗͘Έ΍  w "OESPJEΤϯδχΞ w ߹ಉձࣾ%..DPN$50ࣨॴଐ ࣗݾ঺հ

Slide 3

Slide 3 text

© DMM.com X ͜ͷηογϣϯͷΰʔϧ

Slide 4

Slide 4 text

© DMM.com X w ηογϣϯΛݟͨํʑ͕ɺ,PUMJO༻ͷ֤छ-JOUFSͷ࢖ ͍ํɺಛ௃Λཧղ͢Δ͜ͱ w ηογϣϯΛݟͨํʑ͕ɺ֤छ-JOUFSͷΧελϜ͠ ͨϧʔϧͷ࡞ΕΔΑ͏ʹͳΔ͜ͱ w ηογϣϯΛݟͨํʑ͕ɺ-JOUFSΛٕज़બఆ͢Δ৔ ߹ͷࡐྉʹͳΔ͜ͱ ͜ͷηογϣϯͷΰʔϧ

Slide 5

Slide 5 text

© DMM.com X BHFOEB

Slide 6

Slide 6 text

© DMM.com X w -JOUFSͱ͸ w LUMJOU w Πϯετʔϧํ๏ w ࢖͍ํ w ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ w ϧʔϧͷઃఆํ๏ w ΧελϜϧʔϧͷ࡞Γํ w ࡞ͬͨΧελϜϧʔϧͷద༻ํ๏ w ͦͷଞ w EFUFLU w BOESPJEMJOU w ·ͱΊ BHFOEB

Slide 7

Slide 7 text

© DMM.com X -JOUFSͱ͸

Slide 8

Slide 8 text

© DMM.com X –wikipedia l"MJOUFSPSMJOUSFGFSTUPUPPMTUIBUBOBMZ[FTPVSDF DPEFUPqBHQSPHSBNNJOHFSSPST CVHT TUZMJTUJD FSSPST BOETVTQJDJPVTDPOTUSVDUTz

Slide 9

Slide 9 text

© DMM.com X –wikipedia l-JOUFS΋͘͠͸-JOU͸ɺϓϩάϥϛϯάΤϥʔɺ όάɺॻࣜΤϥʔɺ͓ΑͼٙΘ͍͠ߏ଄ʹϑϥά ΛཱͯΔͨΊͷιʔείʔυΛ෼ੳ͢Δϓϩάϥ ϜͰ͋Δz

Slide 10

Slide 10 text

© DMM.com X LPUMJOͷMJOUFS LPUMJOͷMJOUFS͸ओʹ͸ೋͭɻͦͯ͠ɺBOESPJEͷඪ४MJOU ͕LPUMJOʹ΋ରԠ͍ͯ͠Δɻ w LUMJOU w EFUFLU w BOESPJEMJOU  ͜ͷ̏ͭʹ͍ͭͯઆ໌͍͖ͯ͠·͢ɻ

Slide 11

Slide 11 text

© DMM.com X LUMJOU

Slide 12

Slide 12 text

© DMM.com Πϯετʔϧํ๏

Slide 13

Slide 13 text

© DMM.com X Πϯετʔϧํ๏ $ curl -sSLO https://github.com/shyiko/ktlint/releases/download/ 0.27.0/ktlint && chmod a+x ktlint && sudo mv ktlint /usr/local/bin/ IUUQTHJUIVCDPNTIZJLPLUMJOUJOTUBMMBUJPO 3&"%.&ͷJOTUBMMBUJPOʹै͏ɻ

Slide 14

Slide 14 text

© DMM.com X HSBEMFΛ࢖͏৔߹ QMVHJO͕ೋͭ͋ΔʢQMVHJOͳ͠Ͱ΋ɺઃఆͰ͖Δʣ w IUUQTHJUIVCDPNKMMFJUTDIVILUMJOUHSBEMF w IUUQTHJUIVCDPNKFSFNZNBJMFOLPUMJOUFSHSBEMF ࣗ෼͸ALPMJOUFSHSBEMFAΛ࢖͍ͬͯΔɻ ٕज़બఆ౰࣌ɺLUMJOUHSBEMFͷํͰ͸DVTUPNSVMFΛద ༻Ͱ͖ͳ͔ͬͨͷ͕ཧ༝ɻ ݱࡏ͸ͦͷ໰୊͸ղফ͞Ε͍ͯΔͷͰɺͲͪΒͰ΋ྑ͞ ͦ͏ɻ

Slide 15

Slide 15 text

© DMM.com ࢖͍ํ

Slide 16

Slide 16 text

© DMM.com X ࢖͍ํ LUMJOU LU6OFYQFDUFETQBDJOHBGUFS  LU6OFYQFDUFETQBDJOHBGUFS  LU6OOFDFTTBSZTQBDF T  LU/FFEMFTTCMBOLMJOF T  LU6OFYQFDUFETQBDJOHBGUFS  LU6OFYQFDUFETQBDJOHBGUFS  LU.JTTJOHTQBDFBGUFS LU6OFYQFDUFETQBDJOHBGUFS   ίϚϯυΛଧ͚ͭͩɻΤϥʔݸॴͷҰཡ͕දࣔ͞ΕΔɻ

Slide 17

Slide 17 text

© DMM.com ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ

Slide 18

Slide 18 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ  TQBDFTGPSJOEFOUBUJPO  /PTFNJDPMPOT VOMFTTVTFEUPTFQBSBUFNVMUJQMFTUBUFNFOUTPOUIFTBNFMJOF   /PXJMEDBSEVOVTFEAJNQPSUAT  /PDPOTFDVUJWFCMBOLMJOFT  /PCMBOLMJOFTCFGPSFA^A  /PUSBJMJOHXIJUFTQBDFT  /PA6OJUASFUVSOT AGVOGO\^AJOTUFBEPGAGVOGO6OJU\^A   /PFNQUZ A\^A DMBTTCPEJFT  /PTQBDFTBSPVOESBOHF AA PQFSBUPS  /POFXMJOFCFGPSF CJOBSZ A AAA A A AA AA AA AccA  8IFOXSBQQJOHDIBJOFEDBMMTAA A ABOEA ATIPVMECFQMBDFEPOUIFOFYUMJOF  8IFOBMJOFJTCSPLFOBUBOBTTJHONFOU AA PQFSBUPSUIFCSFBLDPNFTBGUFSUIFTZNCPM  8IFODMBTTGVODUJPOTJHOBUVSFEPFTOUpUPOBTJOHMFMJOF FBDIQBSBNFUFSNVTUCFPOB TFQBSBUFMJOF  $POTJTUFOUTUSJOHUFNQMBUFT AWAJOTUFBEPGA\W^A A\QW^AJOTUFBEPGA\QWUP4USJOH ^A   $POTJTUFOUPSEFSPGNPEJpFST  $POTJTUFOUTQBDJOHBGUFSLFZXPSET DPNNBTBSPVOEDPMPOT DVSMZCSBDFT QBSFOT JOpY PQFSBUPST DPNNFOUT FUD  /FXMJOFBUUIFFOEPGFBDIpMF OPUFOBCMFECZEFGBVMU CVUSFDPNNFOEFE 

Slide 19

Slide 19 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ  Πϯσϯτ͸ͭ  ηϛίϩϯېࢭ  ϫΠϧυΧʔυJNQPSUɺ࢖༻ͯ͠ͳ͍JNQPSUېࢭ  ࿈ଓۭͨ͠ߦېࢭ  A^Aͷ௚લͷۭߦېࢭ  ຤ඌۭߦېࢭ  6OJUͷSFUVSOېࢭ  ۭͷΫϥεϘσΟA\^Aېࢭ  SBOHFΦϖϨʔλʔAAͷલޙʹۭനېࢭ A A AA A A AA AA AA AccAͷΦϖϨʔλͷ௚લʹ վߦېࢭ

Slide 20

Slide 20 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ AA A A A Aͷ௚ޙͰվߦېࢭ AAͷ௚લͰվߦېࢭ ෳ਺ύϥϝʔλͷ৔߹ɺશͯվߦ͢Δ͔ҰߦͰॻ͘ Ұ؏ͨ͠TUSJOHUFNQMBUFʢA\W^AͰ͸ͳͯ͘AWAɻ A\QWUP4USJOH ^AͰͳͯ͘A\QW^Aɻ  Ұ؏ͨ͠म০ࢠͷॱ൪ Ұ؏ͨ͠εϖʔγϯά ֤ϑΝΠϧͷ຤ඌʹվߦΛೖΕΔ σϑΥϧτͰPOʹͳͬͯ ͸ͳ͍͕ɺਪ঑ 

Slide 21

Slide 21 text

© DMM.com ϧʔϧͷઃఆํ๏

Slide 22

Slide 22 text

© DMM.com X ඪ४ϧʔϧͷઃఆํ๏ جຊతʹ֤ϧʔϧʹ͍ͭͯɺFOBCMFEJTBCMFͳͲͷ ઃఆ͸Ͱ͖ͳ͍ɻ ͨͩ͠ɺΠϯσϯταΠζͱϑΝΠϧ຤ඌվߦʹ͍ͭͯ ͸&EJUPS$POpHͰઃఆͰ͖Δɻ [*.{kt,kts}] indent_size=2 continuation_indent_size=2 insert_final_newline=true

Slide 23

Slide 23 text

© DMM.com X ඪ४ϧʔϧͷઃఆํ๏ ·ͨɺಛఆͷ৔ॴ͚ͩɺಛఆͷϧʔϧ΍શϧʔϧΛແࢹ ͢Δ͜ͱ͕Ͱ͖Δ import package.* // ktlint-disable no-wildcard-imports /* ktlint-disable parameter-list-wrapping */ data class A( val a: String, val b: String, val c: String ) /* ktlint-disable parameter-list-wrapping */ /* ktlint-disable */ : શ෦ແࢹ /* ktlint-disable */

Slide 24

Slide 24 text

© DMM.com ΧελϜϧʔϧͷ࡞Γํ

Slide 25

Slide 25 text

© DMM.com ·ͣ͸"45Λ஌Δ

Slide 26

Slide 26 text

© DMM.com X ·ͣ͸"45 ˺14* Λ஌Δ package yourpackage class Hoge { fun fuga(): Int = 2 + 3 }

Slide 27

Slide 27 text

© DMM.com X ·ͣ͸"45 ˺14* Λ஌Δ 'JMF 1"$,"(& %*3&$5*7& $-"44 FMFNFOU DMBTT 8)*5&@41"$& FMFNFOU
 *%&/5*'*&3 8)*5&@41"$& $-"44@#0%: package yourpackage class Hoge { fun fuga(): Int = 2 + 3 } πϦʔߏ଄Ͱղऍ͞ΕΔ

Slide 28

Slide 28 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢ΔΧελϜϧʔϧΛ࡞Δ࣌ fuga(1, 2) fuga( 1, 2 ) /( 0,

Slide 29

Slide 29 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢ΔΧελϜϧʔϧΛ࡞Δ࣌ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 /(ͷ࣌΋0,ͷ࣌΋ "45ͷπϦʔ͸͜ͷΑ͏ʹͳΔ Ұ෦୺ંͬͯ·͢    

Slide 30

Slide 30 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢ΔΧελϜϧʔϧΛ࡞Δ࣌ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5     0, վߦίʔυؚ͕·Ε͍ͯΔ̋

Slide 31

Slide 31 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢ΔΧελϜϧʔϧΛ࡞Δ࣌ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5     /( վߦίʔυؚ͕·Ε͍ͯͳ͍ʷ

Slide 32

Slide 32 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢ΔΧελϜϧʔϧΛ࡞Δ࣌ ΧελϜϧʔϧͷϩδοΫ͸ɺԼهΛ֬ೝ͢Δ w Լهͷߏ଄ʹͳ͍ͬͯΔͱ͖ʹ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 w $0.."ͷ࣍ͷ8)*5&@41"$&ʹվߦίʔυΛؚ·ΕΔ͜ͱ LUMJOUͰ΋EFUFLUͰ΋BOESPJEMJOUͰ΋ͲΕͰ΋ɺ ɹɹɹɹɹɹΧελϜϧʔϧ͸͜ͷΑ͏ʹͯ͠࡞͍͖ͬͯ·͢

Slide 33

Slide 33 text

© DMM.com X ͳΜͱͳ͘Θ͔͚ͬͨͲɺ ͦ΋ͦ΋πϦʔߏ଄͕Ͳ͏ͳͬͯΔͱ͔Θ͔ΒΜʜ

Slide 34

Slide 34 text

© DMM.com X େৎ෉ɺ๻΋Θ͔Γ·ͤΜ

Slide 35

Slide 35 text

© DMM.com X 1TJ7JFXFS࢖͍·͠ΐ͏ IUUQTQMVHJOTKFUCSBJOTDPNQMVHJOQTJWJFXFS

Slide 36

Slide 36 text

© DMM.com LUMJOUͰ$VTUPN-JOU

Slide 37

Slide 37 text

© DMM.com X αϯϓϧͱͯ͠ɺ͜ͷΧελϜϧʔϧΛ࡞Δ fuga(1, 2) fuga( 1, 2 ) /( 0, Ҿ਺ͰA A͕͋ͬͨΒվߦΛଅ͢

Slide 38

Slide 38 text

© DMM.com X खॱ  ςϯϓϨʔτΛDMPOFͯ͘͠Δ  3VMFΛ࡞Δ  3VMF4FU1SPWJEFSΛ࡞Δ  SFTPVSDFT.&5"*/'TFSWJDFT DPNHJUIVCTIZJLPLUMJOUDPSF3VMF4FU1SPWJEFSʹ࡞ͬͨ 3VMF4FU1SPWJEFSΛهड़  KBSΛ࡞Δ

Slide 39

Slide 39 text

© DMM.com X ςϯϓϨʔτΛDMPOFͯ͘͠Δ ςϯϓϨʔτ͕LUMJOUͷϦϙδτϦʹ༻ҙ͞Ε͍ͯΔͷͰɺ͜ ΕΛམͱͯ͘͠Δɻ IUUQTHJUIVCDPNTIZJLPLUMJOUCMPCNBTUFSLUMJOUSVMFTFU UFNQMBUF ෆཁͳαϯϓϧͳͲΛ࡟আͯ͠ɺ࡞੒։࢝ɻ

Slide 40

Slide 40 text

© DMM.com X 3VMFΛ࡞Δ abstract class Rule(val id: String) { ... abstract fun visit( node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit ) } ࡞Γ͍ͨ3VMFΛ࡞ͬͯߦ͘ɻ ΍Δ͜ͱ͸Ұͭɻ 3VMFΛܧঝͯ͠ɺWJTJUϝιουΛ࣮૷͢Δɻ

Slide 41

Slide 41 text

© DMM.com X WJTJUϝιου 'JMF 1"$,"(& %*3&$5*7& $-"44 FMFNFOU DMBTT 8)*5&@41"$& FMFNFOU
 *%&/5*'*&3 8)*5&@41"$& $-"44@#0%: WJTJU WJTJU WJTJU WJTJU WJTJU WJTJU WJTJU WJTJU "45ͷOPEFΛ্͔ΒॱʹḷͬͯWJTJUϝιου͕ݺ͹ΕΔ

Slide 42

Slide 42 text

© DMM.com X WJTJUϝιου WJTJUϝιουͰԼهͷϩδοΫΛॻ͘ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 w $0.."ͷ࣍ͷ8)*5&@41"$&ʹվߦίʔυ͕ͳ͍৔ ߹͸ܯࠂΛग़͢ w Լهͷߏ଄ʹͳ͍ͬͯΔ࣌ʹ

Slide 43

Slide 43 text

© DMM.com X ྫ͑͹͜Μͳײ͡ʹ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 7"-6& "3(6.&/5 -JTU ʹͨͲΓண͍ͨ࣌ WJTJU

Slide 44

Slide 44 text

© DMM.com X ྫ͑͹͜Μͳײ͡ʹ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 7"-6& "3(6.&/5 -JTU ʹͨͲΓண͍ͨ࣌ WJTJU DIJMESFOͷதʹ $0.."͕͍Δ৔߹ʹ

Slide 45

Slide 45 text

© DMM.com X ྫ͑͹͜Μͳײ͡ʹ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 7"-6& "3(6.&/5 -JTU ʹͨͲΓண͍ͨ࣌ WJTJU DIJMESFOͷதʹ $0.."͕͍Δ৔߹ʹ ࣍ͷۭന͕ վߦΛؚΉ͔ʁ

Slide 46

Slide 46 text

© DMM.com X ίʔυʹ͢Δͱ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_PARAMETER_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) } } }

Slide 47

Slide 47 text

© DMM.com X ίʔυʹ͢Δͱ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_ARGUMENT_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) } } } OPEF͕ 7"-6&@"3(6.&/5@-*45ͷ࣌ʹ

Slide 48

Slide 48 text

© DMM.com X ίʔυʹ͢Δͱ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_ARGUMENT_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) } } } OPEF͕ DIJMESFOͷதʹ$0.."͕͋Δ࣌ʹ

Slide 49

Slide 49 text

© DMM.com X ίʔυʹ͢Δͱ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_ARGUMENT_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) } } } ࣍ͷۭനʹ վߦؚ͕·Ε͍ͯΔ͔ʁ

Slide 50

Slide 50 text

© DMM.com X ίʔυʹ͢Δͱ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_PARAMETER_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) } } } վߦ͞Εͯ ͳ͔ͬͨΒ FNJUʂ

Slide 51

Slide 51 text

© DMM.com X 3VMF4FU1SPWJEFSΛ࡞Δ 3VMF4FU1SPWJEFSΛܧঝ͠ɺHFUϝιουΛ࣮૷͢Δɻ ࡞ͬͨ3VMFΛొ࿥͢Δɻ class CustomRuleSetProvider : RuleSetProvider { override fun get(): RuleSet = RuleSet("custom", LineBreakInArgsListRule()) }

Slide 52

Slide 52 text

© DMM.com X DPNHJUIVCTIZJLPLUMJOUDPSF3VMF4FU1SPWJEFS SFTPVSDFT.&5"*/'TFSWJDFT DPNHJUIVCTIZJLPLUMJOUDPSF3VMF4FU1SPWJEFSʹ࡞ͬͨ 3VMF4FU1SPWJEFSΛهड़ com.kgmyshin.ktlint.CustomRuleSetProvider

Slide 53

Slide 53 text

© DMM.com X KBSΛ࡞Δ KBSΛ࡞੒͢Δɻ ./gradlew jar CVJMEMJCT഑Լʹ࡞੒͞ΕΔɻ

Slide 54

Slide 54 text

© DMM.com ࡞ͬͨΧελϜϧʔϧΛద༻͢Δ

Slide 55

Slide 55 text

© DMM.com X ࡞ͬͨΧελϜϧʔϧΛద༻͢Δ $ ktlint -R ktlint-custom-rulseset.jar “src/main/**/*.kt" 3ͰKBSͷύεΛ౉͢ $ ktlint -R ktlint-custom-ruleset.jar “app/src/main/**/*.kt” ... Lint error > ...kt:43:17: should line break Lint error > ....kt:43:33: should line break ͦΕ͚ͩͰ0,ɻ

Slide 56

Slide 56 text

© DMM.com X LPUMJOUFSHSBEMFΛ࢖͍ͬͯΔ৔߹ buildscript { dependencies { classpath "gradle.plugin.org.jmailen.gradle:kotlinter-gradle:1.11.1" classpath files('lint/ktlint/ktlint-custom-ruleset.jar') } } DMBTTQBUIΛ௨͢ $ ./gradlew lintKotlin ... > Task :app:lintKotlinMain Lint error > ...kt:43:17: should line break Lint error > ....kt:43:33: should line break ͦΕ͚ͩͰ0,ɻ

Slide 57

Slide 57 text

© DMM.com ͦͷଞGPSNBUΛ͔͚Δ

Slide 58

Slide 58 text

© DMM.com X GPSNBUΛ͔͚Δ LUMJOU͸ܯࠂΛग़͚ͩ͢Ͱͳ͘ɺ͋Δఔ౓GPSNBUΛ͔͚Δ͜ͱ ͕Ͱ͖Δɻ LPMJOUFSHSBEMFͷ৔߹ $ ktlint -F “src/main/**/*.kt” $ ./gradlew formatKotlin

Slide 59

Slide 59 text

© DMM.com X GPSNBUΛ͔͚Δ data class A( val bb: String, val cc: String, val dd: String ) #FGPSF "GUFS data class A( val bb: String, val cc: String, val dd: String ) $ ./gradlew formatKotlin

Slide 60

Slide 60 text

© DMM.com X ΧελϜϧʔϧͷ৔߹ ΧελϜϧʔϧͷ৔߹Ͱ΋ɺGPSNBUΛ͔͚Δ͜ͱ͸Ͱ͖Δɻ ͨͩ͠ʢ΋ͪΖΜ͚ͩͲʣɺGPSNBUͷϩδοΫΛ࣮૷͢Δඞ ཁ͕͋Δɻ

Slide 61

Slide 61 text

© DMM.com X ઌ΄Ͳͷίʔυ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_PARAMETER_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) } } } GPSNBUΦϓγϣϯ͕͍ͭͯΔ࣌ UVSFʹͳΔ

Slide 62

Slide 62 text

© DMM.com X ઌ΄Ͳͷίʔυ override fun visit( node: ASTNode, autoCorrect: Boolean, emit: ( offset: Int, errorMessage: String, canBeAutoCorrected: Boolean ) -> Unit ) { if (node.elementType == KtNodeTypes.VALUE_PARAMETER_LIST) { val isError = node.children().any { it.elementType == KtTokens.COMMA && it.treeNext.elementType == KtTokens.WHITE_SPACE && !it.treeNext.text.contains("\n") } if (isError) { emit( node.startOffset, "should line break", false ) if (autoCorrect) { format(node) } } } } ௥Ճ

Slide 63

Slide 63 text

© DMM.com X GPSNBUϝιουͷத਎ private fun format(node: ASTNode) { val indent = node.indentSize() node.children().forEach { if (..লུ..) { (it.treeNext as LeafPsiElement).rawReplaceWithText( "\n" + " ".repeat(indent) ) } } } GPSNBUϝιουͷத਎ͷྫɻ ࣮ࡍͷOPEFͷ಺༰Λ௚઀ฤू͢Ε͹0,ɻ

Slide 64

Slide 64 text

© DMM.com X GPSNBUϝιουͷத਎ private fun format(node: ASTNode) { val indent = node.indentSize() node.children().forEach { if (..লུ..) { (it.treeNext as LeafPsiElement).rawReplaceWithText( "\n" + " ".repeat(indent) ) } } } GPSNBUϝιουͷத਎ͷྫɻ ࣮ࡍͷOPEFͷ಺༰Λ௚઀ฤू͢Ε͹0,ɻ

Slide 65

Slide 65 text

© DMM.com X ΧελϜϧʔϧͷ৔߹ data class A( val bb: String, val cc: String, val dd: String ) #FGPSF "GUFS data class A( val bb: String, val cc: String, val dd: String ) $ ./gradlew formatKotlin

Slide 66

Slide 66 text

© DMM.com X EFUFLU

Slide 67

Slide 67 text

© DMM.com Πϯετʔϧํ๏

Slide 68

Slide 68 text

© DMM.com X HSBEMFQSPKFDUʹಋೖ͢Δ৔߹ CVJMEHSBEMFʹԼهΛهड़ɻ buildscript { repositories { jcenter() } } plugins { id "io.gitlab.arturbosch.detekt" version "1.0.0.RC8" } detekt { version = "1.0.0.[version]" defaultProfile { input = file("src/main/kotlin") filters = ".*/resources/.*,.*/build/.*" } }

Slide 69

Slide 69 text

© DMM.com ࢖͍ํ

Slide 70

Slide 70 text

© DMM.com X ࢖͍ํ AHSBEMFXEFUFLU$IFDLAΛ࣮ߦ͢Δ͚ͩ

Slide 71

Slide 71 text

© DMM.com X ࢖͍ํ $ ./gradlew detektCheck : Ruleset: comments Ruleset: complexity - 20min debt LongMethod - 29/20 - [onCreate] at ...kt:45:3 Ruleset: detekt-custom-rules - 5min debt line-break-in-args-list - [A] at ...kt:42:13 : Overall debt: 25min Complexity Report: - 489 lines of code (loc) - 416 source lines of code (sloc) - 263 logical lines of code (lloc) - 3 comment lines of code (cloc) - 46 McCabe complexity (mcc) - 2 number of total code smells - 0 % comment source ratio - 174 mcc per 1000 lloc - 7 code smells per 1000 lloc Project Statistics: - number of properties: 32 - number of functions: 24 - number of classes: 26 - number of packages: 3 - number of kt files: 12 : detekt finished in 1804 ms.

Slide 72

Slide 72 text

© DMM.com X HSBEMFQSPKFDUʹಋೖ͢Δ৔߹ $ ./gradlew detektCheck : Ruleset: comments Ruleset: complexity - 20min debt LongMethod - 29/20 - [onCreate] at ...kt:45:3 Ruleset: detekt-custom-rules - 5min debt line-break-in-args-list - [A] at ...kt:42:13 : Overall debt: 25min Complexity Report: - 489 lines of code (loc) - 416 source lines of code (sloc) - 263 logical lines of code (lloc) - 3 comment lines of code (cloc) - 46 McCabe complexity (mcc) - 2 number of total code smells - 0 % comment source ratio - 174 mcc per 1000 lloc - 7 code smells per 1000 lloc Project Statistics: - number of properties: 32 - number of functions: 24 - number of classes: 26 - number of packages: 3 - number of kt files: 12 : detekt finished in 1804 ms. -JOUͷ݁Ռ

Slide 73

Slide 73 text

© DMM.com X HSBEMFQSPKFDUʹಋೖ͢Δ৔߹ $ ./gradlew detektCheck : Ruleset: comments Ruleset: complexity - 20min debt LongMethod - 29/20 - [onCreate] at ...kt:45:3 Ruleset: detekt-custom-rules - 5min debt line-break-in-args-list - [A] at ...kt:42:13 : Overall debt: 25min Complexity Report: - 489 lines of code (loc) - 416 source lines of code (sloc) - 263 logical lines of code (lloc) - 3 comment lines of code (cloc) - 46 McCabe complexity (mcc) - 2 number of total code smells - 0 % comment source ratio - 174 mcc per 1000 lloc - 7 code smells per 1000 lloc Project Statistics: - number of properties: 32 - number of functions: 24 - number of classes: 26 - number of packages: 3 - number of kt files: 12 : detekt finished in 1804 ms. -JOUͷमਖ਼ʹ͔͔Δ࣌ؒ

Slide 74

Slide 74 text

© DMM.com X HSBEMFQSPKFDUʹಋೖ͢Δ৔߹ $ ./gradlew detektCheck : Ruleset: comments Ruleset: complexity - 20min debt LongMethod - 29/20 - [onCreate] at ...kt:45:3 Ruleset: detekt-custom-rules - 5min debt line-break-in-args-list - [A] at ...kt:42:13 : Overall debt: 25min Complexity Report: - 489 lines of code (loc) - 416 source lines of code (sloc) - 263 logical lines of code (lloc) - 3 comment lines of code (cloc) - 46 McCabe complexity (mcc) - 2 number of total code smells - 0 % comment source ratio - 174 mcc per 1000 lloc - 7 code smells per 1000 lloc Project Statistics: - number of properties: 32 - number of functions: 24 - number of classes: 26 - number of packages: 3 - number of kt files: 12 : detekt finished in 1804 ms. ෳࡶ౓

Slide 75

Slide 75 text

© DMM.com X HSBEMFQSPKFDUʹಋೖ͢Δ৔߹ $ ./gradlew detektCheck : Ruleset: comments Ruleset: complexity - 20min debt LongMethod - 29/20 - [onCreate] at ...kt:45:3 Ruleset: detekt-custom-rules - 5min debt line-break-in-args-list - [A] at ...kt:42:13 : Overall debt: 25min Complexity Report: - 489 lines of code (loc) - 416 source lines of code (sloc) - 263 logical lines of code (lloc) - 3 comment lines of code (cloc) - 46 McCabe complexity (mcc) - 2 number of total code smells - 0 % comment source ratio - 174 mcc per 1000 lloc - 7 code smells per 1000 lloc Project Statistics: - number of properties: 32 - number of functions: 24 - number of classes: 26 - number of packages: 3 - number of kt files: 12 : detekt finished in 1804 ms. ϑΝΠϧ਺ͳͲͷϨϙʔτ

Slide 76

Slide 76 text

© DMM.com ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ

Slide 77

Slide 77 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ͸͍ͬͺ͍͋Δ  $IBJO8SBQQJOH  $MBTT/BNJOH  $PNNFOU4QBDJOH  $PNQMFY$POEJUJPO  $PNQMFY.FUIPE  %VQMJDBUF$BTF*O8IFO&YQSFTTJPO  &NQUZ$BUDI#MPDL  &NQUZ$MBTT#MPDL  &NQUZ%FGBVMU$POTUSVDUPS  &NQUZ%P8IJMF#MPDL  &NQUZ&MTF#MPDL  &NQUZ'JOBMMZ#MPDL  &NQUZ'PS#MPDL  &NQUZ'VODUJPO#MPDL  &NQUZ*G#MPDL  &NQUZ*OJU#MPDL  &NQUZ,U'JMF  &NQUZ4FDPOEBSZ$POTUSVDUPS  &NQUZ8IFO#MPDL  &NQUZ8IJMF#MPDL  &OVN/BNJOH  &RVBMT8JUI)BTI$PEF&YJTU  &YQMJDJU(BSCBHF$PMMFDUJPO$BMM  'JMFOBNF  'JOBM/FXMJOF  'PSCJEEFO$PNNFOU  'PS&BDI0O3BOHF  'VODUJPO/BNJOH  *NQPSU0SEFSJOH  *OEFOUBUJPO  -BSHF$MBTT  -POH.FUIPE  -POH1BSBNFUFS-JTU  .BHJD/VNCFS  .BUDIJOH%FDMBSBUJPO/BNF  .BYJNVN-JOF-FOHUI  .BY-JOF-FOHUI  .PEJpFS0SEFS  .PEJpFS0SEF  /FTUFE#MPDL%  /FX-JOF"U&O  /P#MBOL-JOF#  /P$POTFDVUJW  /P&NQUZ$MBT  /P*U1BSBN*O.  /P-JOF#SFBL"  /P-JOF#SFBL#  /P.VMUJQMF4Q  /P4FNJDPMPO  /P5SBJMJOH4QB  /P6OJU3FUVSO  /P6OVTFE*N  /P8JMEDBSE*N  0CKFDU1SPQFS  0QUJPOBM"CTUS  1BDLBHF/BN  1BSBNFUFS-JT

Slide 78

Slide 78 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ͸͍ͬͺ͍͋Δ  $IBJO8SBQQJOH  $MBTT/BNJOH  $PNNFOU4QBDJOH  $PNQMFY$POEJUJPO  $PNQMFY.FUIPE  %VQMJDBUF$BTF*O8IFO&YQSFTTJPO  &NQUZ$BUDI#MPDL  &NQUZ$MBTT#MPDL  &NQUZ%FGBVMU$POTUSVDUPS  &NQUZ%P8IJMF#MPDL  &NQUZ&MTF#MPDL  &NQUZ'JOBMMZ#MPDL  &NQUZ'PS#MPDL  &NQUZ'VODUJPO#MPDL  &NQUZ*G#MPDL  &NQUZ*OJU#MPDL  &NQUZ,U'JMF  &NQUZ4FDPOEBSZ$POTUSVDUPS  &NQUZ8IFO#MPDL  &NQUZ8IJMF#MPDL  &OVN/BNJOH  &RVBMT8JUI)BTI$PEF&YJTU  &YQMJDJU(BSCBHF$PMMFDUJPO$BMM  'JMFOBNF  'JOBM/FXMJOF  'PSCJEEFO$PNNFOU  'PS&BDI0O3BOHF  'VODUJPO/BNJOH  *NQPSU0SEFSJOH  *OEFOUBUJPO  -BSHF$MBTT  -POH.FUIPE  -POH1BSBNFUFS-JTU  .BHJD/VNCFS  .BUDIJOH%FDMBSBUJPO/BNF  .BYJNVN-JOF-FOHUI  .BY-JOF-FOHUI  .PEJpFS0SEFS  .PEJpFS0SEF  /FTUFE#MPDL%  /FX-JOF"U&O  /P#MBOL-JOF#  /P$POTFDVUJW  /P&NQUZ$MBT  /P*U1BSBN*O.  /P-JOF#SFBL"  /P-JOF#SFBL#  /P.VMUJQMF4Q  /P4FNJDPMPO  /P5SBJMJOH4QB  /P6OJU3FUVSO  /P6OVTFE*N  /P8JMEDBSE*N  0CKFDU1SPQFS  0QUJPOBM"CTUS  1BDLBHF/BN  1BSBNFUFS-JT EFGBVMUͰBDUJWFʹͳ͍ͬͯΔ΋ͷΛ ਺͑Δͱݸʂ

Slide 79

Slide 79 text

© DMM.com ϧʔϧͷઃఆํ๏

Slide 80

Slide 80 text

© DMM.com X ·ͣ͸DPOpHϑΝΠϧΛ࡞Δ HFOFSBUFίϚϯυΛ࣮ߦ͢Δͱɺ ɹɹɹɹɹɹɹɹɹɹɹEFGBVMUEFUFLUDPOpHZNM͕Ͱ͖Δ HSBEMFXEFUFLU(FOFSBUF$POpH

Slide 81

Slide 81 text

© DMM.com X ·ͣ͸DPOpHϑΝΠϧΛ࡞Δ …লུ… style: active: true CollapsibleIfStatements: active: false DataClassContainsFunctions: active: false conversionFunctionPrefix: 'to' EqualsNullCall: active: false ExpressionBodySyntax: active: false includeLineWrapping: false ForbiddenComment: active: true values: 'TODO:,FIXME:,STOPSHIP:' ForbiddenImport: active: false imports: '' FunctionOnlyReturningConstant: active: false ignoreOverridableFunction: true excludedFunctions: 'describeContents'

Slide 82

Slide 82 text

© DMM.com X ·ͣ͸DPOpHϑΝΠϧΛ࡞Δ …লུ… style: active: true CollapsibleIfStatements: active: false DataClassContainsFunctions: active: false conversionFunctionPrefix: 'to' EqualsNullCall: active: false ExpressionBodySyntax: active: false includeLineWrapping: false ForbiddenComment: active: true values: 'TODO:,FIXME:,STOPSHIP:' ForbiddenImport: active: false imports: '' FunctionOnlyReturningConstant: active: false ignoreOverridableFunction: true excludedFunctions: 'describeContents' 3VMF4FU

Slide 83

Slide 83 text

© DMM.com X ·ͣ͸DPOpHϑΝΠϧΛ࡞Δ …লུ… style: active: true CollapsibleIfStatements: active: false DataClassContainsFunctions: active: false conversionFunctionPrefix: 'to' EqualsNullCall: active: false ExpressionBodySyntax: active: false includeLineWrapping: false ForbiddenComment: active: true values: 'TODO:,FIXME:,STOPSHIP:' ForbiddenImport: active: false imports: '' FunctionOnlyReturningConstant: active: false ignoreOverridableFunction: true excludedFunctions: 'describeContents' 3VMF

Slide 84

Slide 84 text

© DMM.com X ·ͣ͸DPOpHϑΝΠϧΛ࡞Δ …লུ… style: active: true CollapsibleIfStatements: active: false DataClassContainsFunctions: active: false conversionFunctionPrefix: 'to' EqualsNullCall: active: false ExpressionBodySyntax: active: false includeLineWrapping: false ForbiddenComment: active: true values: 'TODO:,FIXME:,STOPSHIP:' ForbiddenImport: active: false imports: '' FunctionOnlyReturningConstant: active: false ignoreOverridableFunction: true excludedFunctions: 'describeContents' GBMTF ݸผʹ ઃఆͰ͖Δ

Slide 85

Slide 85 text

© DMM.com ΧελϜϧʔϧͷ࡞Γํ

Slide 86

Slide 86 text

© DMM.com X αϯϓϧͱͯ͠ɺ͜ͷϧʔϧΛͭ͘Δ fuga(1, 2) fuga( 1, 2 ) /( 0, Ҿ਺ͰA A͕͋ͬͨΒվߦΛଅ͢

Slide 87

Slide 87 text

© DMM.com X खॱ  ϓϩδΣΫτ࡞੒  3VMFΛ࡞Δ  3VMF4FU1SPWJEFSΛ࡞Δ  SFTPVSDFT.&5"*/'TFSWJDFT JPHJUMBCBSUVSCPTDIEFUFLUBQJ3VMF4FU1SPWJEFSʹ࡞ͬͨ 3VMF4FU1SPWJEFSΛهड़  KBSΛ࡞Δ

Slide 88

Slide 88 text

© DMM.com X ϓϩδΣΫτ࡞੒ buildscript { ext.kotlin_version = '1.2.60' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } group 'detekt-custom-lint' version '1.0-SNAPSHOT' apply plugin: 'kotlin' repositories { mavenCentral() } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "io.gitlab.arturbosch.detekt:detekt-api:1.0.0.RC8" testCompile "junit:junit:4.12" testCompile "org.assertj:assertj-core:3.10.0" testCompile "io.gitlab.arturbosch.detekt:detekt-api:1.0.0.RC8" testCompile "io.gitlab.arturbosch.detekt:detekt-test:1.0.0.RC8" }

Slide 89

Slide 89 text

© DMM.com X ϓϩδΣΫτ࡞੒ buildscript { ext.kotlin_version = '1.2.60' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } group 'detekt-custom-lint' version '1.0-SNAPSHOT' apply plugin: 'kotlin' repositories { mavenCentral() } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "io.gitlab.arturbosch.detekt:detekt-api:1.0.0.RC8" testCompile "junit:junit:4.12" testCompile "org.assertj:assertj-core:3.10.0" testCompile "io.gitlab.arturbosch.detekt:detekt-api:1.0.0.RC8" testCompile "io.gitlab.arturbosch.detekt:detekt-test:1.0.0.RC8" } LPUMJOͷϓϩδΣΫτΛ࡞ͬͯ EFUFLUBQJΛ௥Ճ

Slide 90

Slide 90 text

© DMM.com X 3VMFΛ࡞Δ ࡞Γ͍ͨ3VMFΛ࡞ͬͯߦ͘ɻ 3VMFΛܧঝͯ͠ɺJTTVFΛ࡞੒ͯ͠ɺద੾ͳWJTJUϝιουΛ࣮ ૷͢ΔɻʢLUMJOUͱҟͳΓෳ਺ͷWJTJUϝιου͕͋Δʣ

Slide 91

Slide 91 text

© DMM.com X ·ͣ͸JTTVFΛ࡞Δ class LineBreakInArgsListDetektRule : Rule() { override val issue: Issue = Issue( id = "line-break-in-args-list", severity = Severity.Style, debt = Debt.FIVE_MINS, description = "should line break" ) } *E ΧςΰϦɺमਖ਼͔͔Δ࣌ؒɺઆ໌ΛҾ਺ʹ*TTVFͷΠϯελ ϯεΛ࡞Δɻ

Slide 92

Slide 92 text

© DMM.com X 3VMFΛ࡞Δ LUMJOUͱҟͳΓෳ਺ͷWJTJUϝιου͕͋Δɻ 'JMF 1"$,"(& %*3&$5*7& $-"44 FMFNFOU DMBTT 8)*5&@41"$& FMFNFOU
 *%&/5*'*&3 8)*5&@41"$& $-"44@#0%: WJTJU'JMF WJTJU1BDLBHF%JSFDUJWF WJTJU$MBTT WJTJU$MBTT#PEZ

Slide 93

Slide 93 text

© DMM.com X 3VMFΛ࡞Δ ͜ΕΛ֬ೝͯ͠ߦ͘ɻ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 w $0.."ͷ࣍ͷ8)*5&@41"$&ʹվߦίʔυΛؚ·ΕΔ͜ͱ w Լهͷߏ଄ʹͳ͍ͬͯΔ࣌ʹ

Slide 94

Slide 94 text

© DMM.com X 3VMFΛ࡞Δ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5

Slide 95

Slide 95 text

© DMM.com X 3VMFΛ࡞Δ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 WJTJU7BMVF"SHVNFOU-JTU WJTJU7BMVF"SHVNFOU-JTUΛ࣮૷͢Δ

Slide 96

Slide 96 text

© DMM.com X 3VMFΛ࡞Δ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 WJTJU7BMVF"SHVNFOU-JTU $0.."ͷ࣍ͷ WJTJU7BMVF"SHVNFOU-JTUΛ࣮૷͢Δ

Slide 97

Slide 97 text

© DMM.com X 3VMFΛ࡞Δ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 WJTJU7BMVF"SHVNFOU-JTU $0.."ͷ࣍ͷ ۭന಺Ͱ վߦ͞ΕͯΔ͔ʁʁʁ WJTJU7BMVF"SHVNFOU-JTUΛ࣮૷͢Δ

Slide 98

Slide 98 text

© DMM.com X 3VMFΛ࡞Δ class LineBreakInArgsListDetektRule : Rule() { override val issue: Issue = Issue( id = "line-break-in-args-list", severity = Severity.Style, debt = Debt.FIVE_MINS, description = "should line break" ) override fun visitValueArgumentList(list: KtValueArgumentList) { super.visitValueArgumentList(list) list.children.forEach { if (it.node.elementType == KtTokens.COMMA && it.nextSibling is PsiWhiteSpace && !it.nextSibling.text.contains("\n") ) { report( CodeSmell( issue, Entity.from(list), "should line break" ) ) return } } } } վߦ͕ͳ͍৔߹͸ɺSFQPSUϝιουΛݺͿɻ

Slide 99

Slide 99 text

© DMM.com X 3VMFΛ࡞Δ class LineBreakInArgsListDetektRule : Rule() { override val issue: Issue = Issue( id = "line-break-in-args-list", severity = Severity.Style, debt = Debt.FIVE_MINS, description = "should line break" ) override fun visitValueArgumentList(list: KtValueArgumentList) { super.visitValueArgumentList(list) list.children.forEach { if (it.node.elementType == KtTokens.COMMA && it.nextSibling is PsiWhiteSpace && !it.nextSibling.text.contains("\n") ) { report( CodeSmell( issue, Entity.from(list), "should line break" ) ) return } } } } վߦ͕ͳ͍৔߹͸ɺSFQPSUϝιουΛݺͿɻ $0.."ͷ ࣍ͷ8)*5&@41"$&͕վߦΛ ؚ·ͳ͍৔߹

Slide 100

Slide 100 text

© DMM.com X 3VMFΛ࡞Δ class LineBreakInArgsListDetektRule : Rule() { override val issue: Issue = Issue( id = "line-break-in-args-list", severity = Severity.Style, debt = Debt.FIVE_MINS, description = "should line break" ) override fun visitValueArgumentList(list: KtValueArgumentList) { super.visitValueArgumentList(list) list.children.forEach { if (it.node.elementType == KtTokens.COMMA && it.nextSibling is PsiWhiteSpace && !it.nextSibling.text.contains("\n") ) { report( CodeSmell( issue, Entity.from(list), "should line break" ) ) return } } } } վߦ͕ͳ͍৔߹͸ɺSFQPSUϝιουΛݺͿɻ SFQPSU͢Δ

Slide 101

Slide 101 text

© DMM.com X 3VMF4FU1SPWJEFSΛ࡞Δ 3VMF4FU1SPWJEFSΛܧঝ͠ɺJOTUBODFϝιουΛ࣮૷͢Δɻ ࡞ͬͨ3VMFΛొ࿥͢Δɻ class CustomRuleSetProvider : RuleSetProvider { override val ruleSetId: String = "detekt-custom-rules" override fun instance(config: Config): RuleSet = RuleSet( ruleSetId, listOf(LineBreakInArgsListDetektRule()) ) }

Slide 102

Slide 102 text

© DMM.com X DPNHJUIVCTIZJLPLUMJOUDPSF3VMF4FU1SPWJEFS SFTPVSDFT.&5"*/'TFSWJDFT JPHJUMBCBSUVSCPTDIEFUFLUBQJ3VMF4FU1SPWJEFSʹ࡞ͬͨ 3VMF4FU1SPWJEFSΛهड़ com.kgmyshin.ktlint.CustomRuleSetProvider

Slide 103

Slide 103 text

© DMM.com X KBSΛ࡞Δ KBSΛ࡞੒͢Δɻ ./gradlew jar CVJMEMJCT഑Լʹ࡞੒͞ΕΔɻ

Slide 104

Slide 104 text

© DMM.com ࡞ͬͨΧελϜϧʔϧΛద༻͢Δ

Slide 105

Slide 105 text

© DMM.com X ࡞ͬͨΧελϜϧʔϧΛద༻͢Δ dependencies { … detekt files("detekt-custom-lint.jar") } EFQFOEFODJFTʹEFUFLUDPOpHVSBUJPOʹKBSΛ௥Ճ͢Δ $ ./gradlew detektCheck : Ruleset: detekt-custom-rules - 5min debt line-break-in-args-list - [A] at ...kt:42:13 ͦΕ͚ͩͰ0,ɻ

Slide 106

Slide 106 text

© DMM.com ͦͷଞGPSNBUΛ͔͚Δ

Slide 107

Slide 107 text

© DMM.com X BVUP$PSSFDU1SPQFSUZ l5IJTPQUJPOJTTUJMMQSFTFOUEVFUPMFHBDZ SFBTPOT*OUIFpSTUNJMFTUPOFSFMFBTFTEFUFLU BMTPGPSNBUUFELPUMJODPEF8JUIJOUIFEFUFLU UFBNXFEFDJEFEUPOPUNFTTXJUIVTFSDPEFBOE MFUPUIFSUPPMTEPUIFGPSNBUUJOHFHJOUFMMJKPS ,U-JOU4UJMMBTEFUFLUDBOCFFYUFOEFEXJUI DVTUPNSVMFT ZPVBSFGSFFUPXSJUFSVMFTXIJDI TVQQPSUBVUPDPSSFDUJPO0OMZXSJUFDPSSFDUJOH DPEFXJUIJOUIFXJUI"VUP$PSSFDU GVODUJPOz IUUQTHJUIVCDPNBSUVSCPTDIEFUFLUCMPCNBTUFSEPDTQBHFTDPOpHVSBUJPOTNEBVUPDPSSFDUQSPQFSUZ

Slide 108

Slide 108 text

© DMM.com X BVUP$PSSFDU1SPQFSUZ w ࠷ॳͷϚΠϧετʔϯͰ͸ϑΥʔϚοτػೳ͸͋ͬͨ w EFUFLUνʔϜ͸ɺࠞཚΛ͚͞ΔͨΊϑΥʔϚοτػೳ Λͳͨ͘͠ w ͨͩ͠ɺΧελϜϧʔϧͰϑΥʔϚοτΛ͢Δ͜ͱ͕ Ͱ͖Δɻ w XJUI"VUP$PSSFDUϝιου಺ʹ࣮૷͍ͯͩ͘͠͞

Slide 109

Slide 109 text

© DMM.com X ΧελϜϧʔϧͰXJUI"VUP$PSSFDUΛ࢖͏ override fun visitValueArgumentList(list: KtValueArgumentList) { super.visitValueArgumentList(list) list.children.forEach { if (it.nextSibling.node.elementType == KtTokens.COMMA && it.nextSibling.nextSibling is PsiWhiteSpace && !it.nextSibling.nextSibling.text.contains("\n") ) { report( CodeSmell( issue, Entity.from(list), "should line break" ) ) withAutoCorrect { format(list) } return } } } } DPOJGHͰABVUP$PSSFDUUVSFAͱͳ͍ͬͯΔ͚࣌ͩ ϑΥʔϚοτ͞ΕΔ

Slide 110

Slide 110 text

© DMM.com X ΧελϜϧʔϧͰXJUI"VUP$PSSFDUΛ࢖͏ override fun visitValueArgumentList(list: KtValueArgumentList) { super.visitValueArgumentList(list) list.children.forEach { if (it.nextSibling.node.elementType == KtTokens.COMMA && it.nextSibling.nextSibling is PsiWhiteSpace && !it.nextSibling.nextSibling.text.contains("\n") ) { report( CodeSmell( issue, Entity.from(list), "should line break" ) ) withAutoCorrect { format(list) } return } } } } DPOJGHͰABVUP$PSSFDUUVSFAͱͳ͍ͬͯΔ͚࣌ͩ ϑΥʔϚοτ͞ΕΔ

Slide 111

Slide 111 text

© DMM.com ͪͳΈʹ

Slide 112

Slide 112 text

© DMM.com X EFUFDUGPSNBUUJOH EFUFLUGPSNBUUJOHΛCVJMEHSBEMF಺ͰEFUFLUDPOpHVSBUJPOʹࢦ ఆ͢Δ͜ͱͰ,UMJOUͷඪ४ϧʔϧΛ௥ՃͰ͖Δ dependencies { detekt “io.gitlab.arturbosch.detekt:detekt-formatting:1.0.0.RC8" } ˞GPSNBUͨ͠Γͱ͔͸ಛʹؔ܎ͳ͍Ͱ͢

Slide 113

Slide 113 text

© DMM.com X BOESPJEMJOU

Slide 114

Slide 114 text

© DMM.com ࢖͍ํ

Slide 115

Slide 115 text

© DMM.com X ࢖͍ํ HSBEMFXMJOU ʜ 3BOMJOUPOWBSJBOUEFCVHJTTVFTGPVOE 3BOMJOUPOWBSJBOUSFMFBTFJTTVFTGPVOE 8SPUF)5.-SFQPSUUPpMFCVJMESFQPSUTMJOUSFTVMUTIUNM 8SPUF9.-SFQPSUUPpMFCVJMESFQPSUTMJOUSFTVMUTYNM ʜ BOESPJEϓϩδΣΫτͰMJOUλεΫΛ࣮ߦ͢Δɻ

Slide 116

Slide 116 text

© DMM.com X ࢖͍ํ BOESPJEϓϩδΣΫτͰMJOUλεΫΛ࣮ߦ͢Δɻ

Slide 117

Slide 117 text

© DMM.com ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ

Slide 118

Slide 118 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ͸͍ͬͺ͍͋Δ  "DDFTTJCJMJUZ%FUFDUPS  "EE+BWBTDSJQU*OUFSGBDF%FUFDUPS  "MBSN%FUFDUPS  "MXBZT4IPX"DUJPO%FUFDUPS  "OOPUBUJPO%FUFDUPS  "QJ%FUFDUPS  "QQ$PNQBU$BMM%FUFDUPS  "QQ$PNQBU3FTPVSDF%FUFDUPS  "QQ*OEFYJOH"QJ%FUFDUPS  "SSBZ4J[F%FUFDUPS  "TTFSU%FUFDUPS  #VJMUJO*TTVF3FHJTUSZ  #VUUPO%FUFDUPS  #ZUF0SEFS.BSL%FUFDUPS  $BMM4VQFS%FUFDUPS  $IJME$PVOU%FUFDUPS  $JQIFS(FU*OTUBODF%FUFDUPS  $MFBOVQ%FUFDUPS  $MJDLBCMF7JFX"DDFTTJCJMJUZ%FUFDUPS  $PNNFOU%FUFDUPS  $POUSPM'MPX(SBQI  $VTUPN7JFX%FUFDUPS  $VU1BTUF%FUFDUPS  %BUF'PSNBU%FUFDUPS  %FQSFDBUJPO%FUFDUPS  %FUFDU.JTTJOH1SFpY  %PT-JOF&OEJOH%FUFDUPS  %VQMJDBUF*E%FUFDUPS  %VQMJDBUF3FTPVSDF%FUFDUPS  &YUSB5FYU%FUFDUPS  'JFME(FUUFS%FUFDUPS  'SBHNFOU%FUFDUPS  'VMM#BDLVQ$POUFOU%FUFDUPS  (FU4JHOBUVSFT%FUFDUPS  (SBEMF%FUFDUPS  (SJE-BZPVU%FUFDUPS  )BOEMFS%FUFDUPS  )BSEDPEFE%FCVH.PEF%FUFDUPS  )BSEDPEFE7B  *DPO%FUFDUPS  *ODMVEF%FUFD  *OF⒏DJFOU8F  *OWBMJE1BDLBH  +BWB1FSGPSNB  +BWB4DSJQU*OUF  -BCFM'PS%FUF  -BZPVU$POTJT  -BZPVU*OqBUJP  -PDBMF%FUFDU  -PDBMF'PMEFS%  -PH%FUFDUPS  .BOJGFTU%FUF  .BOJGFTU5ZQP  .BUI%FUFDUP  .FSHF3PPU'SB  .JTTJOH$MBTT  .JTTJOH*E%FU

Slide 119

Slide 119 text

© DMM.com X ඪ४Ͱ༻ҙ͞Ε͍ͯΔϧʔϧ͸͍ͬͺ͍͋Δ  "DDFTTJCJMJUZ%FUFDUPS  "EE+BWBTDSJQU*OUFSGBDF%FUFDUPS  "MBSN%FUFDUPS  "MXBZT4IPX"DUJPO%FUFDUPS  "OOPUBUJPO%FUFDUPS  "QJ%FUFDUPS  "QQ$PNQBU$BMM%FUFDUPS  "QQ$PNQBU3FTPVSDF%FUFDUPS  "QQ*OEFYJOH"QJ%FUFDUPS  "SSBZ4J[F%FUFDUPS  "TTFSU%FUFDUPS  #VJMUJO*TTVF3FHJTUSZ  #VUUPO%FUFDUPS  #ZUF0SEFS.BSL%FUFDUPS  $BMM4VQFS%FUFDUPS  $IJME$PVOU%FUFDUPS  $JQIFS(FU*OTUBODF%FUFDUPS  $MFBOVQ%FUFDUPS  $MJDLBCMF7JFX"DDFTTJCJMJUZ%FUFDUPS  $PNNFOU%FUFDUPS  $POUSPM'MPX(SBQI  $VTUPN7JFX%FUFDUPS  $VU1BTUF%FUFDUPS  %BUF'PSNBU%FUFDUPS  %FQSFDBUJPO%FUFDUPS  %FUFDU.JTTJOH1SFpY  %PT-JOF&OEJOH%FUFDUPS  %VQMJDBUF*E%FUFDUPS  %VQMJDBUF3FTPVSDF%FUFDUPS  &YUSB5FYU%FUFDUPS  'JFME(FUUFS%FUFDUPS  'SBHNFOU%FUFDUPS  'VMM#BDLVQ$POUFOU%FUFDUPS  (FU4JHOBUVSFT%FUFDUPS  (SBEMF%FUFDUPS  (SJE-BZPVU%FUFDUPS  )BOEMFS%FUFDUPS  )BSEDPEFE%FCVH.PEF%FUFDUPS  )BSEDPEFE7B  *DPO%FUFDUPS  *ODMVEF%FUFD  *OF⒏DJFOU8F  *OWBMJE1BDLBH  +BWB1FSGPSNB  +BWB4DSJQU*OUF  -BCFM'PS%FUF  -BZPVU$POTJT  -BZPVU*OqBUJP  -PDBMF%FUFDU  -PDBMF'PMEFS%  -PH%FUFDUPS  .BOJGFTU%FUF  .BOJGFTU5ZQP  .BUI%FUFDUP  .FSHF3PPU'SB  .JTTJOH$MBTT  .JTTJOH*E%FU YNM KBWB LPUMJOͱ͍ΖΜͳSVMF͕ ࠞࡏ͍ͯ͠Δ

Slide 120

Slide 120 text

© DMM.com ϧʔϧͷઃఆํ๏

Slide 121

Slide 121 text

© DMM.com X ઃఆํ๏ͷҰྫ DPOpHϑΝΠϧΛ࡞੒ͯ͠ɺ֤3VMFʢ͜͜Ͱ͸JTTVFʣ ͝ͱʹઃఆ͢Δɻ

Slide 122

Slide 122 text

© DMM.com X ·ͣ͸DPOpHϑΝΠϧΛ࡞Δ android { ... lintOptions { abortOnError false lintConfig file("path/to/lint/config.xml") } } DPOpHϑΝΠϧΛMJOU$POpHʹઃఆ͢Ε͹0,ɻ

Slide 123

Slide 123 text

© DMM.com ΧελϜϧʔϧͷ࡞Γํ

Slide 124

Slide 124 text

© DMM.com X ͜͏͍͏ͷΛ࡞ͬͯݟ·͢ 3Y+BWBΛ࢖ͬͯͯɺ %JTQPTBCMFΛద੾ʹॲཧͯ͠ͳ͍ͱܯࠂग़͢ΧελϜϧʔϧ

Slide 125

Slide 125 text

© DMM.com X खॱ  ϓϩδΣΫτ࡞੒  %FUFDUPSΛ࡞Δ  *TTVFΛ࡞Δ  3FHJTUSZΛ࡞Δ  3FHJTUSZΛCVJMEHSBEMFʹهड़  KBSΛ࡞Δ

Slide 126

Slide 126 text

© DMM.com X ̍ϓϩδΣΫτΛ࡞Δ HPPHMFTBNQMFTʹςϯϓϨʔτͷΑ͏ͳ΋ͷ͕͋Δͷ ͰɺͦΕʹͳΒ͏ͷ͕ૣ͍ IUUQTHJUIVCDPNHPPHMFTBNQMFTBOESPJEDVTUPN MJOUSVMFTUSFFNBTUFSBOESPJETUVEJP

Slide 127

Slide 127 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } ׬੒ܗ

Slide 128

Slide 128 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } %FUFDUPSΛFYUFOETɺ6BTU4DBOOFSΛJNQMFNFOUTɻ 6BTU͸6OJpFE"45ͷུɻ

Slide 129

Slide 129 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } DSFBUF6BTU)BOEMFSΛPWFSSJEF͢Δɻ ͭ·Γ6&MFNFOU)BOEMFSΛ࣮૷͢Δɻ

Slide 130

Slide 130 text

© DMM.com X 6*&MFNFOU)BOEMFSͱ͸ USFFͷ্͔ΒॱʹTDBO͍ͯͬͯ͠ɺ֤छOPEF͕ݟ͔ͭΔͨ ͼʹWJTJUϝιου͕ݺ͹ΕΔਓɻ ֤छWJTJUϝιουΛPWFSSJEFͯ͠࢖͏ɻ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 WJTJU"SHVNFOU-JTU WJTJU"SHVNFOU WJTJU"SHVNFOU

Slide 131

Slide 131 text

© DMM.com X ࠓճ͸ ࠓճ͸1TJ7JXFSΛݟΔݶΓɺ%05@26"-*'*&%@&913&44*0/ ͕དྷͨ࣌ʹ֬ೝ͢Δ͚ͩͰࡁΈͦ͏ͳͷͰɺ WJTJU2VBMJpFE3FGFSFODF&YQSFTTJPOͷΈΛPWFSJSEF͢Δɻ

Slide 132

Slide 132 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } WJTJUର৅ͷOPEFͷΫϥεҰཡΛHFU"QQMJDBCMF6BTU5ZQFTͰ ฦ٫͢Δɻ͜ΕΛ͠ͳ͍ͱWJTJUϝιου͕ݺ͹Ε·ͤΜ

Slide 133

Slide 133 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } WJTJU2VBMJpFE3FGFSFODF&YQSFTTJPOͷத਎Λઆ໌͠·͢ɻ

Slide 134

Slide 134 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } ਌͕#MPDLA\^AͰɺ

Slide 135

Slide 135 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } ϝιουνΣʔϯͷ࠷ޙ͕ATVCTDSJCF AͰ

Slide 136

Slide 136 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } ͦͷTVCTDJSCFϝιουͷฦΓ஋͕JPSFBDUJWFYEJTQPTBCMFT%JTQPTBCMFͷ࣌ ‐͜Ε͕LUMJOUͱEFUFLUͰ͸ࠓͷॴͰ͖·ͤΜ

Slide 137

Slide 137 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } Ϩϙʔτ͢Δʂ ܯࠂ͕ग़Δ

Slide 138

Slide 138 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // java if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().getContext() != null && node.getPsi().getContext().getContext().toString() .equals(“PsiCodeBlock") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType().getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); } KBWBͷ৔߹΋ॻ͖·͢ɻ6BTU4DBOOFS͸LPUMJOͱKBWBͰ۠ผͳ͘WJTJUͯ͘͠Ε·͢ɻ ͨͩ͠ɺLPUMJOͷ࣌ͱߏ଄͸େମಉ͡Ͱ͕͢ɺ14*ͷܕ͕ҧ͏ͷͰผ్ॻ͘ඞཁ͕͋Γ·͢ɻ

Slide 139

Slide 139 text

© DMM.com X ̏*TTVFΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { public static final Issue ISSUE = Issue.create( "NotHandledDisposable", "Not Handled Disposable", "Disposable should be called dispose.", Category.CORRECTNESS, 6, Severity.ERROR, new Implementation( NotHandledDisposableDetector.class, Scope.JAVA_FILE_SCOPE ) ); *%΍આ໌ɺΧςΰϦ৘ใΛ࣋ͬͨTUBUJDͳ*TTVFΠϯελϯεΛ࡞Γ·͢ɻ ৔ॴ͸Ͳ͜Ͱ΋͍͍͚Ͳɺطଘͷ-JOUΛݟΔݶΓ%FUFDUPSΫϥεʹॻ͍ͯΔͱ͜Ζ͕΄ͱΜͲ Ͱ͢ɻ

Slide 140

Slide 140 text

© DMM.com X ̐3FHJTUSZΛ࡞Δ public class CustomIssueRegistry extends IssueRegistry { @Override public List getIssues() { return Collections.singletonList( NotHandledDisposableDetector.ISSUE ); } } ࡞ͬͨ*TTVFΛొ࿥͢Δ3FHJTUPSZΫϥεΛ࡞Γ·͢ɻ *TTVF͸ෳ਺ొ࿥Ͱ͖·͢ɻ

Slide 141

Slide 141 text

© DMM.com X ̑3FHJTUSZΛCVJMEHSBEMFʹهड़ jar { manifest { attributes("Lint-Registry-v2": "com.kgmyshin.lint.CustomIssueRegistry") } } A-JOU3FHJTUSZ7Aʹઌ΄Ͳ࡞ͬͨ3FHJTUSZΛઃఆ͠·͢ɻ A7AΛ๨Εͳ͍Α͏ʹɻ

Slide 142

Slide 142 text

© DMM.com X KBSΛ࡞Δ KBSΛ࡞੒͢Δɻ ./gradlew jar CVJMEMJCT഑Լʹ࡞੒͞ΕΔɻ

Slide 143

Slide 143 text

© DMM.com ࡞ͬͨΧελϜϧʔϧΛద༻͢Δ

Slide 144

Slide 144 text

© DMM.com X ࡞ͬͨ$VTUPN-JOUͷ࢖͍ํ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.1.10' lintChecks files("lint/custom-lint.jar") } AMJOU$IFDLTpMFT KBSͷύε A Λ௥ՃͰ0,

Slide 145

Slide 145 text

© DMM.com X ࡞ͬͨ$VTUPN-JOUͷ࢖͍ํ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.1.10' lintChecks project(":checks") } ಉҰϓϩδΣΫτʹ͋Δ৔߹͸ɺԼهͷΑ͏ʹEFQFOEFODJFTʹ MJOU$IFDLTQSPKFDU ΧελϜϧʔϧͷϞδϡʔϧ  Λ௥Ճ

Slide 146

Slide 146 text

© DMM.com X ࡞ͬͨ$VTUPN-JOUͷ࢖͍ํ ./gradlew lint : Errors found: /../custom-lint-rules/library/src/main/java/test/pkg/MainJava.java:8: Error: Should handle Disposable [NotHandledDisposable] Single.just("test").subscribe(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /../custom-lint-rules/library/src/main/java/test/pkg/MainKt.kt:8: Error: Should handle Disposable [NotHandledDisposable] Single.just("aa").subscribe() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ : ແࣄಈ͖·ͨ͠ʂ

Slide 147

Slide 147 text

© DMM.com X ·ͱΊ

Slide 148

Slide 148 text

© DMM.com X ൺֱද ඪ४ϧʔϧ ݸผઃఆ $VTUPN-JOU ͦͷଞ LUMJOU ݸऑ΄Ͳ جຊͰ͖ͳ͍ ࡞ΕΔ GPSNBUͰ͖Δ EFUFLU ͨ͘͞Μ͋Δ Ͱ͖Δ ࡞ΕΔ ෳࡶ౓ͳͲ΋ Θ͔Δ BOESPJEMJOU ͨ͘͞Μ͋Δ Ͱ͖Δ ࡞ΕΔ ܕΛݟΕΔ

Slide 149

Slide 149 text

© DMM.com X ·ͱΊ w $VTUPN-JOUͷ࡞Γํ͸ͲΕ΋͍͍ͩͨڞ௨ w LUMJOU͸جຊతʹϧʔϧͷݸผઃఆ͸ͮ͠Β͍ w LUMJOU͸GPSNBU΋Ͱ͖Δ w EFUFLU͸ෳࡶ౓ͳͲ΋Ϩϙʔτ͞ΕΔ w EFUFLU͸GPSNBUػೳ͸΍Ίͨ w BOESPJEMJOU͸KBWBͱLPUMJOΛࠩผ͠ͳ͍VBTUΛ࢖ͬ ͍ͯΔ w BOESPJEMJOU͸ܕΛ֬ೝͰ͖Δ