Add inspections for implicit and explicit 'this' #KT-4580 Fixed
This commit is contained in:
@@ -26,15 +26,28 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun LexicalScope.getImplicitReceiversWithInstance(): Collection<ReceiverParameterDescriptor>
|
fun LexicalScope.getImplicitReceiversWithInstance(): Collection<ReceiverParameterDescriptor>
|
||||||
= getImplicitReceiversWithInstanceToExpression().keys
|
= getImplicitReceiversWithInstanceToExpression().keys
|
||||||
|
|
||||||
interface ReceiverExpressionFactory {
|
interface ReceiverExpressionFactory {
|
||||||
|
val isImmediate: Boolean
|
||||||
|
val expressionText: String
|
||||||
fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
|
fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType: KotlinType): ReceiverExpressionFactory? {
|
||||||
|
return getImplicitReceiversWithInstanceToExpression()
|
||||||
|
.entries
|
||||||
|
.firstOrNull { (receiverDescriptor, _) ->
|
||||||
|
receiverDescriptor.type.isSubtypeOf(receiverType)
|
||||||
|
}
|
||||||
|
?.value
|
||||||
|
}
|
||||||
|
|
||||||
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<ReceiverParameterDescriptor, ReceiverExpressionFactory?> {
|
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<ReceiverParameterDescriptor, ReceiverExpressionFactory?> {
|
||||||
// we use a set to workaround a bug with receiver for companion object present twice in the result of getImplicitReceiversHierarchy()
|
// we use a set to workaround a bug with receiver for companion object present twice in the result of getImplicitReceiversHierarchy()
|
||||||
val receivers = LinkedHashSet(getImplicitReceiversHierarchy())
|
val receivers = LinkedHashSet(getImplicitReceiversHierarchy())
|
||||||
@@ -43,7 +56,7 @@ fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<ReceiverPar
|
|||||||
var current: DeclarationDescriptor? = ownerDescriptor
|
var current: DeclarationDescriptor? = ownerDescriptor
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
if (current is PropertyAccessorDescriptor) {
|
if (current is PropertyAccessorDescriptor) {
|
||||||
current = current.correspondingProperty
|
current = current.correspondingProperty
|
||||||
}
|
}
|
||||||
outerDeclarationsWithInstance.add(current)
|
outerDeclarationsWithInstance.add(current)
|
||||||
|
|
||||||
@@ -75,6 +88,8 @@ fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<ReceiverPar
|
|||||||
}
|
}
|
||||||
val factory = if (expressionText != null)
|
val factory = if (expressionText != null)
|
||||||
object : ReceiverExpressionFactory {
|
object : ReceiverExpressionFactory {
|
||||||
|
override val isImmediate = isImmediateThis
|
||||||
|
override val expressionText get() = expressionText!!
|
||||||
override fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean): KtExpression {
|
override fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean): KtExpression {
|
||||||
return psiFactory.createExpression(if (shortThis && isImmediateThis) "this" else expressionText)
|
return psiFactory.createExpression(if (shortThis && isImmediateThis) "this" else expressionText)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This inspection reports usages of explicit 'this' when it can be omitted.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This inspection reports usages of implicit 'this'.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2623,6 +2623,25 @@
|
|||||||
level="WARNING"
|
level="WARNING"
|
||||||
language="kotlin"
|
language="kotlin"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ExplicitThisInspection"
|
||||||
|
displayName="Redundant explicit 'this'"
|
||||||
|
groupPath="Kotlin"
|
||||||
|
groupName="Redundant constructs"
|
||||||
|
enabledByDefault="true"
|
||||||
|
level="INFORMATION"
|
||||||
|
language="kotlin"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ImplicitThisInspection"
|
||||||
|
displayName="Implicit 'this'"
|
||||||
|
groupPath="Kotlin"
|
||||||
|
groupName="Style issues"
|
||||||
|
enabledByDefault="true"
|
||||||
|
level="INFORMATION"
|
||||||
|
language="kotlin"
|
||||||
|
/>
|
||||||
|
|
||||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantUnitExpressionInspection"
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantUnitExpressionInspection"
|
||||||
displayName="Redundant 'Unit'"
|
displayName="Redundant 'Unit'"
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.LocalQuickFix
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.codeInspection.ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||||
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
|
|
||||||
|
class ExplicitThisInspection : AbstractKotlinInspection() {
|
||||||
|
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : KtVisitorVoid() {
|
||||||
|
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
|
||||||
|
val thisExpression = expression.receiverExpression as? KtThisExpression ?: return
|
||||||
|
|
||||||
|
val context = expression.analyzeFully()
|
||||||
|
val scope = expression.getResolutionScope(context) ?: return
|
||||||
|
|
||||||
|
val selectorExpression = expression.selectorExpression as? KtReferenceExpression ?: return
|
||||||
|
val referenceExpression = selectorExpression as? KtNameReferenceExpression
|
||||||
|
?: selectorExpression.getChildOfType()
|
||||||
|
?: return
|
||||||
|
|
||||||
|
val scopeFunction = when (selectorExpression) {
|
||||||
|
is KtNameReferenceExpression -> LexicalScope::getAllAccessibleVariables
|
||||||
|
is KtCallExpression -> LexicalScope::getAllAccessibleFunctions
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
//we avoid overload-related problems by enforcing that there is only one candidate
|
||||||
|
val candidates = scopeFunction(scope, referenceExpression.getReferencedNameAsName())
|
||||||
|
if (candidates.size != 1) return
|
||||||
|
|
||||||
|
|
||||||
|
val receiverType = context[BindingContext.EXPRESSION_TYPE_INFO, thisExpression]?.type ?: return
|
||||||
|
val expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return
|
||||||
|
|
||||||
|
val label = thisExpression.getLabelName() ?: ""
|
||||||
|
if (!expressionFactory.matchesLabel(label)) return
|
||||||
|
|
||||||
|
holder.registerProblem(thisExpression, "Redundant explicit this", LIKE_UNUSED_SYMBOL, Fix(thisExpression.text))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ReceiverExpressionFactory.matchesLabel(label: String): Boolean {
|
||||||
|
val implicitLabel = expressionText.substringAfter("@", "")
|
||||||
|
return label == implicitLabel || (label == "" && isImmediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Fix(private val text: String) : LocalQuickFix {
|
||||||
|
override fun getFamilyName(): String = "Remove redundant '$text'"
|
||||||
|
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
val thisExpression = descriptor.psiElement as? KtThisExpression ?: return
|
||||||
|
val parent = thisExpression.parent as? KtDotQualifiedExpression ?: return
|
||||||
|
parent.replace(parent.selectorExpression ?: return)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.LocalQuickFix
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||||
|
import org.jetbrains.kotlin.idea.util.getFactoryForImplicitReceiverWithSubtypeOf
|
||||||
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
|
class ImplicitThisInspection : AbstractKotlinInspection() {
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : KtVisitorVoid() {
|
||||||
|
override fun visitExpression(expression: KtExpression) {
|
||||||
|
if (expression !is KtNameReferenceExpression) return
|
||||||
|
if (expression.isSelectorOfDotQualifiedExpression()) return
|
||||||
|
val parent = expression.parent
|
||||||
|
if (parent is KtCallExpression && parent.isSelectorOfDotQualifiedExpression()) return
|
||||||
|
|
||||||
|
val referenceExpression = expression as? KtNameReferenceExpression
|
||||||
|
?: expression.getChildOfType()
|
||||||
|
?: return
|
||||||
|
|
||||||
|
val context = expression.analyzeFully()
|
||||||
|
val scope = expression.getResolutionScope(context) ?: return
|
||||||
|
|
||||||
|
val descriptor = context[BindingContext.REFERENCE_TARGET, referenceExpression] as? CallableDescriptor ?: return
|
||||||
|
val receiverDescriptor = descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter ?: return
|
||||||
|
val receiverType = receiverDescriptor.type
|
||||||
|
|
||||||
|
val expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return
|
||||||
|
val receiverText = if (expressionFactory.isImmediate) "this" else expressionFactory.expressionText
|
||||||
|
|
||||||
|
holder.registerProblem(expression, "Add explicit '$receiverText'", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, Fix(receiverText))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtExpression.isSelectorOfDotQualifiedExpression(): Boolean {
|
||||||
|
val parent = parent
|
||||||
|
return parent is KtDotQualifiedExpression && parent.selectorExpression == this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Fix(private val receiverText: String) : LocalQuickFix {
|
||||||
|
override fun getFamilyName() = "Add explicit '$receiverText'"
|
||||||
|
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
val expression = descriptor.psiElement as? KtExpression ?: return
|
||||||
|
val factory = KtPsiFactory(project)
|
||||||
|
val call = expression.parent as? KtCallExpression ?: expression
|
||||||
|
|
||||||
|
call.replace(factory.createExpressionByPattern("$0.$1", receiverText, call.text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.inspections.ExplicitThisInspection
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Foo().apply {
|
||||||
|
<caret>this@Foo.s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
Foo().apply {
|
||||||
|
<caret>this@Foo.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo.s() {}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
<caret>this@Foo.s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
val s = ""
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
<caret>this@Foo.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar
|
||||||
|
|
||||||
|
|
||||||
|
fun Foo.s() {}
|
||||||
|
fun Bar.s() {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo.s() = ""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo.s() = ""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
"".apply {
|
||||||
|
<caret>this@Foo.s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
"".apply {
|
||||||
|
<caret>s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
"".apply {
|
||||||
|
<caret>this@Foo.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo.s() = ""
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
"".apply {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo.s() = ""
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
"".run {
|
||||||
|
<caret>this@apply.s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
val s = ""
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun s(a: String) {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
<caret>this@Foo.s("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
fun s() {}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
"".run {
|
||||||
|
<caret>this@apply.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar
|
||||||
|
|
||||||
|
fun Foo.s() {}
|
||||||
|
fun Bar.s() {}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
<caret>this@Foo.s("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar
|
||||||
|
|
||||||
|
fun Foo.s(a: String) {}
|
||||||
|
fun Bar.s() {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
var s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val s = ""
|
||||||
|
<caret>this.s = s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.inspections.ImplicitThisInspection
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun Bar.s() = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
Foo().apply apply2@ {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun Bar.s() = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Bar().apply {
|
||||||
|
Foo().apply apply2@ {
|
||||||
|
<caret>this@apply.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
"".apply {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun s() = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
"".apply {
|
||||||
|
<caret>this@Foo.s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class Foo {
|
||||||
|
val f = Foo()
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>f.s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class Foo {
|
||||||
|
val f = Foo()
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.f.s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val s = ""
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<caret>this.s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun test() {
|
||||||
|
<caret>s()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun s() = ""
|
||||||
@@ -621,6 +621,156 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/inspectionsLocal/explicitThis")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ExplicitThis extends AbstractLocalInspectionTest {
|
||||||
|
public void testAllFilesPresentInExplicitThis() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/explicitThis"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("differentReceiverInstance.kt")
|
||||||
|
public void testDifferentReceiverInstance() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstance.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("differentReceiverInstanceExtension.kt")
|
||||||
|
public void testDifferentReceiverInstanceExtension() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/differentReceiverInstanceExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("differentReceiverType.kt")
|
||||||
|
public void testDifferentReceiverType() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/differentReceiverType.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("differentReceiverTypeExtension.kt")
|
||||||
|
public void testDifferentReceiverTypeExtension() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/differentReceiverTypeExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extension.kt")
|
||||||
|
public void testExtension() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/extension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("function.kt")
|
||||||
|
public void testFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/function.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleReceivers.kt")
|
||||||
|
public void testMultipleReceivers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/multipleReceivers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleReceiversExtension.kt")
|
||||||
|
public void testMultipleReceiversExtension() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/multipleReceiversExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedReceivers.kt")
|
||||||
|
public void testNestedReceivers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/nestedReceivers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedReceiversDifferentParameters.kt")
|
||||||
|
public void testNestedReceiversDifferentParameters() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/nestedReceiversDifferentParameters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedReceiversExtension.kt")
|
||||||
|
public void testNestedReceiversExtension() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/nestedReceiversExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedReceiversExtensionDifferentParameters.kt")
|
||||||
|
public void testNestedReceiversExtensionDifferentParameters() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/nestedReceiversExtensionDifferentParameters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("property.kt")
|
||||||
|
public void testProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/property.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("variableWithSameName.kt")
|
||||||
|
public void testVariableWithSameName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/explicitThis/variableWithSameName.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/inspectionsLocal/implicitThis")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ImplicitThis extends AbstractLocalInspectionTest {
|
||||||
|
public void testAllFilesPresentInImplicitThis() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/implicitThis"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("function.kt")
|
||||||
|
public void testFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/function.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionPartOfCall.kt")
|
||||||
|
public void testFunctionPartOfCall() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/functionPartOfCall.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleReceivers.kt")
|
||||||
|
public void testMultipleReceivers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/multipleReceivers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nested.kt")
|
||||||
|
public void testNested() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/nested.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedCall.kt")
|
||||||
|
public void testNestedCall() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/nestedCall.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("property.kt")
|
||||||
|
public void testProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/property.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyPartOfCall.kt")
|
||||||
|
public void testPropertyPartOfCall() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/propertyPartOfCall.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevel.kt")
|
||||||
|
public void testTopLevel() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/implicitThis/topLevel.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/kdocMissingDocumentation")
|
@TestMetadata("idea/testData/inspectionsLocal/kdocMissingDocumentation")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user