diff --git a/404.html b/404.html index 1bb3839a4..ac8441cbc 100644 --- a/404.html +++ b/404.html @@ -10,13 +10,13 @@ Page Not Found | Detekt - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/74ccadee.46979f76.js b/assets/js/74ccadee.46979f76.js new file mode 100644 index 000000000..9a90e6728 --- /dev/null +++ b/assets/js/74ccadee.46979f76.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdetekt_website=self.webpackChunkdetekt_website||[]).push([[3563],{3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return m}});var a=t(7294);function l(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n=0||(l[t]=e[t]);return l}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(l[t]=e[t])}return l}var p=a.createContext({}),s=function(e){var n=a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=s(e.components);return a.createElement(p.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,l=e.mdxType,i=e.originalType,p=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),u=s(t),m=l,k=u["".concat(p,".").concat(m)]||u[m]||c[m]||i;return t?a.createElement(k,o(o({ref:n},d),{},{components:t})):a.createElement(k,o({ref:n},d))}));function m(e,n){var t=arguments,l=n&&n.mdxType;if("string"==typeof e||l){var i=t.length,o=new Array(i);o[0]=u;var r={};for(var p in n)hasOwnProperty.call(n,p)&&(r[p]=n[p]);r.originalType=e,r.mdxType="string"==typeof e?e:l,o[1]=r;for(var s=2;s 0) {\n if (i < 5) {\n println(i)\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-3"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val i = 1\nif (i > 0 && i < 5) {\n println(i)\n}\n")),(0,i.kt)("h3",{id:"dataclasscontainsfunctions"},"DataClassContainsFunctions"),(0,i.kt)("p",null,"This rule reports functions inside data classes which have not been marked as a conversion function."),(0,i.kt)("p",null,"Data classes should mainly be used to store data. This rule assumes that they should not contain any extra functions\naside functions that help with converting objects from/to one another.\nData classes will automatically have a generated ",(0,i.kt)("inlineCode",{parentName:"p"},"equals"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"toString")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"hashCode")," function by the compiler."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 20min"),(0,i.kt)("h4",{id:"configuration-options-1"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"conversionFunctionPrefix")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'to'"),")"),(0,i.kt)("p",{parentName:"li"},"allowed conversion function names"))),(0,i.kt)("h4",{id:"noncompliant-code-4"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class DataClassWithFunctions(val i: Int) {\n fun foo() { }\n}\n")),(0,i.kt)("h3",{id:"dataclassshouldbeimmutable"},"DataClassShouldBeImmutable"),(0,i.kt)("p",null,"This rule reports mutable properties inside data classes."),(0,i.kt)("p",null,"Data classes should mainly be used to store immutable data. This rule assumes that they should not contain any\nmutable properties."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 20min"),(0,i.kt)("h4",{id:"noncompliant-code-5"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class MutableDataClass(var i: Int) {\n var s: String? = null\n}\n")),(0,i.kt)("h4",{id:"compliant-code-4"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class ImmutableDataClass(\n val i: Int,\n val s: String?\n)\n")),(0,i.kt)("h3",{id:"destructuringdeclarationwithtoomanyentries"},"DestructuringDeclarationWithTooManyEntries"),(0,i.kt)("p",null,"Destructuring declarations with too many entries are hard to read and understand.\nTo increase readability they should be refactored to reduce the number of entries or avoid using a destructuring\ndeclaration."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-2"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"maxDestructuringEntries")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"3"),")"),(0,i.kt)("p",{parentName:"li"},"maximum allowed elements in a destructuring declaration"))),(0,i.kt)("h4",{id:"noncompliant-code-6"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class TooManyElements(val a: Int, val b: Int, val c: Int, val d: Int)\nval (a, b, c, d) = TooManyElements(1, 2, 3, 4)\n")),(0,i.kt)("h4",{id:"compliant-code-5"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class FewerElements(val a: Int, val b: Int, val c: Int)\nval (a, b, c) = TooManyElements(1, 2, 3)\n")),(0,i.kt)("h3",{id:"equalsnullcall"},"EqualsNullCall"),(0,i.kt)("p",null,"To compare an object with ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," prefer using ",(0,i.kt)("inlineCode",{parentName:"p"},"=="),". This rule detects and reports instances in the code where the\n",(0,i.kt)("inlineCode",{parentName:"p"},"equals()")," method is used to compare a value with ",(0,i.kt)("inlineCode",{parentName:"p"},"null"),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-7"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun isNull(str: String) = str.equals(null)\n")),(0,i.kt)("h4",{id:"compliant-code-6"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun isNull(str: String) = str == null\n")),(0,i.kt)("h3",{id:"equalsonsignatureline"},"EqualsOnSignatureLine"),(0,i.kt)("p",null,"Requires that the equals sign, when used for an expression style function, is on the same line as the\nrest of the function signature."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-8"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff(): Int\n = 5\n\nfun foo(): Int where V : Int\n = 5\n")),(0,i.kt)("h4",{id:"compliant-code-7"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff() = 5\n\nfun stuff() =\n foo.bar()\n\nfun foo(): Int where V : Int = 5\n")),(0,i.kt)("h3",{id:"explicitcollectionelementaccessmethod"},"ExplicitCollectionElementAccessMethod"),(0,i.kt)("p",null,"In Kotlin functions ",(0,i.kt)("inlineCode",{parentName:"p"},"get")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"set")," can be replaced with the shorter operator \u2014 ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),",\nsee ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/operator-overloading.html#indexed-access-operator"},"Indexed access operator"),".\nPrefer the usage of the indexed access operator ",(0,i.kt)("inlineCode",{parentName:"p"},"[]")," for map or list element access or insert methods."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-9"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val map = mutableMapOf()\nmap.put("key", "value")\nval value = map.get("key")\n')),(0,i.kt)("h4",{id:"compliant-code-8"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val map = mutableMapOf()\nmap["key"] = "value"\nval value = map["key"]\n')),(0,i.kt)("h3",{id:"explicititlambdaparameter"},"ExplicitItLambdaParameter"),(0,i.kt)("p",null,"Lambda expressions are one of the core features of the language. They often include very small chunks of\ncode using only one parameter. In this cases Kotlin can supply the implicit ",(0,i.kt)("inlineCode",{parentName:"p"},"it")," parameter\nto make code more concise. It fits most usecases, but when faced larger or nested chunks of code,\nyou might want to add an explicit name for the parameter. Naming it just ",(0,i.kt)("inlineCode",{parentName:"p"},"it")," is meaningless and only\nmakes your code misleading, especially when dealing with nested functions."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-10"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a?.let { it -> it.plus(1) }\nfoo.flatMapObservable { it -> Observable.fromIterable(it) }\nlistOfPairs.map(::second).forEach { it ->\n it.execute()\n}\ncollection.zipWithNext { it, next -> Pair(it, next) }\n")),(0,i.kt)("h4",{id:"compliant-code-9"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a?.let { it.plus(1) } // Much better to use implicit it\nfoo.flatMapObservable(Observable::fromIterable) // Here we can have a method reference\n\n// For multiline blocks it is usually better come up with a clear and more meaningful name\nlistOfPairs.map(::second).forEach { apiRequest ->\n apiRequest.execute()\n}\n\n// Lambdas with multiple parameter should be named clearly, using it for one of them can be confusing\ncollection.zipWithNext { prev, next ->\n Pair(prev, next)\n}\n")),(0,i.kt)("h3",{id:"expressionbodysyntax"},"ExpressionBodySyntax"),(0,i.kt)("p",null,"Functions which only contain a ",(0,i.kt)("inlineCode",{parentName:"p"},"return")," statement can be collapsed to an expression body. This shortens and\ncleans up the code."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-3"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"includeLineWrapping")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"include return statements with line wraps in it"))),(0,i.kt)("h4",{id:"noncompliant-code-11"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff(): Int {\n return 5\n}\n")),(0,i.kt)("h4",{id:"compliant-code-10"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff() = 5\n\nfun stuff() {\n return\n moreStuff()\n .getStuff()\n .stuffStuff()\n}\n")),(0,i.kt)("h3",{id:"forbiddencomment"},"ForbiddenComment"),(0,i.kt)("p",null,"This rule allows to set a list of comments which are forbidden in the codebase and should only be used during\ndevelopment. Offending code comments will then be reported."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-4"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"values")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['FIXME:', 'STOPSHIP:', 'TODO:']"),")"),(0,i.kt)("p",{parentName:"li"},"forbidden comment strings")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowedPatterns")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"ignores comments which match the specified regular expression. For example ",(0,i.kt)("inlineCode",{parentName:"p"},"Ticket|Task"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"customMessage")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"error message which overrides the default one"))),(0,i.kt)("h4",{id:"noncompliant-code-12"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val a = "" // TODO: remove please\n// FIXME: this is a hack\nfun foo() { }\n// STOPSHIP:\n')),(0,i.kt)("h3",{id:"forbiddenimport"},"ForbiddenImport"),(0,i.kt)("p",null,"This rule allows to set a list of forbidden imports. This can be used to discourage the use of unstable, experimental\nor deprecated APIs. Detekt will then report all imports that are forbidden."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-5"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"imports")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},"imports which should not be used")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"forbiddenPatterns")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"reports imports which match the specified regular expression. For example ",(0,i.kt)("inlineCode",{parentName:"p"},"net.*R"),"."))),(0,i.kt)("h4",{id:"noncompliant-code-13"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"package foo\nimport kotlin.jvm.JvmField\nimport kotlin.SinceKotlin\n")),(0,i.kt)("h3",{id:"forbiddenmethodcall"},"ForbiddenMethodCall"),(0,i.kt)("p",null,"This rule allows to set a list of forbidden methods. This can be used to discourage the use of unstable, experimental\nor deprecated methods, especially for methods imported from external libraries.\nDetekt will then report all method invocations that are forbidden."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-6"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"methods")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['kotlin.io.print', 'kotlin.io.println']"),")"),(0,i.kt)("p",{parentName:"li"},"List of fully qualified method signatures which are forbidden. Methods can be defined without full signature (i.e. ",(0,i.kt)("inlineCode",{parentName:"p"},"java.time.LocalDate.now"),") which will report calls of all methods with this name or with full signature (i.e. ",(0,i.kt)("inlineCode",{parentName:"p"},"java.time.LocalDate(java.time.Clock)"),") which would report only call with this concrete signature. If you want to forbid an extension function like",(0,i.kt)("inlineCode",{parentName:"p"},"fun String.hello(a: Int)")," you should add the receiver parameter as the first parameter like this: ",(0,i.kt)("inlineCode",{parentName:"p"},"hello(kotlin.String, kotlin.Int)")))),(0,i.kt)("h4",{id:"noncompliant-code-14"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"import java.lang.System\nfun main() {\n System.gc()\n}\n")),(0,i.kt)("h3",{id:"forbiddenpublicdataclass"},"ForbiddenPublicDataClass"),(0,i.kt)("p",null,"Data classes are bad for binary compatibility in public APIs. Avoid using them."),(0,i.kt)("p",null,"This rule is aimed at library maintainers. If you are developing a final application you can ignore this issue."),(0,i.kt)("p",null,"More info: ",(0,i.kt)("a",{parentName:"p",href:"https://jakewharton.com/public-api-challenges-in-kotlin/"},"Public API challenges in Kotlin")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 20min"),(0,i.kt)("h4",{id:"configuration-options-7"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignorePackages")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['*.internal', '*.internal.*']"),")"),(0,i.kt)("p",{parentName:"li"},"ignores classes in the specified packages."))),(0,i.kt)("h4",{id:"noncompliant-code-15"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class C(val a: String) // violation: public data class\n")),(0,i.kt)("h4",{id:"compliant-code-11"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal data class C(val a: String)\n")),(0,i.kt)("h3",{id:"forbiddensuppress"},"ForbiddenSuppress"),(0,i.kt)("p",null,"This rule allows to set a list of rules whose suppression is forbidden.\nThis can be used to discourage the abuse of the ",(0,i.kt)("inlineCode",{parentName:"p"},"Suppress")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"SuppressWarnings")," annotations.\nDetekt will report suppression of all forbidden rules.\nThis rule is not capable of reporting suppression of itself, as that's a language feature with precedence."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-8"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"rules")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},"Rules whose suppression is forbidden."))),(0,i.kt)("h4",{id:"noncompliant-code-16"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'package foo\n\n// When the rule "MaximumLineLength" is forbidden\n@Suppress("MaximumLineLength", "UNCHECKED_CAST")\nclass Bar\n')),(0,i.kt)("h4",{id:"compliant-code-12"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'package foo\n\n// When the rule "MaximumLineLength" is forbidden\n@Suppress("UNCHECKED_CAST")\nclass Bar\n')),(0,i.kt)("h3",{id:"forbiddenvoid"},"ForbiddenVoid"),(0,i.kt)("p",null,"This rule detects usages of ",(0,i.kt)("inlineCode",{parentName:"p"},"Void")," and reports them as forbidden.\nThe Kotlin type ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," should be used instead. This type corresponds to the ",(0,i.kt)("inlineCode",{parentName:"p"},"Void")," class in Java\nand has only one value - the ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," object."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-9"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreOverridden")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"ignores void types in signatures of overridden functions")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreUsageInGenerics")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"ignore void types as generic arguments"))),(0,i.kt)("h4",{id:"noncompliant-code-17"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"runnable: () -> Void\nvar aVoid: Void? = null\n")),(0,i.kt)("h4",{id:"compliant-code-13"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"runnable: () -> Unit\nVoid::class\n")),(0,i.kt)("h3",{id:"functiononlyreturningconstant"},"FunctionOnlyReturningConstant"),(0,i.kt)("p",null,"A function that only returns a single constant can be misleading. Instead, prefer declaring the constant\nas a ",(0,i.kt)("inlineCode",{parentName:"p"},"const val"),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-10"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreOverridableFunction")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if overriden functions should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreActualFunction")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if actual functions should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludedFunctions")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"excluded functions")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"excludeAnnotatedFunction"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotated")," instead"),(0,i.kt)("p",{parentName:"li"},"allows to provide a list of annotations that disable this check"))),(0,i.kt)("h4",{id:"noncompliant-code-18"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun functionReturningConstantString() = "1"\n')),(0,i.kt)("h4",{id:"compliant-code-14"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'const val constantString = "1"\n')),(0,i.kt)("h3",{id:"librarycodemustspecifyreturntype"},"LibraryCodeMustSpecifyReturnType"),(0,i.kt)("p",null,"Functions/properties exposed as public APIs of a library should have an explicit return type.\nInferred return type can easily be changed by mistake which may lead to breaking changes."),(0,i.kt)("p",null,"See also: ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors"},"Kotlin 1.4 Explicit API")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-19"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'// code from a library\nval strs = listOf("foo, bar")\nfun bar() = 5\nclass Parser {\n fun parse() = ...\n}\n')),(0,i.kt)("h4",{id:"compliant-code-15"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'// code from a library\nval strs: List = listOf("foo, bar")\nfun bar(): Int = 5\n\nclass Parser {\n fun parse(): ParsingResult = ...\n}\n')),(0,i.kt)("h3",{id:"libraryentitiesshouldnotbepublic"},"LibraryEntitiesShouldNotBePublic"),(0,i.kt)("p",null,"Library typealias and classes should be internal or private."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-20"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"// code from a library\nclass A\n")),(0,i.kt)("h4",{id:"compliant-code-16"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"// code from a library\ninternal class A\n")),(0,i.kt)("h3",{id:"loopwithtoomanyjumpstatements"},"LoopWithTooManyJumpStatements"),(0,i.kt)("p",null,"Loops which contain multiple ",(0,i.kt)("inlineCode",{parentName:"p"},"break")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"continue")," statements are hard to read and understand.\nTo increase readability they should be refactored into simpler loops."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-11"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"maxJumpCount")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"1"),")"),(0,i.kt)("p",{parentName:"li"},"maximum allowed jumps in a loop"))),(0,i.kt)("h4",{id:"noncompliant-code-21"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val strs = listOf("foo, bar")\nfor (str in strs) {\n if (str == "bar") {\n break\n } else {\n continue\n }\n}\n')),(0,i.kt)("h3",{id:"magicnumber"},"MagicNumber"),(0,i.kt)("p",null,"This rule detects and reports usages of magic numbers in the code. Prefer defining constants with clear names\ndescribing what the magic number means."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-12"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreNumbers")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['-1', '0', '1', '2']"),")"),(0,i.kt)("p",{parentName:"li"},"numbers which do not count as magic numbers")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreHashCodeFunction")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in hashCode functions should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignorePropertyDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in property declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreLocalVariableDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in local variable declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreConstantDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in constant declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreCompanionObjectPropertyDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in companion object declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotation")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in annotations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreNamedArgument")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in named arguments should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreEnums")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in enums should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreRanges")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in ranges should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreExtensionFunctions")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers as subject of an extension function should be ignored"))),(0,i.kt)("h4",{id:"noncompliant-code-22"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'class User {\n\n fun checkName(name: String) {\n if (name.length > 42) {\n throw IllegalArgumentException("username is too long")\n }\n // ...\n }\n}\n')),(0,i.kt)("h4",{id:"compliant-code-17"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'class User {\n\n fun checkName(name: String) {\n if (name.length > MAX_USERNAME_SIZE) {\n throw IllegalArgumentException("username is too long")\n }\n // ...\n }\n\n companion object {\n private const val MAX_USERNAME_SIZE = 42\n }\n}\n')),(0,i.kt)("h3",{id:"mandatorybracesifstatements"},"MandatoryBracesIfStatements"),(0,i.kt)("p",null,"This rule detects multi-line ",(0,i.kt)("inlineCode",{parentName:"p"},"if")," statements which do not have braces.\nAdding braces would improve readability and avoid possible errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-23"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val i = 1\nif (i > 0)\n println(i)\n")),(0,i.kt)("h4",{id:"compliant-code-18"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val x = if (condition) 5 else 4\n")),(0,i.kt)("h3",{id:"mandatorybracesloops"},"MandatoryBracesLoops"),(0,i.kt)("p",null,"This rule detects multi-line ",(0,i.kt)("inlineCode",{parentName:"p"},"for")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"while")," loops which do not have braces.\nAdding braces would improve readability and avoid possible errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-24"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'for (i in 0..10)\n println(i)\n\nwhile (true)\n println("Hello, world")\n\ndo\n println("Hello, world")\nwhile (true)\n')),(0,i.kt)("h4",{id:"compliant-code-19"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'for (i in 0..10) {\n println(i)\n}\n\nfor (i in 0..10) println(i)\n\nwhile (true) {\n println("Hello, world")\n}\n\nwhile (true) println("Hello, world")\n\ndo {\n println("Hello, world")\n} while (true)\n\ndo println("Hello, world") while (true)\n')),(0,i.kt)("h3",{id:"maxlinelength"},"MaxLineLength"),(0,i.kt)("p",null,"This rule reports lines of code which exceed a defined maximum line length."),(0,i.kt)("p",null,"Long lines might be hard to read on smaller screens or printouts. Additionally, having a maximum line length\nin the codebase will help make the code more uniform."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-13"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"maxLineLength")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"120"),")"),(0,i.kt)("p",{parentName:"li"},"maximum line length")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludePackageStatements")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if package statements should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeImportStatements")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if import statements should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeCommentStatements")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if comment statements should be ignored"))),(0,i.kt)("h3",{id:"maybeconst"},"MayBeConst"),(0,i.kt)("p",null,"This rule identifies and reports properties (",(0,i.kt)("inlineCode",{parentName:"p"},"val"),") that may be ",(0,i.kt)("inlineCode",{parentName:"p"},"const val")," instead.\nUsing ",(0,i.kt)("inlineCode",{parentName:"p"},"const val")," can lead to better performance of the resulting bytecode as well as better interoperability with\nJava."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": MayBeConstant"),(0,i.kt)("h4",{id:"noncompliant-code-25"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val myConstant = "abc"\n')),(0,i.kt)("h4",{id:"compliant-code-20"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'const val MY_CONSTANT = "abc"\n')),(0,i.kt)("h3",{id:"modifierorder"},"ModifierOrder"),(0,i.kt)("p",null,"This rule reports cases in the code where modifiers are not in the correct order. The default modifier order is\ntaken from: ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/coding-conventions.html#modifiers-order"},"Modifiers order")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-26"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"lateinit internal val str: String\n")),(0,i.kt)("h4",{id:"compliant-code-21"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal lateinit val str: String\n")),(0,i.kt)("h3",{id:"multilinelambdaitparameter"},"MultilineLambdaItParameter"),(0,i.kt)("p",null,"Lambda expressions are very useful in a lot of cases, and they often include very small chunks of\ncode using only one parameter. In this cases Kotlin can supply the implicit ",(0,i.kt)("inlineCode",{parentName:"p"},"it")," parameter\nto make code more concise. However, when you are dealing with lambdas that contain multiple statements,\nyou might end up with code that is hard to read if you don't specify a readable, descriptive parameter name\nexplicitly."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-27"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val digits = 1234.let {\n println(it)\n listOf(it)\n}\n\nval digits = 1234.let { it ->\n println(it)\n listOf(it)\n}\n\nval flat = listOf(listOf(1), listOf(2)).mapIndexed { index, it ->\n println(it)\n it + index\n}\n")),(0,i.kt)("h4",{id:"compliant-code-22"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val digits = 1234.let { explicitParameterName ->\n println(explicitParameterName)\n listOf(explicitParameterName)\n}\n\nval lambda = { item: Int, that: String ->\n println(item)\n item.toString() + that\n}\n\nval digits = 1234.let { listOf(it) }\nval digits = 1234.let {\n listOf(it)\n}\nval digits = 1234.let { it -> listOf(it) }\nval digits = 1234.let { it ->\n listOf(it)\n}\nval digits = 1234.let { explicit -> listOf(explicit) }\nval digits = 1234.let { explicit ->\n listOf(explicit)\n}\n")),(0,i.kt)("h3",{id:"nestedclassesvisibility"},"NestedClassesVisibility"),(0,i.kt)("p",null,"Nested classes inherit their visibility from the parent class\nand are often used to implement functionality local to the class it is nested in.\nThese nested classes can't have a higher visibility than their parent.\nHowever, the visibility can be further restricted by using a private modifier for instance.\nIn internal classes the ",(0,i.kt)("em",{parentName:"p"},"explicit")," public modifier for nested classes is misleading and thus unnecessary,\nbecause the nested class still has an internal visibility."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-28"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal class Outer {\n // explicit public modifier still results in an internal nested class\n public class Nested\n}\n")),(0,i.kt)("h4",{id:"compliant-code-23"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal class Outer {\n class Nested1\n internal class Nested2\n}\n")),(0,i.kt)("h3",{id:"newlineatendoffile"},"NewLineAtEndOfFile"),(0,i.kt)("p",null,"This rule reports files which do not end with a line separator."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"notabs"},"NoTabs"),(0,i.kt)("p",null,"This rule reports if tabs are used in Kotlin files.\nAccording to\n",(0,i.kt)("a",{parentName:"p",href:"https://android.github.io/kotlin-guides/style.html#whitespace-characters"},"Google's Kotlin style guide"),"\nthe only whitespace chars that are allowed in a source file are the line terminator sequence\nand the ASCII horizontal space character (0x20). Strings containing tabs are allowed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"nullablebooleancheck"},"NullableBooleanCheck"),(0,i.kt)("p",null,"Detects nullable boolean checks which use an elvis expression ",(0,i.kt)("inlineCode",{parentName:"p"},"?:")," rather than equals ",(0,i.kt)("inlineCode",{parentName:"p"},"=="),"."),(0,i.kt)("p",null,"Per the ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/coding-conventions.html#nullable-boolean-values-in-conditions"},"Kotlin coding conventions"),"\nconverting a nullable boolean property to non-null should be done via ",(0,i.kt)("inlineCode",{parentName:"p"},"!= false")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"== true"),"\nrather than ",(0,i.kt)("inlineCode",{parentName:"p"},"?: true")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"?: false")," (respectively)."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-29"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"value ?: true\nvalue ?: false\n")),(0,i.kt)("h4",{id:"compliant-code-24"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"value != false\nvalue == true\n")),(0,i.kt)("h3",{id:"objectliteraltolambda"},"ObjectLiteralToLambda"),(0,i.kt)("p",null,"An anonymous object that does nothing other than the implementation of a single method\ncan be used as a lambda."),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/java-interop.html#sam-conversions"},"SAM conversions"),",\n",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/fun-interfaces.html"},"Functional (SAM) interfaces")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-30"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"object : Foo {\n override fun bar() {\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-25"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"Foo {\n}\n")),(0,i.kt)("h3",{id:"optionalabstractkeyword"},"OptionalAbstractKeyword"),(0,i.kt)("p",null,"This rule reports ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract")," modifiers which are unnecessary and can be removed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-31"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"abstract interface Foo { // abstract keyword not needed\n\n abstract fun x() // abstract keyword not needed\n abstract var y: Int // abstract keyword not needed\n}\n")),(0,i.kt)("h4",{id:"compliant-code-26"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"interface Foo {\n\n fun x()\n var y: Int\n}\n")),(0,i.kt)("h3",{id:"optionalunit"},"OptionalUnit"),(0,i.kt)("p",null,"It is not necessary to define a return type of ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," on functions or to specify a lone Unit statement.\nThis rule detects and reports instances where the ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," return type is specified on functions and the occurrences\nof a lone Unit statement."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-32"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(): Unit {\n return Unit\n}\nfun foo() = Unit\n\nfun doesNothing() {\n Unit\n}\n")),(0,i.kt)("h4",{id:"compliant-code-27"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo() { }\n\n// overridden no-op functions are allowed\noverride fun foo() = Unit\n")),(0,i.kt)("h3",{id:"optionalwhenbraces"},"OptionalWhenBraces"),(0,i.kt)("p",null,"This rule reports unnecessary braces in when expressions. These optional braces should be removed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-33"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val i = 1\nwhen (i) {\n 1 -> { println("one") } // unnecessary curly braces since there is only one statement\n else -> println("else")\n}\n')),(0,i.kt)("h4",{id:"compliant-code-28"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val i = 1\nwhen (i) {\n 1 -> println("one")\n else -> println("else")\n}\n')),(0,i.kt)("h3",{id:"prefertooverpairsyntax"},"PreferToOverPairSyntax"),(0,i.kt)("p",null,"This rule detects the usage of the Pair constructor to create pairs of values."),(0,i.kt)("p",null,"Using ","<","value1",">"," to ","<","value2",">"," is preferred."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-34"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val pair = Pair(1, 2)\n")),(0,i.kt)("h4",{id:"compliant-code-29"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val pair = 1 to 2\n")),(0,i.kt)("h3",{id:"protectedmemberinfinalclass"},"ProtectedMemberInFinalClass"),(0,i.kt)("p",null,"Kotlin classes are ",(0,i.kt)("inlineCode",{parentName:"p"},"final")," by default. Thus classes which are not marked as ",(0,i.kt)("inlineCode",{parentName:"p"},"open")," should not contain any ",(0,i.kt)("inlineCode",{parentName:"p"},"protected"),"\nmembers. Consider using ",(0,i.kt)("inlineCode",{parentName:"p"},"private")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"internal")," modifiers instead."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-35"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class ProtectedMemberInFinalClass {\n protected var i = 0\n}\n")),(0,i.kt)("h4",{id:"compliant-code-30"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class ProtectedMemberInFinalClass {\n private var i = 0\n}\n")),(0,i.kt)("h3",{id:"redundantexplicittype"},"RedundantExplicitType"),(0,i.kt)("p",null,"Local properties do not need their type to be explicitly provided when the inferred type matches the explicit type."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-36"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun function() {\n val x: String = "string"\n}\n')),(0,i.kt)("h4",{id:"compliant-code-31"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun function() {\n val x = "string"\n}\n')),(0,i.kt)("h3",{id:"redundanthigherordermapusage"},"RedundantHigherOrderMapUsage"),(0,i.kt)("p",null,"Redundant maps add complexity to the code and accomplish nothing. They should be removed or replaced with the proper\noperator."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-37"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(list: List): List {\n return list\n .filter { it > 5 }\n .map { it }\n}\n\nfun bar(list: List): List {\n return list\n .filter { it > 5 }\n .map {\n doSomething(it)\n it\n }\n}\n\nfun baz(set: Set): List {\n return set.map { it }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-32"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(list: List): List {\n return list\n .filter { it > 5 }\n}\n\nfun bar(list: List): List {\n return list\n .filter { it > 5 }\n .onEach {\n doSomething(it)\n }\n}\n\nfun baz(set: Set): List {\n return set.toList()\n}\n")),(0,i.kt)("h3",{id:"redundantvisibilitymodifierrule"},"RedundantVisibilityModifierRule"),(0,i.kt)("p",null,"This rule checks for redundant visibility modifiers.\nOne exemption is the\n",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors"},"explicit API mode"),"\nIn this mode, the visibility modifier should be defined explicitly even if it is public.\nHence, the rule ignores the visibility modifiers in explicit API mode."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": RedundantVisibilityModifier"),(0,i.kt)("h4",{id:"noncompliant-code-38"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"public interface Foo { // public per default\n\n public fun bar() // public per default\n}\n")),(0,i.kt)("h4",{id:"compliant-code-33"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"interface Foo {\n\n fun bar()\n}\n")),(0,i.kt)("h3",{id:"returncount"},"ReturnCount"),(0,i.kt)("p",null,"Restrict the number of return methods allowed in methods."),(0,i.kt)("p",null,"Having many exit points in a function can be confusing and impacts readability of the\ncode."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-14"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"max")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"2"),")"),(0,i.kt)("p",{parentName:"li"},"define the maximum number of return statements allowed per function")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludedFunctions")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'equals'"),")"),(0,i.kt)("p",{parentName:"li"},"define functions to be ignored by this check")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeLabeled")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if labeled return statements should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeReturnFromLambda")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if labeled return from a lambda should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeGuardClauses")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if true guard clauses at the beginning of a method should be ignored"))),(0,i.kt)("h4",{id:"noncompliant-code-39"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun foo(i: Int): String {\n when (i) {\n 1 -> return "one"\n 2 -> return "two"\n else -> return "other"\n }\n}\n')),(0,i.kt)("h4",{id:"compliant-code-34"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun foo(i: Int): String {\n return when (i) {\n 1 -> "one"\n 2 -> "two"\n else -> "other"\n }\n}\n')),(0,i.kt)("h3",{id:"safecast"},"SafeCast"),(0,i.kt)("p",null,"This rule inspects casts and reports casts which could be replaced with safe casts instead."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-40"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun numberMagic(number: Number) {\n val i = if (number is Int) number else null\n // ...\n}\n")),(0,i.kt)("h4",{id:"compliant-code-35"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun numberMagic(number: Number) {\n val i = number as? Int\n // ...\n}\n")),(0,i.kt)("h3",{id:"serialversionuidinserializableclass"},"SerialVersionUIDInSerializableClass"),(0,i.kt)("p",null,"Classes which implement the ",(0,i.kt)("inlineCode",{parentName:"p"},"Serializable")," interface should also correctly declare a ",(0,i.kt)("inlineCode",{parentName:"p"},"serialVersionUID"),".\nThis rule verifies that a ",(0,i.kt)("inlineCode",{parentName:"p"},"serialVersionUID")," was correctly defined."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-41"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class IncorrectSerializable : Serializable {\n\n companion object {\n val serialVersionUID = 1 // wrong declaration for UID\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-36"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class CorrectSerializable : Serializable {\n\n companion object {\n const val serialVersionUID = 1L\n }\n}\n")),(0,i.kt)("h3",{id:"spacingbetweenpackageandimports"},"SpacingBetweenPackageAndImports"),(0,i.kt)("p",null,"This rule verifies spacing between package and import statements as well as between import statements and class\ndeclarations."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-42"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"package foo\nimport a.b\nclass Bar { }\n")),(0,i.kt)("h4",{id:"compliant-code-37"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"package foo\n\nimport a.b\n\nclass Bar { }\n")),(0,i.kt)("h3",{id:"throwscount"},"ThrowsCount"),(0,i.kt)("p",null,"Functions should have clear ",(0,i.kt)("inlineCode",{parentName:"p"},"throw")," statements. Functions with many ",(0,i.kt)("inlineCode",{parentName:"p"},"throw")," statements can be harder to read and lead\nto confusion. Instead, prefer limiting the number of ",(0,i.kt)("inlineCode",{parentName:"p"},"throw")," statements in a function."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-15"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"max")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"2"),")"),(0,i.kt)("p",{parentName:"li"},"maximum amount of throw statements in a method")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeGuardClauses")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if set to true, guard clauses do not count towards the allowed throws count"))),(0,i.kt)("h4",{id:"noncompliant-code-43"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(i: Int) {\n when (i) {\n 1 -> throw IllegalArgumentException()\n 2 -> throw IllegalArgumentException()\n 3 -> throw IllegalArgumentException()\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-38"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(i: Int) {\n when (i) {\n 1,2,3 -> throw IllegalArgumentException()\n }\n}\n")),(0,i.kt)("h3",{id:"trailingwhitespace"},"TrailingWhitespace"),(0,i.kt)("p",null,"This rule reports lines that end with a whitespace."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"underscoresinnumericliterals"},"UnderscoresInNumericLiterals"),(0,i.kt)("p",null,"This rule detects and reports long base 10 numbers which should be separated with underscores\nfor readability. For ",(0,i.kt)("inlineCode",{parentName:"p"},"Serializable")," classes or objects, the field ",(0,i.kt)("inlineCode",{parentName:"p"},"serialVersionUID")," is\nexplicitly ignored. For floats and doubles, anything to the right of the decimal point is ignored."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-16"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"acceptableDecimalLength"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"5"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"acceptableLength")," instead"),(0,i.kt)("p",{parentName:"li"},"Length under which base 10 numbers are not required to have underscores")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"acceptableLength")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"4"),")"),(0,i.kt)("p",{parentName:"li"},"Maximum number of consecutive digits that a numeric literal can have without using an underscore")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowNonStandardGrouping")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"If set to false, groups of exactly three digits must be used. If set to true, 100_00 is allowed."))),(0,i.kt)("h4",{id:"noncompliant-code-44"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"const val DEFAULT_AMOUNT = 1000000\n")),(0,i.kt)("h4",{id:"compliant-code-39"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"const val DEFAULT_AMOUNT = 1_000_000\n")),(0,i.kt)("h3",{id:"unnecessaryabstractclass"},"UnnecessaryAbstractClass"),(0,i.kt)("p",null,"This rule inspects ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract")," classes. In case an ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract class")," does not have any concrete members it should be\nrefactored into an interface. Abstract classes which do not define any ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract")," members should instead be\nrefactored into concrete classes."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-17"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"excludeAnnotatedClasses"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotated")," instead"),(0,i.kt)("p",{parentName:"li"},"Allows you to provide a list of annotations that disable this check."))),(0,i.kt)("h4",{id:"noncompliant-code-45"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"abstract class OnlyAbstractMembersInAbstractClass { // violation: no concrete members\n\n abstract val i: Int\n abstract fun f()\n}\n\nabstract class OnlyConcreteMembersInAbstractClass { // violation: no abstract members\n\n val i: Int = 0\n fun f() { }\n}\n")),(0,i.kt)("h3",{id:"unnecessaryannotationusesitetarget"},"UnnecessaryAnnotationUseSiteTarget"),(0,i.kt)("p",null,"This rule inspects the use of the Annotation use-site Target. In case that the use-site Target is not needed it can\nbe removed. For more information check the kotlin documentation:\n",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets"},"Annotation use-site targets")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-46"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'@property:Inject private val foo: String = "bar" // violation: unnecessary @property:\n\nclass Module(@param:Inject private val foo: String) // violation: unnecessary @param:\n')),(0,i.kt)("h4",{id:"compliant-code-40"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class Module(@Inject private val foo: String)\n")),(0,i.kt)("h3",{id:"unnecessaryapply"},"UnnecessaryApply"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"apply")," expressions are used frequently, but sometimes their usage should be replaced with\nan ordinary method/extension function call to reduce visual complexity"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-47"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'config.apply { version = "1.2" } // can be replaced with `config.version = "1.2"`\nconfig?.apply { environment = "test" } // can be replaced with `config?.environment = "test"`\nconfig?.apply { println(version) } // `apply` can be replaced by `let`\n')),(0,i.kt)("h4",{id:"compliant-code-41"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'config.apply {\n version = "1.2"\n environment = "test"\n}\n')),(0,i.kt)("h3",{id:"unnecessarybackticks"},"UnnecessaryBackticks"),(0,i.kt)("p",null,"This rule reports unnecessary backticks."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-48"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class `HelloWorld`\n")),(0,i.kt)("h4",{id:"compliant-code-42"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class HelloWorld\n")),(0,i.kt)("h3",{id:"unnecessaryfilter"},"UnnecessaryFilter"),(0,i.kt)("p",null,"Unnecessary filters add complexity to the code and accomplish nothing. They should be removed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-49"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val x = listOf(1, 2, 3)\n .filter { it > 1 }\n .count()\n\nval x = listOf(1, 2, 3)\n .filter { it > 1 }\n .isEmpty()\n")),(0,i.kt)("h4",{id:"compliant-code-43"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val x = listOf(1, 2, 3)\n .count { it > 2 }\n}\n\nval x = listOf(1, 2, 3)\n .none { it > 1 }\n")),(0,i.kt)("h3",{id:"unnecessaryinheritance"},"UnnecessaryInheritance"),(0,i.kt)("p",null,"This rule reports unnecessary super types. Inheriting from ",(0,i.kt)("inlineCode",{parentName:"p"},"Any")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"Object")," is unnecessary and should simply be\nremoved."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-50"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class A : Any()\nclass B : Object()\n")),(0,i.kt)("h3",{id:"unnecessaryinnerclass"},"UnnecessaryInnerClass"),(0,i.kt)("p",null,"This rule reports unnecessary inner classes. Nested classes that do not access members from the outer class do\nnot require the ",(0,i.kt)("inlineCode",{parentName:"p"},"inner")," qualifier."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-51"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'class A {\n val foo = "BAR"\n\n inner class B {\n val fizz = "BUZZ"\n\n fun printFizz() {\n println(fizz)\n }\n }\n}\n')),(0,i.kt)("h3",{id:"unnecessarylet"},"UnnecessaryLet"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"let")," expressions are used extensively in our code for null-checking and chaining functions,\nbut sometimes their usage should be replaced with an ordinary method/extension function call\nto reduce visual complexity."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-52"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a.let { print(it) } // can be replaced with `print(a)`\na.let { it.plus(1) } // can be replaced with `a.plus(1)`\na?.let { it.plus(1) } // can be replaced with `a?.plus(1)`\na?.let { that -> that.plus(1) }?.let { it.plus(1) } // can be replaced with `a?.plus(1)?.plus(1)`\na.let { 1.plus(1) } // can be replaced with `1.plus(1)`\na?.let { 1.plus(1) } // can be replaced with `if (a != null) 1.plus(1)`\n")),(0,i.kt)("h4",{id:"compliant-code-44"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a?.let { print(it) }\na?.let { 1.plus(it) } ?.let { msg -> print(msg) }\na?.let { it.plus(it) }\nval b = a?.let { 1.plus(1) }\n")),(0,i.kt)("h3",{id:"unnecessaryparentheses"},"UnnecessaryParentheses"),(0,i.kt)("p",null,"This rule reports unnecessary parentheses around expressions.\nThese unnecessary parentheses can safely be removed."),(0,i.kt)("p",null,"Added in v1.0.0.RC4"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-53"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val local = (5 + 3)\n\nif ((local == 8)) { }\n\nfun foo() {\n function({ input -> println(input) })\n}\n")),(0,i.kt)("h4",{id:"compliant-code-45"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val local = 5 + 3\n\nif (local == 8) { }\n\nfun foo() {\n function { input -> println(input) }\n}\n")),(0,i.kt)("h3",{id:"untilinsteadofrangeto"},"UntilInsteadOfRangeTo"),(0,i.kt)("p",null,"Reports calls to '..' operator instead of calls to 'until'.\n'until' is applicable in cases where the upper range value is described as\nsome value subtracted by 1. 'until' helps to prevent off-by-one errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-54"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"for (i in 0 .. 10 - 1) {}\nval range = 0 .. 10 - 1\n")),(0,i.kt)("h4",{id:"compliant-code-46"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"for (i in 0 until 10) {}\nval range = 0 until 10\n")),(0,i.kt)("h3",{id:"unusedimports"},"UnusedImports"),(0,i.kt)("p",null,"This rule reports unused imports. Unused imports are dead code and should be removed.\nExempt from this rule are imports resulting from references to elements within KDoc and\nfrom destructuring declarations (componentN imports)."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"unusedprivateclass"},"UnusedPrivateClass"),(0,i.kt)("p",null,"Reports unused private classes. If private classes are unused they should be removed. Otherwise, this dead code\ncan lead to confusion and potential bugs."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": unused"),(0,i.kt)("h3",{id:"unusedprivatemember"},"UnusedPrivateMember"),(0,i.kt)("p",null,"Reports unused private properties, function parameters and functions.\nIf these private elements are unused they should be removed. Otherwise, this dead code\ncan lead to confusion and potential bugs."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": UNUSED_VARIABLE, UNUSED_PARAMETER, unused"),(0,i.kt)("h4",{id:"configuration-options-18"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowedNames")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'(_|ignored|expected|serialVersionUID)'"),")"),(0,i.kt)("p",{parentName:"li"},"unused private member names matching this regex are ignored"))),(0,i.kt)("h3",{id:"useanyornoneinsteadoffind"},"UseAnyOrNoneInsteadOfFind"),(0,i.kt)("p",null,"Turn on this rule to flag ",(0,i.kt)("inlineCode",{parentName:"p"},"find")," calls for null check that can be replaced with a ",(0,i.kt)("inlineCode",{parentName:"p"},"any")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"none")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-55"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"listOf(1, 2, 3).find { it == 4 } != null\nlistOf(1, 2, 3).find { it == 4 } == null\n")),(0,i.kt)("h4",{id:"compliant-code-47"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"listOf(1, 2, 3).any { it == 4 }\nlistOf(1, 2, 3).none { it == 4 }\n")),(0,i.kt)("h3",{id:"usearrayliteralsinannotations"},"UseArrayLiteralsInAnnotations"),(0,i.kt)("p",null,"This rule detects annotations which use the arrayOf(...) syntax instead of the array literal ","[...]"," syntax.\nThe latter should be preferred as it is more readable."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-56"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'@PositiveCase(arrayOf("..."))\n')),(0,i.kt)("h4",{id:"compliant-code-48"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'@NegativeCase(["..."])\n')),(0,i.kt)("h3",{id:"usechecknotnull"},"UseCheckNotNull"),(0,i.kt)("p",null,"Turn on this rule to flag ",(0,i.kt)("inlineCode",{parentName:"p"},"check")," calls for not-null check that can be replaced with a ",(0,i.kt)("inlineCode",{parentName:"p"},"checkNotNull")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-57"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"check(x != null)\n")),(0,i.kt)("h4",{id:"compliant-code-49"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"checkNotNull(x)\n")),(0,i.kt)("h3",{id:"usecheckorerror"},"UseCheckOrError"),(0,i.kt)("p",null,"Kotlin provides a concise way to check invariants as well as pre- and post-conditions.\nPrefer them instead of manually throwing an IllegalStateException."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-58"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'if (value == null) throw IllegalStateException("value should not be null")\nif (value < 0) throw IllegalStateException("value is $value but should be at least 0")\nwhen(a) {\n 1 -> doSomething()\n else -> throw IllegalStateException("Unexpected value")\n}\n')),(0,i.kt)("h4",{id:"compliant-code-50"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'checkNotNull(value) { "value should not be null" }\ncheck(value >= 0) { "value is $value but should be at least 0" }\nwhen(a) {\n 1 -> doSomething()\n else -> error("Unexpected value")\n}\n')),(0,i.kt)("h3",{id:"usedataclass"},"UseDataClass"),(0,i.kt)("p",null,"Classes that simply hold data should be refactored into a ",(0,i.kt)("inlineCode",{parentName:"p"},"data class"),". Data classes are specialized to hold data\nand generate ",(0,i.kt)("inlineCode",{parentName:"p"},"hashCode"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"equals")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"toString")," implementations as well."),(0,i.kt)("p",null,"Read more about ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/data-classes.html"},"data classes")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-19"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"excludeAnnotatedClasses"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotated")," instead"),(0,i.kt)("p",{parentName:"li"},"allows to provide a list of annotations that disable this check")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowVars")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"allows to relax this rule in order to exclude classes that contains one (or more) vars"))),(0,i.kt)("h4",{id:"noncompliant-code-59"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class DataClassCandidate(val i: Int) {\n val i2: Int = 0\n}\n")),(0,i.kt)("h4",{id:"compliant-code-51"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class DataClass(val i: Int, val i2: Int)\n\n// classes with delegating interfaces are compliant\ninterface I\nclass B() : I\nclass A(val b: B) : I by b\n")),(0,i.kt)("h3",{id:"useemptycounterpart"},"UseEmptyCounterpart"),(0,i.kt)("p",null,'Instantiation of an object\'s "empty" state should use the object\'s "empty" initializer for clarity purposes.'),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-60"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"arrayOf()\nlistOf() // or listOfNotNull()\nmapOf()\nsequenceOf()\nsetOf()\n")),(0,i.kt)("h4",{id:"compliant-code-52"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"emptyArray()\nemptyList()\nemptyMap()\nemptySequence()\nemptySet()\n")),(0,i.kt)("h3",{id:"useifemptyorifblank"},"UseIfEmptyOrIfBlank"),(0,i.kt)("p",null,"This rule detects ",(0,i.kt)("inlineCode",{parentName:"p"},"isEmpty")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"isBlank")," calls to assign a default value. They can be replaced with ",(0,i.kt)("inlineCode",{parentName:"p"},"ifEmpty")," or\n",(0,i.kt)("inlineCode",{parentName:"p"},"ifBlank")," calls."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-61"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun test(list: List, s: String) {\n val a = if (list.isEmpty()) listOf(1) else list\n val b = if (list.isNotEmpty()) list else listOf(2)\n val c = if (s.isBlank()) "foo" else s\n val d = if (s.isNotBlank()) s else "bar"\n}\n')),(0,i.kt)("h4",{id:"compliant-code-53"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun test(list: List, s: String) {\n val a = list.ifEmpty { listOf(1) }\n val b = list.ifEmpty { listOf(2) }\n val c = s.ifBlank { "foo" }\n val d = s.ifBlank { "bar" }\n}\n')),(0,i.kt)("h3",{id:"useifinsteadofwhen"},"UseIfInsteadOfWhen"),(0,i.kt)("p",null,"Binary expressions are better expressed using an ",(0,i.kt)("inlineCode",{parentName:"p"},"if")," expression than a ",(0,i.kt)("inlineCode",{parentName:"p"},"when")," expression."),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/coding-conventions.html#if-versus-when"},"if versus when")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-62"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"when (x) {\n null -> true\n else -> false\n}\n")),(0,i.kt)("h4",{id:"compliant-code-54"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"if (x == null) true else false\n")),(0,i.kt)("h3",{id:"useisnullorempty"},"UseIsNullOrEmpty"),(0,i.kt)("p",null,"This rule detects null or empty checks that can be replaced with ",(0,i.kt)("inlineCode",{parentName:"p"},"isNullOrEmpty()")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-63"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(x: List?) {\n if (x == null || x.isEmpty()) return\n}\nfun bar(x: List?) {\n if (x == null || x.count() == 0) return\n}\nfun baz(x: List?) {\n if (x == null || x.size == 0) return\n}\n")),(0,i.kt)("h4",{id:"compliant-code-55"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"if (x.isNullOrEmpty()) return\n")),(0,i.kt)("h3",{id:"useorempty"},"UseOrEmpty"),(0,i.kt)("p",null,"This rule detects ",(0,i.kt)("inlineCode",{parentName:"p"},"?: emptyList()")," that can be replaced with ",(0,i.kt)("inlineCode",{parentName:"p"},"orEmpty()")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-64"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun test(x: List?, s: String?) {\n val a = x ?: emptyList()\n val b = s ?: ""\n}\n')),(0,i.kt)("h4",{id:"compliant-code-56"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun test(x: List?, s: String?) {\n val a = x.orEmpty()\n val b = s.orEmpty()\n}\n")),(0,i.kt)("h3",{id:"userequire"},"UseRequire"),(0,i.kt)("p",null,"Kotlin provides a much more concise way to check preconditions than to manually throw an\nIllegalArgumentException."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-65"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'if (value == null) throw IllegalArgumentException("value should not be null")\nif (value < 0) throw IllegalArgumentException("value is $value but should be at least 0")\n')),(0,i.kt)("h4",{id:"compliant-code-57"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'requireNotNull(value) { "value should not be null" }\nrequire(value >= 0) { "value is $value but should be at least 0" }\n')),(0,i.kt)("h3",{id:"userequirenotnull"},"UseRequireNotNull"),(0,i.kt)("p",null,"Turn on this rule to flag ",(0,i.kt)("inlineCode",{parentName:"p"},"require")," calls for not-null check that can be replaced with a ",(0,i.kt)("inlineCode",{parentName:"p"},"requireNotNull")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-66"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"require(x != null)\n")),(0,i.kt)("h4",{id:"compliant-code-58"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"requireNotNull(x)\n")),(0,i.kt)("h3",{id:"uselesscallonnotnull"},"UselessCallOnNotNull"),(0,i.kt)("p",null,"The Kotlin stdlib provides some functions that are designed to operate on references that may be null. These\nfunctions can also be called on non-nullable references or on collections or sequences that are known to be empty -\nthe calls are redundant in this case and can be removed or should be changed to a call that does not check whether\nthe value is null or not."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-67"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val testList = listOf("string").orEmpty()\nval testList2 = listOf("string").orEmpty().map { _ }\nval testList3 = listOfNotNull("string")\nval testString = ""?.isNullOrBlank()\n')),(0,i.kt)("h4",{id:"compliant-code-59"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val testList = listOf("string")\nval testList2 = listOf("string").map { }\nval testList3 = listOf("string")\nval testString = ""?.isBlank()\n')),(0,i.kt)("h3",{id:"utilityclasswithpublicconstructor"},"UtilityClassWithPublicConstructor"),(0,i.kt)("p",null,"A class which only contains utility variables and functions with no concrete implementation can be refactored\ninto an ",(0,i.kt)("inlineCode",{parentName:"p"},"object")," or a class with a non-public constructor.\nFurthermore, this rule reports utility classes which are not final."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-68"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class UtilityClassViolation {\n\n // public constructor here\n constructor() {\n // ...\n }\n\n companion object {\n val i = 0\n }\n}\n\nopen class UtilityClassViolation private constructor() {\n\n // ...\n}\n")),(0,i.kt)("h4",{id:"compliant-code-60"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class UtilityClass {\n\n private constructor() {\n // ...\n }\n\n companion object {\n val i = 0\n }\n}\nobject UtilityClass {\n\n val i = 0\n}\n")),(0,i.kt)("h3",{id:"varcouldbeval"},"VarCouldBeVal"),(0,i.kt)("p",null,"Reports var declarations (both local variables and private class properties) that could be val,\nas they are not re-assigned. Val declarations are assign-once (read-only), which makes understanding\nthe current state easier."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": CanBeVal"),(0,i.kt)("h4",{id:"configuration-options-20"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreLateinitVar")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"Whether to ignore uninitialized lateinit vars"))),(0,i.kt)("h4",{id:"noncompliant-code-69"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun example() {\n var i = 1 // violation: this variable is never re-assigned\n val j = i + 1\n}\n")),(0,i.kt)("h4",{id:"compliant-code-61"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun example() {\n val i = 1\n val j = i + 1\n}\n")),(0,i.kt)("h3",{id:"wildcardimport"},"WildcardImport"),(0,i.kt)("p",null,"Wildcard imports should be replaced with imports using fully qualified class names. This helps increase clarity of\nwhich classes are imported and helps prevent naming conflicts."),(0,i.kt)("p",null,"Library updates can introduce naming clashes with your own classes which might result in compilation errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"NOTE"),": This rule has a twin implementation NoWildcardImports in the formatting rule set (a wrapped KtLint rule).\nWhen suppressing an issue of WildcardImport in the baseline file, make sure to suppress the corresponding NoWildcardImports issue."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-21"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeImports")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['java.util.*']"),")"),(0,i.kt)("p",{parentName:"li"},"Define a list of package names that should be allowed to be imported with wildcard imports."))),(0,i.kt)("h4",{id:"noncompliant-code-70"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"import io.gitlab.arturbosch.detekt.*\n\nclass DetektElements {\n val element1 = DetektElement1()\n val element2 = DetektElement2()\n}\n")),(0,i.kt)("h4",{id:"compliant-code-62"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"import io.gitlab.arturbosch.detekt.DetektElement1\nimport io.gitlab.arturbosch.detekt.DetektElement2\n\nclass DetektElements {\n val element1 = DetektElement1()\n val element2 = DetektElement2()\n}\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/74ccadee.e5a52a2f.js b/assets/js/74ccadee.e5a52a2f.js deleted file mode 100644 index 6b3cf8de3..000000000 --- a/assets/js/74ccadee.e5a52a2f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdetekt_website=self.webpackChunkdetekt_website||[]).push([[3563],{3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return m}});var a=t(7294);function l(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n=0||(l[t]=e[t]);return l}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(l[t]=e[t])}return l}var p=a.createContext({}),s=function(e){var n=a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=s(e.components);return a.createElement(p.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,l=e.mdxType,i=e.originalType,p=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),u=s(t),m=l,k=u["".concat(p,".").concat(m)]||u[m]||c[m]||i;return t?a.createElement(k,o(o({ref:n},d),{},{components:t})):a.createElement(k,o({ref:n},d))}));function m(e,n){var t=arguments,l=n&&n.mdxType;if("string"==typeof e||l){var i=t.length,o=new Array(i);o[0]=u;var r={};for(var p in n)hasOwnProperty.call(n,p)&&(r[p]=n[p]);r.originalType=e,r.mdxType="string"==typeof e?e:l,o[1]=r;for(var s=2;s 0) {\n if (i < 5) {\n println(i)\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-3"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val i = 1\nif (i > 0 && i < 5) {\n println(i)\n}\n")),(0,i.kt)("h3",{id:"dataclasscontainsfunctions"},"DataClassContainsFunctions"),(0,i.kt)("p",null,"This rule reports functions inside data classes which have not been marked as a conversion function."),(0,i.kt)("p",null,"Data classes should mainly be used to store data. This rule assumes that they should not contain any extra functions\naside functions that help with converting objects from/to one another.\nData classes will automatically have a generated ",(0,i.kt)("inlineCode",{parentName:"p"},"equals"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"toString")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"hashCode")," function by the compiler."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 20min"),(0,i.kt)("h4",{id:"configuration-options-1"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"conversionFunctionPrefix")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'to'"),")"),(0,i.kt)("p",{parentName:"li"},"allowed conversion function names"))),(0,i.kt)("h4",{id:"noncompliant-code-4"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class DataClassWithFunctions(val i: Int) {\n fun foo() { }\n}\n")),(0,i.kt)("h3",{id:"dataclassshouldbeimmutable"},"DataClassShouldBeImmutable"),(0,i.kt)("p",null,"This rule reports mutable properties inside data classes."),(0,i.kt)("p",null,"Data classes should mainly be used to store immutable data. This rule assumes that they should not contain any\nmutable properties."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 20min"),(0,i.kt)("h4",{id:"noncompliant-code-5"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class MutableDataClass(var i: Int) {\n var s: String? = null\n}\n")),(0,i.kt)("h4",{id:"compliant-code-4"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class ImmutableDataClass(\n val i: Int,\n val s: String?\n)\n")),(0,i.kt)("h3",{id:"destructuringdeclarationwithtoomanyentries"},"DestructuringDeclarationWithTooManyEntries"),(0,i.kt)("p",null,"Destructuring declarations with too many entries are hard to read and understand.\nTo increase readability they should be refactored to reduce the number of entries or avoid using a destructuring\ndeclaration."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-2"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"maxDestructuringEntries")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"3"),")"),(0,i.kt)("p",{parentName:"li"},"maximum allowed elements in a destructuring declaration"))),(0,i.kt)("h4",{id:"noncompliant-code-6"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class TooManyElements(val a: Int, val b: Int, val c: Int, val d: Int)\nval (a, b, c, d) = TooManyElements(1, 2, 3, 4)\n")),(0,i.kt)("h4",{id:"compliant-code-5"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class FewerElements(val a: Int, val b: Int, val c: Int)\nval (a, b, c) = TooManyElements(1, 2, 3)\n")),(0,i.kt)("h3",{id:"equalsnullcall"},"EqualsNullCall"),(0,i.kt)("p",null,"To compare an object with ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," prefer using ",(0,i.kt)("inlineCode",{parentName:"p"},"=="),". This rule detects and reports instances in the code where the\n",(0,i.kt)("inlineCode",{parentName:"p"},"equals()")," method is used to compare a value with ",(0,i.kt)("inlineCode",{parentName:"p"},"null"),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-7"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun isNull(str: String) = str.equals(null)\n")),(0,i.kt)("h4",{id:"compliant-code-6"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun isNull(str: String) = str == null\n")),(0,i.kt)("h3",{id:"equalsonsignatureline"},"EqualsOnSignatureLine"),(0,i.kt)("p",null,"Requires that the equals sign, when used for an expression style function, is on the same line as the\nrest of the function signature."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-8"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff(): Int\n = 5\n\nfun foo(): Int where V : Int\n = 5\n")),(0,i.kt)("h4",{id:"compliant-code-7"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff() = 5\n\nfun stuff() =\n foo.bar()\n\nfun foo(): Int where V : Int = 5\n")),(0,i.kt)("h3",{id:"explicitcollectionelementaccessmethod"},"ExplicitCollectionElementAccessMethod"),(0,i.kt)("p",null,"In Kotlin functions ",(0,i.kt)("inlineCode",{parentName:"p"},"get")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"set")," can be replaced with the shorter operator \u2014 ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),",\nsee ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/operator-overloading.html#indexed-access-operator"},"Indexed access operator"),".\nPrefer the usage of the indexed access operator ",(0,i.kt)("inlineCode",{parentName:"p"},"[]")," for map or list element access or insert methods."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-9"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val map = mutableMapOf()\nmap.put("key", "value")\nval value = map.get("key")\n')),(0,i.kt)("h4",{id:"compliant-code-8"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val map = mutableMapOf()\nmap["key"] = "value"\nval value = map["key"]\n')),(0,i.kt)("h3",{id:"explicititlambdaparameter"},"ExplicitItLambdaParameter"),(0,i.kt)("p",null,"Lambda expressions are one of the core features of the language. They often include very small chunks of\ncode using only one parameter. In this cases Kotlin can supply the implicit ",(0,i.kt)("inlineCode",{parentName:"p"},"it")," parameter\nto make code more concise. It fits most usecases, but when faced larger or nested chunks of code,\nyou might want to add an explicit name for the parameter. Naming it just ",(0,i.kt)("inlineCode",{parentName:"p"},"it")," is meaningless and only\nmakes your code misleading, especially when dealing with nested functions."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-10"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a?.let { it -> it.plus(1) }\nfoo.flatMapObservable { it -> Observable.fromIterable(it) }\nlistOfPairs.map(::second).forEach { it ->\n it.execute()\n}\ncollection.zipWithNext { it, next -> Pair(it, next) }\n")),(0,i.kt)("h4",{id:"compliant-code-9"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a?.let { it.plus(1) } // Much better to use implicit it\nfoo.flatMapObservable(Observable::fromIterable) // Here we can have a method reference\n\n// For multiline blocks it is usually better come up with a clear and more meaningful name\nlistOfPairs.map(::second).forEach { apiRequest ->\n apiRequest.execute()\n}\n\n// Lambdas with multiple parameter should be named clearly, using it for one of them can be confusing\ncollection.zipWithNext { prev, next ->\n Pair(prev, next)\n}\n")),(0,i.kt)("h3",{id:"expressionbodysyntax"},"ExpressionBodySyntax"),(0,i.kt)("p",null,"Functions which only contain a ",(0,i.kt)("inlineCode",{parentName:"p"},"return")," statement can be collapsed to an expression body. This shortens and\ncleans up the code."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-3"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"includeLineWrapping")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"include return statements with line wraps in it"))),(0,i.kt)("h4",{id:"noncompliant-code-11"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff(): Int {\n return 5\n}\n")),(0,i.kt)("h4",{id:"compliant-code-10"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun stuff() = 5\n\nfun stuff() {\n return\n moreStuff()\n .getStuff()\n .stuffStuff()\n}\n")),(0,i.kt)("h3",{id:"forbiddencomment"},"ForbiddenComment"),(0,i.kt)("p",null,"This rule allows to set a list of comments which are forbidden in the codebase and should only be used during\ndevelopment. Offending code comments will then be reported."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-4"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"values")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['FIXME:', 'STOPSHIP:', 'TODO:']"),")"),(0,i.kt)("p",{parentName:"li"},"forbidden comment strings")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowedPatterns")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"ignores comments which match the specified regular expression. For example ",(0,i.kt)("inlineCode",{parentName:"p"},"Ticket|Task"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"customMessage")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"error message which overrides the default one"))),(0,i.kt)("h4",{id:"noncompliant-code-12"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val a = "" // TODO: remove please\n// FIXME: this is a hack\nfun foo() { }\n// STOPSHIP:\n')),(0,i.kt)("h3",{id:"forbiddenimport"},"ForbiddenImport"),(0,i.kt)("p",null,"This rule allows to set a list of forbidden imports. This can be used to discourage the use of unstable, experimental\nor deprecated APIs. Detekt will then report all imports that are forbidden."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-5"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"imports")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},"imports which should not be used")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"forbiddenPatterns")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"reports imports which match the specified regular expression. For example ",(0,i.kt)("inlineCode",{parentName:"p"},"net.*R"),"."))),(0,i.kt)("h4",{id:"noncompliant-code-13"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"package foo\nimport kotlin.jvm.JvmField\nimport kotlin.SinceKotlin\n")),(0,i.kt)("h3",{id:"forbiddenmethodcall"},"ForbiddenMethodCall"),(0,i.kt)("p",null,"This rule allows to set a list of forbidden methods. This can be used to discourage the use of unstable, experimental\nor deprecated methods, especially for methods imported from external libraries.\nDetekt will then report all method invocations that are forbidden."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-6"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"methods")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['kotlin.io.print', 'kotlin.io.println']"),")"),(0,i.kt)("p",{parentName:"li"},"List of fully qualified method signatures which are forbidden. Methods can be defined without full signature (i.e. ",(0,i.kt)("inlineCode",{parentName:"p"},"java.time.LocalDate.now"),") which will report calls of all methods with this name or with full signature (i.e. ",(0,i.kt)("inlineCode",{parentName:"p"},"java.time.LocalDate(java.time.Clock)"),") which would report only call with this concrete signature. If you want to forbid an extension function like",(0,i.kt)("inlineCode",{parentName:"p"},"fun String.hello(a: Int)")," you should add the receiver parameter as the first parameter like this: ",(0,i.kt)("inlineCode",{parentName:"p"},"hello(kotlin.String, kotlin.Int)")))),(0,i.kt)("h4",{id:"noncompliant-code-14"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"import java.lang.System\nfun main() {\n System.gc()\n}\n")),(0,i.kt)("h3",{id:"forbiddenpublicdataclass"},"ForbiddenPublicDataClass"),(0,i.kt)("p",null,"Data classes are bad for binary compatibility in public APIs. Avoid using them."),(0,i.kt)("p",null,"This rule is aimed at library maintainers. If you are developing a final application you can ignore this issue."),(0,i.kt)("p",null,"More info: ",(0,i.kt)("a",{parentName:"p",href:"https://jakewharton.com/public-api-challenges-in-kotlin/"},"Public API challenges in Kotlin")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 20min"),(0,i.kt)("h4",{id:"configuration-options-7"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignorePackages")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['*.internal', '*.internal.*']"),")"),(0,i.kt)("p",{parentName:"li"},"ignores classes in the specified packages."))),(0,i.kt)("h4",{id:"noncompliant-code-15"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class C(val a: String) // violation: public data class\n")),(0,i.kt)("h4",{id:"compliant-code-11"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal data class C(val a: String)\n")),(0,i.kt)("h3",{id:"forbiddensuppress"},"ForbiddenSuppress"),(0,i.kt)("p",null,"This rule allows to set a list of rules whose suppression is forbidden.\nThis can be used to discourage the abuse of the ",(0,i.kt)("inlineCode",{parentName:"p"},"Suppress")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"SuppressWarnings")," annotations.\nDetekt will report suppression of all forbidden rules.\nThis rule is not capable of reporting suppression of itself, as that's a language feature with precedence."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-8"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"rules")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},"Rules whose suppression is forbidden."))),(0,i.kt)("h4",{id:"noncompliant-code-16"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'package foo\n\n// When the rule "MaximumLineLength" is forbidden\n@Suppress("MaximumLineLength", "UNCHECKED_CAST")\nclass Bar\n')),(0,i.kt)("h4",{id:"compliant-code-12"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'package foo\n\n// When the rule "MaximumLineLength" is forbidden\n@Suppress("UNCHECKED_CAST")\nclass Bar\n')),(0,i.kt)("h3",{id:"forbiddenvoid"},"ForbiddenVoid"),(0,i.kt)("p",null,"This rule detects usages of ",(0,i.kt)("inlineCode",{parentName:"p"},"Void")," and reports them as forbidden.\nThe Kotlin type ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," should be used instead. This type corresponds to the ",(0,i.kt)("inlineCode",{parentName:"p"},"Void")," class in Java\nand has only one value - the ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," object."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-9"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreOverridden")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"ignores void types in signatures of overridden functions")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreUsageInGenerics")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"ignore void types as generic arguments"))),(0,i.kt)("h4",{id:"noncompliant-code-17"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"runnable: () -> Void\nvar aVoid: Void? = null\n")),(0,i.kt)("h4",{id:"compliant-code-13"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"runnable: () -> Unit\nVoid::class\n")),(0,i.kt)("h3",{id:"functiononlyreturningconstant"},"FunctionOnlyReturningConstant"),(0,i.kt)("p",null,"A function that only returns a single constant can be misleading. Instead, prefer declaring the constant\nas a ",(0,i.kt)("inlineCode",{parentName:"p"},"const val"),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-10"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreOverridableFunction")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if overriden functions should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreActualFunction")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if actual functions should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludedFunctions")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"''"),")"),(0,i.kt)("p",{parentName:"li"},"excluded functions")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"excludeAnnotatedFunction"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotated")," instead"),(0,i.kt)("p",{parentName:"li"},"allows to provide a list of annotations that disable this check"))),(0,i.kt)("h4",{id:"noncompliant-code-18"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun functionReturningConstantString() = "1"\n')),(0,i.kt)("h4",{id:"compliant-code-14"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'const val constantString = "1"\n')),(0,i.kt)("h3",{id:"librarycodemustspecifyreturntype"},"LibraryCodeMustSpecifyReturnType"),(0,i.kt)("p",null,"Functions/properties exposed as public APIs of a library should have an explicit return type.\nInferred return type can easily be changed by mistake which may lead to breaking changes."),(0,i.kt)("p",null,"See also: ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors"},"Kotlin 1.4 Explicit API")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-19"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'// code from a library\nval strs = listOf("foo, bar")\nfun bar() = 5\nclass Parser {\n fun parse() = ...\n}\n')),(0,i.kt)("h4",{id:"compliant-code-15"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'// code from a library\nval strs: List = listOf("foo, bar")\nfun bar(): Int = 5\n\nclass Parser {\n fun parse(): ParsingResult = ...\n}\n')),(0,i.kt)("h3",{id:"libraryentitiesshouldnotbepublic"},"LibraryEntitiesShouldNotBePublic"),(0,i.kt)("p",null,"Library typealias and classes should be internal or private."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-20"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"// code from a library\nclass A\n")),(0,i.kt)("h4",{id:"compliant-code-16"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"// code from a library\ninternal class A\n")),(0,i.kt)("h3",{id:"loopwithtoomanyjumpstatements"},"LoopWithTooManyJumpStatements"),(0,i.kt)("p",null,"Loops which contain multiple ",(0,i.kt)("inlineCode",{parentName:"p"},"break")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"continue")," statements are hard to read and understand.\nTo increase readability they should be refactored into simpler loops."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-11"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"maxJumpCount")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"1"),")"),(0,i.kt)("p",{parentName:"li"},"maximum allowed jumps in a loop"))),(0,i.kt)("h4",{id:"noncompliant-code-21"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val strs = listOf("foo, bar")\nfor (str in strs) {\n if (str == "bar") {\n break\n } else {\n continue\n }\n}\n')),(0,i.kt)("h3",{id:"magicnumber"},"MagicNumber"),(0,i.kt)("p",null,"This rule detects and reports usages of magic numbers in the code. Prefer defining constants with clear names\ndescribing what the magic number means."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-12"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreNumbers")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['-1', '0', '1', '2']"),")"),(0,i.kt)("p",{parentName:"li"},"numbers which do not count as magic numbers")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreHashCodeFunction")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in hashCode functions should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignorePropertyDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in property declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreLocalVariableDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in local variable declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreConstantDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in constant declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreCompanionObjectPropertyDeclaration")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in companion object declarations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotation")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in annotations should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreNamedArgument")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in named arguments should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreEnums")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in enums should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreRanges")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers in ranges should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreExtensionFunctions")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"whether magic numbers as subject of an extension function should be ignored"))),(0,i.kt)("h4",{id:"noncompliant-code-22"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'class User {\n\n fun checkName(name: String) {\n if (name.length > 42) {\n throw IllegalArgumentException("username is too long")\n }\n // ...\n }\n}\n')),(0,i.kt)("h4",{id:"compliant-code-17"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'class User {\n\n fun checkName(name: String) {\n if (name.length > MAX_USERNAME_SIZE) {\n throw IllegalArgumentException("username is too long")\n }\n // ...\n }\n\n companion object {\n private const val MAX_USERNAME_SIZE = 42\n }\n}\n')),(0,i.kt)("h3",{id:"mandatorybracesifstatements"},"MandatoryBracesIfStatements"),(0,i.kt)("p",null,"This rule detects multi-line ",(0,i.kt)("inlineCode",{parentName:"p"},"if")," statements which do not have braces.\nAdding braces would improve readability and avoid possible errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-23"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val i = 1\nif (i > 0)\n println(i)\n")),(0,i.kt)("h4",{id:"compliant-code-18"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val x = if (condition) 5 else 4\n")),(0,i.kt)("h3",{id:"mandatorybracesloops"},"MandatoryBracesLoops"),(0,i.kt)("p",null,"This rule detects multi-line ",(0,i.kt)("inlineCode",{parentName:"p"},"for")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"while")," loops which do not have braces.\nAdding braces would improve readability and avoid possible errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-24"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'for (i in 0..10)\n println(i)\n\nwhile (true)\n println("Hello, world")\n\ndo\n println("Hello, world")\nwhile (true)\n')),(0,i.kt)("h4",{id:"compliant-code-19"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'for (i in 0..10) {\n println(i)\n}\n\nfor (i in 0..10) println(i)\n\nwhile (true) {\n println("Hello, world")\n}\n\nwhile (true) println("Hello, world")\n\ndo {\n println("Hello, world")\n} while (true)\n\ndo println("Hello, world") while (true)\n')),(0,i.kt)("h3",{id:"maxlinelength"},"MaxLineLength"),(0,i.kt)("p",null,"This rule reports lines of code which exceed a defined maximum line length."),(0,i.kt)("p",null,"Long lines might be hard to read on smaller screens or printouts. Additionally, having a maximum line length\nin the codebase will help make the code more uniform."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-13"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"maxLineLength")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"120"),")"),(0,i.kt)("p",{parentName:"li"},"maximum line length")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludePackageStatements")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if package statements should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeImportStatements")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if import statements should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeCommentStatements")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if comment statements should be ignored"))),(0,i.kt)("h3",{id:"maybeconst"},"MayBeConst"),(0,i.kt)("p",null,"This rule identifies and reports properties (",(0,i.kt)("inlineCode",{parentName:"p"},"val"),") that may be ",(0,i.kt)("inlineCode",{parentName:"p"},"const val")," instead.\nUsing ",(0,i.kt)("inlineCode",{parentName:"p"},"const val")," can lead to better performance of the resulting bytecode as well as better interoperability with\nJava."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": MayBeConstant"),(0,i.kt)("h4",{id:"noncompliant-code-25"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val myConstant = "abc"\n')),(0,i.kt)("h4",{id:"compliant-code-20"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'const val MY_CONSTANT = "abc"\n')),(0,i.kt)("h3",{id:"modifierorder"},"ModifierOrder"),(0,i.kt)("p",null,"This rule reports cases in the code where modifiers are not in the correct order. The default modifier order is\ntaken from: ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/coding-conventions.html#modifiers-order"},"Modifiers order")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-26"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"lateinit internal val str: String\n")),(0,i.kt)("h4",{id:"compliant-code-21"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal lateinit val str: String\n")),(0,i.kt)("h3",{id:"multilinelambdaitparameter"},"MultilineLambdaItParameter"),(0,i.kt)("p",null,"Lambda expressions are very useful in a lot of cases, and they often include very small chunks of\ncode using only one parameter. In this cases Kotlin can supply the implicit ",(0,i.kt)("inlineCode",{parentName:"p"},"it")," parameter\nto make code more concise. However, when you are dealing with lambdas that contain multiple statements,\nyou might end up with code that is hard to read if you don't specify a readable, descriptive parameter name\nexplicitly."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-27"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val digits = 1234.let {\n println(it)\n listOf(it)\n}\n\nval digits = 1234.let { it ->\n println(it)\n listOf(it)\n}\n\nval flat = listOf(listOf(1), listOf(2)).mapIndexed { index, it ->\n println(it)\n it + index\n}\n")),(0,i.kt)("h4",{id:"compliant-code-22"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val digits = 1234.let { explicitParameterName ->\n println(explicitParameterName)\n listOf(explicitParameterName)\n}\n\nval lambda = { item: Int, that: String ->\n println(item)\n item.toString() + that\n}\n\nval digits = 1234.let { listOf(it) }\nval digits = 1234.let {\n listOf(it)\n}\nval digits = 1234.let { it -> listOf(it) }\nval digits = 1234.let { it ->\n listOf(it)\n}\nval digits = 1234.let { explicit -> listOf(explicit) }\nval digits = 1234.let { explicit ->\n listOf(explicit)\n}\n")),(0,i.kt)("h3",{id:"nestedclassesvisibility"},"NestedClassesVisibility"),(0,i.kt)("p",null,"Nested classes inherit their visibility from the parent class\nand are often used to implement functionality local to the class it is nested in.\nThese nested classes can't have a higher visibility than their parent.\nHowever, the visibility can be further restricted by using a private modifier for instance.\nIn internal classes the ",(0,i.kt)("em",{parentName:"p"},"explicit")," public modifier for nested classes is misleading and thus unnecessary,\nbecause the nested class still has an internal visibility."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-28"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal class Outer {\n // explicit public modifier still results in an internal nested class\n public class Nested\n}\n")),(0,i.kt)("h4",{id:"compliant-code-23"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"internal class Outer {\n class Nested1\n internal class Nested2\n}\n")),(0,i.kt)("h3",{id:"newlineatendoffile"},"NewLineAtEndOfFile"),(0,i.kt)("p",null,"This rule reports files which do not end with a line separator."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"notabs"},"NoTabs"),(0,i.kt)("p",null,"This rule reports if tabs are used in Kotlin files.\nAccording to\n",(0,i.kt)("a",{parentName:"p",href:"https://android.github.io/kotlin-guides/style.html#whitespace-characters"},"Google's Kotlin style guide"),"\nthe only whitespace chars that are allowed in a source file are the line terminator sequence\nand the ASCII horizontal space character (0x20). Strings containing tabs are allowed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"nullablebooleancheck"},"NullableBooleanCheck"),(0,i.kt)("p",null,"Detects nullable boolean checks which use an elvis expression ",(0,i.kt)("inlineCode",{parentName:"p"},"?:")," rather than equals ",(0,i.kt)("inlineCode",{parentName:"p"},"=="),"."),(0,i.kt)("p",null,"Per the ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/coding-conventions.html#nullable-boolean-values-in-conditions"},"Kotlin coding conventions"),"\nconverting a nullable boolean property to non-null should be done via ",(0,i.kt)("inlineCode",{parentName:"p"},"!= false")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"== true"),"\nrather than ",(0,i.kt)("inlineCode",{parentName:"p"},"?: true")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"?: false")," (respectively)."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-29"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"value ?: true\nvalue ?: false\n")),(0,i.kt)("h4",{id:"compliant-code-24"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"value != false\nvalue == true\n")),(0,i.kt)("h3",{id:"objectliteraltolambda"},"ObjectLiteralToLambda"),(0,i.kt)("p",null,"An anonymous object that does nothing other than the implementation of a single method\ncan be used as a lambda."),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/java-interop.html#sam-conversions"},"SAM conversions"),",\n",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/fun-interfaces.html"},"Functional (SAM) interfaces")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-30"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"object : Foo {\n override fun bar() {\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-25"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"Foo {\n}\n")),(0,i.kt)("h3",{id:"optionalabstractkeyword"},"OptionalAbstractKeyword"),(0,i.kt)("p",null,"This rule reports ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract")," modifiers which are unnecessary and can be removed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-31"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"abstract interface Foo { // abstract keyword not needed\n\n abstract fun x() // abstract keyword not needed\n abstract var y: Int // abstract keyword not needed\n}\n")),(0,i.kt)("h4",{id:"compliant-code-26"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"interface Foo {\n\n fun x()\n var y: Int\n}\n")),(0,i.kt)("h3",{id:"optionalunit"},"OptionalUnit"),(0,i.kt)("p",null,"It is not necessary to define a return type of ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," on functions or to specify a lone Unit statement.\nThis rule detects and reports instances where the ",(0,i.kt)("inlineCode",{parentName:"p"},"Unit")," return type is specified on functions and the occurrences\nof a lone Unit statement."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-32"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(): Unit {\n return Unit\n}\nfun foo() = Unit\n\nfun doesNothing() {\n Unit\n}\n")),(0,i.kt)("h4",{id:"compliant-code-27"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo() { }\n\n// overridden no-op functions are allowed\noverride fun foo() = Unit\n")),(0,i.kt)("h3",{id:"optionalwhenbraces"},"OptionalWhenBraces"),(0,i.kt)("p",null,"This rule reports unnecessary braces in when expressions. These optional braces should be removed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-33"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val i = 1\nwhen (i) {\n 1 -> { println("one") } // unnecessary curly braces since there is only one statement\n else -> println("else")\n}\n')),(0,i.kt)("h4",{id:"compliant-code-28"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val i = 1\nwhen (i) {\n 1 -> println("one")\n else -> println("else")\n}\n')),(0,i.kt)("h3",{id:"prefertooverpairsyntax"},"PreferToOverPairSyntax"),(0,i.kt)("p",null,"This rule detects the usage of the Pair constructor to create pairs of values."),(0,i.kt)("p",null,"Using ","<","value1",">"," to ","<","value2",">"," is preferred."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-34"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val pair = Pair(1, 2)\n")),(0,i.kt)("h4",{id:"compliant-code-29"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val pair = 1 to 2\n")),(0,i.kt)("h3",{id:"protectedmemberinfinalclass"},"ProtectedMemberInFinalClass"),(0,i.kt)("p",null,"Kotlin classes are ",(0,i.kt)("inlineCode",{parentName:"p"},"final")," by default. Thus classes which are not marked as ",(0,i.kt)("inlineCode",{parentName:"p"},"open")," should not contain any ",(0,i.kt)("inlineCode",{parentName:"p"},"protected"),"\nmembers. Consider using ",(0,i.kt)("inlineCode",{parentName:"p"},"private")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"internal")," modifiers instead."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-35"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class ProtectedMemberInFinalClass {\n protected var i = 0\n}\n")),(0,i.kt)("h4",{id:"compliant-code-30"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class ProtectedMemberInFinalClass {\n private var i = 0\n}\n")),(0,i.kt)("h3",{id:"redundantexplicittype"},"RedundantExplicitType"),(0,i.kt)("p",null,"Local properties do not need their type to be explicitly provided when the inferred type matches the explicit type."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-36"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun function() {\n val x: String = "string"\n}\n')),(0,i.kt)("h4",{id:"compliant-code-31"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun function() {\n val x = "string"\n}\n')),(0,i.kt)("h3",{id:"redundanthigherordermapusage"},"RedundantHigherOrderMapUsage"),(0,i.kt)("p",null,"Redundant maps add complexity to the code and accomplish nothing. They should be removed or replaced with the proper\noperator."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-37"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(list: List): List {\n return list\n .filter { it > 5 }\n .map { it }\n}\n\nfun bar(list: List): List {\n return list\n .filter { it > 5 }\n .map {\n doSomething(it)\n it\n }\n}\n\nfun baz(set: Set): List {\n return set.map { it }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-32"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(list: List): List {\n return list\n .filter { it > 5 }\n}\n\nfun bar(list: List): List {\n return list\n .filter { it > 5 }\n .onEach {\n doSomething(it)\n }\n}\n\nfun baz(set: Set): List {\n return set.toList()\n}\n")),(0,i.kt)("h3",{id:"redundantvisibilitymodifierrule"},"RedundantVisibilityModifierRule"),(0,i.kt)("p",null,"This rule checks for redundant visibility modifiers.\nOne exemption is the\n",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors"},"explicit API mode"),"\nIn this mode, the visibility modifier should be defined explicitly even if it is public.\nHence, the rule ignores the visibility modifiers in explicit API mode."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": RedundantVisibilityModifier"),(0,i.kt)("h4",{id:"noncompliant-code-38"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"public interface Foo { // public per default\n\n public fun bar() // public per default\n}\n")),(0,i.kt)("h4",{id:"compliant-code-33"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"interface Foo {\n\n fun bar()\n}\n")),(0,i.kt)("h3",{id:"returncount"},"ReturnCount"),(0,i.kt)("p",null,"Restrict the number of return methods allowed in methods."),(0,i.kt)("p",null,"Having many exit points in a function can be confusing and impacts readability of the\ncode."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-14"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"max")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"2"),")"),(0,i.kt)("p",{parentName:"li"},"define the maximum number of return statements allowed per function")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludedFunctions")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'equals'"),")"),(0,i.kt)("p",{parentName:"li"},"define functions to be ignored by this check")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeLabeled")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if labeled return statements should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeReturnFromLambda")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),")"),(0,i.kt)("p",{parentName:"li"},"if labeled return from a lambda should be ignored")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeGuardClauses")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if true guard clauses at the beginning of a method should be ignored"))),(0,i.kt)("h4",{id:"noncompliant-code-39"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun foo(i: Int): String {\n when (i) {\n 1 -> return "one"\n 2 -> return "two"\n else -> return "other"\n }\n}\n')),(0,i.kt)("h4",{id:"compliant-code-34"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun foo(i: Int): String {\n return when (i) {\n 1 -> "one"\n 2 -> "two"\n else -> "other"\n }\n}\n')),(0,i.kt)("h3",{id:"safecast"},"SafeCast"),(0,i.kt)("p",null,"This rule inspects casts and reports casts which could be replaced with safe casts instead."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-40"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun numberMagic(number: Number) {\n val i = if (number is Int) number else null\n // ...\n}\n")),(0,i.kt)("h4",{id:"compliant-code-35"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun numberMagic(number: Number) {\n val i = number as? Int\n // ...\n}\n")),(0,i.kt)("h3",{id:"serialversionuidinserializableclass"},"SerialVersionUIDInSerializableClass"),(0,i.kt)("p",null,"Classes which implement the ",(0,i.kt)("inlineCode",{parentName:"p"},"Serializable")," interface should also correctly declare a ",(0,i.kt)("inlineCode",{parentName:"p"},"serialVersionUID"),".\nThis rule verifies that a ",(0,i.kt)("inlineCode",{parentName:"p"},"serialVersionUID")," was correctly defined."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-41"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class IncorrectSerializable : Serializable {\n\n companion object {\n val serialVersionUID = 1 // wrong declaration for UID\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-36"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class CorrectSerializable : Serializable {\n\n companion object {\n const val serialVersionUID = 1L\n }\n}\n")),(0,i.kt)("h3",{id:"spacingbetweenpackageandimports"},"SpacingBetweenPackageAndImports"),(0,i.kt)("p",null,"This rule verifies spacing between package and import statements as well as between import statements and class\ndeclarations."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-42"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"package foo\nimport a.b\nclass Bar { }\n")),(0,i.kt)("h4",{id:"compliant-code-37"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"package foo\n\nimport a.b\n\nclass Bar { }\n")),(0,i.kt)("h3",{id:"throwscount"},"ThrowsCount"),(0,i.kt)("p",null,"Functions should have clear ",(0,i.kt)("inlineCode",{parentName:"p"},"throw")," statements. Functions with many ",(0,i.kt)("inlineCode",{parentName:"p"},"throw")," statements can be harder to read and lead\nto confusion. Instead, prefer limiting the number of ",(0,i.kt)("inlineCode",{parentName:"p"},"throw")," statements in a function."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 10min"),(0,i.kt)("h4",{id:"configuration-options-15"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"max")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"2"),")"),(0,i.kt)("p",{parentName:"li"},"maximum amount of throw statements in a method")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeGuardClauses")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"if set to true, guard clauses do not count towards the allowed throws count"))),(0,i.kt)("h4",{id:"noncompliant-code-43"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(i: Int) {\n when (i) {\n 1 -> throw IllegalArgumentException()\n 2 -> throw IllegalArgumentException()\n 3 -> throw IllegalArgumentException()\n }\n}\n")),(0,i.kt)("h4",{id:"compliant-code-38"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(i: Int) {\n when (i) {\n 1,2,3 -> throw IllegalArgumentException()\n }\n}\n")),(0,i.kt)("h3",{id:"trailingwhitespace"},"TrailingWhitespace"),(0,i.kt)("p",null,"This rule reports lines that end with a whitespace."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"underscoresinnumericliterals"},"UnderscoresInNumericLiterals"),(0,i.kt)("p",null,"This rule detects and reports long base 10 numbers which should be separated with underscores\nfor readability. For ",(0,i.kt)("inlineCode",{parentName:"p"},"Serializable")," classes or objects, the field ",(0,i.kt)("inlineCode",{parentName:"p"},"serialVersionUID")," is\nexplicitly ignored. For floats and doubles, anything to the right of the decimal point is ignored."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-16"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"acceptableDecimalLength"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"5"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"acceptableLength")," instead"),(0,i.kt)("p",{parentName:"li"},"Length under which base 10 numbers are not required to have underscores")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"acceptableLength")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"4"),")"),(0,i.kt)("p",{parentName:"li"},"Maximum number of consecutive digits that a numeric literal can have without using an underscore")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowNonStandardGrouping")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"If set to false, groups of exactly three digits must be used. If set to true, 100_00 is allowed."))),(0,i.kt)("h4",{id:"noncompliant-code-44"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"const val DEFAULT_AMOUNT = 1000000\n")),(0,i.kt)("h4",{id:"compliant-code-39"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"const val DEFAULT_AMOUNT = 1_000_000\n")),(0,i.kt)("h3",{id:"unnecessaryabstractclass"},"UnnecessaryAbstractClass"),(0,i.kt)("p",null,"This rule inspects ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract")," classes. In case an ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract class")," does not have any concrete members it should be\nrefactored into an interface. Abstract classes which do not define any ",(0,i.kt)("inlineCode",{parentName:"p"},"abstract")," members should instead be\nrefactored into concrete classes."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-17"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"excludeAnnotatedClasses"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotated")," instead"),(0,i.kt)("p",{parentName:"li"},"Allows you to provide a list of annotations that disable this check."))),(0,i.kt)("h4",{id:"noncompliant-code-45"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"abstract class OnlyAbstractMembersInAbstractClass { // violation: no concrete members\n\n abstract val i: Int\n abstract fun f()\n}\n\nabstract class OnlyConcreteMembersInAbstractClass { // violation: no abstract members\n\n val i: Int = 0\n fun f() { }\n}\n")),(0,i.kt)("h3",{id:"unnecessaryannotationusesitetarget"},"UnnecessaryAnnotationUseSiteTarget"),(0,i.kt)("p",null,"This rule inspects the use of the Annotation use-site Target. In case that the use-site Target is not needed it can\nbe removed. For more information check the kotlin documentation:\n",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets"},"Annotation use-site targets")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-46"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'@property:Inject private val foo: String = "bar" // violation: unnecessary @property:\n\nclass Module(@param:Inject private val foo: String) // violation: unnecessary @param:\n')),(0,i.kt)("h4",{id:"compliant-code-40"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class Module(@Inject private val foo: String)\n")),(0,i.kt)("h3",{id:"unnecessaryapply"},"UnnecessaryApply"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"apply")," expressions are used frequently, but sometimes their usage should be replaced with\nan ordinary method/extension function call to reduce visual complexity"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-47"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'config.apply { version = "1.2" } // can be replaced with `config.version = "1.2"`\nconfig?.apply { environment = "test" } // can be replaced with `config?.environment = "test"`\nconfig?.apply { println(version) } // `apply` can be replaced by `let`\n')),(0,i.kt)("h4",{id:"compliant-code-41"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'config.apply {\n version = "1.2"\n environment = "test"\n}\n')),(0,i.kt)("h3",{id:"unnecessarybackticks"},"UnnecessaryBackticks"),(0,i.kt)("p",null,"This rule reports unnecessary backticks."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-48"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class `HelloWorld`\n")),(0,i.kt)("h4",{id:"compliant-code-42"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class HelloWorld\n")),(0,i.kt)("h3",{id:"unnecessaryfilter"},"UnnecessaryFilter"),(0,i.kt)("p",null,"Unnecessary filters add complexity to the code and accomplish nothing. They should be removed."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-49"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val x = listOf(1, 2, 3)\n .filter { it > 1 }\n .count()\n\nval x = listOf(1, 2, 3)\n .filter { it > 1 }\n .isEmpty()\n")),(0,i.kt)("h4",{id:"compliant-code-43"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val x = listOf(1, 2, 3)\n .count { it > 2 }\n}\n\nval x = listOf(1, 2, 3)\n .none { it > 1 }\n")),(0,i.kt)("h3",{id:"unnecessaryinheritance"},"UnnecessaryInheritance"),(0,i.kt)("p",null,"This rule reports unnecessary super types. Inheriting from ",(0,i.kt)("inlineCode",{parentName:"p"},"Any")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"Object")," is unnecessary and should simply be\nremoved."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-50"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class A : Any()\nclass B : Object()\n")),(0,i.kt)("h3",{id:"unnecessaryinnerclass"},"UnnecessaryInnerClass"),(0,i.kt)("p",null,"This rule reports unnecessary inner classes. Nested classes that do not access members from the outer class do\nnot require the ",(0,i.kt)("inlineCode",{parentName:"p"},"inner")," qualifier."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-51"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'class A {\n val foo = "BAR"\n\n inner class B {\n val fizz = "BUZZ"\n\n fun printFizz() {\n println(fizz)\n }\n }\n}\n')),(0,i.kt)("h3",{id:"unnecessarylet"},"UnnecessaryLet"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"let")," expressions are used extensively in our code for null-checking and chaining functions,\nbut sometimes their usage should be replaced with an ordinary method/extension function call\nto reduce visual complexity."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-52"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a.let { print(it) } // can be replaced with `print(a)`\na.let { it.plus(1) } // can be replaced with `a.plus(1)`\na?.let { it.plus(1) } // can be replaced with `a?.plus(1)`\na?.let { that -> that.plus(1) }?.let { it.plus(1) } // can be replaced with `a?.plus(1)?.plus(1)`\na.let { 1.plus(1) } // can be replaced with `1.plus(1)`\na?.let { 1.plus(1) } // can be replaced with `if (a != null) 1.plus(1)`\n")),(0,i.kt)("h4",{id:"compliant-code-44"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"a?.let { print(it) }\na?.let { 1.plus(it) } ?.let { msg -> print(msg) }\na?.let { it.plus(it) }\nval b = a?.let { 1.plus(1) }\n")),(0,i.kt)("h3",{id:"unnecessaryparentheses"},"UnnecessaryParentheses"),(0,i.kt)("p",null,"This rule reports unnecessary parentheses around expressions.\nThese unnecessary parentheses can safely be removed."),(0,i.kt)("p",null,"Added in v1.0.0.RC4"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-53"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val local = (5 + 3)\n\nif ((local == 8)) { }\n\nfun foo() {\n function({ input -> println(input) })\n}\n")),(0,i.kt)("h4",{id:"compliant-code-45"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"val local = 5 + 3\n\nif (local == 8) { }\n\nfun foo() {\n function { input -> println(input) }\n}\n")),(0,i.kt)("h3",{id:"untilinsteadofrangeto"},"UntilInsteadOfRangeTo"),(0,i.kt)("p",null,"Reports calls to '..' operator instead of calls to 'until'.\n'until' is applicable in cases where the upper range value is described as\nsome value subtracted by 1. 'until' helps to prevent off-by-one errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-54"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"for (i in 0 .. 10 - 1) {}\nval range = 0 .. 10 - 1\n")),(0,i.kt)("h4",{id:"compliant-code-46"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"for (i in 0 until 10) {}\nval range = 0 until 10\n")),(0,i.kt)("h3",{id:"unusedimports"},"UnusedImports"),(0,i.kt)("p",null,"This rule reports unused imports. Unused imports are dead code and should be removed.\nExempt from this rule are imports resulting from references to elements within KDoc and\nfrom destructuring declarations (componentN imports)."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h3",{id:"unusedprivateclass"},"UnusedPrivateClass"),(0,i.kt)("p",null,"Reports unused private classes. If private classes are unused they should be removed. Otherwise, this dead code\ncan lead to confusion and potential bugs."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": unused"),(0,i.kt)("h3",{id:"unusedprivatemember"},"UnusedPrivateMember"),(0,i.kt)("p",null,"Reports unused private properties, function parameters and functions.\nIf these private elements are unused they should be removed. Otherwise, this dead code\ncan lead to confusion and potential bugs."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": UNUSED_VARIABLE, UNUSED_PARAMETER, unused"),(0,i.kt)("h4",{id:"configuration-options-18"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowedNames")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'(_|ignored|expected|serialVersionUID)'"),")"),(0,i.kt)("p",{parentName:"li"},"unused private member names matching this regex are ignored"))),(0,i.kt)("h3",{id:"useanyornoneinsteadoffind"},"UseAnyOrNoneInsteadOfFind"),(0,i.kt)("p",null,"Turn on this rule to flag ",(0,i.kt)("inlineCode",{parentName:"p"},"find")," calls for null check that can be replaced with a ",(0,i.kt)("inlineCode",{parentName:"p"},"any")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"none")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-55"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"listOf(1, 2, 3).find { it == 4 } != null\nlistOf(1, 2, 3).find { it == 4 } == null\n")),(0,i.kt)("h4",{id:"compliant-code-47"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"listOf(1, 2, 3).any { it == 4 }\nlistOf(1, 2, 3).none { it == 4 }\n")),(0,i.kt)("h3",{id:"usearrayliteralsinannotations"},"UseArrayLiteralsInAnnotations"),(0,i.kt)("p",null,"This rule detects annotations which use the arrayOf(...) syntax instead of the array literal ","[...]"," syntax.\nThe latter should be preferred as it is more readable."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-56"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'@PositiveCase(arrayOf("..."))\n')),(0,i.kt)("h4",{id:"compliant-code-48"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'@NegativeCase(["..."])\n')),(0,i.kt)("h3",{id:"usechecknotnull"},"UseCheckNotNull"),(0,i.kt)("p",null,"Turn on this rule to flag ",(0,i.kt)("inlineCode",{parentName:"p"},"check")," calls for not-null check that can be replaced with a ",(0,i.kt)("inlineCode",{parentName:"p"},"checkNotNull")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-57"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"check(x != null)\n")),(0,i.kt)("h4",{id:"compliant-code-49"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"checkNotNull(x)\n")),(0,i.kt)("h3",{id:"usecheckorerror"},"UseCheckOrError"),(0,i.kt)("p",null,"Kotlin provides a concise way to check invariants as well as pre- and post-conditions.\nPrefer them instead of manually throwing an IllegalStateException."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-58"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'if (value == null) throw IllegalStateException("value should not be null")\nif (value < 0) throw IllegalStateException("value is $value but should be at least 0")\nwhen(a) {\n 1 -> doSomething()\n else -> throw IllegalStateException("Unexpected value")\n}\n')),(0,i.kt)("h4",{id:"compliant-code-50"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'checkNotNull(value) { "value should not be null" }\ncheck(value >= 0) { "value is $value but should be at least 0" }\nwhen(a) {\n 1 -> doSomething()\n else -> error("Unexpected value")\n}\n')),(0,i.kt)("h3",{id:"usedataclass"},"UseDataClass"),(0,i.kt)("p",null,"Classes that simply hold data should be refactored into a ",(0,i.kt)("inlineCode",{parentName:"p"},"data class"),". Data classes are specialized to hold data\nand generate ",(0,i.kt)("inlineCode",{parentName:"p"},"hashCode"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"equals")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"toString")," implementations as well."),(0,i.kt)("p",null,"Read more about ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/data-classes.html"},"data classes")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-19"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("del",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"del"},"excludeAnnotatedClasses"))," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),")"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Deprecated"),": Use ",(0,i.kt)("inlineCode",{parentName:"p"},"ignoreAnnotated")," instead"),(0,i.kt)("p",{parentName:"li"},"allows to provide a list of annotations that disable this check")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"allowVars")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"allows to relax this rule in order to exclude classes that contains one (or more) vars"))),(0,i.kt)("h4",{id:"noncompliant-code-59"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class DataClassCandidate(val i: Int) {\n val i2: Int = 0\n}\n")),(0,i.kt)("h4",{id:"compliant-code-51"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"data class DataClass(val i: Int, val i2: Int)\n\n// classes with delegating interfaces are compliant\ninterface I\nclass B() : I\nclass A(val b: B) : I by b\n")),(0,i.kt)("h3",{id:"useemptycounterpart"},"UseEmptyCounterpart"),(0,i.kt)("p",null,'Instantiation of an object\'s "empty" state should use the object\'s "empty" initializer for clarity purposes.'),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-60"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"arrayOf()\nlistOf() // or listOfNotNull()\nmapOf()\nsequenceOf()\nsetOf()\n")),(0,i.kt)("h4",{id:"compliant-code-52"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"emptyArray()\nemptyList()\nemptyMap()\nemptySequence()\nemptySet()\n")),(0,i.kt)("h3",{id:"useifemptyorifblank"},"UseIfEmptyOrIfBlank"),(0,i.kt)("p",null,"This rule detects ",(0,i.kt)("inlineCode",{parentName:"p"},"isEmpty")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"isBlank")," calls to assign a default value. They can be replaced with ",(0,i.kt)("inlineCode",{parentName:"p"},"ifEmpty")," or\n",(0,i.kt)("inlineCode",{parentName:"p"},"ifBlank")," calls."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-61"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun test(list: List, s: String) {\n val a = if (list.isEmpty()) listOf(1) else list\n val b = if (list.isNotEmpty()) list else listOf(2)\n val c = if (s.isBlank()) "foo" else s\n val d = if (s.isNotBlank()) s else "bar"\n}\n')),(0,i.kt)("h4",{id:"compliant-code-53"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun test(list: List, s: String) {\n val a = list.ifEmpty { listOf(1) }\n val b = list.ifEmpty { listOf(2) }\n val c = s.ifBlank { "foo" }\n val d = s.ifBlank { "bar" }\n}\n')),(0,i.kt)("h3",{id:"useifinsteadofwhen"},"UseIfInsteadOfWhen"),(0,i.kt)("p",null,"Binary expressions are better expressed using an ",(0,i.kt)("inlineCode",{parentName:"p"},"if")," expression than a ",(0,i.kt)("inlineCode",{parentName:"p"},"when")," expression."),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"https://kotlinlang.org/docs/coding-conventions.html#if-versus-when"},"if versus when")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": No"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-62"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"when (x) {\n null -> true\n else -> false\n}\n")),(0,i.kt)("h4",{id:"compliant-code-54"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"if (x == null) true else false\n")),(0,i.kt)("h3",{id:"useisnullorempty"},"UseIsNullOrEmpty"),(0,i.kt)("p",null,"This rule detects null or empty checks that can be replaced with ",(0,i.kt)("inlineCode",{parentName:"p"},"isNullOrEmpty()")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-63"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun foo(x: List?) {\n if (x == null || x.isEmpty()) return\n}\nfun bar(x: List?) {\n if (x == null || x.count() == 0) return\n}\nfun baz(x: List?) {\n if (x == null || x.size == 0) return\n}\n")),(0,i.kt)("h4",{id:"compliant-code-55"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"if (x.isNullOrEmpty()) return\n")),(0,i.kt)("h3",{id:"useorempty"},"UseOrEmpty"),(0,i.kt)("p",null,"This rule detects ",(0,i.kt)("inlineCode",{parentName:"p"},"?: emptyList()")," that can be replaced with ",(0,i.kt)("inlineCode",{parentName:"p"},"orEmpty()")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-64"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'fun test(x: List?, s: String?) {\n val a = x ?: emptyList()\n val b = s ?: ""\n}\n')),(0,i.kt)("h4",{id:"compliant-code-56"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun test(x: List?, s: String?) {\n val a = x.orEmpty()\n val b = s.orEmpty()\n}\n")),(0,i.kt)("h3",{id:"userequire"},"UseRequire"),(0,i.kt)("p",null,"Kotlin provides a much more concise way to check preconditions than to manually throw an\nIllegalArgumentException."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-65"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'if (value == null) throw IllegalArgumentException("value should not be null")\nif (value < 0) throw IllegalArgumentException("value is $value but should be at least 0")\n')),(0,i.kt)("h4",{id:"compliant-code-57"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'requireNotNull(value) { "value should not be null" }\nrequire(value >= 0) { "value is $value but should be at least 0" }\n')),(0,i.kt)("h3",{id:"userequirenotnull"},"UseRequireNotNull"),(0,i.kt)("p",null,"Turn on this rule to flag ",(0,i.kt)("inlineCode",{parentName:"p"},"require")," calls for not-null check that can be replaced with a ",(0,i.kt)("inlineCode",{parentName:"p"},"requireNotNull")," call."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.21.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-66"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"require(x != null)\n")),(0,i.kt)("h4",{id:"compliant-code-58"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"requireNotNull(x)\n")),(0,i.kt)("h3",{id:"uselesscallonnotnull"},"UselessCallOnNotNull"),(0,i.kt)("p",null,"The Kotlin stdlib provides some functions that are designed to operate on references that may be null. These\nfunctions can also be called on non-nullable references or on collections or sequences that are known to be empty -\nthe calls are redundant in this case and can be removed or should be changed to a call that does not check whether\nthe value is null or not."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-67"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val testList = listOf("string").orEmpty()\nval testList2 = listOf("string").orEmpty().map { _ }\nval testList3 = listOfNotNull("string")\nval testString = ""?.isNullOrBlank()\n')),(0,i.kt)("h4",{id:"compliant-code-59"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},'val testList = listOf("string")\nval testList2 = listOf("string").map { }\nval testList3 = listOf("string")\nval testString = ""?.isBlank()\n')),(0,i.kt)("h3",{id:"utilityclasswithpublicconstructor"},"UtilityClassWithPublicConstructor"),(0,i.kt)("p",null,"A class which only contains utility variables and functions with no concrete implementation can be refactored\ninto an ",(0,i.kt)("inlineCode",{parentName:"p"},"object")," or a class with a non-public constructor.\nFurthermore, this rule reports utility classes which are not final."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.2.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"noncompliant-code-68"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class UtilityClassViolation {\n\n // public constructor here\n constructor() {\n // ...\n }\n\n companion object {\n val i = 0\n }\n}\n\nopen class UtilityClassViolation private constructor() {\n\n // ...\n}\n")),(0,i.kt)("h4",{id:"compliant-code-60"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"class UtilityClass {\n\n private constructor() {\n // ...\n }\n\n companion object {\n val i = 0\n }\n}\nobject UtilityClass {\n\n val i = 0\n}\n")),(0,i.kt)("h3",{id:"varcouldbeval"},"VarCouldBeVal"),(0,i.kt)("p",null,"Reports var declarations (both local variables and private class properties) that could be val,\nas they are not re-assigned. Val declarations are assign-once (read-only), which makes understanding\nthe current state easier."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.16.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Requires Type Resolution")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Aliases"),": CanBeVal"),(0,i.kt)("h4",{id:"configuration-options-20"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"ignoreLateinitVar")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),")"),(0,i.kt)("p",{parentName:"li"},"Whether to ignore uninitialized lateinit vars"))),(0,i.kt)("h4",{id:"noncompliant-code-69"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun example() {\n var i = 1 // violation: this variable is never re-assigned\n val j = i + 1\n}\n")),(0,i.kt)("h4",{id:"compliant-code-61"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"fun example() {\n val i = 1\n val j = i + 1\n}\n")),(0,i.kt)("h3",{id:"wildcardimport"},"WildcardImport"),(0,i.kt)("p",null,"Wildcard imports should be replaced with imports using fully qualified class names. This helps increase clarity of\nwhich classes are imported and helps prevent naming conflicts."),(0,i.kt)("p",null,"Library updates can introduce naming clashes with your own classes which might result in compilation errors."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"NOTE"),": This rule has a twin implementation NoWildcardImports in the formatting rule set (a wrapped KtLint rule).\nWhen suppressing an issue of WildcardImport in the baseline file, make sure to suppress the corresponding NoWildcardImports issue."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Active by default"),": Yes - Since v1.0.0"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Debt"),": 5min"),(0,i.kt)("h4",{id:"configuration-options-21"},"Configuration options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"excludeImports")," (default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['java.util.*']"),")"),(0,i.kt)("p",{parentName:"li"},"Define a list of package names that should be allowed to be imported with wildcard imports."))),(0,i.kt)("h4",{id:"noncompliant-code-70"},"Noncompliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"import io.gitlab.arturbosch.detekt.*\n\nclass DetektElements {\n val element1 = DetektElement1()\n val element2 = DetektElement2()\n}\n")),(0,i.kt)("h4",{id:"compliant-code-62"},"Compliant Code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-kotlin"},"import io.gitlab.arturbosch.detekt.DetektElement1\nimport io.gitlab.arturbosch.detekt.DetektElement2\n\nclass DetektElements {\n val element1 = DetektElement1()\n val element2 = DetektElement2()\n}\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.1400333a.js b/assets/js/runtime~main.4d889f54.js similarity index 99% rename from assets/js/runtime~main.1400333a.js rename to assets/js/runtime~main.4d889f54.js index 2dc6510e2..cf7d76972 100644 --- a/assets/js/runtime~main.1400333a.js +++ b/assets/js/runtime~main.4d889f54.js @@ -1 +1 @@ -!function(){"use strict";var e,a,c,f,t,n={},r={};function d(e){var a=r[e];if(void 0!==a)return a.exports;var c=r[e]={exports:{}};return n[e].call(c.exports,c,c.exports,d),c.exports}d.m=n,e=[],d.O=function(a,c,f,t){if(!c){var n=1/0;for(u=0;u=t)&&Object.keys(d.O).every((function(e){return d.O[e](c[o])}))?c.splice(o--,1):(r=!1,t0&&e[u-1][2]>t;u--)e[u]=e[u-1];e[u]=[c,f,t]},d.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(a,{a:a}),a},c=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var t=Object.create(null);d.r(t);var n={};a=a||[null,c({}),c([]),c(c)];for(var r=2&f&&e;"object"==typeof r&&!~a.indexOf(r);r=c(r))Object.getOwnPropertyNames(r).forEach((function(a){n[a]=function(){return e[a]}}));return n.default=function(){return e},d.d(t,n),t},d.d=function(e,a){for(var c in a)d.o(a,c)&&!d.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce((function(a,c){return d.f[c](e,a),a}),[]))},d.u=function(e){return"assets/js/"+({53:"935f2afb",241:"0e58a75f",253:"9aa28b63",439:"34af2f29",496:"6cfc4513",533:"b2b675dd",577:"8d2e55ce",673:"1082fd90",948:"200fe7cf",1119:"b2374579",1159:"5af69848",1395:"aee7a483",1466:"c7e442c8",1477:"b2f554cd",1713:"a7023ddc",1826:"855fb3b0",1961:"7039eadf",1964:"20013cb7",2101:"e9eeb40d",2199:"d3ffa58f",2356:"6d31d76d",2535:"814f3328",2666:"37ea7a12",2821:"4279727d",3003:"613ac473",3036:"1381ccb6",3089:"a6aa9e1f",3125:"e61da2af",3206:"f8409a7e",3480:"23530380",3514:"4465087c",3563:"74ccadee",3608:"9e4087bc",3954:"d640b5a6",4013:"01a85c17",4100:"ca539021",4195:"c4f5d8e4",4284:"a9cc6c1a",4487:"3511eed3",4685:"cfb1619e",4715:"3885f9ba",4902:"aad0aa44",5648:"a74a2902",5764:"13aa2ba4",5822:"8fa637ad",5962:"5249f512",5991:"7d7fd0cd",6062:"394f3ef8",6103:"ccc49370",6221:"b11bad44",6262:"a8a3190f",6366:"e174dfcc",6640:"27346d8c",7495:"3c945758",7571:"dced5fe6",7918:"17896441",7920:"1a4e3797",8139:"11bb9066",8610:"6875c492",8943:"b689ddcd",8971:"b3d3aa70",9018:"45e4cbec",9277:"a5e1ffa9",9514:"1be78505",9529:"313bfdc8",9697:"3b7b7886"}[e]||e)+"."+{53:"6e4b2f94",241:"6ae78f39",253:"64f68d09",439:"eaa0499d",496:"b2a2216c",533:"43111bdf",577:"7139a06e",673:"183c9094",948:"75318279",1119:"290ca8bb",1142:"025a99f0",1159:"abfeecde",1395:"029a8520",1466:"b97db8be",1477:"b437ee28",1713:"6e9a2696",1826:"4331bbed",1961:"7f3d9ede",1964:"c984936d",2101:"195c8f84",2199:"897841e1",2356:"1ad89035",2535:"03cd1496",2666:"07307ebf",2821:"9247079c",3003:"6fce6412",3036:"dd6bc72a",3089:"50017a75",3125:"4ed8bcc1",3206:"facdbf90",3480:"e6cf335b",3514:"706e322d",3562:"3a1c02bb",3563:"e5a52a2f",3608:"00180bd9",3954:"b3c875dc",4013:"27f4848c",4100:"b07b9924",4195:"2ac44d4c",4284:"551684fe",4487:"98b061d2",4685:"44bc71a6",4715:"f1a88cc0",4902:"54e67268",4972:"5b11ba56",5648:"94a600ee",5764:"75cb7ba6",5822:"4ee452f9",5962:"ce3f1c14",5991:"3ef48746",6062:"bca217f9",6103:"a68de2ee",6221:"5198c6db",6262:"a32567b7",6366:"fb38840e",6640:"32a7dfa9",6945:"10823ef2",7495:"48340865",7571:"c1300b6d",7918:"d42751a7",7920:"d9f75329",8139:"78a66a4a",8610:"18e4bd59",8894:"4cfb11da",8943:"a8bf8c16",8971:"ed53c836",9018:"ed7be015",9277:"f5cc31e9",9514:"84280c34",9529:"58c2dd14",9697:"21e3aaba"}[e]+".js"},d.miniCssF=function(e){},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},f={},t="detekt-website:",d.l=function(e,a,c,n){if(f[e])f[e].push(a);else{var r,o;if(void 0!==c)for(var b=document.getElementsByTagName("script"),u=0;u=t)&&Object.keys(d.O).every((function(e){return d.O[e](c[o])}))?c.splice(o--,1):(r=!1,t0&&e[u-1][2]>t;u--)e[u]=e[u-1];e[u]=[c,f,t]},d.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(a,{a:a}),a},c=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var t=Object.create(null);d.r(t);var n={};a=a||[null,c({}),c([]),c(c)];for(var r=2&f&&e;"object"==typeof r&&!~a.indexOf(r);r=c(r))Object.getOwnPropertyNames(r).forEach((function(a){n[a]=function(){return e[a]}}));return n.default=function(){return e},d.d(t,n),t},d.d=function(e,a){for(var c in a)d.o(a,c)&&!d.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce((function(a,c){return d.f[c](e,a),a}),[]))},d.u=function(e){return"assets/js/"+({53:"935f2afb",241:"0e58a75f",253:"9aa28b63",439:"34af2f29",496:"6cfc4513",533:"b2b675dd",577:"8d2e55ce",673:"1082fd90",948:"200fe7cf",1119:"b2374579",1159:"5af69848",1395:"aee7a483",1466:"c7e442c8",1477:"b2f554cd",1713:"a7023ddc",1826:"855fb3b0",1961:"7039eadf",1964:"20013cb7",2101:"e9eeb40d",2199:"d3ffa58f",2356:"6d31d76d",2535:"814f3328",2666:"37ea7a12",2821:"4279727d",3003:"613ac473",3036:"1381ccb6",3089:"a6aa9e1f",3125:"e61da2af",3206:"f8409a7e",3480:"23530380",3514:"4465087c",3563:"74ccadee",3608:"9e4087bc",3954:"d640b5a6",4013:"01a85c17",4100:"ca539021",4195:"c4f5d8e4",4284:"a9cc6c1a",4487:"3511eed3",4685:"cfb1619e",4715:"3885f9ba",4902:"aad0aa44",5648:"a74a2902",5764:"13aa2ba4",5822:"8fa637ad",5962:"5249f512",5991:"7d7fd0cd",6062:"394f3ef8",6103:"ccc49370",6221:"b11bad44",6262:"a8a3190f",6366:"e174dfcc",6640:"27346d8c",7495:"3c945758",7571:"dced5fe6",7918:"17896441",7920:"1a4e3797",8139:"11bb9066",8610:"6875c492",8943:"b689ddcd",8971:"b3d3aa70",9018:"45e4cbec",9277:"a5e1ffa9",9514:"1be78505",9529:"313bfdc8",9697:"3b7b7886"}[e]||e)+"."+{53:"6e4b2f94",241:"6ae78f39",253:"64f68d09",439:"eaa0499d",496:"b2a2216c",533:"43111bdf",577:"7139a06e",673:"183c9094",948:"75318279",1119:"290ca8bb",1142:"025a99f0",1159:"abfeecde",1395:"029a8520",1466:"b97db8be",1477:"b437ee28",1713:"6e9a2696",1826:"4331bbed",1961:"7f3d9ede",1964:"c984936d",2101:"195c8f84",2199:"897841e1",2356:"1ad89035",2535:"03cd1496",2666:"07307ebf",2821:"9247079c",3003:"6fce6412",3036:"dd6bc72a",3089:"50017a75",3125:"4ed8bcc1",3206:"facdbf90",3480:"e6cf335b",3514:"706e322d",3562:"3a1c02bb",3563:"46979f76",3608:"00180bd9",3954:"b3c875dc",4013:"27f4848c",4100:"b07b9924",4195:"2ac44d4c",4284:"551684fe",4487:"98b061d2",4685:"44bc71a6",4715:"f1a88cc0",4902:"54e67268",4972:"5b11ba56",5648:"94a600ee",5764:"75cb7ba6",5822:"4ee452f9",5962:"ce3f1c14",5991:"3ef48746",6062:"bca217f9",6103:"a68de2ee",6221:"5198c6db",6262:"a32567b7",6366:"fb38840e",6640:"32a7dfa9",6945:"10823ef2",7495:"48340865",7571:"c1300b6d",7918:"d42751a7",7920:"d9f75329",8139:"78a66a4a",8610:"18e4bd59",8894:"4cfb11da",8943:"a8bf8c16",8971:"ed53c836",9018:"ed7be015",9277:"f5cc31e9",9514:"84280c34",9529:"58c2dd14",9697:"21e3aaba"}[e]+".js"},d.miniCssF=function(e){},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},f={},t="detekt-website:",d.l=function(e,a,c,n){if(f[e])f[e].push(a);else{var r,o;if(void 0!==c)for(var b=document.getElementsByTagName("script"),u=0;u