diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt index ea6711e5c37..658b4651a0e 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt @@ -27,6 +27,9 @@ import java.util.HashSet class ConstructorConverter(private val converter: Converter) { private val typeConverter = converter.typeConverter + private val tempValName: String = "__" + private fun tempValIdentifier(): Identifier = Identifier(tempValName, false).assignNoPrototype() + public fun convertConstructor(constructor: PsiMethod, annotations: Annotations, modifiers: Modifiers, @@ -285,6 +288,49 @@ class ConstructorConverter(private val converter: Converter) { return statements } - private val tempValName: String = "__" - private fun tempValIdentifier(): Identifier = Identifier(tempValName, false).assignNoPrototype() + private fun PsiMethod.isPrimaryConstructor(): Boolean { + if (!isConstructor()) return false + val parent = getParent() + if (parent !is PsiClass) return false + return parent.getPrimaryConstructor() == this + } + + private fun PsiClass.getPrimaryConstructor(): PsiMethod? { + val constructors = getConstructors() + when (constructors.size) { + 0 -> return null + + 1 -> return constructors.single() + + else -> { + val toTargetConstructorMap = HashMap() + for (constructor in constructors) { + val firstStatement = constructor.getBody()?.getStatements()?.firstOrNull() + val refExpr = ((firstStatement as? PsiExpressionStatement) + ?.getExpression() as? PsiMethodCallExpression) + ?.getMethodExpression() + if (refExpr != null && refExpr.getCanonicalText() == "this") { + val target = refExpr.resolve() as? PsiMethod + if (target != null && target.isConstructor()) { + val finalTarget = toTargetConstructorMap[target] ?: target!!/*TODO: see KT-5335*/ + toTargetConstructorMap[constructor] = finalTarget + for (entry in toTargetConstructorMap.entrySet()) { + if (entry.getValue() == constructor) { + entry.setValue(finalTarget) + } + } + } + } + } + + val candidates = constructors.filter { it !in toTargetConstructorMap } + if (candidates.size != 1) return null // there should be only one constructor which does not call other constructor + val candidate = candidates.single() + return if (toTargetConstructorMap.values().all { it == candidate } /* all other constructors call our candidate (directly or indirectly)*/) + candidate + else + null + } + } + } } \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt deleted file mode 100644 index d373f0f1b83..00000000000 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2010-2013 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.jet.j2k - -import com.intellij.psi.* -import java.util.HashMap - -fun PsiMethod.isPrimaryConstructor(): Boolean { - if (!isConstructor()) return false - val parent = getParent() - if (parent !is PsiClass) return false - return parent.getPrimaryConstructor() == this -} - -fun PsiClass.getPrimaryConstructor(): PsiMethod? { - val constructors = getConstructors() - when (constructors.size) { - 0 -> return null - - 1 -> return constructors.single() - - else -> { - val toTargetConstructorMap = HashMap() - for (constructor in constructors) { - val firstStatement = constructor.getBody()?.getStatements()?.firstOrNull() - val refExpr = ((firstStatement as? PsiExpressionStatement) - ?.getExpression() as? PsiMethodCallExpression) - ?.getMethodExpression() - if (refExpr != null && refExpr.getCanonicalText() == "this") { - val target = refExpr.resolve() as? PsiMethod - if (target != null && target.isConstructor()) { - val finalTarget = toTargetConstructorMap[target] ?: target!!/*TODO: see KT-5335*/ - toTargetConstructorMap[constructor] = finalTarget - for (entry in toTargetConstructorMap.entrySet()) { - if (entry.getValue() == constructor) { - entry.setValue(finalTarget) - } - } - } - } - } - - val candidates = constructors.filter { it !in toTargetConstructorMap } - if (candidates.size != 1) return null // there should be only one constructor which does not call other constructor - val candidate = candidates.single() - return if (toTargetConstructorMap.values().all { it == candidate } /* all other constructors call our candidate (directly or indirectly)*/) - candidate - else - null - } - } -} - -fun PsiElement.getContainingMethod(): PsiMethod? { - var context = getContext() - while (context != null) { - val _context = context!! - if (_context is PsiMethod) return _context - context = _context.getContext() - } - return null -} - -fun PsiElement.getContainingConstructor(): PsiMethod? { - val method = getContainingMethod() - return if (method?.isConstructor() == true) method else null -} - -fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean { - val ref = getMethodExpression() - if (ref.getCanonicalText() == "super") { - return ref.resolve()?.isConstructor() ?: false - } - return false -} - -fun PsiElement.isConstructor(): Boolean = this is PsiMethod && this.isConstructor() diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt index 6570b940239..98f48b8f9e6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt @@ -22,10 +22,8 @@ import com.intellij.psi.util.PsiUtil import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.jet.j2k.ast.* -import com.intellij.codeInsight.AnnotationUtil -import com.intellij.codeInsight.NullableNotNullManager -fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier.toKotlin(it) }.makeString(".") +fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier.toKotlin(it) }.joinToString(".") fun findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection { return ReferencesSearch.search(variable, LocalSearchScope(scope)).findAll().filterIsInstance(javaClass()) @@ -111,3 +109,28 @@ fun PsiElement.isInSingleLine(): Boolean { } return true } + +fun PsiElement.getContainingMethod(): PsiMethod? { + var context = getContext() + while (context != null) { + val _context = context!! + if (_context is PsiMethod) return _context + context = _context.getContext() + } + return null +} + +fun PsiElement.getContainingConstructor(): PsiMethod? { + val method = getContainingMethod() + return if (method?.isConstructor() == true) method else null +} + +fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean { + val ref = getMethodExpression() + if (ref.getCanonicalText() == "super") { + return ref.resolve()?.isConstructor() ?: false + } + return false +} + +fun PsiElement.isConstructor(): Boolean = this is PsiMethod && this.isConstructor()