detektのルール日本語訳

detektの概要や導入については以下をご参照ください。
[Kotlinの静的解析ツール「detekt」のセットアップ方法](https://medium.com/@nagendran.p/integrating-detekt-in-the-android-studio-442128e971f8)


## 注意

公式ページのルールを簡単に翻訳してまとめたものです。
英語に慣れている方は公式ページを直接見るのがいいです。
https://detekt.github.io/detekt/complexity.html

また、間違っている箇所や不適切な箇所がありましたら教えていただけると嬉しいです。
## 環境

- Kotlin：1.5.31
- Android Studio：Arctic Fox
- detekt：1.18.1

## Default
デフォルトで有効になっているルールの一覧です。
### Complexity Rule
##### [ComplexCondition](https://detekt.github.io/detekt/complexity.html#complexcondition)

複雑な条件は、どのような場合にその条件が真か偽かを理解するのが難しくなります。複雑な条件を読みやすく理解しやすくするためには、条件を適切な名前の関数や変数に抽出し、それらを代わりに呼び出すことを検討してください。

```kotlin
// bad
val str = "foo"
val isFoo = if (str.startsWith("foo") && !str.endsWith("foo") && !str.endsWith("bar") && !str.endsWith("_")) {
    // ...
}

// good
val str = "foo"
val isFoo = if (str.startsWith("foo") && hasCorrectEnding()) {
    // ...
}

fun hasCorrectEnding() = return !str.endsWith("foo") && !str.endsWith("bar") && !str.endsWith("_")

```

##### [ComplexMethod](https://detekt.github.io/detekt/complexity.html#complexmethod)
複雑なメソッドは、理解するのも読むのも大変です。複雑なメソッドがどのような副作用を持つのか、明らかではないかもしれません。複雑なメソッドは、より理解しやすい小さなメソッドに分割することをお勧めします。
このルールでは、[McCabeのCyclomatic Complexity (MCC)](https://www.ndepend.com/docs/code-metrics#CC)という指標を使用して、関数のソースコード内の線形独立パスの数を測定します。独立したパスの数が多いほど、そのメソッドは複雑です。
[MCC循環的複雑度について -Qiita](https://qiita.com/yut_arrows/items/16749e02313109071338)

測定対象
・Conditional statements - if, else if, when
・Jump statements - continue, break
・Loops - for, while, do-while, forEach
・Operators &&, ||, ?:
・Exceptions - catch, use
・Scope Functions - let, run, with, apply, and also


##### [LargeClass](https://detekt.github.io/detekt/complexity.html#largeclass)
このルールでは、大規模なクラスを報告します。クラスは通常、1つの責任を持つべきです。一度に多くのことをするのではなく、大きなクラスを小さなクラスに分割することをお勧めします。
デフォルトはクラス内のソースコードの行数は600以内にするのがベスト

##### [LongMethod](https://detekt.github.io/detekt/complexity.html#longmethod)
メソッドは1つの責任を持つべきです。行数長いメソッドは、そのメソッドが一度に多くのケースを処理していることを示します。機能を明確に説明して分かりやすい名前付きの行数少なくて小さなメソッドをお勧めします。
行数長いメソッドの機能の一部を別の小さなメソッドに抽出します。
デフォルトはメソッド内のソースコードの行数は60以内にするのがベスト

##### [LongParameterList](https://detekt.github.io/detekt/complexity.html#longparameterlist)
コンストラクタや関数の引数の数は少なくすべきです。

```kotlin
// bad
fun sign(userName: String, userId: Int, userSex: String, userMail: String, isCheck: Boolean, token: String) { }

// good
data class User (
  var userName: String = "", 
  var userId: Int = 0, 
  var userSex: String = "",
  var userMail: String = "",
)
fun sign(user: User, isCheck: Boolean, token: String) { }

```
##### [NestedBlockDepth](https://detekt.github.io/detekt/complexity.html#nestedblockdepth)
最大４レベルの深さでネストすべきです。

```kotlin
// bad
fun f_0(type: ItemType, isCheck: Boolean) {
   when (type) {
      ItemType.Article -> {
          if (isCheck) {
              if (article.isNotLoading) {
                    //do something
              }
          }
      }
   }
}
// good
fun f_0(type: ItemType, isCheck: Boolean) {
   when (type) {
      ItemType.Article -> {
          f_1(isCheck)
      }
   }
}
fun f_1(isCheck: Boolean) {
     if (isCheck) {
         if (article.isNotLoading) {
               //do something
          }
     }
}
```
##### [TooManyFunctions](https://detekt.github.io/detekt/complexity.html#toomanyfunctions)
ファイル、クラス、インターフェース、オブジェクト、および列挙内の関数を少なくすべき。
関数が多すぎると、単一責任原則の違反となります。明らかにコードの別の部分にまとめられている機能を抽出することをお勧めします。
デフォルト11個以内

### Empty-blocks
##### [EmptyCatchBlock](https://detekt.github.io/detekt/empty-blocks.html#emptycatchblock)
空のキャッチブロックがあります。
空のキャッチ・ブロックは、例外が無視され、処理されないことを示します。例外を意図的に無視する場合は、 allowedExceptionNameRegexに指定した名前を使用して明示する必要があります。

```kotlin
// bad
fun f() {
     try {
        //do something
     } catch (e: PackageManager.NameNotFoundException) {

     }
}
// good
fun f() {
     try {
        //do something
     } catch (e: PackageManager.NameNotFoundException) {
        //do something for fixing Exception
     }
}
```

##### [EmptyClassBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyclassblock)
空のクラスがあります。

##### [EmptyDefaultConstructor](https://detekt.github.io/detekt/empty-blocks.html#emptydefaultconstructor)
空のデフォルトコンストラクタがあります。

##### [EmptyDoWhileBlock](https://detekt.github.io/detekt/empty-blocks.html#emptydowhileblock)
空のdo/whileループがあります。

##### [EmptyElseBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyelseblock)
空のelseブロックがあります。

##### [EmptyFinallyBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyfinallyblock)
空のfinallyブロックがあります。

##### [EmptyForBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyforblock)
空のforブロックがあります。

##### [EmptyFunctionBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyfunctionblock)
空の関数ブロックがあります。

##### [EmptyIfBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyifblock)
空のifブロックがあります。

##### [EmptyInitBlock](https://detekt.github.io/detekt/empty-blocks.html#emptyinitblock)
空のinitブロックがあります。

##### [EmptyKtFile](https://detekt.github.io/detekt/empty-blocks.html#emptyktfile)
空のKotlinファイルがあります。

##### [EmptySecondaryConstructor](https://detekt.github.io/detekt/empty-blocks.html#emptysecondaryconstructor)
空のセカンダリコンストラクタブロックがあります。

##### [EmptyTryBlock](https://detekt.github.io/detekt/empty-blocks.html#emptytryblock)
空のtryブロックがあります。

##### [EmptyWhenBlock](https://detekt.github.io/detekt/empty-blocks.html#emptywhenblock)
空のwhenブロックがあります。

##### [EmptyWhileBlock](https://detekt.github.io/detekt/empty-blocks.html#emptywhileblock)
空のwhileブロックがあります。

### Exceptions
##### [ExceptionRaisedInUnexpectedLocation](https://detekt.github.io/detekt/exceptions.html#exceptionraisedinunexpectedlocation)
絶対に例外を発生させてはいけない関数内で例外をスローしてはいけない

```kotlin
// bad
class Foo {
    override fun toString(): String {
        throw IllegalStateException() // exception should not be thrown here
    }
}
// good
class Foo {
    override fun toString(): String {
       //do something
    }
}
```

##### [PrintStackTrace](https://detekt.github.io/detekt/exceptions.html#printstacktrace)
例外を握りつぶしてはいけない

```kotlin
// bad
fun foo() {
    Thread.dumpStack()
}
fun bar() {
    try {
        // ...
    } catch (e: IOException) {
        e.printStackTrace()
    }
}
// good
val LOGGER = Logger.getLogger()
fun bar() {
    try {
        // ...
    } catch (e: IOException) {
        LOGGER.info(e)
    }
}
```

##### [RethrowCaughtException](https://detekt.github.io/detekt/exceptions.html#rethrowcaughtexception)
例外をキャッチされた後、修正なしで再スローしてはいけない

```kotlin
// bad
fun foo() {
    try {
        // ...
    } catch (e: IOException) {
        throw e
    }
}
// good
fun foo() {
    try {
        // ...
    } catch (e: IOException) {
        throw MyException(e)
    }
    try {
        // ...
    } catch (e: IOException) {
        print(e)
        throw e
    }
    try {
        // ...
    } catch (e: IOException) {
        print(e.message)
        throw e
    }
}
```

##### [ReturnFromFinally](https://detekt.github.io/detekt/exceptions.html#returnfromfinally)
finallyブロックでreturn文を使用すると、tryブロックでスローされた例外を破棄されるので
finallyブロックでreturn文を使用してはいけない

```kotlin
// bad
fun foo() {
    try {
        throw MyException()
    } finally {
        return // prevents MyException from being propagated
    }
}

// good
fun foo() {
    try {
        throw MyException()
    } catch(e: MyException) {
        // do something
    }
}
```

##### [SwallowedException](https://detekt.github.io/detekt/exceptions.html#swallowedexception)
例外を使用しないといけない。または例外をスローすべき

```kotlin
// bad
fun foo() {
    try {
        // ...
    } catch(e: IOException) {
        throw MyException(e.message) // e is swallowed
    }
    try {
        // ...
    } catch(e: IOException) {
        throw MyException() // e is swallowed
    }
    try {
        // ...
    } catch(e: IOException) {
        bar() // exception is unused
    }
}

// good
fun foo() {
    try {
        // ...
    } catch(e: IOException) {
        throw MyException(e)
    }
    try {
        // ...
    } catch(e: IOException) {
        println(e) // logging is ok here
    }
}
```

##### [ThrowingExceptionFromFinally](https://detekt.github.io/detekt/exceptions.html#throwingexceptionfromfinally)
finallyブロックから例外を投げることは、混乱や例外の破棄につながるため、避けるべきです。

```kotlin
// bad
fun foo() {
    try {
        // ...
    } finally {
        throw IOException()
    }
}
// good
fun foo() {
    try {
        // ...
    } catch (e: MyException) {
        throw IOException()
    }
}
```

##### [ThrowingExceptionsWithoutMessageOrCause](https://detekt.github.io/detekt/exceptions.html#throwingexceptionswithoutmessageorcause)
対象例外は引数や詳細な説明なしにスローされてはいけない。

デフォルト対象
['ArrayIndexOutOfBoundsException', 'Exception', 'IllegalArgumentException', 'IllegalMonitorStateException', 'IllegalStateException', 'IndexOutOfBoundsException', 'NullPointerException', 'RuntimeException', 'Throwable']

```kotlin
// bad
fun foo(bar: Int) {
    if (bar < 1) {
        throw IllegalArgumentException()
    }
    // ...
}
// good
fun foo(bar: Int) {
    if (bar < 1) {
        throw IllegalArgumentException("bar must be greater than zero")
    }
    // ...
}
```

##### [ThrowingNewInstanceOfSameException](https://detekt.github.io/detekt/exceptions.html#throwingnewinstanceofsameexception)
例外を同じ例外タイプの中に包んで、再度スローすることはしてはいけない。

```kotlin
// bad
fun foo() {
    try {
        // ...
    } catch (e: IllegalStateException) {
        throw IllegalStateException(e) // rethrows the same exception
    }
}
// good
fun foo() {
    try {
        // ...
    } catch (e: IllegalStateException) {
        throw MyException(e)
    }
}
```

##### [TooGenericExceptionCaught](https://detekt.github.io/detekt/exceptions.html#toogenericexceptioncaught)
現在処理されているケースに対する特定の例外をキャッチすることが望ましい
キャッチする例外の範囲が広すぎると、意図しない例外がキャッチされてしまう可能性があります

デフォルト対象
['ArrayIndexOutOfBoundsException', 'Error', 'Exception', 'IllegalMonitorStateException', 'IndexOutOfBoundsException', 'NullPointerException', 'RuntimeException', 'Throwable']

```kotlin
// bad
fun foo() {
    try {
        // ... do some I/O
    } catch(e: Exception) { } // too generic exception caught here
}
// good
fun foo() {
    try {
        // ... do some I/O
    } catch(e: IOException) { }
}
```

##### [TooGenericExceptionThrown](https://detekt.github.io/detekt/exceptions.html#toogenericexceptionthrown)
現在発生しているケースに対して特定の例外をスローすることが望ましい
スローする例外の範囲が広すぎると、意図しない例外がキャッチされてしまう可能性があります

デフォルト対象
['Error', 'Exception', 'RuntimeException', 'Throwable']

```kotlin
// bad
fun foo(bar: Int) {
    if (bar < 1) {
        throw Exception() // too generic exception thrown here
    }
    // ...
}

// good
fun foo(bar: Int) {
    if (bar < 1) {
        throw IllegalArgumentException("bar must be greater than zero")
    }
    // ...
}
```

### Naming
##### [ClassNaming](https://detekt.github.io/detekt/naming.html#classnaming)
指定された命名規則に従わないクラスやオブジェクトがあります
(default: '[A-Z][a-zA-Z0-9]*')

##### [ConstructorParameterNaming](https://detekt.github.io/detekt/naming.html#constructorparameternaming)
指定された命名規則に従わないコンストラクタのパラメータがあります
(default: '[a-z][A-Za-z0-9]*')

##### [EnumNaming](https://detekt.github.io/detekt/naming.html#enumnaming)
指定された命名規則に従わないEnumがあります
(default: '[A-Z][_a-zA-Z0-9]*')

##### [FunctionNaming](https://detekt.github.io/detekt/naming.html#functionnaming)
指定された命名規則に従わない関数があります
(default: '([a-z][a-zA-Z0-9]*)|(`.*`)')

##### [FunctionParameterNaming](https://detekt.github.io/detekt/naming.html#functionparameternaming)
指定された命名規則に従わない関数のパラメータがあります
(default: '[a-z][A-Za-z0-9]*')

##### [MatchingDeclarationName](https://detekt.github.io/detekt/naming.html#matchingdeclarationname)
ファイルの名前は、そのファイルの中のコードが何をするかを説明するものでなければなりません。

```kotlin
// bad
class Foo // FooUtils.kt

fun Bar.toFoo(): Foo = ...
fun Foo.toBar(): Bar = ...

// good
class Foo { // Foo.kt
    fun stuff() = 42
}

fun Bar.toFoo(): Foo = ...

```

##### [MemberNameEqualsClassName](https://detekt.github.io/detekt/naming.html#membernameequalsclassname)
クラスまたはオブジェクトと同じ名を持つメンバー関数や変数があります。
クラスのインスタンスを作成するファクトリー関数は、このルールの対象外です。

```kotlin
// bad
class MethodNameEqualsClassName {

    fun methodNameEqualsClassName() { }
}

class PropertyNameEqualsClassName {

    val propertyEqualsClassName = 0
}

// good
class Manager {

    companion object {
        // factory functions can have the same name as the class
        fun manager(): Manager {
            return Manager()
        }
    }
}

```

##### [ObjectPropertyNaming](https://detekt.github.io/detekt/naming.html#objectpropertynaming)
指定された命名規則に従わないオブジェクト内のプロパティがあります。

constantPattern (default: '[A-Za-z][_A-Za-z0-9]*')
propertyPattern (default: '[A-Za-z][_A-Za-z0-9]*')
private PropertyPattern (default: '(_)?[A-Za-z][_A-Za-z0-9]*')

##### [PackageNaming](https://detekt.github.io/detekt/naming.html#packagenaming)
指定された命名規則に従わないパッケージがあります。

(default: '[a-z]+(\.[a-z][A-Za-z0-9]*)*')

##### [TopLevelPropertyNaming](https://detekt.github.io/detekt/naming.html#toplevelpropertynaming)
指定された命名規則に従わないトップレベルの定数があります。

constantPattern (default: '[A-Z][_A-Z0-9]*')
propertyPattern (default: '[A-Za-z][_A-Za-z0-9]*')
private PropertyPattern (default: '_?[A-Za-z][_A-Za-z0-9]*')

##### [VariableNaming](https://detekt.github.io/detekt/naming.html#variablenaming)
指定された命名規則に従わない変数があります。

variablePattern (default: '[a-z][A-Za-z0-9]*')
private VariablePattern (default: '(_)?[a-z][A-Za-z0-9]*')

### Performance
##### [ArrayPrimitive](https://detekt.github.io/detekt/performance.html#arrayprimitive)
Arrayを使用すると、暗黙のボックス化が発生し、パフォーマンスが低下します。Kotlin に特化した Array インスタンスの使用を推奨します。

```kotlin
// bad
fun function(array: Array<Int>) { }

fun returningFunction(): Array<Double> { }

// good
fun function(array: IntArray) { }

fun returningFunction(): DoubleArray { }
```

##### [ForEachOnRange](https://detekt.github.io/detekt/performance.html#foreachonrange)
範囲内でforEachメソッドを使用すると、パフォーマンスが大きく低下します。シンプルなforループの使用をお勧めします。
ベンチマークによると、レンジに対してforEachを使用すると、単純なforループに比べてパフォーマンスが大幅に低下することがわかっています。

```kotlin
// bad
(1..10).forEach {
    println(it)
}
(1 until 10).forEach {
    println(it)
}
(10 downTo 1).forEach {
    println(it)
}

// good
for (i in 1..10) {
    println(i)
}
```

##### [SpreadOperator](https://detekt.github.io/detekt/performance.html#spreadoperator)
ほとんどの場合、拡散演算子を使用すると、メソッドを呼び出す前に、配列の完全なコピーが作成されます。
v1.1.60 以降の Kotlin コンパイラには、配列コンストラクタ関数が vararg パラメータに渡される引数の作成に使用されている場合、配列のコピーをスキップする最適化が施されています。

```kotlin
// bad
val strs = arrayOf("value one", "value two")
val foo = bar(*strs)

fun bar(vararg strs: String) {
    strs.forEach { println(it) }
}

// good
// array copy skipped in this case since Kotlin 1.1.60
val foo = bar(*arrayOf("value one", "value two"))

// array not passed so no array copy is required
val foo2 = bar("value one", "value two")

fun bar(vararg strs: String) {
    strs.forEach { println(it) }
}
```

##### [UnnecessaryTemporaryInstantiation](https://detekt.github.io/detekt/performance.html#unnecessarytemporaryinstantiation)
プリミティブ型を String に変換する際、一時的なオブジェクトを使用しないようにしました。これは、プリミティブ型を直接使用する場合と比較して、パフォーマンス上のペナルティがあります。

```kotlin
// bad
val i = Integer(1).toString() // temporary Integer instantiation just for the conversion

// good
val i = Integer.toString(1)
```

### Potential-bugs
##### [DuplicateCaseInWhenExpression](https://detekt.github.io/detekt/potential-bugs.html#duplicatecaseinwhenexpression)
when式の中に重複したcase文フラグがあります。

```kotlin
// bad
when (i) {
    1 -> println("one")
    1 -> println("one")
    else -> println("else")
}

// good
when (i) {
    1 -> println("one")
    else -> println("else")
}
```

##### [EqualsAlwaysReturnsTrueOrFalse](https://detekt.github.io/detekt/potential-bugs.html#equalsalwaysreturnstrueorfalse)
常にtrueまたはfalseを返すequals()メソッドがあります。

```kotlin
// bad
override fun equals(other: Any?): Boolean {
    return true
}

// good
override fun equals(other: Any?): Boolean {
    return this === other
}
```

##### [EqualsWithHashCodeExist](https://detekt.github.io/detekt/potential-bugs.html#equalswithhashcodeexist)
クラスがequals()メソッドをオーバーライドする際には、hashCode()メソッドもオーバーライドする必要があります。

```kotlin
// bad
class Foo {

    override fun equals(other: Any?): Boolean {
        return super.equals(other)
    }
}

// good
class Foo {

    override fun equals(other: Any?): Boolean {
        return super.equals(other)
    }

    override fun hashCode(): Int {
        return super.hashCode()
    }
}
```

##### [ExplicitGarbageCollectionCall](https://detekt.github.io/detekt/potential-bugs.html#explicitgarbagecollectioncall)
ガベージコレクタを明示的に呼び出す必要はありません。

##### [ImplicitDefaultLocale](https://detekt.github.io/detekt/potential-bugs.html#implicitdefaultlocale)
文字列のフォーマットや大文字小文字の変換を行う際に、暗黙のデフォルト値を使用するよりも、[java.util.Locale]を明示的に渡すことをお勧めします。
デフォルトのロケールは、ほとんどの場合、HTTPヘッダのような機械で読めるテキストには不適切です。

```kotlin
// bad
String.format("Timestamp: %d", System.currentTimeMillis())

val str: String = getString()
str.toUpperCase()
str.toLowerCase()

// good
String.format(Locale.US, "Timestamp: %d", System.currentTimeMillis())

val str: String = getString()
str.toUpperCase(Locale.US)
str.toLowerCase(Locale.US)
```

##### [InvalidRange](https://detekt.github.io/detekt/potential-bugs.html#invalidrange)
無効な範囲があります。

```kotlin
// bad
for (i in 2..1) {}
for (i in 1 downTo 2) {}

val range1 = 2 until 1
val range2 = 2 until 2

// good
for (i in 2..2) {}
for (i in 2 downTo 2) {}

val range = 2 until 3
```

##### [IteratorHasNextCallsNextMethod](https://detekt.github.io/detekt/potential-bugs.html#iteratorhasnextcallsnextmethod)
IteratorインターフェースのhasNext()メソッド内でnextメソッドを呼び出してはいけない。

```kotlin
// bad
class MyIterator : Iterator<String> {

    override fun hasNext(): Boolean {
        return next() != null
    }
}

// good
class MyIterator : Iterator<String> {

    override fun hasNext(): Boolean {
        return // ...
    }

　　override fun next(): String {
        return // ...
    }
}
```

##### [IteratorNotThrowingNoSuchElementException](https://detekt.github.io/detekt/potential-bugs.html#iteratornotthrowingnosuchelementexception)
next()メソッドの実装で返すべき要素がなくなったときに NoSuchElementException を投げるべきです。

```kotlin
// bad
class MyIterator : Iterator<String> {

    override fun next(): String {
        return ""
    }
}

// good
class MyIterator : Iterator<String> {

    override fun next(): String {
        if (!this.hasNext()) {
            throw NoSuchElementException()
        }
        // ...
    }
}
```

##### [RedundantElseInWhen](https://detekt.github.io/detekt/potential-bugs.html#redundantelseinwhen)
冗長なelseケースを含むwhen式があります。

```kotlin
// bad
enum class Color {
    RED,
    GREEN,
    BLUE
}

fun whenOnEnumFail(c: Color) {
    when(c) {
        Color.BLUE -> {}
        Color.GREEN -> {}
        Color.RED -> {}
        else -> {} // no use
    }
}

// good
enum class Color {
    RED,
    GREEN,
    BLUE
}

fun whenOnEnumCompliant(c: Color) {
    when(c) {
        Color.BLUE -> {}
        Color.GREEN -> {}
        else -> {}
    }
}

fun whenOnEnumCompliant2(c: Color) {
    when(c) {
        Color.BLUE -> {}
        Color.GREEN -> {}
        Color.RED -> {}
    }
}
```

##### [UnnecessaryNotNullOperator](https://detekt.github.io/detekt/potential-bugs.html#unnecessarynotnulloperator)
不要なnot-null演算子(!!)の使用があります。

```kotlin
// bad
val a = 1
val b = a!!

// good
val a = 1
val b = a
```

##### [UnnecessarySafeCall](https://detekt.github.io/detekt/potential-bugs.html#unnecessarysafecall)
不要なセーフコール演算子(?)使用があります。

```kotlin
// bad
val a: String = ""
val b = a?.length

// good
val a: String? = null
val b = a?.length
```

##### [UnreachableCode](https://detekt.github.io/detekt/potential-bugs.html#unreachablecode)
呼び出されないコードがあります。

```kotlin
// bad
for (i in 1..2) {
    break
    println() // unreachable
}

throw IllegalArgumentException()
println() // unreachable

fun f() {
    return
    println() // unreachable
}


// good
for (i in 1..2) {
　　println()
    break
}

println()
throw IllegalArgumentException()

fun f() {
　　 println()
    return
}

```

##### [UnsafeCallOnNullableType](https://detekt.github.io/detekt/potential-bugs.html#unsafecallonnullabletype)
nullable型に対する安全でない呼び出しがあります。

```kotlin
// bad
fun foo(str: String?) {
    println(str!!.length)
}

// good
fun foo(str: String?) {
    println(str?.length)
}

```

##### [UnsafeCast](https://detekt.github.io/detekt/potential-bugs.html#unsafecast)
絶対に成功しないキャストがあります。

```kotlin
// bad
fun foo(s: String) {
    println(s as Int)
}

fun bar(s: String) {
    println(s as? Int)
}

// good
fun foo(s: Any) {
    println(s as Int)
}
```

##### [WrongEqualsTypeParameter](https://detekt.github.io/detekt/potential-bugs.html#wrongequalstypeparameter)
誤って型付けされたパラメータを取り込む equals() メソッドがあります。

```kotlin
// bad
class Foo {

    fun equals(other: String): Boolean {
        return super.equals(other)
    }
}

// good
class Foo {

    fun equals(other: Any?): Boolean {
        return super.equals(other)
    }
}
```

### Style
##### [EqualsNullCall](https://detekt.github.io/detekt/style.html#equalsnullcall)
オブジェクトをnullと比較するには、==を使用することをお勧めします。

```kotlin
// bad
fun isNull(str: String) = str.equals(null)

// good
fun isNull(str: String) = str == null
```

##### [ForbiddenComment](https://detekt.github.io/detekt/style.html#forbiddencomment)
開発時にのみ使用されるべきコメントがあります。

```kotlin
// bad
val a = "" // TODO: remove please
// FIXME: this is a hack
fun foo() { }
// STOPSHIP:
```

##### [ForbiddenPublicDataClass](https://detekt.github.io/detekt/style.html#forbiddenpublicdataclass)
データクラスは、パブリックAPIのバイナリ互換性に悪影響を及ぼします。使用を避けてください。

このルールはライブラリのメンテナに向けたものです。もしあなたが最終的なアプリケーションを開発しているのであれば、この問題は無視して構いません。

```kotlin
// bad
data class C(val a: String) // violation: public data class

// good
internal data class C(val a: String)
```

##### [FunctionOnlyReturningConstant](https://detekt.github.io/detekt/style.html#functiononlyreturningconstant)
1つの定数を返すだけの関数があります。const valを使用すべき。

```kotlin
// bad
fun functionReturningConstantString() = "1"

// good
const val constantString = "1"
```

##### [LibraryCodeMustSpecifyReturnType](https://detekt.github.io/detekt/style.html#librarycodemustspecifyreturntype)
ライブラリのパブリックAPIとして公開される関数やプロパティには、明示的な戻り値の型が必要です。

```kotlin
// bad
// code from a library
val strs = listOf("foo, bar")
fun bar() = 5
class Parser {
    fun parse() = ...
}

// good
// code from a library
val strs: List<String> = listOf("foo, bar")
fun bar(): Int = 5

class Parser {
    fun parse(): ParsingResult = ...
}
```

##### [LibraryEntitiesShouldNotBePublic](https://detekt.github.io/detekt/style.html#libraryentitiesshouldnotbepublic)
ライブラリのタイプエイリアスとクラスは、internalまたはprivateを使用すべき

```kotlin
// bad
// code from a library
class A

// good
// code from a library
internal class A
```

##### [LoopWithTooManyJumpStatements](https://detekt.github.io/detekt/style.html#loopwithtoomanyjumpstatements)
複数のbreakまたはcontinueステートメントを含むループは、読んで理解しにくい。

```kotlin
// bad
val strs = listOf("foo, bar")
for (str in strs) {
    if (str == "bar") {
        break
    } else {
        continue
    }
}
```

##### [MagicNumber](https://detekt.github.io/detekt/style.html#magicnumber)
マジックナンバーの使用があります。

```kotlin
// bad
class User {

    fun checkName(name: String) {
        if (name.length > 42) {
            throw IllegalArgumentException("username is too long")
        }
        // ...
    }
}

// good
class User {

    fun checkName(name: String) {
        if (name.length > MAX_USERNAME_SIZE) {
            throw IllegalArgumentException("username is too long")
        }
        // ...
    }

    companion object {
        private const val MAX_USERNAME_SIZE = 42
    }
}
```

##### [MaxLineLength](https://detekt.github.io/detekt/style.html#maxlinelength)
定義された最大行長を超えるコードがあります。

(default: 120行)

##### [MayBeConst](https://detekt.github.io/detekt/style.html#maybeconst)
const val を使用する可能性のあるプロパティ (val) があります。
const valを使用すると、生成されるバイトコードのパフォーマンスが向上するだけでなく、Javaとの相互運用性も向上します。

```kotlin
// bad
val myConstant = "abc"

// good
const val MY_CONSTANT = "abc"
}
```

##### [ModifierOrder](https://detekt.github.io/detekt/style.html#modifierorder)
正しい順序でない修飾語があります。

```kotlin
// bad
lateinit internal val str: String

// good
internal lateinit val str: String
}
```

##### [NestedClassesVisibility](https://detekt.github.io/detekt/style.html#nestedclassesvisibility)
ネストクラスが親クラスよりアクセスレベル高い修飾語の使用があります。

```kotlin
// bad
internal class Outer {
    // explicit public modifier still results in an internal nested class
    public class Nested
}


// good
internal class Outer {
    class Nested1
    internal class Nested2
}
```

##### [NewLineAtEndOfFile](https://detekt.github.io/detekt/style.html#newlineatendoffile)
ファイル末尾に改行を入れるべき

実際に「C, C++」では、改行なしのソースファイルだと未定義扱いになり誤作動を引き起こす、とのこと。

##### [OptionalAbstractKeyword](https://detekt.github.io/detekt/style.html#optionalabstractkeyword)
不要で削除可能な抽象的な修飾語があります。

```kotlin
// bad
abstract interface Foo { // abstract keyword not needed

    abstract fun x() // abstract keyword not needed
    abstract var y: Int // abstract keyword not needed
}

// good
interface Foo {

    fun x()
    var y: Int
}
```

##### [ProtectedMemberInFinalClass](https://detekt.github.io/detekt/style.html#protectedmemberinfinalclass)
Kotlin のクラスはデフォルトで final です。したがって、open と protected メンバを含むべきではありません。代わりに private や internal を使うべき

```kotlin
// bad
class ProtectedMemberInFinalClass {
    protected var i = 0
}

// good
class ProtectedMemberInFinalClass {
    private var i = 0
}
```

##### [ReturnCount](https://detekt.github.io/detekt/style.html#returncount)
メソッド内で使用できるreturnの数を制限する

(default: 2)

```kotlin
// bad
fun foo(i: Int): String {
    when (i) {
        1 -> return "one"
        2 -> return "two"
        else -> return "other"
    }
}

// good
fun foo(i: Int): String {
    return when (i) {
        1 -> "one"
        2 -> "two"
        else -> "other"
    }
}
```

##### [SafeCast](https://detekt.github.io/detekt/style.html#safecast)
このルールはキャストを検査し、代わりに安全なキャストに置き換えることができる

```kotlin
// bad
fun numberMagic(number: Number) {
    val i = if (number is Int) number else null
    // ...
}


// good
fun numberMagic(number: Number) {
    val i = number as? Int
    // ...
}
```

##### [SerialVersionUIDInSerializableClass](https://detekt.github.io/detekt/style.html#serialversionuidinserializableclass)
Serializableインターフェースを実装しているクラスは、serialVersionUIDも正しく宣言する必要があります

```kotlin
// bad
class IncorrectSerializable : Serializable {

    companion object {
        val serialVersionUID = 1 // wrong declaration for UID
    }
}

// good
class CorrectSerializable : Serializable {

    companion object {
        const val serialVersionUID = 1L
    }
}
```

##### [ThrowsCount](https://detekt.github.io/detekt/style.html#throwscount)
メソッド内で使用できるthrowの数を制限する

(default: 2)

```kotlin
// bad
fun foo(i: Int) {
    when (i) {
        1 -> throw IllegalArgumentException()
        2 -> throw IllegalArgumentException()
        3 -> throw IllegalArgumentException()
    }
}

// good
fun foo(i: Int) {
    when (i) {
        1,2,3 -> throw IllegalArgumentException()
    }
}
```

##### [UnnecessaryAbstractClass](https://detekt.github.io/detekt/style.html#unnecessaryabstractclass)
抽象クラスが具象メンバーを持たない場合は、インターフェイスにリファクタリングする必要があります。
抽象的なメンバーを定義していない抽象クラスは、代わりに具象クラスにリファクタリングする必要があります。

```kotlin
// bad
abstract class OnlyAbstractMembersInAbstractClass { // violation: no concrete members

    abstract val i: Int
    abstract fun f()
}

abstract class OnlyConcreteMembersInAbstractClass { // violation: no abstract members

    val i: Int = 0
    fun f() { }
}
```

##### [UnnecessaryApply](https://detekt.github.io/detekt/style.html#unnecessaryapply)
apply式は頻繁に使用されますが、見た目の複雑さを軽減するために、通常のメソッドや拡張機能の呼び出しに置き換えるべき。

```kotlin
// bad
config.apply { version = "1.2" } // can be replaced with `config.version = "1.2"`
config?.apply { environment = "test" } // can be replaced with `config?.environment = "test"`
config?.apply { println(version) } // `apply` can be replaced by `let`

// good
config.apply {
    version = "1.2"
    environment = "test"
}
```

##### [UnnecessaryInheritance](https://detekt.github.io/detekt/style.html#unnecessaryinheritance)
不要なスーパータイプあります。
AnyやObjectからの継承は不要

```kotlin
// bad
class A : Any()
class B : Object()

// good
class A
class B
```

##### [UnusedPrivateClass](https://detekt.github.io/detekt/style.html#unusedprivateclass)
使用されていないプライベートクラスがあります。

##### [UnusedPrivateMember](https://detekt.github.io/detekt/style.html#unusedprivatemember)
使用されていないプライベートプロパティ、関数パラメータがあります。

##### [UselessCallOnNotNull](https://detekt.github.io/detekt/style.html#uselesscallonnotnull)
Kotlin stdlibには、NULLの可能性がある参照を操作するために設計された関数がいくつか用意されています。

```kotlin
// bad
val testList = listOf("string").orEmpty()
val testList2 = listOf("string").orEmpty().map { _ }
val testList3 = listOfNotNull("string")
val testString = ""?.isNullOrBlank()

// good
val testList = listOf("string")
val testList2 = listOf("string").map { }
val testList3 = listOf("string")
val testString = ""?.isBlank()
```

##### [UtilityClassWithPublicConstructor](https://detekt.github.io/detekt/style.html#utilityclasswithpublicconstructor)
具体的な実装を伴わないユーティリティー変数や関数のみを含むクラスは、オブジェクトや非公開のコンストラクタを持つクラスにリファクタリングすることができます。

```kotlin
// bad
class UtilityClassViolation {

    // public constructor here
    constructor() {
        // ...
    }

    companion object {
        val i = 0
    }
}

open class UtilityClassViolation private constructor() {

    // ...
}

// good
class UtilityClass {

    private constructor() {
        // ...
    }

    companion object {
        val i = 0
    }
}
object UtilityClass {

    val i = 0
}
```

##### [VarCouldBeVal](https://detekt.github.io/detekt/style.html#varcouldbeval)
var宣言は、再割り当てされないため、valにすべき

```kotlin
// bad
fun example() {
    var i = 1 // violation: this variable is never re-assigned
    val j = i + 1
}

// good
fun example() {
    val i = 1
    val j = i + 1
}
```

##### [WildcardImport](https://detekt.github.io/detekt/style.html#wildcardimport)
ワイルドカードによるインポートは、完全修飾クラス名を用いたインポートに置き換えるべきです。これにより、どのクラスがインポートされているかが明確になり、ネーミングコンフリクトを防ぐことができます。

```kotlin
// bad
import io.gitlab.arturbosch.detekt.*

class DetektElements {
    val element1 = DetektElement1()
    val element2 = DetektElement2()
}

// good
import io.gitlab.arturbosch.detekt.DetektElement1
import io.gitlab.arturbosch.detekt.DetektElement2

class DetektElements {
    val element1 = DetektElement1()
    val element2 = DetektElement2()
}
```