Redundant Sam Constructor inspection
This commit is contained in:
+1
-1
@@ -86,7 +86,7 @@ public class SingleAbstractMethodUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static JetType getFunctionTypeForSamType(@NotNull JetType samType) {
|
public static JetType getFunctionTypeForSamType(@NotNull JetType samType) {
|
||||||
// e.g. samType == Comparator<String>?
|
// e.g. samType == Comparator<String>?
|
||||||
|
|
||||||
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
|
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
|
||||||
|
|||||||
@@ -1078,6 +1078,13 @@
|
|||||||
level="WARNING"
|
level="WARNING"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection"
|
||||||
|
displayName="Redundant SAM constructor"
|
||||||
|
groupName="Kotlin"
|
||||||
|
enabledByDefault="true"
|
||||||
|
level="WARNING"
|
||||||
|
/>
|
||||||
|
|
||||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.kdoc.KDocUnresolvedReferenceInspection"
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.kdoc.KDocUnresolvedReferenceInspection"
|
||||||
displayName="Unresolved reference in KDoc"
|
displayName="Unresolved reference in KDoc"
|
||||||
groupName="Kotlin"
|
groupName="Kotlin"
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.*
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.SamCodegenUtil
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
|
import org.jetbrains.kotlin.idea.core.getResolutionScope
|
||||||
|
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||||
|
|
||||||
|
public class RedundantSamConstructorInspection : AbstractKotlinInspection() {
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||||
|
return object : JetVisitorVoid() {
|
||||||
|
private fun createQuickFix(expression: JetCallExpression): LocalQuickFix {
|
||||||
|
return object : LocalQuickFix {
|
||||||
|
override fun getName() = "Remove redundant SAM-constructor"
|
||||||
|
override fun getFamilyName() = name
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
replaceSamConstructorCall(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createQuickFix(expressions: List<JetCallExpression>): LocalQuickFix {
|
||||||
|
return object : LocalQuickFix {
|
||||||
|
override fun getName() = "Remove redundant SAM-constructors"
|
||||||
|
override fun getFamilyName() = name
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
for (callExpression in expressions) {
|
||||||
|
replaceSamConstructorCall(callExpression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCallExpression(expression: JetCallExpression) {
|
||||||
|
if (expression.valueArguments.isEmpty()) return
|
||||||
|
|
||||||
|
val samConstructorCalls = samConstructorCallsToBeConverted(expression)
|
||||||
|
if (samConstructorCalls.isEmpty()) return
|
||||||
|
if (samConstructorCalls.size() == 1) {
|
||||||
|
val single = samConstructorCalls.single()
|
||||||
|
val problemDescriptor = holder.manager.
|
||||||
|
createProblemDescriptor(single.calleeExpression!!,
|
||||||
|
single.typeArgumentList ?: single.calleeExpression!!,
|
||||||
|
"Redundant SAM-constructor",
|
||||||
|
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||||
|
isOnTheFly,
|
||||||
|
createQuickFix(single))
|
||||||
|
|
||||||
|
holder.registerProblem(problemDescriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val problemDescriptor = holder.manager.
|
||||||
|
createProblemDescriptor(expression.valueArgumentList!!,
|
||||||
|
"Redundant SAM-constructors",
|
||||||
|
createQuickFix(samConstructorCalls),
|
||||||
|
ProblemHighlightType.WEAK_WARNING,
|
||||||
|
isOnTheFly)
|
||||||
|
|
||||||
|
holder.registerProblem(problemDescriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
public fun replaceSamConstructorCall(callExpression: JetCallExpression): JetExpression {
|
||||||
|
val functionalArgument = callExpression.samConstructorValueArgument()?.getArgumentExpression()
|
||||||
|
?: throw AssertionError("SAM-constructor should have a FunctionLiteralExpression as single argument: ${callExpression.getElementTextWithContext()}")
|
||||||
|
return callExpression.replace(functionalArgument) as JetExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canBeReplaced(parentCall: JetCallExpression, callExpressions: List<JetCallExpression>): Boolean {
|
||||||
|
val context = parentCall.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
|
||||||
|
val calleeExpression = parentCall.calleeExpression ?: return false
|
||||||
|
val scope = context[BindingContext.RESOLUTION_SCOPE, calleeExpression] ?: return false
|
||||||
|
|
||||||
|
val originalCall = parentCall.getResolvedCall(context) ?: return false
|
||||||
|
|
||||||
|
val dataFlow = context.getDataFlowInfo(parentCall)
|
||||||
|
val callResolver = parentCall.getResolutionFacade().frontendService<CallResolver>()
|
||||||
|
val newCall = CallWithNewArguments(originalCall.call, callExpressions)
|
||||||
|
|
||||||
|
val qualifiedExpression = parentCall.getQualifiedExpressionForSelectorOrThis()
|
||||||
|
val expectedType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, qualifiedExpression] ?: TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
|
||||||
|
val resolutionResults = callResolver.resolveFunctionCall(BindingTraceContext(), scope, newCall, expectedType, dataFlow, false)
|
||||||
|
|
||||||
|
if (!resolutionResults.isSuccess) return false
|
||||||
|
|
||||||
|
val samAdapterOriginalDescriptor = SamCodegenUtil.getOriginalIfSamAdapter(resolutionResults.resultingDescriptor) ?: return false
|
||||||
|
return samAdapterOriginalDescriptor.original == originalCall.resultingDescriptor.original
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CallWithNewArguments(original: Call, val callExpressions: List<JetCallExpression>): DelegatingCall(original) {
|
||||||
|
private val newArguments: List<ValueArgument>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val factory = JetPsiFactory(callElement)
|
||||||
|
newArguments = original.valueArguments.map { argument ->
|
||||||
|
argument.getArgumentExpression()
|
||||||
|
?.check { callExpressions.contains(it) }
|
||||||
|
?.let { factory.createArgument(replaceSamConstructorCall(it.copy() as JetCallExpression), argument.getArgumentName()?.asName) }
|
||||||
|
?: argument
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValueArguments() = newArguments
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun samConstructorCallsToBeConverted(functionCall: JetCallExpression): List<JetCallExpression> {
|
||||||
|
if (functionCall.valueArguments.all { !canBeSamConstructorCall(it) }) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val bindingContext = functionCall.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
val functionResolvedCall = functionCall.getResolvedCall(bindingContext) ?: return emptyList()
|
||||||
|
if (!functionResolvedCall.status.isSuccess) return emptyList()
|
||||||
|
|
||||||
|
val samConstructorCalls = functionCall.valueArguments.map {
|
||||||
|
(it.getArgumentExpression() as? JetCallExpression)
|
||||||
|
?.check { it.getResolvedCall(bindingContext)?.resultingDescriptor?.original is SamConstructorDescriptor }
|
||||||
|
}.filterNotNull()
|
||||||
|
|
||||||
|
if (samConstructorCalls.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
val originalFunctionDescriptor = functionResolvedCall.resultingDescriptor.original as? FunctionDescriptor ?: return emptyList()
|
||||||
|
val containingClass = originalFunctionDescriptor.containingDeclaration as? ClassDescriptor ?: return emptyList()
|
||||||
|
|
||||||
|
// SAM adapters for static functions
|
||||||
|
for (staticFunWithSameName in containingClass.staticScope.getFunctions(functionResolvedCall.resultingDescriptor.name, NoLookupLocation.FROM_IDE)) {
|
||||||
|
if (staticFunWithSameName is SamAdapterDescriptor<*>) {
|
||||||
|
if (isSamAdapterSuitableForCall(staticFunWithSameName, originalFunctionDescriptor, samConstructorCalls.size())) {
|
||||||
|
return samConstructorCalls.check { canBeReplaced(functionCall, it) } ?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAM adapters for member functions
|
||||||
|
val resolutionScope = functionCall.getResolutionScope(bindingContext, functionCall.getResolutionFacade())
|
||||||
|
val syntheticExtensions = resolutionScope.getSyntheticExtensionFunctions(
|
||||||
|
containingClass.defaultType.singletonList(),
|
||||||
|
functionResolvedCall.resultingDescriptor.name,
|
||||||
|
NoLookupLocation.FROM_IDE
|
||||||
|
)
|
||||||
|
for (syntheticExtension in syntheticExtensions) {
|
||||||
|
val samAdapter = syntheticExtension as? SamAdapterExtensionFunctionDescriptor ?: continue
|
||||||
|
if (isSamAdapterSuitableForCall(samAdapter, originalFunctionDescriptor, samConstructorCalls.size())) {
|
||||||
|
return samConstructorCalls.check { canBeReplaced(functionCall, it) } ?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canBeSamConstructorCall(argument: JetValueArgument): Boolean {
|
||||||
|
val argumentExpression = argument.getArgumentExpression()
|
||||||
|
if (argumentExpression !is JetCallExpression) return false
|
||||||
|
|
||||||
|
return argumentExpression.samConstructorValueArgument() != null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JetCallExpression.samConstructorValueArgument(): JetValueArgument? {
|
||||||
|
return valueArguments.singleOrNull()?.check { it.getArgumentExpression() is JetFunctionLiteralExpression }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isSamAdapterSuitableForCall(
|
||||||
|
samAdapter: FunctionDescriptor,
|
||||||
|
originalFunction: FunctionDescriptor,
|
||||||
|
samConstructorsCount: Int
|
||||||
|
): Boolean {
|
||||||
|
val samAdapterOriginalFunction = SamCodegenUtil.getOriginalIfSamAdapter(samAdapter)?.original
|
||||||
|
if (samAdapterOriginalFunction != originalFunction) return false
|
||||||
|
|
||||||
|
val parametersWithSamTypeCount = originalFunction.valueParameters.count {
|
||||||
|
SingleAbstractMethodUtils.getFunctionTypeForSamType(it.type) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
return parametersWithSamTypeCount == samConstructorsCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public class A<T> {
|
||||||
|
public void foo(JFunction1<T> r) {}
|
||||||
|
|
||||||
|
public static <T> JFunction1<T> expectedType(JFunction1<T> r) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public class GenericClass1 {
|
||||||
|
public static <T> void staticFun1(JFunction1<T> r) {}
|
||||||
|
public static <T> void staticFun2(JFunction1<T> r1, JFunction1<T> r2) {}
|
||||||
|
public static <T> void staticFunWithOtherParam(int r1, JFunction1<T> r2) {}
|
||||||
|
|
||||||
|
public <T> void memberFun1(JFunction1<T> r) {}
|
||||||
|
public <T> void memberFun2(JFunction1<T> r1, JFunction1<T> r2) {}
|
||||||
|
public <T> void memberFunWithOtherParam(int r1, JFunction1<T> r2) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public class GenericClass2 {
|
||||||
|
public static <T> void staticFun1(JFunction0<T> r) {}
|
||||||
|
public static <T> void staticFun2(JFunction0<T> r1, JFunction0<T> r2) {}
|
||||||
|
public static <T> void staticFunWithOtherParam(int r1, JFunction0<T> r2) {}
|
||||||
|
|
||||||
|
public <T> void memberFun1(JFunction0<T> r) {}
|
||||||
|
public <T> void memberFun2(JFunction0<T> r1, JFunction0<T> r2) {}
|
||||||
|
public <T> void memberFunWithOtherParam(int r1, JFunction0<T> r2) {}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public class GenericClassCantBeReplaced {
|
||||||
|
public static <T> void staticFun1(JFunction0<T> r) {}
|
||||||
|
public static <T> void staticFun1(JFunction1<T> r) {}
|
||||||
|
|
||||||
|
public static <T> void staticFun2(JFunction0<T> r1, JFunction0<T> r2) {}
|
||||||
|
public static <T> void staticFun2(JFunction1<T> r1, JFunction1<T> r2) {}
|
||||||
|
|
||||||
|
public <T> void memberFun1(JFunction0<T> r) {}
|
||||||
|
public <T> void memberFun1(JFunction1<T> r) {}
|
||||||
|
|
||||||
|
public <T> void memberFun2(JFunction0<T> r1, JFunction0<T> r2) {}
|
||||||
|
public <T> void memberFun2(JFunction1<T> r1, JFunction1<T> r2) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public interface JFunction0<T> {
|
||||||
|
T foo();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public interface JFunction1<T> {
|
||||||
|
void foo(T t);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
public class MyJavaClass {
|
||||||
|
public static void staticFun1(Runnable r) {}
|
||||||
|
public static void staticFun2(Runnable r1, Runnable r2) {}
|
||||||
|
public static void staticFunWithOtherParam(int r1, Runnable r2) {}
|
||||||
|
|
||||||
|
public void memberFun1(Runnable r) {}
|
||||||
|
public void memberFun2(Runnable r1, Runnable r2) {}
|
||||||
|
public void memberFunWithOtherParam(int r1, Runnable r2) {}
|
||||||
|
|
||||||
|
public static <T> void foo1(Runnable r, T t) {}
|
||||||
|
public static <T> void foo2(T t, Runnable r) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
import a.A.*
|
||||||
|
|
||||||
|
fun testExpectedType() {
|
||||||
|
val s1: JFunction1<String> = A.expectedType(JFunction1<String> { })
|
||||||
|
val s2: JFunction1<String> = expectedType(JFunction1<String> { })
|
||||||
|
}
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
<problems>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructor.kt</file>
|
||||||
|
<line>9</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructor.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructor.kt</file>
|
||||||
|
<line>11</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructor.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WEAK_WARNING">Redundant SAM-constructors</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructor.kt</file>
|
||||||
|
<line>22</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructor.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructor.kt</file>
|
||||||
|
<line>25</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructor.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructor.kt</file>
|
||||||
|
<line>27</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructor.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructor.kt</file>
|
||||||
|
<line>38</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructor.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructorWithGenericsInReturnType.kt</file>
|
||||||
|
<line>9</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructorWithGenericsInReturnType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructorWithGenericsInReturnType.kt</file>
|
||||||
|
<line>11</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructorWithGenericsInReturnType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WEAK_WARNING">Redundant SAM-constructors</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructorWithGenericsInReturnType.kt</file>
|
||||||
|
<line>15</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructorWithGenericsInReturnType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructorWithGenericsInReturnType.kt</file>
|
||||||
|
<line>18</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructorWithGenericsInReturnType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructorWithGenericsInReturnType.kt</file>
|
||||||
|
<line>20</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructorWithGenericsInReturnType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>redundantSamConstructorWithGenericsInReturnType.kt</file>
|
||||||
|
<line>24</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/redundantSamConstructorWithGenericsInReturnType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>otherGenericsInParams.kt</file>
|
||||||
|
<line>6</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/otherGenericsInParams.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>otherGenericsInParams.kt</file>
|
||||||
|
<line>8</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/otherGenericsInParams.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>otherGenericsInParams.kt</file>
|
||||||
|
<line>11</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/otherGenericsInParams.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM-constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>expectedType.kt</file>
|
||||||
|
<line>7</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/expectedType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>expectedType.kt</file>
|
||||||
|
<line>8</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/expectedType.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant SAM constructor</problem_class>
|
||||||
|
<description>Redundant SAM-constructor</description>
|
||||||
|
</problem>
|
||||||
|
</problems>
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
import a.A.*
|
||||||
|
|
||||||
|
fun testExpectedType() {
|
||||||
|
val s1: JFunction1<String> = A.expectedType({ })
|
||||||
|
val s2: JFunction1<String> = expectedType({ })
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection
|
||||||
Vendored
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
MyJavaClass.foo1({ }, 1)
|
||||||
|
MyJavaClass.foo1(Runnable { }, Runnable { })
|
||||||
|
MyJavaClass.foo2(1, { })
|
||||||
|
MyJavaClass.foo2(Runnable { }, Runnable { })
|
||||||
|
|
||||||
|
A<String>().foo({})
|
||||||
|
}
|
||||||
Vendored
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val runnable = Runnable { }
|
||||||
|
val klass = MyJavaClass()
|
||||||
|
|
||||||
|
MyJavaClass.staticFun1({ })
|
||||||
|
MyJavaClass.staticFun1(runnable)
|
||||||
|
MyJavaClass.staticFun2({ }, { })
|
||||||
|
MyJavaClass.staticFun2(runnable, Runnable { })
|
||||||
|
MyJavaClass.staticFun2({ }, { })
|
||||||
|
MyJavaClass.staticFun2(
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
},
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
})
|
||||||
|
|
||||||
|
MyJavaClass.staticFunWithOtherParam(1, { })
|
||||||
|
MyJavaClass.staticFunWithOtherParam(1, runnable)
|
||||||
|
|
||||||
|
klass.memberFun1({ })
|
||||||
|
klass.memberFun1(runnable)
|
||||||
|
klass.memberFun2({ }, { })
|
||||||
|
klass.memberFun2(runnable, Runnable { })
|
||||||
|
klass.memberFun2({ }, { })
|
||||||
|
klass.memberFun2(
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
},
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
})
|
||||||
|
|
||||||
|
klass.memberFunWithOtherParam(1, { })
|
||||||
|
klass.memberFunWithOtherParam(1, runnable)
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun testGenerics() {
|
||||||
|
val runnable = JFunction1<String> { }
|
||||||
|
val klass = GenericClass1()
|
||||||
|
|
||||||
|
GenericClass1.staticFun1(JFunction1<String> { })
|
||||||
|
GenericClass1.staticFun1(runnable)
|
||||||
|
GenericClass1.staticFun2(JFunction1<String> { }, JFunction1<String> { })
|
||||||
|
GenericClass1.staticFun2(runnable, JFunction1<String> { })
|
||||||
|
GenericClass1.staticFun2({ s: String -> }, { s: String -> })
|
||||||
|
|
||||||
|
GenericClass1.staticFunWithOtherParam(1, JFunction1<String> { })
|
||||||
|
GenericClass1.staticFunWithOtherParam(1, runnable)
|
||||||
|
|
||||||
|
klass.memberFun1(JFunction1<String> { })
|
||||||
|
klass.memberFun1(runnable)
|
||||||
|
klass.memberFun2(JFunction1<String> { }, JFunction1<String> { })
|
||||||
|
klass.memberFun2(runnable, JFunction1<String> { })
|
||||||
|
klass.memberFun2({ s: String -> }, { s: String -> })
|
||||||
|
|
||||||
|
klass.memberFunWithOtherParam(1, JFunction1<String> { })
|
||||||
|
klass.memberFunWithOtherParam(1, runnable)
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun testGenericsReturnType() {
|
||||||
|
val runnable = JFunction0 { "" }
|
||||||
|
val klass = GenericClass2()
|
||||||
|
|
||||||
|
GenericClass2.staticFun1({ "" })
|
||||||
|
GenericClass2.staticFun1(runnable)
|
||||||
|
GenericClass2.staticFun2({ "" }, { "" })
|
||||||
|
GenericClass2.staticFun2(runnable, JFunction0 { "" })
|
||||||
|
GenericClass2.staticFun2({ -> "" }, { -> "" })
|
||||||
|
|
||||||
|
GenericClass2.staticFunWithOtherParam(1, { "" })
|
||||||
|
GenericClass2.staticFunWithOtherParam(1, runnable)
|
||||||
|
|
||||||
|
klass.memberFun1({ "" })
|
||||||
|
klass.memberFun1(runnable)
|
||||||
|
klass.memberFun2({ "" }, { "" })
|
||||||
|
klass.memberFun2(runnable, JFunction0 { "" })
|
||||||
|
klass.memberFun2({ -> "" }, { -> "" })
|
||||||
|
|
||||||
|
klass.memberFunWithOtherParam(1, { "" })
|
||||||
|
klass.memberFunWithOtherParam(1, runnable)
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun testNonApplicableAmbiguity() {
|
||||||
|
GenericClassCantBeReplaced.staticFun1(JFunction0 { "" })
|
||||||
|
GenericClassCantBeReplaced.staticFun2(JFunction0 { "" }, JFunction0 { "" })
|
||||||
|
|
||||||
|
val klass = GenericClassCantBeReplaced()
|
||||||
|
klass.memberFun1(JFunction0 { "" })
|
||||||
|
klass.memberFun2(JFunction0 { "" }, JFunction0 { "" })
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
MyJavaClass.foo1(Runnable { }, 1)
|
||||||
|
MyJavaClass.foo1(Runnable { }, Runnable { })
|
||||||
|
MyJavaClass.foo2(1, Runnable { })
|
||||||
|
MyJavaClass.foo2(Runnable { }, Runnable { })
|
||||||
|
|
||||||
|
A<String>().foo(JFunction1<String> {})
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val runnable = Runnable { }
|
||||||
|
val klass = MyJavaClass()
|
||||||
|
|
||||||
|
MyJavaClass.staticFun1(Runnable { })
|
||||||
|
MyJavaClass.staticFun1(runnable)
|
||||||
|
MyJavaClass.staticFun2(Runnable { }, Runnable { })
|
||||||
|
MyJavaClass.staticFun2(runnable, Runnable { })
|
||||||
|
MyJavaClass.staticFun2({ }, { })
|
||||||
|
MyJavaClass.staticFun2(
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
},
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
})
|
||||||
|
|
||||||
|
MyJavaClass.staticFunWithOtherParam(1, Runnable { })
|
||||||
|
MyJavaClass.staticFunWithOtherParam(1, runnable)
|
||||||
|
|
||||||
|
klass.memberFun1(Runnable { })
|
||||||
|
klass.memberFun1(runnable)
|
||||||
|
klass.memberFun2(Runnable { }, Runnable { })
|
||||||
|
klass.memberFun2(runnable, Runnable { })
|
||||||
|
klass.memberFun2({ }, { })
|
||||||
|
klass.memberFun2(
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
},
|
||||||
|
object: Runnable {
|
||||||
|
override fun run() { }
|
||||||
|
})
|
||||||
|
|
||||||
|
klass.memberFunWithOtherParam(1, Runnable { })
|
||||||
|
klass.memberFunWithOtherParam(1, runnable)
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun testGenerics() {
|
||||||
|
val runnable = JFunction1<String> { }
|
||||||
|
val klass = GenericClass1()
|
||||||
|
|
||||||
|
GenericClass1.staticFun1(JFunction1<String> { })
|
||||||
|
GenericClass1.staticFun1(runnable)
|
||||||
|
GenericClass1.staticFun2(JFunction1<String> { }, JFunction1<String> { })
|
||||||
|
GenericClass1.staticFun2(runnable, JFunction1<String> { })
|
||||||
|
GenericClass1.staticFun2({ s: String -> }, { s: String -> })
|
||||||
|
|
||||||
|
GenericClass1.staticFunWithOtherParam(1, JFunction1<String> { })
|
||||||
|
GenericClass1.staticFunWithOtherParam(1, runnable)
|
||||||
|
|
||||||
|
klass.memberFun1(JFunction1<String> { })
|
||||||
|
klass.memberFun1(runnable)
|
||||||
|
klass.memberFun2(JFunction1<String> { }, JFunction1<String> { })
|
||||||
|
klass.memberFun2(runnable, JFunction1<String> { })
|
||||||
|
klass.memberFun2({ s: String -> }, { s: String -> })
|
||||||
|
|
||||||
|
klass.memberFunWithOtherParam(1, JFunction1<String> { })
|
||||||
|
klass.memberFunWithOtherParam(1, runnable)
|
||||||
|
}
|
||||||
idea/testData/inspections/redundantSamConstructor/redundantSamConstructorWithGenericsInReturnType.kt
Vendored
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package redundantSamConstructor
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun testGenericsReturnType() {
|
||||||
|
val runnable = JFunction0 { "" }
|
||||||
|
val klass = GenericClass2()
|
||||||
|
|
||||||
|
GenericClass2.staticFun1(JFunction0 { "" })
|
||||||
|
GenericClass2.staticFun1(runnable)
|
||||||
|
GenericClass2.staticFun2(JFunction0 { "" }, JFunction0 { "" })
|
||||||
|
GenericClass2.staticFun2(runnable, JFunction0 { "" })
|
||||||
|
GenericClass2.staticFun2({ -> "" }, { -> "" })
|
||||||
|
|
||||||
|
GenericClass2.staticFunWithOtherParam(1, JFunction0 { "" })
|
||||||
|
GenericClass2.staticFunWithOtherParam(1, runnable)
|
||||||
|
|
||||||
|
klass.memberFun1(JFunction0 { "" })
|
||||||
|
klass.memberFun1(runnable)
|
||||||
|
klass.memberFun2(JFunction0 { "" }, JFunction0 { "" })
|
||||||
|
klass.memberFun2(runnable, JFunction0 { "" })
|
||||||
|
klass.memberFun2({ -> "" }, { -> "" })
|
||||||
|
|
||||||
|
klass.memberFunWithOtherParam(1, JFunction0 { "" })
|
||||||
|
klass.memberFunWithOtherParam(1, runnable)
|
||||||
|
}
|
||||||
@@ -22,7 +22,9 @@ import com.intellij.codeInspection.LocalInspectionTool
|
|||||||
import com.intellij.codeInspection.ex.EntryPointsManagerBase
|
import com.intellij.codeInspection.ex.EntryPointsManagerBase
|
||||||
import com.intellij.codeInspection.ex.InspectionManagerEx
|
import com.intellij.codeInspection.ex.InspectionManagerEx
|
||||||
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
|
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
|
||||||
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.testFramework.IdeaTestUtil
|
import com.intellij.testFramework.IdeaTestUtil
|
||||||
import com.intellij.testFramework.InspectionTestUtil
|
import com.intellij.testFramework.InspectionTestUtil
|
||||||
import com.intellij.testFramework.LightProjectDescriptor
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
@@ -31,10 +33,12 @@ import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
|||||||
import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.JetLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.JetLightProjectDescriptor
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.JetTestUtils
|
import org.jetbrains.kotlin.test.JetTestUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
public abstract class AbstractJetInspectionTest: JetLightCodeInsightFixtureTestCase() {
|
public abstract class AbstractJetInspectionTest: JetLightCodeInsightFixtureTestCase() {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -66,6 +70,7 @@ public abstract class AbstractJetInspectionTest: JetLightCodeInsightFixtureTestC
|
|||||||
with(myFixture) {
|
with(myFixture) {
|
||||||
setTestDataPath("${JetTestUtils.getHomeDirectory()}/$srcDir")
|
setTestDataPath("${JetTestUtils.getHomeDirectory()}/$srcDir")
|
||||||
|
|
||||||
|
val afterFiles = srcDir.listFiles { it.name == "inspectionData" }?.single()?.listFiles { it.extension == "after" } ?: emptyArray()
|
||||||
val psiFiles = srcDir.walkTopDown().filter { it.name != "inspectionData" }.map {
|
val psiFiles = srcDir.walkTopDown().filter { it.name != "inspectionData" }.map {
|
||||||
file ->
|
file ->
|
||||||
if (file.isDirectory) {
|
if (file.isDirectory) {
|
||||||
@@ -115,6 +120,23 @@ public abstract class AbstractJetInspectionTest: JetLightCodeInsightFixtureTestC
|
|||||||
|
|
||||||
InspectionTestUtil.runTool(toolWrapper, scope, globalContext)
|
InspectionTestUtil.runTool(toolWrapper, scope, globalContext)
|
||||||
InspectionTestUtil.compareToolResults(globalContext, toolWrapper, false, inspectionsTestDir.getPath())
|
InspectionTestUtil.compareToolResults(globalContext, toolWrapper, false, inspectionsTestDir.getPath())
|
||||||
|
|
||||||
|
if (afterFiles.isNotEmpty()) {
|
||||||
|
globalContext.getPresentation(toolWrapper).problemDescriptors.forEach {
|
||||||
|
problem ->
|
||||||
|
problem.fixes?.forEach {
|
||||||
|
CommandProcessor.getInstance().executeCommand(project, {
|
||||||
|
runWriteAction { it.applyFix(project, problem) }
|
||||||
|
}, it.name, it.familyName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (filePath in afterFiles) {
|
||||||
|
val kotlinFile = psiFiles.first { filePath.name == it.name + ".after" }
|
||||||
|
JetTestUtils.assertEqualsToFile(filePath, kotlinFile.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (isWithRuntime) {
|
if (isWithRuntime) {
|
||||||
|
|||||||
@@ -88,6 +88,12 @@ public class JetInspectionTestGenerated extends AbstractJetInspectionTest {
|
|||||||
JetTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/inspections"), Pattern.compile("^(inspections\\.test)$"));
|
JetTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/inspections"), Pattern.compile("^(inspections\\.test)$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("redundantSamConstructor/inspectionData/inspections.test")
|
||||||
|
public void testRedundantSamConstructor_inspectionData_Inspections_test() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/redundantSamConstructor/inspectionData/inspections.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("spelling/inspectionData/inspections.test")
|
@TestMetadata("spelling/inspectionData/inspections.test")
|
||||||
public void testSpelling_inspectionData_Inspections_test() throws Exception {
|
public void testSpelling_inspectionData_Inspections_test() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/spelling/inspectionData/inspections.test");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/spelling/inspectionData/inspections.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user