diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 6297b116a6a..7e94a59fac5 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -658,6 +658,11 @@ public class KotlinBuiltIns { return getAnnotation().getDefaultType(); } + @NotNull + public ClassDescriptor getPropertyMetadata() { + return getBuiltInClassByName("PropertyMetadata"); + } + @NotNull public ClassDescriptor getPropertyMetadataImpl() { return getBuiltInClassByName("PropertyMetadataImpl"); diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties index 95f42359bcc..1f85637b473 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -184,7 +184,7 @@ map.platform.class.to.kotlin.multiple=Change all usages of ''{0}'' in this file map.platform.class.to.kotlin.advertisement=Choose an appropriate Kotlin class map.platform.class.to.kotlin.family=Change to Kotlin class create.from.usage.family=Create from usage -create.function.from.usage=Create function ''{0}'' from usage +create.0.from.usage=Create {0} from usage create.property.from.usage=Create property ''{0}'' from usage create.local.variable.from.usage=Create local variable ''{0}'' create.parameter.from.usage=Create parameter ''{0}'' diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixRegistrar.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixRegistrar.java index 2c5a2da3d08..2709f077fe1 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixRegistrar.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixRegistrar.java @@ -264,5 +264,8 @@ public class QuickFixRegistrar { QuickFixes.factories.put(NEXT_NONE_APPLICABLE, CreateNextFunctionActionFactory.INSTANCE$); QuickFixes.factories.put(ITERATOR_MISSING, CreateIteratorFunctionActionFactory.INSTANCE$); QuickFixes.factories.put(COMPONENT_FUNCTION_MISSING, CreateComponentFunctionActionFactory.INSTANCE$); + + QuickFixes.factories.put(DELEGATE_SPECIAL_FUNCTION_MISSING, CreatePropertyDelegateAccessorsActionFactory.INSTANCE$); + QuickFixes.factories.put(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, CreatePropertyDelegateAccessorsActionFactory.INSTANCE$); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt index 00f9f33cada..46a9a1ac01a 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt @@ -101,7 +101,7 @@ fun List.getTypeByRenderedType(renderedType: String): JetType? = firstOrNull { it.renderedType == renderedType }?.theType class CallableBuilderConfiguration( - val callableInfo: CallableInfo, + val callableInfos: List, val originalExpression: JetExpression, val currentFile: JetFile, val currentEditor: Editor @@ -128,6 +128,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { public var placement: CallablePlacement by Delegates.notNull() + private val elementsToShorten = ArrayList() + fun computeTypeCandidates(typeInfo: TypeInfo): List = typeCandidates.getOrPut(typeInfo) { typeInfo.getPossibleTypes(this).map { TypeCandidate(it) } } @@ -165,19 +167,27 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { } } + private fun buildNext(iterator: Iterator) { + if (iterator.hasNext()) { + val context = Context(iterator.next()) + runWriteAction { context.buildAndRunTemplate { buildNext(iterator) } } + } + else { + ShortenReferences.process(elementsToShorten) + } + } + fun build() { try { if (finished) throw IllegalStateException("Current builder has already finished") - - val context = Context() - runWriteAction { context.buildAndRunTemplate() } + buildNext(config.callableInfos.iterator()) } finally { finished = true } } - private inner class Context { + private inner class Context(val callableInfo: CallableInfo) { val skipReturnType: Boolean val isExtension: Boolean val containingFile: JetFile @@ -231,12 +241,13 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { val substitutions = ownerTypeArguments.zip(classTypeParameters).map { JetTypeSubstitution(it.first.getType(), it.second.getType()) }.copyToArray() - config.callableInfo.parameterInfos.forEach { + + callableInfo.parameterInfos.forEach { computeTypeCandidates(it.typeInfo, substitutions, scope) } - val returnTypeCandidates = computeTypeCandidates(config.callableInfo.returnTypeInfo, substitutions, scope) - skipReturnType = config.callableInfo is FunctionInfo + val returnTypeCandidates = computeTypeCandidates(callableInfo.returnTypeInfo, substitutions, scope) + skipReturnType = callableInfo is FunctionInfo && returnTypeCandidates.size == 1 && returnTypeCandidates.first().theType.isUnit() @@ -245,9 +256,9 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { // figure out type parameter renames to avoid conflicts typeParameterNameMap = getTypeParameterRenames(scope) - config.callableInfo.parameterInfos.forEach { renderTypeCandidates(it.typeInfo, typeParameterNameMap) } + callableInfo.parameterInfos.forEach { renderTypeCandidates(it.typeInfo, typeParameterNameMap) } if (!skipReturnType) { - renderTypeCandidates(config.callableInfo.returnTypeInfo, typeParameterNameMap) + renderTypeCandidates(callableInfo.returnTypeInfo, typeParameterNameMap) } receiverTypeCandidate?.render(typeParameterNameMap) } @@ -262,7 +273,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { private fun createDeclarationSkeleton(): JetCallableDeclaration { with (config) { val assignmentToReplace = - if (containingElement is JetBlockExpression && (config.callableInfo as? PropertyInfo)?.writable ?: false) { + if (containingElement is JetBlockExpression && (callableInfo as? PropertyInfo)?.writable ?: false) { originalExpression as JetBinaryExpression } else null @@ -367,13 +378,13 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { allTypeParametersNotInScope.addAll(receiverTypeCandidate?.typeParameters?.toList() ?: Collections.emptyList()) - config.callableInfo.parameterInfos.stream() + callableInfo.parameterInfos.stream() .flatMap { typeCandidates[it.typeInfo]!!.stream() } .flatMap { it.typeParameters.stream() } .toCollection(allTypeParametersNotInScope) if (!skipReturnType) { - computeTypeCandidates(config.callableInfo.returnTypeInfo).stream().flatMapTo(allTypeParametersNotInScope) { it.typeParameters.stream() } + computeTypeCandidates(callableInfo.returnTypeInfo).stream().flatMapTo(allTypeParametersNotInScope) { it.typeParameters.stream() } } val validator = CollectingValidator { scope.getClassifier(Name.identifier(it)) == null } @@ -383,7 +394,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { } private fun setupTypeReferencesForShortening(declaration: JetCallableDeclaration, - typeRefsToShorten: MutableList, + typeRefsToShorten: MutableList, parameterTypeExpressions: List) { if (isExtension) { val receiverTypeRef = JetPsiFactory(declaration).createType(receiverTypeCandidate!!.theType.renderLong(typeParameterNameMap)) @@ -397,7 +408,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { val returnTypeRef = declaration.getTypeReference() if (returnTypeRef != null) { - val returnType = typeCandidates[config.callableInfo.returnTypeInfo]!!.getTypeByRenderedType( + val returnType = typeCandidates[callableInfo.returnTypeInfo]!!.getTypeByRenderedType( returnTypeRef.getText() ?: throw AssertionError("Expression for return type shouldn't be empty: declaration = ${declaration.getText()}") ) @@ -440,7 +451,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFqName(it).asString()) properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, it.getName().asString()) } - properties.setProperty(ATTRIBUTE_FUNCTION_NAME, config.callableInfo.name) + properties.setProperty(ATTRIBUTE_FUNCTION_NAME, callableInfo.name) val bodyText = try { fileTemplate!!.getText(properties) @@ -460,7 +471,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { private fun setupReturnTypeTemplate(builder: TemplateBuilder, declaration: JetCallableDeclaration): TypeExpression? { val returnTypeRef = declaration.getTypeReference() ?: return null - val candidates = typeCandidates[config.callableInfo.returnTypeInfo]!! + val candidates = typeCandidates[callableInfo.returnTypeInfo]!! return when (candidates.size) { 0 -> null @@ -478,7 +489,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { } private fun setupValVarTemplate(builder: TemplateBuilder, property: JetProperty) { - if (!(config.callableInfo as PropertyInfo).writable) { + if (!(callableInfo as PropertyInfo).writable) { builder.replaceElement(property.getValOrVarNode().getPsi()!!, ValVarExpression) } } @@ -487,12 +498,12 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { val typeParameterMap = HashMap>() val receiverTypeParameterNames = receiverTypeCandidate?.let { it.typeParameterNames!! } ?: ArrayUtil.EMPTY_STRING_ARRAY - config.callableInfo.parameterInfos.stream().flatMap { typeCandidates[it.typeInfo]!!.stream() }.forEach { + callableInfo.parameterInfos.stream().flatMap { typeCandidates[it.typeInfo]!!.stream() }.forEach { typeParameterMap[it.renderedType!!] = it.typeParameterNames!! } if (declaration.getTypeReference() != null) { - typeCandidates[config.callableInfo.returnTypeInfo]!!.forEach { + typeCandidates[callableInfo.returnTypeInfo]!!.forEach { typeParameterMap[it.renderedType!!] = it.typeParameterNames!! } } @@ -502,10 +513,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { } private fun setupParameterTypeTemplates(builder: TemplateBuilder, parameterList: List): List { - assert(parameterList.size == config.callableInfo.parameterInfos.size) + assert(parameterList.size == callableInfo.parameterInfos.size) val typeParameters = ArrayList() - for ((parameter, jetParameter) in config.callableInfo.parameterInfos.zip(parameterList)) { + for ((parameter, jetParameter) in callableInfo.parameterInfos.zip(parameterList)) { val parameterTypeExpression = TypeExpression(typeCandidates[parameter.typeInfo]!!) val parameterTypeRef = jetParameter.getTypeReference()!! builder.replaceElement(parameterTypeRef, parameterTypeExpression) @@ -542,7 +553,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { typeRef.replace(fullyQualifiedReceiverTypeRef) } - fun buildAndRunTemplate() { + // build templates + fun buildAndRunTemplate(onFinish: () -> Unit) { val declarationSkeleton = createDeclarationSkeleton() val project = declarationSkeleton.getProject() val declarationPointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(declarationSkeleton) @@ -576,7 +588,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it val templateImpl = builder.buildInlineTemplate() as TemplateImpl val variables = templateImpl.getVariables()!! - for (i in 0..(config.callableInfo.parameterInfos.size - 1)) { + for (i in 0..(callableInfo.parameterInfos.size - 1)) { Collections.swap(variables, i * 2, i * 2 + 1) } @@ -596,7 +608,6 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { val newDeclaration = PsiTreeUtil.findElementOfClassAtOffset( containingFile, offset, javaClass(), false )!! - val typeRefsToShorten = ArrayList() ApplicationManager.getApplication()!!.runWriteAction { // file templates @@ -605,9 +616,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { } // change short type names to fully qualified ones (to be shortened below) - setupTypeReferencesForShortening(newDeclaration, typeRefsToShorten, parameterTypeExpressions) - ShortenReferences.process(typeRefsToShorten) + setupTypeReferencesForShortening(newDeclaration, elementsToShorten, parameterTypeExpressions) } + + onFinish() } }) } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt index b44c7b0d318..1cd49e4f456 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt @@ -10,24 +10,42 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil import org.jetbrains.jet.lang.psi.JetClassOrObject import org.jetbrains.jet.plugin.refactoring.chooseContainerElementIfNecessary -import org.jetbrains.jet.plugin.refactoring.getExtractionContainers import org.jetbrains.jet.lang.psi.JetClassBody import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.* import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList public class CreateCallableFromUsageFix( originalExpression: JetExpression, - val callableInfo: CallableInfo) : CreateFromUsageFixBase(originalExpression) { - override fun getText(): String { - val key = when (callableInfo.kind) { - CallableKind.FUNCTION -> "create.function.from.usage" - CallableKind.PROPERTY -> "create.property.from.usage" + val callableInfos: List) : CreateFromUsageFixBase(originalExpression) { + { + if (callableInfos.size > 1) { + val callableInfo = callableInfos.first() + + val receiver = callableInfo.receiverTypeInfo + if (!callableInfos.all { it.receiverTypeInfo == receiver }) throw AssertionError("All functions must have common receiver") + + val containers = callableInfo.possibleContainers + if (!callableInfos.all { it.possibleContainers == containers }) throw AssertionError("All functions must have common containers") } - return JetBundle.message(key, callableInfo.name) + } + + override fun getText(): String { + val renderedCallables = callableInfos.map { + val kind = when (it.kind) { + CallableKind.FUNCTION -> "function" + CallableKind.PROPERTY -> "property" + } + "$kind '${it.name}'" + } + + return JetBundle.message("create.0.from.usage", renderedCallables.joinToString()) } override fun invoke(project: Project, editor: Editor?, file: JetFile?) { - val callableBuilder = CallableBuilderConfiguration(callableInfo, element as JetExpression, file!!, editor!!).createBuilder() + val callableInfo = callableInfos.firstOrNull() ?: return + + val callableBuilder = CallableBuilderConfiguration(callableInfos, element as JetExpression, file!!, editor!!).createBuilder() fun runBuilder(placement: CallablePlacement) { callableBuilder.placement = placement @@ -59,3 +77,10 @@ public class CreateCallableFromUsageFix( } } } + +public fun CreateCallableFromUsageFix( + originalExpression: JetExpression, + callableInfo: CallableInfo +) : CreateCallableFromUsageFix { + return CreateCallableFromUsageFix(originalExpression, callableInfo.singletonOrEmptyList()) +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreatePropertyDelegateAccessorsActionFactory.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreatePropertyDelegateAccessorsActionFactory.kt new file mode 100644 index 00000000000..39c593e2603 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreatePropertyDelegateAccessorsActionFactory.kt @@ -0,0 +1,68 @@ +package org.jetbrains.jet.plugin.quickfix.createFromUsage.createFunction + +import org.jetbrains.jet.plugin.quickfix.JetSingleIntentionActionFactory +import org.jetbrains.jet.lang.diagnostics.Diagnostic +import com.intellij.codeInsight.intention.IntentionAction +import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.TypeInfo +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.ParameterInfo +import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.FunctionInfo +import org.jetbrains.jet.lang.psi.JetProperty +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache +import org.jetbrains.jet.lang.resolve.BindingContext +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor +import org.jetbrains.jet.lang.psi.psiUtil.getParentByType +import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.CallableInfo +import com.intellij.util.SmartList +import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor + +object CreatePropertyDelegateAccessorsActionFactory : JetSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val expression = diagnostic.getPsiElement() as? JetExpression ?: return null + val context = AnalyzerFacadeWithCache.getContextForElement(expression) + [suppress("UNCHECKED_CAST")] + + fun isApplicableForAccessor(accessor: PropertyAccessorDescriptor?): Boolean = + accessor != null && context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor] == null + + val builtIns = KotlinBuiltIns.getInstance() + + val property = expression.getParentByType(javaClass()) ?: return null + val propertyDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? PropertyDescriptor + ?: return null + + val propertyReceiver = propertyDescriptor.getExtensionReceiverParameter() ?: propertyDescriptor.getDispatchReceiverParameter() + val propertyType = propertyDescriptor.getType() + + val accessorReceiverType = TypeInfo(expression, Variance.IN_VARIANCE) + val thisRefParam = ParameterInfo(TypeInfo(propertyReceiver?.getType() ?: builtIns.getNullableNothingType(), Variance.IN_VARIANCE)) + val metadataParam = ParameterInfo(TypeInfo(builtIns.getPropertyMetadata().getDefaultType(), Variance.IN_VARIANCE)) + + val callableInfos = SmartList() + + if (isApplicableForAccessor(propertyDescriptor.getGetter())) { + val getterInfo = FunctionInfo( + name = "get", + receiverTypeInfo = accessorReceiverType, + returnTypeInfo = TypeInfo(propertyType, Variance.OUT_VARIANCE), + parameterInfos = listOf(thisRefParam, metadataParam) + ) + callableInfos.add(getterInfo) + } + + if (propertyDescriptor.isVar() && isApplicableForAccessor(propertyDescriptor.getSetter())) { + val newValueParam = ParameterInfo(TypeInfo(propertyType, Variance.IN_VARIANCE)) + val setterInfo = FunctionInfo( + name = "set", + receiverTypeInfo = accessorReceiverType, + returnTypeInfo = TypeInfo(builtIns.getUnitType(), Variance.OUT_VARIANCE), + parameterInfos = listOf(thisRefParam, metadataParam, newValueParam) + ) + callableInfos.add(setterInfo) + } + + return CreateCallableFromUsageFix(expression, callableInfos) + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createVariable/CreateLocalVariableActionFactory.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createVariable/CreateLocalVariableActionFactory.kt index 1438fa61e94..38562f8cf6b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createVariable/CreateLocalVariableActionFactory.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createVariable/CreateLocalVariableActionFactory.kt @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.psi.JetClassBody import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.PropertyInfo import org.jetbrains.jet.lang.psi.psiUtil.getAssignmentByLHS import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.getExpressionForTypeGuess +import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList object CreateLocalVariableActionFactory: JetSingleIntentionActionFactory() { override fun createAction(diagnostic: Diagnostic): IntentionAction? { @@ -50,7 +51,7 @@ object CreateLocalVariableActionFactory: JetSingleIntentionActionFactory() { override fun getText(): String = JetBundle.message("create.local.variable.from.usage", propertyInfo.name) override fun invoke(project: Project, editor: Editor?, file: JetFile?) { - with (CallableBuilderConfiguration(propertyInfo, assignment ?: refExpr, file!!, editor!!).createBuilder()) { + with (CallableBuilderConfiguration(propertyInfo.singletonOrEmptyList(), assignment ?: refExpr, file!!, editor!!).createBuilder()) { val actualContainer = when (container) { is JetBlockExpression -> container else -> ConvertToBlockBodyAction().convert(container as JetDeclarationWithBody).getBodyExpression()!! diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVal.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVal.kt new file mode 100644 index 00000000000..9ebb47bd0bd --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVal.kt @@ -0,0 +1,11 @@ +// "Create function 'get' from usage" "true" +class F { + fun get(x: X, propertyMetadata: PropertyMetadata): Int { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} + +class X { + val f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVar.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVar.kt new file mode 100644 index 00000000000..0372753794e --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVar.kt @@ -0,0 +1,15 @@ +// "Create function 'get', function 'set' from usage" "true" +class F { + fun get(x: X, propertyMetadata: PropertyMetadata): Int { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + fun set(x: X, propertyMetadata: PropertyMetadata, i: Int) { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} + +class X { + var f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVarMissingGet.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVarMissingGet.kt new file mode 100644 index 00000000000..b2112615c52 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVarMissingGet.kt @@ -0,0 +1,12 @@ +// "Create function 'get' from usage" "true" +class F { + fun set(x: X, propertyMetadata: PropertyMetadata, i: Int) { } + + fun get(x: X, propertyMetadata: PropertyMetadata): Int { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} + +class X { + var f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVarMissingSet.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVarMissingSet.kt new file mode 100644 index 00000000000..6d58d4a2178 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/afterVarMissingSet.kt @@ -0,0 +1,12 @@ +// "Create function 'set' from usage" "true" +class F { + fun get(x: X, propertyMetadata: PropertyMetadata): Int = 1 + + fun set(x: X, propertyMetadata: PropertyMetadata, i: Int) { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} + +class X { + var f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVal.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVal.kt new file mode 100644 index 00000000000..0e045f7eaeb --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVal.kt @@ -0,0 +1,8 @@ +// "Create function 'get' from usage" "true" +class F { + +} + +class X { + val f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVar.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVar.kt new file mode 100644 index 00000000000..686d6d4421d --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVar.kt @@ -0,0 +1,8 @@ +// "Create function 'get', function 'set' from usage" "true" +class F { + +} + +class X { + var f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingGet.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingGet.kt new file mode 100644 index 00000000000..35ef5b1cb21 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingGet.kt @@ -0,0 +1,8 @@ +// "Create function 'get' from usage" "true" +class F { + fun set(x: X, propertyMetadata: PropertyMetadata, i: Int) { } +} + +class X { + var f: Int by F() +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingSet.kt b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingSet.kt new file mode 100644 index 00000000000..4bbbf734233 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingSet.kt @@ -0,0 +1,8 @@ +// "Create function 'set' from usage" "true" +class F { + fun get(x: X, propertyMetadata: PropertyMetadata): Int = 1 +} + +class X { + var f: Int by F() +} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java index a3864576148..e8e6a3711d5 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -440,13 +440,13 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/beforeAddFunctionParameterAndChangeTypes.kt"); doTest(fileName); } - + @TestMetadata("beforeAddFunctionParameterLongNameRuntime.kt") public void testAddFunctionParameterLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/beforeAddFunctionParameterLongNameRuntime.kt"); doTest(fileName); } - + @TestMetadata("beforeAddParameterNotAvailableForBuiltins.kt") public void testAddParameterNotAvailableForBuiltins() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/beforeAddParameterNotAvailableForBuiltins.kt"); @@ -628,7 +628,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { @TestMetadata("idea/testData/quickfix/createFromUsage/createFunction") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({CreateFunction.BinaryOperations.class, CreateFunction.Call.class, CreateFunction.Component.class, CreateFunction.Get.class, CreateFunction.HasNext.class, CreateFunction.Invoke.class, CreateFunction.Iterator.class, CreateFunction.Next.class, CreateFunction.Set.class, CreateFunction.UnaryOperations.class}) + @InnerTestClasses({CreateFunction.BinaryOperations.class, CreateFunction.Call.class, CreateFunction.Component.class, CreateFunction.DelegateAccessors.class, CreateFunction.Get.class, CreateFunction.HasNext.class, CreateFunction.Invoke.class, CreateFunction.Iterator.class, CreateFunction.Next.class, CreateFunction.Set.class, CreateFunction.UnaryOperations.class}) @RunWith(JUnit3RunnerWithInners.class) public static class CreateFunction extends AbstractQuickFixTest { public void testAllFilesPresentInCreateFunction() throws Exception { @@ -795,13 +795,13 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeFunOnUserType.kt"); doTest(fileName); } - + @TestMetadata("beforeFunOnUserTypeWithDeclarations.kt") public void testFunOnUserTypeWithDeclarations() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeFunOnUserTypeWithDeclarations.kt"); doTest(fileName); } - + @TestMetadata("beforeFunOnUserTypeWithTypeParams.kt") public void testFunOnUserTypeWithTypeParams() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeFunOnUserTypeWithTypeParams.kt"); @@ -962,6 +962,39 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DelegateAccessors extends AbstractQuickFixTest { + public void testAllFilesPresentInDelegateAccessors() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors"), Pattern.compile("^before(\\w+)\\.kt$"), true); + } + + @TestMetadata("beforeVal.kt") + public void testVal() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVal.kt"); + doTest(fileName); + } + + @TestMetadata("beforeVar.kt") + public void testVar() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVar.kt"); + doTest(fileName); + } + + @TestMetadata("beforeVarMissingGet.kt") + public void testVarMissingGet() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingGet.kt"); + doTest(fileName); + } + + @TestMetadata("beforeVarMissingSet.kt") + public void testVarMissingSet() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/delegateAccessors/beforeVarMissingSet.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/get") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -3201,13 +3234,13 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeAddition/beforeWrongGetterParameterType.kt"); doTest(fileName); } - + @TestMetadata("beforeWrongGetterParameterTypeLongNameRuntime.kt") public void testWrongGetterParameterTypeLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeAddition/beforeWrongGetterParameterTypeLongNameRuntime.kt"); doTest(fileName); } - + @TestMetadata("beforeWrongSetterParameterType.kt") public void testWrongSetterParameterType() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeAddition/beforeWrongSetterParameterType.kt"); @@ -3268,25 +3301,25 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeChangeFunctionLiteralParameterTypeToFunctionType.kt"); doTest(fileName); } - + @TestMetadata("beforeChangeFunctionLiteralParameterTypeToFunctionTypeLongNameRuntime.kt") public void testChangeFunctionLiteralParameterTypeToFunctionTypeLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeChangeFunctionLiteralParameterTypeToFunctionTypeLongNameRuntime.kt"); doTest(fileName); } - + @TestMetadata("beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt") public void testChangeFunctionReturnTypeToMatchExpectedTypeOfCall() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt"); doTest(fileName); } - + @TestMetadata("beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCallLongNameRuntime.kt") public void testChangeFunctionReturnTypeToMatchExpectedTypeOfCallLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCallLongNameRuntime.kt"); doTest(fileName); } - + @TestMetadata("beforeChangeReturnTypeWhenFunctionNameIsMissing.kt") public void testChangeReturnTypeWhenFunctionNameIsMissing() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeChangeReturnTypeWhenFunctionNameIsMissing.kt"); @@ -3316,13 +3349,13 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeExpectedParameterTypeMismatch.kt"); doTest(fileName); } - + @TestMetadata("beforeExpectedParameterTypeMismatchLongNameRuntime.kt") public void testExpectedParameterTypeMismatchLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeExpectedParameterTypeMismatchLongNameRuntime.kt"); doTest(fileName); } - + @TestMetadata("beforeExpectedReturnTypeMismatch.kt") public void testExpectedReturnTypeMismatch() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeExpectedReturnTypeMismatch.kt"); @@ -3346,13 +3379,13 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforePropertyTypeMismatch.kt"); doTest(fileName); } - + @TestMetadata("beforePropertyTypeMismatchLongNameRuntime.kt") public void testPropertyTypeMismatchLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforePropertyTypeMismatchLongNameRuntime.kt"); doTest(fileName); } - + @TestMetadata("beforeReturnTypeMismatch.kt") public void testReturnTypeMismatch() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/beforeReturnTypeMismatch.kt"); @@ -3426,13 +3459,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/casts/beforeTypeMismatch5.kt"); doTest(fileName); } - + @TestMetadata("beforeTypeMismatchLongNameRuntime.kt") public void testTypeMismatchLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/casts/beforeTypeMismatchLongNameRuntime.kt"); doTest(fileName); } - } @TestMetadata("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch") @@ -3538,7 +3570,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType5.kt"); doTest(fileName); } - + @TestMetadata("beforeChangeParameterTypeLongNameRuntime.kt") public void testChangeParameterTypeLongNameRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeParameterTypeLongNameRuntime.kt");