DangerでTextViewのandroid:maxLinesがないことをチェックしようとした
APIからデータを受け取ってTextViewに表示するとき、大きいデータだと際限なく表示されてしまうので android:maxLines
を設定されたい。結構忘れがちなのでDangerで自動チェックしようとした...けどやりたかったことを全部満たすのは大変そうだったので妥協した話。
やりたかったこと
- レイアウトファイルのdiffのTextView内に
android:maxLines
がなかったら警告する - 警告にはファイルと行数を指定してPR上から飛べるようにする(e.g.
warn("android:maxLinesがありません", file: "app/src/main/res/layout/content_main.xml", line: 10)
) - 既存のTextViewには警告を出さない
結論から言うと最後の 既存のTextViewには警告を出さない
を諦めた
どうチェックするか?
Dangerではgit.diffでdiffが取れるのでパースできる。もしくは
active_files = (git.modified_files + git.added_files).uniq layout_files = active_files.select { |file| file.include?("app/src/main/res/layout/") }
とすれば変更されたレイアウトファイル一覧が取れるので そのファイル全体を読み込んでパースすることもできる。
まずgit.diffをパースする場合、問題としては行数が取れない。diffと実際のファイルを比べて行数を取ってくるのはしんどい...妥協としてTextViewの始まりから終わりまでを表示させてみたが削除部分が誤判定されてしまい排除しなくてはいけなく、更にしんどい...
in_textview = false maxline_exists = false textview_line = [] git.diff.patch.lines.each do |diff_line| if /^.*<TextView$/ === diff_line in_textview = true textview_line.clear message("In TextView, #{diff_line}") end if in_textview textview_line.push(diff_line) if diff_line.include?("</TextView>") || diff_line.include?("/>") in_textview = false if !maxline_exists message("Please add android:maxLines\n```xml\n#{textview_line.join()}```") end elsif diff_line.include?("android:maxLines") maxline_exists = true end end end
レイアウトファイル全体をパースする場合、PRでの変更外も警告してしまうので鬱陶しい可能性がある。 android:maxLines
が必要ないラベルなどがあると常に警告されてしまう。とはいえ行数が取れるので表示自体は理想通りになる。
active_files = (git.modified_files + git.added_files).uniq layout_files = active_files.select { |file| file.include?("app/src/main/res/layout/") } in_textview = false maxline_exists = false textview_line_num = 0 layout_files.each do |filename| file = File.read(filename) lines = file.lines lines.each_with_index do |l, num| if l.include?("<TextView") in_textview = true textview_line_num = num + 1 end if in_textview if l.include?("</TextView>") || l.include?("/>") in_textview = false if !maxline_exists message("Please add android:maxLines", file: "#{filename}", line: textview_line_num) end elsif l.include?("android:maxLines") maxline_exists = true end end end end
結論
警告表示が理想的なレイアウトファイル全体をパースする方向で妥協した。不要な警告なら無視すればよいし、例えばstyleが適用されてたらスキップするとか改善のしようはありそう。