Extract Function: Approximate non-resolvable types with nearest resolvable supertype when possible

#KT-7120 Fixed
This commit is contained in:
Alexey Sedunov
2015-03-27 13:42:43 +03:00
parent a90d020859
commit eb594a2897
22 changed files with 224 additions and 86 deletions
@@ -20,15 +20,12 @@ import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.JetClassBody;
import org.jetbrains.kotlin.psi.JetClassOrObject;
import org.jetbrains.kotlin.psi.JetExpression;
import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.TraceBasedRedeclarationHandler;
@@ -158,12 +155,12 @@ public final class JetScopeUtils {
}
@Nullable
public static JetScope getResolutionScope(@NotNull JetExpression expression, @NotNull AnalysisResult analysisResult) {
PsiElement parent = expression.getParent();
public static JetScope getResolutionScope(@NotNull PsiElement element, @NotNull BindingContext context) {
PsiElement parent = element.getParent();
if (parent instanceof JetClassBody) {
JetClassOrObject classOrObject = (JetClassOrObject) parent.getParent();
ClassDescriptor classDescriptor = analysisResult.getBindingContext().get(BindingContext.CLASS, classOrObject);
ClassDescriptor classDescriptor = context.get(BindingContext.CLASS, classOrObject);
if (classDescriptor instanceof ClassDescriptorWithResolutionScopes) {
return ((ClassDescriptorWithResolutionScopes) classDescriptor).getScopeForMemberDeclarationResolution();
}
@@ -171,10 +168,14 @@ public final class JetScopeUtils {
}
if (parent instanceof JetFile) {
PackageViewDescriptor packageView = analysisResult.getModuleDescriptor().getPackage(((JetFile) parent).getPackageFqName());
PackageFragmentDescriptor packageFragment = context.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, (JetFile) parent);
if (packageFragment == null) return null;
PackageViewDescriptor packageView = packageFragment.getContainingDeclaration().getPackage(((JetFile) parent).getPackageFqName());
return packageView != null ? packageView.getMemberScope() : null;
}
return analysisResult.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression);
JetExpression expression = PsiTreeUtil.getParentOfType(element, JetExpression.class, false);
return expression != null ? context.get(BindingContext.RESOLUTION_SCOPE, expression) : null;
}
}
@@ -20,7 +20,10 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.CollectionClassMapping
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.resolve.scopes.JetScope
import java.util.LinkedHashSet
import org.jetbrains.kotlin.types.typeUtil.substitute
@@ -87,3 +90,19 @@ public fun JetType.nullability(): TypeNullability {
else -> TypeNullability.NOT_NULL
}
}
fun JetType.isResolvableInScope(scope: JetScope?, checkTypeParameters: Boolean): Boolean {
if (canBeReferencedViaImport()) return true
val descriptor = getConstructor().getDeclarationDescriptor()
if (descriptor == null || descriptor.getName().isSpecial()) return false
if (!checkTypeParameters && descriptor is TypeParameterDescriptor) return true
return scope != null && scope.getClassifier(descriptor.getName()) == descriptor
}
public fun JetType.approximateWithResolvableType(scope: JetScope?, checkTypeParameters: Boolean): JetType {
if (isError() || isResolvableInScope(scope, checkTypeParameters)) return this
return supertypes().firstOrNull { it.isResolvableInScope(scope, checkTypeParameters) }
?: KotlinBuiltIns.getInstance().getAnyType()
}
@@ -20,21 +20,15 @@ import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters1;
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters2;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.imports.ImportsPackage;
import org.jetbrains.kotlin.idea.util.UtilPackage;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -44,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils;
import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.kotlin.types.TypeUtils;
import java.util.Collections;
import java.util.LinkedList;
@@ -54,36 +47,12 @@ import java.util.List;
public class QuickFixFactoryForTypeMismatchError extends JetIntentionActionsFactory {
private final static Logger LOG = Logger.getInstance(QuickFixFactoryForTypeMismatchError.class);
private static boolean isResolvableType(@NotNull JetType type, @Nullable JetScope scope) {
if (ImportsPackage.canBeReferencedViaImport(type)) return true;
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (descriptor == null || descriptor.getName().isSpecial()) return false;
return scope != null && scope.getClassifier(descriptor.getName()) == descriptor;
}
private static JetType approximateWithResolvableType(@NotNull JetType type, @Nullable final JetScope scope) {
if (isResolvableType(type, scope)) return type;
JetType superType = KotlinPackage.firstOrNull(
TypeUtils.getAllSupertypes(type),
new Function1<JetType, Boolean>() {
@Override
public Boolean invoke(JetType type) {
return isResolvableType(type, scope);
}
}
);
return superType != null ? superType : KotlinBuiltIns.getInstance().getAnyType();
}
@NotNull
@Override
protected List<IntentionAction> doCreateActions(@NotNull Diagnostic diagnostic) {
List<IntentionAction> actions = new LinkedList<IntentionAction>();
AnalysisResult analysisResult = ResolvePackage.analyzeFullyAndGetResult((JetFile) diagnostic.getPsiFile());
BindingContext context = analysisResult.getBindingContext();
BindingContext context = ResolvePackage.analyzeFully((JetFile) diagnostic.getPsiFile());
PsiElement diagnosticElement = diagnostic.getPsiElement();
if (!(diagnosticElement instanceof JetExpression)) {
@@ -133,8 +102,8 @@ public class QuickFixFactoryForTypeMismatchError extends JetIntentionActionsFact
JetExpression initializer = property.getInitializer();
if (QuickFixUtil.canEvaluateTo(initializer, expression) ||
(getter != null && QuickFixUtil.canFunctionOrGetterReturnExpression(property.getGetter(), expression))) {
JetScope scope = JetScopeUtils.getResolutionScope(property, analysisResult);
JetType typeToInsert = approximateWithResolvableType(expressionType, scope);
JetScope scope = JetScopeUtils.getResolutionScope(property, context);
JetType typeToInsert = UtilPackage.approximateWithResolvableType(expressionType, scope, false);
actions.add(new ChangeVariableTypeFix(property, typeToInsert));
}
}
@@ -147,8 +116,8 @@ public class QuickFixFactoryForTypeMismatchError extends JetIntentionActionsFact
? BindingContextUtilPackage.getTargetFunction((JetReturnExpression) expressionParent, context)
: PsiTreeUtil.getParentOfType(expression, JetFunction.class, true);
if (function instanceof JetFunction && QuickFixUtil.canFunctionOrGetterReturnExpression(function, expression)) {
JetScope scope = JetScopeUtils.getResolutionScope(function, analysisResult);
JetType typeToInsert = approximateWithResolvableType(expressionType, scope);
JetScope scope = JetScopeUtils.getResolutionScope(function, context);
JetType typeToInsert = UtilPackage.approximateWithResolvableType(expressionType, scope, false);
actions.add(new ChangeFunctionReturnTypeFix((JetFunction) function, typeToInsert));
}
@@ -187,8 +156,8 @@ public class QuickFixFactoryForTypeMismatchError extends JetIntentionActionsFact
? expressionType
: context.get(BindingContext.EXPRESSION_TYPE, valueArgument.getArgumentExpression());
if (correspondingParameter != null && valueArgumentType != null) {
JetScope scope = JetScopeUtils.getResolutionScope(valueArgument.getArgumentExpression(), analysisResult);
JetType typeToInsert = approximateWithResolvableType(valueArgumentType, scope);
JetScope scope = JetScopeUtils.getResolutionScope(valueArgument.getArgumentExpression(), context);
JetType typeToInsert = UtilPackage.approximateWithResolvableType(valueArgumentType, scope, true);
actions.add(new ChangeParameterTypeFix(correspondingParameter, typeToInsert));
}
}
@@ -19,14 +19,11 @@ package org.jetbrains.kotlin.idea.refactoring;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.JetElement;
import org.jetbrains.kotlin.psi.JetExpression;
import org.jetbrains.kotlin.psi.JetVisitorVoid;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils;
@@ -76,7 +73,7 @@ public class JetNameValidatorImpl extends JetNameValidator {
private boolean checkElement(String name, PsiElement sibling, final Set<JetScope> visitedScopes) {
if (!(sibling instanceof JetElement)) return true;
final AnalysisResult analysisResult = ResolvePackage.analyzeAndGetResult((JetElement) sibling);
final BindingContext context = ResolvePackage.analyze((JetElement) sibling);
final Name identifier = Name.identifier(name);
final Ref<Boolean> result = new Ref<Boolean>(true);
@@ -90,7 +87,7 @@ public class JetNameValidatorImpl extends JetNameValidator {
@Override
public void visitExpression(@NotNull JetExpression expression) {
JetScope resolutionScope = JetScopeUtils.getResolutionScope(expression, analysisResult);
JetScope resolutionScope = JetScopeUtils.getResolutionScope(expression, context);
if (resolutionScope != null) {
if (!visitedScopes.add(resolutionScope)) return;
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.imports.importableFqNameSafe
import org.jetbrains.kotlin.idea.refactoring.*
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage
@@ -52,6 +51,8 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputVa
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.ParameterUpdate
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValueBoxer.AsList
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
import org.jetbrains.kotlin.idea.util.isResolvableInScope
import org.jetbrains.kotlin.idea.util.makeNullable
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
@@ -63,6 +64,8 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver
import org.jetbrains.kotlin.types.*
@@ -127,7 +130,9 @@ private fun List<Instruction>.getExitPoints(): List<Instruction> =
private fun List<Instruction>.getResultTypeAndExpressions(
bindingContext: BindingContext,
options: ExtractionOptions): Pair<JetType, List<JetExpression>> {
targetScope: JetScope?,
options: ExtractionOptions
): Pair<JetType, List<JetExpression>> {
fun instructionToExpression(instruction: Instruction, unwrapReturn: Boolean): JetExpression? {
return when (instruction) {
is ReturnValueInstruction ->
@@ -148,7 +153,9 @@ private fun List<Instruction>.getResultTypeAndExpressions(
}
val resultTypes = map(::instructionToType).filterNotNull()
val resultType = if (resultTypes.isNotEmpty()) CommonSupertypes.commonSupertype(resultTypes) else DEFAULT_RETURN_TYPE
var commonSupertype = if (resultTypes.isNotEmpty()) CommonSupertypes.commonSupertype(resultTypes) else DEFAULT_RETURN_TYPE
val resultType = if (options.allowSpecialClassNames) commonSupertype else commonSupertype.approximateWithResolvableType(targetScope, false)
val expressions = map { instructionToExpression(it, false) }.filterNotNull()
return resultType to expressions
@@ -217,6 +224,7 @@ private fun ExtractionData.analyzeControlFlow(
bindingContext: BindingContext,
modifiedVarDescriptors: Map<VariableDescriptor, List<JetExpression>>,
options: ExtractionOptions,
targetScope: JetScope?,
parameters: Set<Parameter>
): Pair<ControlFlow, ErrorMessage?> {
val exitPoints = localInstructions.getExitPoints()
@@ -269,8 +277,8 @@ private fun ExtractionData.analyzeControlFlow(
val nonLocallyUsedDeclarations = getLocalDeclarationsWithNonLocalUsages(pseudocode, localInstructions, bindingContext)
val (declarationsToCopy, declarationsToReport) = nonLocallyUsedDeclarations.partition { it is JetProperty && it.isLocal() }
val (typeOfDefaultFlow, defaultResultExpressions) = defaultExits.getResultTypeAndExpressions(bindingContext, options)
val (returnValueType, valuedReturnExpressions) = valuedReturnExits.getResultTypeAndExpressions(bindingContext, options)
val (typeOfDefaultFlow, defaultResultExpressions) = defaultExits.getResultTypeAndExpressions(bindingContext, targetScope, options)
val (returnValueType, valuedReturnExpressions) = valuedReturnExits.getResultTypeAndExpressions(bindingContext, targetScope, options)
val emptyControlFlow =
ControlFlow(Collections.emptyList(), { OutputValueBoxer.AsTuple(it, module) }, declarationsToCopy)
@@ -421,14 +429,14 @@ fun TypeParameter.collectReferencedTypes(bindingContext: BindingContext): List<J
.filterNotNull()
}
private fun JetType.isExtractable(): Boolean {
private fun JetType.isExtractable(targetScope: JetScope?): Boolean {
return collectReferencedTypes(true).fold(true) { (extractable, typeToCheck) ->
val parameterTypeDescriptor = typeToCheck.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor
val typeParameter = parameterTypeDescriptor?.let {
DescriptorToSourceUtils.descriptorToDeclaration(it)
} as? JetTypeParameter
extractable && (typeParameter != null || typeToCheck.canBeReferencedViaImport())
extractable && (typeParameter != null || typeToCheck.isResolvableInScope(targetScope, false))
}
}
@@ -436,6 +444,7 @@ private fun JetType.processTypeIfExtractable(
typeParameters: MutableSet<TypeParameter>,
nonDenotableTypes: MutableSet<JetType>,
options: ExtractionOptions,
targetScope: JetScope?,
processTypeArguments: Boolean = true
): Boolean {
return collectReferencedTypes(processTypeArguments).fold(true) { (extractable, typeToCheck) ->
@@ -450,7 +459,7 @@ private fun JetType.processTypeIfExtractable(
extractable
}
typeToCheck.canBeReferencedViaImport() ->
typeToCheck.isResolvableInScope(targetScope, false) ->
extractable
options.allowSpecialClassNames && typeToCheck.isSpecial() ->
@@ -470,7 +479,8 @@ private fun JetType.processTypeIfExtractable(
private class MutableParameter(
override val argumentText: String,
override val originalDescriptor: DeclarationDescriptor,
override val receiverCandidate: Boolean
override val receiverCandidate: Boolean,
private val targetScope: JetScope?
): Parameter {
// All modifications happen in the same thread
private var writable: Boolean = true
@@ -525,7 +535,7 @@ private class MutableParameter(
override fun getParameterTypeCandidates(allowSpecialClassNames: Boolean): List<JetType> {
return if (!allowSpecialClassNames) {
parameterTypeCandidates.filter { it.isExtractable() }
parameterTypeCandidates.filter { it.isExtractable(targetScope) }
} else {
parameterTypeCandidates
}
@@ -560,6 +570,7 @@ private fun ExtractionData.inferParametersInfo(
commonParent: PsiElement,
pseudocode: Pseudocode,
bindingContext: BindingContext,
targetScope: JetScope?,
modifiedVarDescriptors: Set<VariableDescriptor>
): ParametersInfo {
val info = ParametersInfo()
@@ -610,7 +621,7 @@ private fun ExtractionData.inferParametersInfo(
if (referencedClassDescriptor != null) {
if (!referencedClassDescriptor.getDefaultType().processTypeIfExtractable(
info.typeParameters, info.nonDenotableTypes, options, false
info.typeParameters, info.nonDenotableTypes, options, targetScope, false
)) continue
info.replacementMap[refInfo.offsetInBody] = FqNameReplacement(originalDescriptor.importableFqNameSafe)
@@ -642,7 +653,7 @@ private fun ExtractionData.inferParametersInfo(
else
(thisExpr ?: ref).getText() ?: throw AssertionError("'this' reference shouldn't be empty: code fragment = $codeFragmentText")
MutableParameter(argumentText, descriptorToExtract, extractThis)
MutableParameter(argumentText, descriptorToExtract, extractThis, targetScope)
}
if (!extractThis) {
@@ -681,7 +692,9 @@ private fun ExtractionData.inferParametersInfo(
)
for ((descriptorToExtract, parameter) in extractedDescriptorToParameter) {
if (!parameter.getParameterType(options.allowSpecialClassNames).processTypeIfExtractable(info.typeParameters, info.nonDenotableTypes, options)) continue
if (!parameter
.getParameterType(options.allowSpecialClassNames)
.processTypeIfExtractable(info.typeParameters, info.nonDenotableTypes, options, targetScope)) continue
with (parameter) {
if (currentName == null) {
@@ -693,7 +706,7 @@ private fun ExtractionData.inferParametersInfo(
}
for (typeToCheck in info.typeParameters.flatMapTo(HashSet<JetType>()) { it.collectReferencedTypes(bindingContext) }) {
typeToCheck.processTypeIfExtractable(info.typeParameters, info.nonDenotableTypes, options)
typeToCheck.processTypeIfExtractable(info.typeParameters, info.nonDenotableTypes, options, targetScope)
}
@@ -765,6 +778,8 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
val bindingContext = commonParent.getContextForContainingDeclarationBody()
if (bindingContext == null) return noContainerError
val targetScope = JetScopeUtils.getResolutionScope(targetSibling, bindingContext)
val pseudocodeDeclaration =
PsiTreeUtil.getParentOfType(commonParent, javaClass<JetDeclarationWithBody>(), javaClass<JetClassOrObject>())
?: commonParent.getNonStrictParentOfType<JetProperty>()
@@ -786,7 +801,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
val modifiedVarDescriptorsWithExpressions = localInstructions.getModifiedVarDescriptors(bindingContext)
val paramsInfo = inferParametersInfo(commonParent, pseudocode, bindingContext, modifiedVarDescriptorsWithExpressions.keySet())
val paramsInfo = inferParametersInfo(commonParent, pseudocode, bindingContext, targetScope, modifiedVarDescriptorsWithExpressions.keySet())
if (paramsInfo.errorMessage != null) {
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(paramsInfo.errorMessage!!))
}
@@ -803,12 +818,13 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
bindingContext,
modifiedVarDescriptorsForControlFlow,
options,
targetScope,
paramsInfo.parameters
)
controlFlowMessage?.let { messages.add(it) }
val returnType = controlFlow.outputValueBoxer.returnType
returnType.processTypeIfExtractable(paramsInfo.typeParameters, paramsInfo.nonDenotableTypes, options)
returnType.processTypeIfExtractable(paramsInfo.typeParameters, paramsInfo.nonDenotableTypes, options, targetScope)
if (paramsInfo.nonDenotableTypes.isNotEmpty()) {
val typeStr = paramsInfo.nonDenotableTypes.map {it.renderForMessage()}.sort()
@@ -3,6 +3,7 @@ LineBreakpoint created at ceObject.kt:5
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
ceObject.kt:5
Compile bytecode for (object: T {}).test()
Compile bytecode for (object: T { fun a() = 1 }).a()
Compile bytecode for object: T {}
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
@@ -12,5 +12,8 @@ trait T {
// EXPRESSION: (object: T {}).test()
// RESULT: 1: I
// EXPRESSION: (object: T { fun a() = 1 }).a()
// RESULT: 1: I
// EXPRESSION: object: T {}
// RESULT: instance of packageForDebugger.PackageForDebuggerPackage$debugFile$@packagePartHASH$myFun$1(id=ID): LpackageForDebugger/PackageForDebuggerPackage$debugFile$@packagePartHASH$myFun$1;
@@ -1 +1 @@
Cannot extract method since following types are not denotable in the target scope: &lt;no name provided&gt;
Following declarations are used outside of selected code fragment: override fun call(): Int
@@ -1,15 +1,5 @@
trait Callable<T> {
fun call(): T
}
trait T
fun foo(a: Int): Int {
// SIBLING:
val o = object: Callable<Int> {
val b: Int = 1
override fun call(): Int {
return <selection>a + b</selection>
}
}
return o.call()
fun foo(): T {
return <selection>object: T() {}</selection>
}
@@ -0,0 +1,7 @@
trait T
fun foo(): T {
return t()
}
private fun t() = object : T() {}
@@ -0,0 +1,15 @@
trait Callable<T> {
fun call(): T
}
fun foo(a: Int): Int {
// SIBLING:
val o = object: Callable<Int> {
val b: Int = 1
override fun call(): Int {
return <selection>a + b</selection>
}
}
return o.call()
}
@@ -0,0 +1,10 @@
trait T
fun foo(): T {
class A: T
// SIBLING:
fun bar(): T {
return <selection>A()</selection>
}
}
@@ -0,0 +1,12 @@
trait T
fun foo(): T {
class A: T
fun a() = A()
// SIBLING:
fun bar(): T {
return a()
}
}
@@ -0,0 +1,13 @@
// PARAM_DESCRIPTOR: val a: foo.A defined in foo.bar
// PARAM_TYPES: T
trait T
// SIBLING:
fun foo(): T {
class A: T
fun bar(): T {
val a = A()
return <selection>a</selection>
}
}
@@ -0,0 +1,15 @@
// PARAM_DESCRIPTOR: val a: foo.A defined in foo.bar
// PARAM_TYPES: T
trait T
// SIBLING:
fun foo(): T {
class A: T
fun bar(): T {
val a = A()
return t(a)
}
}
private fun t(a: T) = a
@@ -0,0 +1,13 @@
// PARAM_DESCRIPTOR: val a: foo.A defined in foo.bar
// PARAM_TYPES: foo.A, T
trait T
fun foo(): T {
class A: T
// SIBLING:
fun bar(): T {
val a = A()
return <selection>a</selection>
}
}
@@ -0,0 +1,15 @@
// PARAM_DESCRIPTOR: val a: foo.A defined in foo.bar
// PARAM_TYPES: foo.A, T
trait T
fun foo(): T {
class A: T
fun a(a: A) = a
// SIBLING:
fun bar(): T {
val a = A()
return a(a)
}
}
@@ -0,0 +1,11 @@
trait T
// SIBLING:
fun foo(): T {
class A: T
fun bar(): A {
val a = A()
return <selection>a</selection>
}
}
@@ -0,0 +1 @@
Cannot extract method since following types are not denotable in the target scope: A
@@ -1897,11 +1897,41 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
doExtractFunctionTest(fileName);
}
@TestMetadata("anonymousObjectWithCall.kt")
public void testAnonymousObjectWithCall() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes/anonymousObjectWithCall.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("localClass.kt")
public void testLocalClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes/localClass.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("localClassWithSuperclass.kt")
public void testLocalClassWithSuperclass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes/localClassWithSuperclass.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("localClassWithSuperclassParameter.kt")
public void testLocalClassWithSuperclassParameter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes/localClassWithSuperclassParameter.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("localClassWithSuperclassParameterInLocalFun.kt")
public void testLocalClassWithSuperclassParameterInLocalFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes/localClassWithSuperclassParameterInLocalFun.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("localClassWithSuperclassParameterNoApproximation.kt")
public void testLocalClassWithSuperclassParameterNoApproximation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes/localClassWithSuperclassParameterNoApproximation.kt");
doExtractFunctionTest(fileName);
}
}
}