Run code cleanup on j2k module

This commit is contained in:
Natalia Ukhorskaya
2015-11-12 10:19:48 +03:00
parent a983e6cf60
commit c79ffbac5c
53 changed files with 667 additions and 664 deletions
@@ -27,20 +27,20 @@ import java.lang.annotation.ElementType
import java.lang.annotation.Target import java.lang.annotation.Target
class AnnotationConverter(private val converter: Converter) { class AnnotationConverter(private val converter: Converter) {
private val annotationsToRemove: Set<String> = (NullableNotNullManager.getInstance(converter.project).getNotNulls() private val annotationsToRemove: Set<String> = (NullableNotNullManager.getInstance(converter.project).notNulls
+ NullableNotNullManager.getInstance(converter.project).getNullables() + NullableNotNullManager.getInstance(converter.project).nullables
+ listOf(CommonClassNames.JAVA_LANG_OVERRIDE, javaClass<ElementType>().name)).toSet() + listOf(CommonClassNames.JAVA_LANG_OVERRIDE, ElementType::class.java.name)).toSet()
public fun isImportNotRequired(annotationName: String): Boolean { public fun isImportNotRequired(annotationName: String): Boolean {
return annotationName in annotationsToRemove || annotationName == javaClass<Target>().name return annotationName in annotationsToRemove || annotationName == Target::class.java.name
} }
public fun convertAnnotations(owner: PsiModifierListOwner): Annotations public fun convertAnnotations(owner: PsiModifierListOwner): Annotations
= convertAnnotationsOnly(owner) + convertModifiersToAnnotations(owner) = convertAnnotationsOnly(owner) + convertModifiersToAnnotations(owner)
private fun convertAnnotationsOnly(owner: PsiModifierListOwner): Annotations { private fun convertAnnotationsOnly(owner: PsiModifierListOwner): Annotations {
val modifierList = owner.getModifierList() val modifierList = owner.modifierList
val annotations = modifierList?.getAnnotations()?.filter { it.getQualifiedName() !in annotationsToRemove } val annotations = modifierList?.annotations?.filter { !annotationsToRemove.containsRaw(it.qualifiedName) }
var convertedAnnotations: List<Annotation> = if (annotations != null && annotations.isNotEmpty()) { var convertedAnnotations: List<Annotation> = if (annotations != null && annotations.isNotEmpty()) {
val newLines = if (!modifierList!!.isInSingleLine()) { val newLines = if (!modifierList!!.isInSingleLine()) {
@@ -49,8 +49,8 @@ class AnnotationConverter(private val converter: Converter) {
else { else {
var child: PsiElement? = modifierList var child: PsiElement? = modifierList
while (true) { while (true) {
child = child!!.getNextSibling() child = child!!.nextSibling
if (child == null || child.getTextLength() != 0) break if (child == null || child.textLength != 0) break
} }
if (child is PsiWhiteSpace) !child.isInSingleLine() else false if (child is PsiWhiteSpace) !child.isInSingleLine() else false
} }
@@ -72,11 +72,11 @@ class AnnotationConverter(private val converter: Converter) {
} }
private fun convertDeprecatedJavadocTag(element: PsiDocCommentOwner): Annotation? { private fun convertDeprecatedJavadocTag(element: PsiDocCommentOwner): Annotation? {
val deprecatedTag = element.getDocComment()?.findTagByName("deprecated") ?: return null val deprecatedTag = element.docComment?.findTagByName("deprecated") ?: return null
val deferredExpression = converter.deferredElement<Expression> { val deferredExpression = converter.deferredElement<Expression> {
LiteralExpression("\"" + StringUtil.escapeStringCharacters(deprecatedTag.content()) + "\"").assignNoPrototype() LiteralExpression("\"" + StringUtil.escapeStringCharacters(deprecatedTag.content()) + "\"").assignNoPrototype()
} }
return Annotation(Identifier("Deprecated").assignPrototype(deprecatedTag.getNameElement()), return Annotation(Identifier("Deprecated").assignPrototype(deprecatedTag.nameElement),
listOf(null to deferredExpression), newLineAfter = true) listOf(null to deferredExpression), newLineAfter = true)
.assignPrototype(deprecatedTag) .assignPrototype(deprecatedTag)
} }
@@ -100,8 +100,8 @@ class AnnotationConverter(private val converter: Converter) {
} }
public fun convertAnnotation(annotation: PsiAnnotation, newLineAfter: Boolean): Annotation? { public fun convertAnnotation(annotation: PsiAnnotation, newLineAfter: Boolean): Annotation? {
val qualifiedName = annotation.getQualifiedName() val qualifiedName = annotation.qualifiedName
if (qualifiedName == CommonClassNames.JAVA_LANG_DEPRECATED && annotation.getParameterList().getAttributes().isEmpty()) { if (qualifiedName == CommonClassNames.JAVA_LANG_DEPRECATED && annotation.parameterList.attributes.isEmpty()) {
val deferredExpression = converter.deferredElement<Expression> { LiteralExpression("\"\"").assignNoPrototype() } val deferredExpression = converter.deferredElement<Expression> { LiteralExpression("\"\"").assignNoPrototype() }
return Annotation(Identifier("Deprecated").assignNoPrototype(), listOf(null to deferredExpression), newLineAfter).assignPrototype(annotation) //TODO: insert comment return Annotation(Identifier("Deprecated").assignNoPrototype(), listOf(null to deferredExpression), newLineAfter).assignPrototype(annotation) //TODO: insert comment
} }
@@ -114,7 +114,7 @@ class AnnotationConverter(private val converter: Converter) {
else { else {
val value = attributes[0].value val value = attributes[0].value
arguments = when (value) { arguments = when (value) {
is PsiArrayInitializerMemberValue -> value.getInitializers().filterIsInstance<PsiReferenceExpression>() is PsiArrayInitializerMemberValue -> value.initializers.filterIsInstance<PsiReferenceExpression>()
.flatMap { mapTargetByName(it) } .flatMap { mapTargetByName(it) }
.toSet() .toSet()
is PsiReferenceExpression -> mapTargetByName(value) is PsiReferenceExpression -> mapTargetByName(value)
@@ -122,7 +122,7 @@ class AnnotationConverter(private val converter: Converter) {
} }
} }
val deferredExpressionList = arguments.map { val deferredExpressionList = arguments.map {
val name = it.name() val name = it.name
null to converter.deferredElement<Expression> { null to converter.deferredElement<Expression> {
QualifiedExpression(Identifier("AnnotationTarget", false).assignNoPrototype(), QualifiedExpression(Identifier("AnnotationTarget", false).assignNoPrototype(),
Identifier(name, false).assignNoPrototype()) Identifier(name, false).assignNoPrototype())
@@ -132,19 +132,19 @@ class AnnotationConverter(private val converter: Converter) {
deferredExpressionList, newLineAfter).assignPrototype(annotation) deferredExpressionList, newLineAfter).assignPrototype(annotation)
} }
val nameRef = annotation.getNameReferenceElement() val nameRef = annotation.nameReferenceElement
val name = Identifier((nameRef ?: return null).getText()!!).assignPrototype(nameRef) val name = Identifier((nameRef ?: return null).text!!).assignPrototype(nameRef)
val annotationClass = nameRef.resolve() as? PsiClass val annotationClass = nameRef.resolve() as? PsiClass
val arguments = annotation.getParameterList().getAttributes().flatMap { val arguments = annotation.parameterList.attributes.flatMap {
val parameterName = it.getName() ?: "value" val parameterName = it.name ?: "value"
val method = annotationClass?.findMethodsByName(parameterName, false)?.firstOrNull() val method = annotationClass?.findMethodsByName(parameterName, false)?.firstOrNull()
val expectedType = method?.getReturnType() val expectedType = method?.returnType
val attrName = it.getName()?.let { Identifier(it).assignNoPrototype() } val attrName = it.name?.let { Identifier(it).assignNoPrototype() }
val value = it.getValue() val value = it.value
val isVarArg = parameterName == "value" /* converted to vararg in Kotlin */ val isVarArg = parameterName == "value" /* converted to vararg in Kotlin */
val attrValues = convertAttributeValue(value, expectedType, isVarArg, it.getName() == null) val attrValues = convertAttributeValue(value, expectedType, isVarArg, it.name == null)
attrValues.map { attrName to converter.deferredElement(it) } attrValues.map { attrName to converter.deferredElement(it) }
} }
@@ -152,8 +152,8 @@ class AnnotationConverter(private val converter: Converter) {
} }
public fun convertAnnotationMethodDefault(method: PsiAnnotationMethod): DeferredElement<Expression>? { public fun convertAnnotationMethodDefault(method: PsiAnnotationMethod): DeferredElement<Expression>? {
val value = method.getDefaultValue() ?: return null val value = method.defaultValue ?: return null
return converter.deferredElement(convertAttributeValue(value, method.getReturnType(), false, false).single()) return converter.deferredElement(convertAttributeValue(value, method.returnType, false, false).single())
} }
private fun convertAttributeValue(value: PsiAnnotationMemberValue?, expectedType: PsiType?, isVararg: Boolean, isUnnamed: Boolean): List<(CodeConverter) -> Expression> { private fun convertAttributeValue(value: PsiAnnotationMemberValue?, expectedType: PsiType?, isVararg: Boolean, isUnnamed: Boolean): List<(CodeConverter) -> Expression> {
@@ -161,8 +161,8 @@ class AnnotationConverter(private val converter: Converter) {
is PsiExpression -> listOf({ codeConverter -> convertExpressionValue(codeConverter, value, expectedType) }) is PsiExpression -> listOf({ codeConverter -> convertExpressionValue(codeConverter, value, expectedType) })
is PsiArrayInitializerMemberValue -> { is PsiArrayInitializerMemberValue -> {
val componentType = (expectedType as? PsiArrayType)?.getComponentType() val componentType = (expectedType as? PsiArrayType)?.componentType
val componentGenerators = value.getInitializers().map { convertAttributeValue(it, componentType, false, true).single() } val componentGenerators = value.initializers.map { convertAttributeValue(it, componentType, false, true).single() }
if (isVararg && isUnnamed) { if (isVararg && isUnnamed) {
componentGenerators componentGenerators
} }
@@ -171,13 +171,13 @@ class AnnotationConverter(private val converter: Converter) {
} }
} }
else -> listOf({ codeConverter -> DummyStringExpression(value?.getText() ?: "").assignPrototype(value) }) else -> listOf({ codeConverter -> DummyStringExpression(value?.text ?: "").assignPrototype(value) })
} }
} }
private fun convertExpressionValue(codeConverter: CodeConverter, value: PsiExpression, expectedType: PsiType?): Expression { private fun convertExpressionValue(codeConverter: CodeConverter, value: PsiExpression, expectedType: PsiType?): Expression {
val expression = if (value is PsiClassObjectAccessExpression) { val expression = if (value is PsiClassObjectAccessExpression) {
val type = converter.convertTypeElement(value.getOperand(), Nullability.NotNull) val type = converter.convertTypeElement(value.operand, Nullability.NotNull)
ClassLiteralExpression(type) ClassLiteralExpression(type)
} }
else { else {
@@ -204,7 +204,7 @@ class AnnotationConverter(private val converter: Converter) {
} }
} }
else { else {
DummyStringExpression(value.getText()!!).assignPrototype(value) DummyStringExpression(value.text!!).assignPrototype(value)
} }
} }
} }
@@ -69,13 +69,13 @@ class ClassBodyConverter(private val psiClass: PsiClass,
classKind.isOpen(), classKind.isOpen(),
converter.referenceSearcher) converter.referenceSearcher)
val constructorConverter = if (psiClass.getName() != null && !classKind.isObject()) val constructorConverter = if (psiClass.name != null && !classKind.isObject())
ConstructorConverter(psiClass, converter, { field -> memberToPropertyInfo[field]!! }, overloadReducer) ConstructorConverter(psiClass, converter, { field -> memberToPropertyInfo[field]!! }, overloadReducer)
else else
null null
val convertedMembers = LinkedHashMap<PsiMember, Member>() val convertedMembers = LinkedHashMap<PsiMember, Member>()
for (element in psiClass.getChildren()) { for (element in psiClass.children) {
if (element is PsiMember) { if (element is PsiMember) {
if (element is PsiAnnotationMethod) continue // converted in convertAnnotationType() if (element is PsiAnnotationMethod) continue // converted in convertAnnotationType()
if (classKind.isObject() && element.isConstructor()) continue // no constructor in object if (classKind.isObject() && element.isConstructor()) continue // no constructor in object
@@ -90,11 +90,11 @@ class ClassBodyConverter(private val psiClass: PsiClass,
fieldsToDrop.forEach { convertedMembers.remove(it) } fieldsToDrop.forEach { convertedMembers.remove(it) }
val lBrace = LBrace().assignPrototype(psiClass.getLBrace()) val lBrace = LBrace().assignPrototype(psiClass.lBrace)
val rBrace = RBrace().assignPrototype(psiClass.getRBrace()) val rBrace = RBrace().assignPrototype(psiClass.rBrace)
if (classKind.isObject()) { if (classKind.isObject()) {
val psiMembers = convertedMembers.keySet() val psiMembers = convertedMembers.keys
if (psiMembers.all { it is PsiMethod }) { // for object with no fields we can use faster external usage processing if (psiMembers.all { it is PsiMethod }) { // for object with no fields we can use faster external usage processing
converter.addUsageProcessing(ToObjectWithOnlyMethodsProcessing(psiClass)) converter.addUsageProcessing(ToObjectWithOnlyMethodsProcessing(psiClass))
} }
@@ -107,7 +107,7 @@ class ClassBodyConverter(private val psiClass: PsiClass,
} }
} }
return ClassBody(null, null, convertedMembers.values().toList(), emptyList(), lBrace, rBrace, classKind) return ClassBody(null, null, convertedMembers.values.toList(), emptyList(), lBrace, rBrace, classKind)
} }
val useCompanionObject = shouldGenerateCompanionObject(convertedMembers) val useCompanionObject = shouldGenerateCompanionObject(convertedMembers)
@@ -125,7 +125,7 @@ class ClassBodyConverter(private val psiClass: PsiClass,
companionObjectMembers.add(member) companionObjectMembers.add(member)
if (psiMember is PsiMethod /* fields in companion object can be accessed as fields from java */ if (psiMember is PsiMethod /* fields in companion object can be accessed as fields from java */
&& !psiMember.hasModifierProperty(PsiModifier.PRIVATE)) { && !psiMember.hasModifierProperty(PsiModifier.PRIVATE)) {
converter.addUsageProcessing(MethodIntoObjectProcessing(psiMember, SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.getIdentifier())) converter.addUsageProcessing(MethodIntoObjectProcessing(psiMember, SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.identifier))
} }
} }
else { else {
@@ -180,7 +180,7 @@ class ClassBodyConverter(private val psiClass: PsiClass,
// do not convert private static methods into companion object if possible // do not convert private static methods into companion object if possible
private fun shouldGenerateCompanionObject(convertedMembers: Map<PsiMember, Member>): Boolean { private fun shouldGenerateCompanionObject(convertedMembers: Map<PsiMember, Member>): Boolean {
val members = convertedMembers.keySet().filter { !it.isConstructor() } val members = convertedMembers.keys.filter { !it.isConstructor() }
val companionObjectMembers = members.filter { it !is PsiClass && it !is PsiEnumConstant && it.hasModifierProperty(PsiModifier.STATIC) } val companionObjectMembers = members.filter { it !is PsiClass && it !is PsiEnumConstant && it.hasModifierProperty(PsiModifier.STATIC) }
val nestedClasses = members.filterIsInstance<PsiClass>().filter { it.hasModifierProperty(PsiModifier.STATIC) } val nestedClasses = members.filterIsInstance<PsiClass>().filter { it.hasModifierProperty(PsiModifier.STATIC) }
if (companionObjectMembers.all { it is PsiMethod && it.hasModifierProperty(PsiModifier.PRIVATE) }) { if (companionObjectMembers.all { it is PsiMethod && it.hasModifierProperty(PsiModifier.PRIVATE) }) {
+18 -20
View File
@@ -25,9 +25,7 @@ import org.jetbrains.kotlin.j2k.ast.Element
import org.jetbrains.kotlin.j2k.ast.SpacesInheritance import org.jetbrains.kotlin.j2k.ast.SpacesInheritance
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import java.util.ArrayList import java.util.*
import java.util.HashSet
import java.util.LinkedHashSet
fun<T> CodeBuilder.buildList(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder { fun<T> CodeBuilder.buildList(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder {
if (generators.isNotEmpty()) { if (generators.isNotEmpty()) {
@@ -72,7 +70,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
append(docConverter.convertDocComment(element), false) append(docConverter.convertDocComment(element), false)
} }
else { else {
append(element.getText()!!, element.isEndOfLineComment()) append(element.text!!, element.isEndOfLineComment())
} }
} }
@@ -245,7 +243,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
private fun MutableList<PsiElement>.collectCommentsAndSpacesBefore(element: PsiElement): MutableList<PsiElement> { private fun MutableList<PsiElement>.collectCommentsAndSpacesBefore(element: PsiElement): MutableList<PsiElement> {
if (element == topElement) return this if (element == topElement) return this
val prev = element.getPrevSibling() val prev = element.prevSibling
if (prev != null) { if (prev != null) {
if (prev.isCommentOrSpace()) { if (prev.isCommentOrSpace()) {
if (prev !in commentsAndSpacesUsed) { if (prev !in commentsAndSpacesUsed) {
@@ -258,7 +256,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
} }
} }
else { else {
collectCommentsAndSpacesBefore(element.getParent()!!) collectCommentsAndSpacesBefore(element.parent!!)
} }
return this return this
} }
@@ -266,7 +264,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
private fun MutableList<PsiElement>.collectCommentsAndSpacesAfter(element: PsiElement): MutableList<PsiElement> { private fun MutableList<PsiElement>.collectCommentsAndSpacesAfter(element: PsiElement): MutableList<PsiElement> {
if (element == topElement) return this if (element == topElement) return this
val next = element.getNextSibling() val next = element.nextSibling
if (next != null) { if (next != null) {
if (next.isCommentOrSpace()) { if (next.isCommentOrSpace()) {
if (next is PsiWhiteSpace && next.hasLineBreaks()) return this // do not attach anything on next line after element if (next is PsiWhiteSpace && next.hasLineBreaks()) return this // do not attach anything on next line after element
@@ -280,13 +278,13 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
} }
} }
else { else {
collectCommentsAndSpacesAfter(element.getParent()!!) collectCommentsAndSpacesAfter(element.parent!!)
} }
return this return this
} }
private fun MutableList<PsiElement>.collectCommentsAndSpacesAtStart(element: PsiElement): MutableList<PsiElement> { private fun MutableList<PsiElement>.collectCommentsAndSpacesAtStart(element: PsiElement): MutableList<PsiElement> {
var child = element.getFirstChild() var child = element.firstChild
while(child != null) { while(child != null) {
if (child.isCommentOrSpace()) { if (child.isCommentOrSpace()) {
if (child !in commentsAndSpacesUsed) add(child) else break if (child !in commentsAndSpacesUsed) add(child) else break
@@ -295,13 +293,13 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
collectCommentsAndSpacesAtStart(child) collectCommentsAndSpacesAtStart(child)
break break
} }
child = child.getNextSibling() child = child.nextSibling
} }
return this return this
} }
private fun MutableList<PsiElement>.collectCommentsAndSpacesAtEnd(element: PsiElement): MutableList<PsiElement> { private fun MutableList<PsiElement>.collectCommentsAndSpacesAtEnd(element: PsiElement): MutableList<PsiElement> {
var child = element.getLastChild() var child = element.lastChild
while(child != null) { while(child != null) {
if (child.isCommentOrSpace()) { if (child.isCommentOrSpace()) {
if (child !in commentsAndSpacesUsed) add(child) else break if (child !in commentsAndSpacesUsed) add(child) else break
@@ -310,7 +308,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
collectCommentsAndSpacesAtEnd(child) collectCommentsAndSpacesAtEnd(child)
break break
} }
child = child.getPrevSibling() child = child.prevSibling
} }
return this return this
} }
@@ -323,7 +321,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
other.isEmpty() -> return this other.isEmpty() -> return this
else -> { else -> {
val result = ArrayList<T>(size() + other.size()) val result = ArrayList<T>(size + other.size)
result.addAll(this) result.addAll(this)
result.addAll(other) result.addAll(other)
return result return result
@@ -332,7 +330,7 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
} }
fun<T> List<T>.reversed(): List<T> { fun<T> List<T>.reversed(): List<T> {
return if (size() <= 1) return if (size <= 1)
this this
else else
this.asReversed() this.asReversed()
@@ -340,20 +338,20 @@ class CodeBuilder(private val topElement: PsiElement?, private var docConverter:
fun PsiElement.isCommentOrSpace() = this is PsiComment || this is PsiWhiteSpace fun PsiElement.isCommentOrSpace() = this is PsiComment || this is PsiWhiteSpace
fun PsiElement.isEndOfLineComment() = this is PsiComment && getTokenType() == JavaTokenType.END_OF_LINE_COMMENT fun PsiElement.isEndOfLineComment() = this is PsiComment && tokenType == JavaTokenType.END_OF_LINE_COMMENT
fun PsiElement.isEmptyElement() = getFirstChild() == null && getTextLength() == 0 fun PsiElement.isEmptyElement() = firstChild == null && textLength == 0
fun PsiWhiteSpace.lineBreakCount() = StringUtil.getLineBreakCount(getText()) fun PsiWhiteSpace.lineBreakCount() = StringUtil.getLineBreakCount(text)
fun PsiWhiteSpace.hasLineBreaks() = StringUtil.containsLineBreak(getText()) fun PsiWhiteSpace.hasLineBreaks() = StringUtil.containsLineBreak(text)
fun CharSequence.trailingLineBreakCount(): Int { fun CharSequence.trailingLineBreakCount(): Int {
var i = length() - 1 var i = length - 1
while (i >= 0 && this[i] == '\n') { while (i >= 0 && this[i] == '\n') {
i-- i--
} }
return length() - i - 1 return length - i - 1
} }
} }
} }
@@ -46,9 +46,9 @@ class CodeConverter(
public fun convertBlock(block: PsiCodeBlock?, notEmpty: Boolean = true, statementFilter: (PsiStatement) -> Boolean = { true }): Block { public fun convertBlock(block: PsiCodeBlock?, notEmpty: Boolean = true, statementFilter: (PsiStatement) -> Boolean = { true }): Block {
if (block == null) return Block.Empty if (block == null) return Block.Empty
val lBrace = LBrace().assignPrototype(block.getLBrace()) val lBrace = LBrace().assignPrototype(block.lBrace)
val rBrace = RBrace().assignPrototype(block.getRBrace()) val rBrace = RBrace().assignPrototype(block.rBrace)
return Block(block.getStatements().filter(statementFilter).map { convertStatement(it) }, lBrace, rBrace, notEmpty).assignPrototype(block) return Block(block.statements.filter(statementFilter).map { convertStatement(it) }, lBrace, rBrace, notEmpty).assignPrototype(block)
} }
public fun convertStatement(statement: PsiStatement?): Statement { public fun convertStatement(statement: PsiStatement?): Statement {
@@ -71,7 +71,7 @@ class CodeConverter(
public fun convertLocalVariable(variable: PsiLocalVariable): LocalVariable { public fun convertLocalVariable(variable: PsiLocalVariable): LocalVariable {
val isVal = variable.hasModifierProperty(PsiModifier.FINAL) || val isVal = variable.hasModifierProperty(PsiModifier.FINAL) ||
variable.getInitializer() == null/* we do not know actually and prefer val until we have better analysis*/ || variable.initializer == null/* we do not know actually and prefer val until we have better analysis*/ ||
!variable.hasWriteAccesses(converter.referenceSearcher, variable.getContainingMethod()) !variable.hasWriteAccesses(converter.referenceSearcher, variable.getContainingMethod())
val type = typeConverter.convertVariableType(variable) val type = typeConverter.convertVariableType(variable)
val explicitType = type.check { settings.specifyLocalVariableTypeByDefault || converter.shouldDeclareVariableType(variable, type, isVal) } val explicitType = type.check { settings.specifyLocalVariableTypeByDefault || converter.shouldDeclareVariableType(variable, type, isVal) }
@@ -79,7 +79,7 @@ class CodeConverter(
converter.convertAnnotations(variable), converter.convertAnnotations(variable),
converter.convertModifiers(variable, false), converter.convertModifiers(variable, false),
explicitType, explicitType,
convertExpression(variable.getInitializer(), variable.getType()), convertExpression(variable.initializer, variable.type),
isVal).assignPrototype(variable) isVal).assignPrototype(variable)
} }
@@ -89,19 +89,19 @@ class CodeConverter(
var convertedExpression = convertExpression(expression) var convertedExpression = convertExpression(expression)
if (expectedType == null || expectedType == PsiType.VOID) return convertedExpression if (expectedType == null || expectedType == PsiType.VOID) return convertedExpression
val actualType = expression.getType() ?: return convertedExpression val actualType = expression.type ?: return convertedExpression
if (actualType is PsiPrimitiveType || actualType is PsiClassType && expectedType is PsiPrimitiveType) { if (actualType is PsiPrimitiveType || actualType is PsiClassType && expectedType is PsiPrimitiveType) {
convertedExpression = BangBangExpression.surroundIfNullable(convertedExpression) convertedExpression = BangBangExpression.surroundIfNullable(convertedExpression)
} }
if (needConversion(actualType, expectedType)) { if (needConversion(actualType, expectedType)) {
val expectedTypeStr = expectedType.getCanonicalText() val expectedTypeStr = expectedType.canonicalText
if (expression is PsiLiteralExpression) { if (expression is PsiLiteralExpression) {
if (expectedTypeStr == "float" || expectedTypeStr == "double") { if (expectedTypeStr == "float" || expectedTypeStr == "double") {
var text = convertedExpression.canonicalCode() var text = convertedExpression.canonicalCode()
if (text.last() in setOf('f', 'L')) { if (text.last() in setOf('f', 'L')) {
text = text.substring(0, text.length() - 1) text = text.substring(0, text.length - 1)
} }
if (expectedTypeStr == "float") { if (expectedTypeStr == "float") {
text += "f" text += "f"
@@ -115,8 +115,8 @@ class CodeConverter(
} }
} }
else if (expression is PsiPrefixExpression && expression.isLiteralWithSign()) { else if (expression is PsiPrefixExpression && expression.isLiteralWithSign()) {
val operandConverted = convertExpression(expression.getOperand(), expectedType) val operandConverted = convertExpression(expression.operand, expectedType)
convertedExpression = PrefixExpression(Operator(expression.getOperationSign().getTokenType()).assignPrototype(expression.getOperationSign()), operandConverted) convertedExpression = PrefixExpression(Operator(expression.operationSign.tokenType).assignPrototype(expression.operationSign), operandConverted)
} }
else { else {
val conversion = PRIMITIVE_TYPE_CONVERSIONS[expectedTypeStr] val conversion = PRIMITIVE_TYPE_CONVERSIONS[expectedTypeStr]
@@ -131,7 +131,7 @@ class CodeConverter(
public fun convertedExpressionType(expression: PsiExpression, expectedType: PsiType): Type { public fun convertedExpressionType(expression: PsiExpression, expectedType: PsiType): Type {
var convertedExpression = convertExpression(expression) var convertedExpression = convertExpression(expression)
val actualType = expression.getType() ?: return ErrorType() val actualType = expression.type ?: return ErrorType()
var resultType = typeConverter.convertType(actualType, if (convertedExpression.isNullable) Nullability.Nullable else Nullability.NotNull) var resultType = typeConverter.convertType(actualType, if (convertedExpression.isNullable) Nullability.Nullable else Nullability.NotNull)
if (actualType is PsiPrimitiveType && resultType.isNullable || if (actualType is PsiPrimitiveType && resultType.isNullable ||
@@ -140,7 +140,7 @@ class CodeConverter(
} }
if (needConversion(actualType, expectedType)) { if (needConversion(actualType, expectedType)) {
val expectedTypeStr = expectedType.getCanonicalText() val expectedTypeStr = expectedType.canonicalText
val willConvert = if (convertedExpression is LiteralExpression val willConvert = if (convertedExpression is LiteralExpression
|| expression is PsiPrefixExpression && expression.isLiteralWithSign() ) || expression is PsiPrefixExpression && expression.isLiteralWithSign() )
@@ -157,11 +157,11 @@ class CodeConverter(
} }
private fun PsiPrefixExpression.isLiteralWithSign() private fun PsiPrefixExpression.isLiteralWithSign()
= getOperand() is PsiLiteralExpression && getOperationTokenType() in setOf(JavaTokenType.PLUS, JavaTokenType.MINUS) = operand is PsiLiteralExpression && operationTokenType in setOf(JavaTokenType.PLUS, JavaTokenType.MINUS)
private fun needConversion(actual: PsiType, expected: PsiType): Boolean { private fun needConversion(actual: PsiType, expected: PsiType): Boolean {
val expectedStr = expected.getCanonicalText() val expectedStr = expected.canonicalText
val actualStr = actual.getCanonicalText() val actualStr = actual.canonicalText
return expectedStr != actualStr && return expectedStr != actualStr &&
expectedStr != typeConversionMap[actualStr] && expectedStr != typeConversionMap[actualStr] &&
actualStr != typeConversionMap[expectedStr] actualStr != typeConversionMap[expectedStr]
@@ -27,11 +27,11 @@ class ConstructorConverter(
private val fieldToPropertyInfo: (PsiField) -> PropertyInfo, private val fieldToPropertyInfo: (PsiField) -> PropertyInfo,
private val overloadReducer: OverloadReducer private val overloadReducer: OverloadReducer
) { ) {
private val constructors = psiClass.getConstructors().asList() private val constructors = psiClass.constructors.asList()
private val toTargetConstructorMap = buildToTargetConstructorMap() private val toTargetConstructorMap = buildToTargetConstructorMap()
private val primaryConstructor: PsiMethod? = when (constructors.size()) { private val primaryConstructor: PsiMethod? = when (constructors.size) {
0 -> null 0 -> null
1 -> constructors.single() 1 -> constructors.single()
else -> choosePrimaryConstructor() else -> choosePrimaryConstructor()
@@ -39,25 +39,25 @@ class ConstructorConverter(
private fun choosePrimaryConstructor(): PsiMethod? { private fun choosePrimaryConstructor(): PsiMethod? {
val candidates = constructors.filter { it !in toTargetConstructorMap } 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 if (candidates.size != 1) return null // there should be only one constructor which does not call other constructor
val primary = candidates.single() val primary = candidates.single()
if (toTargetConstructorMap.values().any() { it != primary }) return null // all other constructors call our candidate (directly or indirectly) if (toTargetConstructorMap.values.any() { it != primary }) return null // all other constructors call our candidate (directly or indirectly)
return primary return primary
} }
private fun buildToTargetConstructorMap(): Map<PsiMethod, PsiMethod> { private fun buildToTargetConstructorMap(): Map<PsiMethod, PsiMethod> {
val toTargetConstructorMap = HashMap<PsiMethod, PsiMethod>() val toTargetConstructorMap = HashMap<PsiMethod, PsiMethod>()
for (constructor in constructors) { for (constructor in constructors) {
val firstStatement = constructor.getBody()?.getStatements()?.firstOrNull() val firstStatement = constructor.body?.statements?.firstOrNull()
val methodCall = (firstStatement as? PsiExpressionStatement)?.getExpression() as? PsiMethodCallExpression val methodCall = (firstStatement as? PsiExpressionStatement)?.expression as? PsiMethodCallExpression
if (methodCall != null) { if (methodCall != null) {
val refExpr = methodCall.getMethodExpression() val refExpr = methodCall.methodExpression
if (refExpr.getCanonicalText() == "this") { if (refExpr.canonicalText == "this") {
val target = refExpr.resolve() as? PsiMethod val target = refExpr.resolve() as? PsiMethod
if (target != null && target.isConstructor()) { if (target != null && target.isConstructor) {
val finalTarget = toTargetConstructorMap[target] ?: target val finalTarget = toTargetConstructorMap[target] ?: target
toTargetConstructorMap[constructor] = finalTarget toTargetConstructorMap[constructor] = finalTarget
for (entry in toTargetConstructorMap.entrySet()) { for (entry in toTargetConstructorMap.entries) {
if (entry.value == constructor) { if (entry.value == constructor) {
entry.setValue(finalTarget) entry.setValue(finalTarget)
} }
@@ -87,7 +87,7 @@ class ConstructorConverter(
val thisOrSuper = findThisOrSuperCall(constructor) val thisOrSuper = findThisOrSuperCall(constructor)
val thisOrSuperDeferred = if (thisOrSuper != null) val thisOrSuperDeferred = if (thisOrSuper != null)
converter.deferredElement { it.convertExpression(thisOrSuper.getExpression()) } converter.deferredElement { it.convertExpression(thisOrSuper.expression) }
else else
null null
@@ -99,7 +99,7 @@ class ConstructorConverter(
} }
return null return null
} }
}).convertBlock(constructor.getBody())) }).convertBlock(constructor.body))
} }
SecondaryConstructor(annotations, modifiers, params, converter.deferredElement(::convertBody), thisOrSuperDeferred) SecondaryConstructor(annotations, modifiers, params, converter.deferredElement(::convertBody), thisOrSuperDeferred)
@@ -108,9 +108,9 @@ class ConstructorConverter(
} }
private fun findThisOrSuperCall(constructor: PsiMethod): PsiExpressionStatement? { private fun findThisOrSuperCall(constructor: PsiMethod): PsiExpressionStatement? {
val statement = constructor.getBody()?.getStatements()?.firstOrNull() as? PsiExpressionStatement ?: return null val statement = constructor.body?.statements?.firstOrNull() as? PsiExpressionStatement ?: return null
val methodCall = statement.getExpression() as? PsiMethodCallExpression ?: return null val methodCall = statement.expression as? PsiMethodCallExpression ?: return null
val text = methodCall.getMethodExpression().getText() val text = methodCall.methodExpression.text
return if (text == "this" || text == "super") statement else null return if (text == "this" || text == "super") statement else null
} }
@@ -118,9 +118,9 @@ class ConstructorConverter(
modifiers: Modifiers, modifiers: Modifiers,
fieldsToDrop: MutableSet<PsiField>, fieldsToDrop: MutableSet<PsiField>,
postProcessBody: (Block) -> Block): PrimaryConstructor { postProcessBody: (Block) -> Block): PrimaryConstructor {
val params = primaryConstructor!!.getParameterList().getParameters() val params = primaryConstructor!!.parameterList.parameters
val parameterToField = HashMap<PsiParameter, Pair<PsiField, Type>>() val parameterToField = HashMap<PsiParameter, Pair<PsiField, Type>>()
val body = primaryConstructor.getBody() val body = primaryConstructor.body
val parameterUsageReplacementMap = HashMap<String, String>() val parameterUsageReplacementMap = HashMap<String, String>()
val correctedTypeConverter = converter.withSpecialContext(psiClass).typeConverter /* to correct nested class references */ val correctedTypeConverter = converter.withSpecialContext(psiClass).typeConverter /* to correct nested class references */
@@ -151,8 +151,8 @@ class ConstructorConverter(
fieldsToDrop.add(field) fieldsToDrop.add(field)
val fieldName = propertyInfo.name val fieldName = propertyInfo.name
if (fieldName != parameter.getName()) { if (fieldName != parameter.name) {
parameterUsageReplacementMap.put(parameter.getName()!!, fieldName) parameterUsageReplacementMap.put(parameter.name!!, fieldName)
} }
} }
@@ -179,10 +179,10 @@ class ConstructorConverter(
fun CodeConverter.correct() = withSpecialExpressionConverter(ReplacingExpressionConverter(parameterUsageReplacementMap)) fun CodeConverter.correct() = withSpecialExpressionConverter(ReplacingExpressionConverter(parameterUsageReplacementMap))
val statement = primaryConstructor.getBody()?.getStatements()?.firstOrNull() val statement = primaryConstructor.body?.statements?.firstOrNull()
val methodCall = (statement as? PsiExpressionStatement)?.getExpression() as? PsiMethodCallExpression val methodCall = (statement as? PsiExpressionStatement)?.expression as? PsiMethodCallExpression
if (methodCall != null && methodCall.isSuperConstructorCall()) { if (methodCall != null && methodCall.isSuperConstructorCall()) {
baseClassParams = methodCall.getArgumentList().getExpressions().map { baseClassParams = methodCall.argumentList.expressions.map {
correctedConverter.deferredElement { codeConverter -> codeConverter.correct().convertExpression(it) } correctedConverter.deferredElement { codeConverter -> codeConverter.correct().convertExpression(it) }
} }
} }
@@ -218,25 +218,25 @@ class ConstructorConverter(
} }
private fun findBackingFieldForConstructorParameter(parameter: PsiParameter, constructor: PsiMethod): Pair<PsiField, PsiStatement>? { private fun findBackingFieldForConstructorParameter(parameter: PsiParameter, constructor: PsiMethod): Pair<PsiField, PsiStatement>? {
val body = constructor.getBody() ?: return null val body = constructor.body ?: return null
val refs = converter.referenceSearcher.findVariableUsages(parameter, body) val refs = converter.referenceSearcher.findVariableUsages(parameter, body)
if (refs.any { PsiUtil.isAccessedForWriting(it) }) return null if (refs.any { PsiUtil.isAccessedForWriting(it) }) return null
for (ref in refs) { for (ref in refs) {
val assignment = ref.getParent() as? PsiAssignmentExpression ?: continue val assignment = ref.parent as? PsiAssignmentExpression ?: continue
if (assignment.getOperationSign().getTokenType() != JavaTokenType.EQ) continue if (assignment.operationSign.tokenType != JavaTokenType.EQ) continue
val assignee = assignment.getLExpression() as? PsiReferenceExpression ?: continue val assignee = assignment.lExpression as? PsiReferenceExpression ?: continue
if (!assignee.isQualifierEmptyOrThis()) continue if (!assignee.isQualifierEmptyOrThis()) continue
val field = assignee.resolve() as? PsiField ?: continue val field = assignee.resolve() as? PsiField ?: continue
if (field.getContainingClass() != constructor.getContainingClass()) continue if (field.containingClass != constructor.containingClass) continue
if (field.hasModifierProperty(PsiModifier.STATIC)) continue if (field.hasModifierProperty(PsiModifier.STATIC)) continue
if (field.getInitializer() != null) continue if (field.initializer != null) continue
// assignment should be a top-level statement // assignment should be a top-level statement
val statement = assignment.getParent() as? PsiExpressionStatement ?: continue val statement = assignment.parent as? PsiExpressionStatement ?: continue
if (statement.getParent() != body) continue if (statement.parent != body) continue
// and no other assignments to field should exist in the constructor // and no other assignments to field should exist in the constructor
if (converter.referenceSearcher.findVariableUsages(field, body).any { it != assignee && PsiUtil.isAccessedForWriting(it) && it.isQualifierEmptyOrThis() }) continue if (converter.referenceSearcher.findVariableUsages(field, body).any { it != assignee && PsiUtil.isAccessedForWriting(it) && it.isQualifierEmptyOrThis() }) continue
@@ -248,19 +248,19 @@ class ConstructorConverter(
return null return null
} }
private fun PsiExpression.isSuperConstructorCall() = (this as? PsiMethodCallExpression)?.getMethodExpression()?.getText() == "super" private fun PsiExpression.isSuperConstructorCall() = (this as? PsiMethodCallExpression)?.methodExpression?.text == "super"
private fun PsiExpression.isThisConstructorCall() = (this as? PsiMethodCallExpression)?.getMethodExpression()?.getText() == "this" private fun PsiExpression.isThisConstructorCall() = (this as? PsiMethodCallExpression)?.methodExpression?.text == "this"
private inner open class ReplacingExpressionConverter(val parameterUsageReplacementMap: Map<String, String>) : SpecialExpressionConverter { private inner open class ReplacingExpressionConverter(val parameterUsageReplacementMap: Map<String, String>) : SpecialExpressionConverter {
override fun convertExpression(expression: PsiExpression, codeConverter: CodeConverter): Expression? { override fun convertExpression(expression: PsiExpression, codeConverter: CodeConverter): Expression? {
if (expression is PsiReferenceExpression && expression.getQualifier() == null) { if (expression is PsiReferenceExpression && expression.qualifier == null) {
val replacement = parameterUsageReplacementMap[expression.getReferenceName()] val replacement = parameterUsageReplacementMap[expression.referenceName]
if (replacement != null) { if (replacement != null) {
val target = expression.resolve() val target = expression.resolve()
if (target is PsiParameter) { if (target is PsiParameter) {
val scope = target.getDeclarationScope() val scope = target.declarationScope
// we do not check for exactly this constructor because default values reference parameters in other constructors // we do not check for exactly this constructor because default values reference parameters in other constructors
if (scope is PsiMember && scope.isConstructor() && scope.getParent() == psiClass) { if (scope is PsiMember && scope.isConstructor() && scope.parent == psiClass) {
return Identifier(replacement, codeConverter.typeConverter.variableNullability(target).isNullable(codeConverter.settings)) return Identifier(replacement, codeConverter.typeConverter.variableNullability(target).isNullable(codeConverter.settings))
} }
} }
+66 -66
View File
@@ -51,7 +51,7 @@ class Converter private constructor(
// state which may differ in different converter's // state which may differ in different converter's
public class PersonalState(val specialContext: PsiElement?) public class PersonalState(val specialContext: PsiElement?)
public val project: Project = elementToConvert.getProject() public val project: Project = elementToConvert.project
public val typeConverter: TypeConverter = TypeConverter(this) public val typeConverter: TypeConverter = TypeConverter(this)
public val annotationConverter: AnnotationConverter = AnnotationConverter(this) public val annotationConverter: AnnotationConverter = AnnotationConverter(this)
@@ -113,7 +113,7 @@ class Converter private constructor(
is PsiImportList -> convertImportList(element) is PsiImportList -> convertImportList(element)
is PsiImportStatementBase -> convertImport(element, false) is PsiImportStatementBase -> convertImport(element, false)
is PsiAnnotation -> annotationConverter.convertAnnotation(element, newLineAfter = false) is PsiAnnotation -> annotationConverter.convertAnnotation(element, newLineAfter = false)
is PsiPackageStatement -> PackageStatement(quoteKeywords(element.getPackageName() ?: "")).assignPrototype(element) is PsiPackageStatement -> PackageStatement(quoteKeywords(element.packageName ?: "")).assignPrototype(element)
is PsiJavaCodeReferenceElement -> { is PsiJavaCodeReferenceElement -> {
if (element.parent is PsiReferenceList) { if (element.parent is PsiReferenceList) {
val factory = JavaPsiFacade.getInstance(project).elementFactory val factory = JavaPsiFacade.getInstance(project).elementFactory
@@ -129,7 +129,7 @@ class Converter private constructor(
// we use loop with index because new deferred elements can be added during unfolding // we use loop with index because new deferred elements can be added during unfolding
var i = 0 var i = 0
while (i < commonState.deferredElements.size()) { while (i < commonState.deferredElements.size) {
val deferredElement = commonState.deferredElements[i++] val deferredElement = commonState.deferredElements[i++]
deferredElement.unfold(codeConverter.withConverter(this.withState(deferredElement.converterState))) deferredElement.unfold(codeConverter.withConverter(this.withState(deferredElement.converterState)))
} }
@@ -152,7 +152,7 @@ class Converter private constructor(
} }
private fun convertFile(javaFile: PsiJavaFile): File { private fun convertFile(javaFile: PsiJavaFile): File {
var convertedChildren = javaFile.getChildren().mapNotNull { convertTopElement(it) } var convertedChildren = javaFile.children.mapNotNull { convertTopElement(it) }
return File(convertedChildren).assignPrototype(javaFile) return File(convertedChildren).assignPrototype(javaFile)
} }
@@ -160,26 +160,26 @@ class Converter private constructor(
= annotationConverter.convertAnnotations(owner) = annotationConverter.convertAnnotations(owner)
public fun convertClass(psiClass: PsiClass): Class { public fun convertClass(psiClass: PsiClass): Class {
if (psiClass.isAnnotationType()) { if (psiClass.isAnnotationType) {
return convertAnnotationType(psiClass) return convertAnnotationType(psiClass)
} }
val annotations = convertAnnotations(psiClass) val annotations = convertAnnotations(psiClass)
var modifiers = convertModifiers(psiClass, false) var modifiers = convertModifiers(psiClass, false)
val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList()) val typeParameters = convertTypeParameterList(psiClass.typeParameterList)
val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes()) val extendsTypes = convertToNotNullableTypes(psiClass.extendsListTypes)
val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes()) val implementsTypes = convertToNotNullableTypes(psiClass.implementsListTypes)
val name = psiClass.declarationIdentifier() val name = psiClass.declarationIdentifier()
return when { return when {
psiClass.isInterface() -> { psiClass.isInterface -> {
val classBody = ClassBodyConverter(psiClass, ClassKind.INTERFACE, this).convertBody() val classBody = ClassBodyConverter(psiClass, ClassKind.INTERFACE, this).convertBody()
Interface(name, annotations, modifiers, typeParameters, extendsTypes, implementsTypes, classBody) Interface(name, annotations, modifiers, typeParameters, extendsTypes, implementsTypes, classBody)
} }
psiClass.isEnum() -> { psiClass.isEnum -> {
modifiers = modifiers.without(Modifier.ABSTRACT) modifiers = modifiers.without(Modifier.ABSTRACT)
val hasInheritors = psiClass.getFields().any { it is PsiEnumConstant && it.getInitializingClass() != null } val hasInheritors = psiClass.fields.any { it is PsiEnumConstant && it.initializingClass != null }
val classBody = ClassBodyConverter(psiClass, if (hasInheritors) ClassKind.OPEN_ENUM else ClassKind.FINAL_ENUM, this).convertBody() val classBody = ClassBodyConverter(psiClass, if (hasInheritors) ClassKind.OPEN_ENUM else ClassKind.FINAL_ENUM, this).convertBody()
Enum(name, annotations, modifiers, typeParameters, implementsTypes, classBody) Enum(name, annotations, modifiers, typeParameters, implementsTypes, classBody)
} }
@@ -190,7 +190,7 @@ class Converter private constructor(
Object(name, annotations, modifiers.without(Modifier.ABSTRACT), classBody) Object(name, annotations, modifiers.without(Modifier.ABSTRACT), classBody)
} }
else { else {
if (psiClass.getContainingClass() != null && !psiClass.hasModifierProperty(PsiModifier.STATIC)) { if (psiClass.containingClass != null && !psiClass.hasModifierProperty(PsiModifier.STATIC)) {
modifiers = modifiers.with(Modifier.INNER) modifiers = modifiers.with(Modifier.INNER)
} }
@@ -214,25 +214,25 @@ class Converter private constructor(
} }
private fun shouldConvertIntoObject(psiClass: PsiClass): Boolean { private fun shouldConvertIntoObject(psiClass: PsiClass): Boolean {
val methods = psiClass.getMethods() val methods = psiClass.methods
val fields = psiClass.getFields() val fields = psiClass.fields
val classes = psiClass.getInnerClasses() val classes = psiClass.innerClasses
if (methods.isEmpty() && fields.isEmpty()) return false if (methods.isEmpty() && fields.isEmpty()) return false
fun isStatic(member: PsiMember) = member.hasModifierProperty(PsiModifier.STATIC) fun isStatic(member: PsiMember) = member.hasModifierProperty(PsiModifier.STATIC)
if (!methods.all { isStatic(it) || it.isConstructor() } || !fields.all(::isStatic) || !classes.all(::isStatic)) return false if (!methods.all { isStatic(it) || it.isConstructor } || !fields.all(::isStatic) || !classes.all(::isStatic)) return false
val constructors = psiClass.getConstructors() val constructors = psiClass.constructors
if (constructors.size() > 1) return false if (constructors.size > 1) return false
val constructor = constructors.singleOrNull() val constructor = constructors.singleOrNull()
if (constructor != null) { if (constructor != null) {
if (!constructor.hasModifierProperty(PsiModifier.PRIVATE)) return false if (!constructor.hasModifierProperty(PsiModifier.PRIVATE)) return false
if (constructor.getParameterList().getParameters().isNotEmpty()) return false if (constructor.parameterList.parameters.isNotEmpty()) return false
if (constructor.getBody()?.getStatements()?.isNotEmpty() ?: false) return false if (constructor.body?.statements?.isNotEmpty() ?: false) return false
if (constructor.getModifierList().getAnnotations().isNotEmpty()) return false if (constructor.modifierList.annotations.isNotEmpty()) return false
} }
if (psiClass.getExtendsListTypes().isNotEmpty() || psiClass.getImplementsListTypes().isNotEmpty()) return false if (psiClass.extendsListTypes.isNotEmpty() || psiClass.implementsListTypes.isNotEmpty()) return false
if (psiClass.getTypeParameters().isNotEmpty()) return false if (psiClass.typeParameters.isNotEmpty()) return false
if (referenceSearcher.hasInheritors(psiClass)) return false if (referenceSearcher.hasInheritors(psiClass)) return false
@@ -241,11 +241,11 @@ class Converter private constructor(
private fun convertAnnotationType(psiClass: PsiClass): Class { private fun convertAnnotationType(psiClass: PsiClass): Class {
val paramModifiers = Modifiers(listOf(Modifier.PUBLIC)).assignNoPrototype() val paramModifiers = Modifiers(listOf(Modifier.PUBLIC)).assignNoPrototype()
val annotationMethods = psiClass.getMethods().filterIsInstance<PsiAnnotationMethod>() val annotationMethods = psiClass.methods.filterIsInstance<PsiAnnotationMethod>()
val (methodsNamedValue, otherMethods) = annotationMethods.partition { it.getName() == "value" } val (methodsNamedValue, otherMethods) = annotationMethods.partition { it.name == "value" }
fun createParameter(type: Type, method: PsiAnnotationMethod): FunctionParameter { fun createParameter(type: Type, method: PsiAnnotationMethod): FunctionParameter {
type.assignPrototype(method.getReturnTypeElement(), CommentsAndSpacesInheritance.NO_SPACES) type.assignPrototype(method.returnTypeElement, CommentsAndSpacesInheritance.NO_SPACES)
return FunctionParameter(method.declarationIdentifier(), return FunctionParameter(method.declarationIdentifier(),
type, type,
@@ -263,15 +263,15 @@ class Converter private constructor(
// Argument named `value` comes first if it exists // Argument named `value` comes first if it exists
// Convert it as vararg if it's array // Convert it as vararg if it's array
methodsNamedValue.map { method -> methodsNamedValue.map { method ->
val returnType = method.getReturnType() val returnType = method.returnType
val typeConverted = if (returnType is PsiArrayType) val typeConverted = if (returnType is PsiArrayType)
VarArgType(convertType(returnType.getComponentType())) VarArgType(convertType(returnType.componentType))
else else
convertType(returnType) convertType(returnType)
createParameter(typeConverted, method) createParameter(typeConverted, method)
} + } +
otherMethods.map { method -> createParameter(convertType(method.getReturnType()), method) } otherMethods.map { method -> createParameter(convertType(method.returnType), method) }
val parameterList = ParameterList(parameters).assignNoPrototype() val parameterList = ParameterList(parameters).assignNoPrototype()
val constructorSignature = if (parameterList.parameters.isNotEmpty()) val constructorSignature = if (parameterList.parameters.isNotEmpty())
@@ -295,7 +295,7 @@ class Converter private constructor(
} }
public fun convertInitializer(initializer: PsiClassInitializer): Initializer { public fun convertInitializer(initializer: PsiClassInitializer): Initializer {
return Initializer(deferredElement { codeConverter -> codeConverter.convertBlock(initializer.getBody()) }, return Initializer(deferredElement { codeConverter -> codeConverter.convertBlock(initializer.body) },
convertModifiers(initializer, false)).assignPrototype(initializer) convertModifiers(initializer, false)).assignPrototype(initializer)
} }
@@ -312,11 +312,11 @@ class Converter private constructor(
val name = propertyInfo.identifier val name = propertyInfo.identifier
if (field is PsiEnumConstant) { if (field is PsiEnumConstant) {
assert(getMethod == null && setMethod == null) assert(getMethod == null && setMethod == null)
val argumentList = field.getArgumentList() val argumentList = field.argumentList
val params = deferredElement { codeConverter -> val params = deferredElement { codeConverter ->
ExpressionList(codeConverter.convertExpressions(argumentList?.getExpressions() ?: arrayOf<PsiExpression>())).assignPrototype(argumentList) ExpressionList(codeConverter.convertExpressions(argumentList?.expressions ?: arrayOf<PsiExpression>())).assignPrototype(argumentList)
} }
val body = field.getInitializingClass()?.let { convertAnonymousClassBody(it) } val body = field.initializingClass?.let { convertAnonymousClassBody(it) }
return EnumConstant(name, annotations, modifiers, params, body) return EnumConstant(name, annotations, modifiers, params, body)
.assignPrototype(field, CommentsAndSpacesInheritance.LINE_BREAKS) .assignPrototype(field, CommentsAndSpacesInheritance.LINE_BREAKS)
} }
@@ -443,12 +443,12 @@ class Converter private constructor(
} }
public fun shouldDeclareVariableType(variable: PsiVariable, type: Type, canChangeType: Boolean): Boolean { public fun shouldDeclareVariableType(variable: PsiVariable, type: Type, canChangeType: Boolean): Boolean {
val initializer = variable.getInitializer() val initializer = variable.initializer
if (initializer == null || initializer.isNullLiteral()) return true if (initializer == null || initializer.isNullLiteral()) return true
if (canChangeType) return false if (canChangeType) return false
var initializerType = createDefaultCodeConverter().convertedExpressionType(initializer, variable.getType()) var initializerType = createDefaultCodeConverter().convertedExpressionType(initializer, variable.type)
if (initializerType is ErrorType) return false // do not add explicit type when initializer is not resolved, let user add it if really needed if (initializerType is ErrorType) return false // do not add explicit type when initializer is not resolved, let user add it if really needed
return type != initializerType return type != initializerType
} }
@@ -467,7 +467,7 @@ class Converter private constructor(
var modifiers = convertModifiers(method, classKind.isOpen()) var modifiers = convertModifiers(method, classKind.isOpen())
val statementsToInsert = ArrayList<Statement>() val statementsToInsert = ArrayList<Statement>()
for (parameter in method.getParameterList().getParameters()) { for (parameter in method.parameterList.parameters) {
if (parameter.hasWriteAccesses(referenceSearcher, method)) { if (parameter.hasWriteAccesses(referenceSearcher, method)) {
val variable = LocalVariable(parameter.declarationIdentifier(), val variable = LocalVariable(parameter.declarationIdentifier(),
Annotations.Empty, Annotations.Empty,
@@ -487,15 +487,15 @@ class Converter private constructor(
} }
} }
val function = if (method.isConstructor() && constructorConverter != null) { val function = if (method.isConstructor && constructorConverter != null) {
constructorConverter.convertConstructor(method, annotations, modifiers, fieldsToDrop!!, postProcessBody) constructorConverter.convertConstructor(method, annotations, modifiers, fieldsToDrop!!, postProcessBody)
} }
else { else {
val containingClass = method.getContainingClass() val containingClass = method.containingClass
if (settings.openByDefault) { if (settings.openByDefault) {
val isEffectivelyFinal = method.hasModifierProperty(PsiModifier.FINAL) || val isEffectivelyFinal = method.hasModifierProperty(PsiModifier.FINAL) ||
containingClass != null && (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isEnum()) containingClass != null && (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isEnum)
if (!isEffectivelyFinal && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.isPrivate) { if (!isEffectivelyFinal && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.isPrivate) {
modifiers = modifiers.with(Modifier.OPEN) modifiers = modifiers.with(Modifier.OPEN)
} }
@@ -503,9 +503,9 @@ class Converter private constructor(
var params = convertParameterList(method, overloadReducer) var params = convertParameterList(method, overloadReducer)
val typeParameterList = convertTypeParameterList(method.getTypeParameterList()) val typeParameterList = convertTypeParameterList(method.typeParameterList)
var body = deferredElement { codeConverter: CodeConverter -> var body = deferredElement { codeConverter: CodeConverter ->
val body = codeConverter.withMethodReturnType(method.getReturnType()).convertBlock(method.getBody()) val body = codeConverter.withMethodReturnType(method.returnType).convertBlock(method.body)
postProcessBody(body) postProcessBody(body)
} }
Function(method.declarationIdentifier(), annotations, modifiers, returnType, typeParameterList, params, body, classKind == ClassKind.INTERFACE) Function(method.declarationIdentifier(), annotations, modifiers, returnType, typeParameterList, params, body, classKind == ClassKind.INTERFACE)
@@ -534,27 +534,27 @@ class Converter private constructor(
* Overrides of methods from Object should not be marked as overrides in Kotlin unless the class itself has java ancestors * Overrides of methods from Object should not be marked as overrides in Kotlin unless the class itself has java ancestors
*/ */
private fun isOverride(method: PsiMethod): Boolean { private fun isOverride(method: PsiMethod): Boolean {
val superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures() val superSignatures = method.hierarchicalMethodSignature.superSignatures
val overridesMethodNotFromObject = superSignatures.any { val overridesMethodNotFromObject = superSignatures.any {
it.getMethod().getContainingClass()?.getQualifiedName() != JAVA_LANG_OBJECT it.method.containingClass?.qualifiedName != JAVA_LANG_OBJECT
} }
if (overridesMethodNotFromObject) return true if (overridesMethodNotFromObject) return true
val overridesMethodFromObject = superSignatures.any { val overridesMethodFromObject = superSignatures.any {
it.getMethod().getContainingClass()?.getQualifiedName() == JAVA_LANG_OBJECT it.method.containingClass?.qualifiedName == JAVA_LANG_OBJECT
} }
if (overridesMethodFromObject) { if (overridesMethodFromObject) {
when (method.getName()) { when (method.name) {
"equals", "hashCode", "toString" -> return true // these methods from java.lang.Object exist in kotlin.Any "equals", "hashCode", "toString" -> return true // these methods from java.lang.Object exist in kotlin.Any
else -> { else -> {
val containing = method.getContainingClass() val containing = method.containingClass
if (containing != null) { if (containing != null) {
val hasOtherJavaSuperclasses = containing.getSuperTypes().any { val hasOtherJavaSuperclasses = containing.superTypes.any {
//TODO: correctly check for kotlin class //TODO: correctly check for kotlin class
val klass = it.resolve() val klass = it.resolve()
klass != null && klass.getQualifiedName() != JAVA_LANG_OBJECT && !inConversionScope(klass) klass != null && klass.qualifiedName != JAVA_LANG_OBJECT && !inConversionScope(klass)
} }
if (hasOtherJavaSuperclasses) return true if (hasOtherJavaSuperclasses) return true
} }
@@ -579,15 +579,15 @@ class Converter private constructor(
} }
public fun convertCodeReferenceElement(element: PsiJavaCodeReferenceElement, hasExternalQualifier: Boolean, typeArgsConverted: List<Element>? = null): ReferenceElement { public fun convertCodeReferenceElement(element: PsiJavaCodeReferenceElement, hasExternalQualifier: Boolean, typeArgsConverted: List<Element>? = null): ReferenceElement {
val typeArgs = typeArgsConverted ?: typeConverter.convertTypes(element.getTypeParameters()) val typeArgs = typeArgsConverted ?: typeConverter.convertTypes(element.typeParameters)
if (element.isQualified()) { if (element.isQualified) {
var result = Identifier.toKotlin(element.getReferenceName()!!) var result = Identifier.toKotlin(element.referenceName!!)
var qualifier = element.getQualifier() var qualifier = element.qualifier
while (qualifier != null) { while (qualifier != null) {
val codeRefElement = qualifier as PsiJavaCodeReferenceElement val codeRefElement = qualifier as PsiJavaCodeReferenceElement
result = Identifier.toKotlin(codeRefElement.getReferenceName()!!) + "." + result result = Identifier.toKotlin(codeRefElement.referenceName!!) + "." + result
qualifier = codeRefElement.getQualifier() qualifier = codeRefElement.qualifier
} }
return ReferenceElement(Identifier(result).assignNoPrototype(), typeArgs).assignPrototype(element) return ReferenceElement(Identifier(result).assignNoPrototype(), typeArgs).assignPrototype(element)
} }
@@ -603,17 +603,17 @@ class Converter private constructor(
} }
} }
return ReferenceElement(Identifier(element.getReferenceName()!!).assignNoPrototype(), typeArgs).assignPrototype(element) return ReferenceElement(Identifier(element.referenceName!!).assignNoPrototype(), typeArgs).assignPrototype(element)
} }
} }
private fun constructNestedClassReferenceIdentifier(psiClass: PsiClass, context: PsiElement): Identifier? { private fun constructNestedClassReferenceIdentifier(psiClass: PsiClass, context: PsiElement): Identifier? {
val outerClass = psiClass.getContainingClass() val outerClass = psiClass.containingClass
if (outerClass != null if (outerClass != null
&& !PsiTreeUtil.isAncestor(outerClass, context, true) && !PsiTreeUtil.isAncestor(outerClass, context, true)
&& !psiClass.isImported(context.getContainingFile() as PsiJavaFile)) { && !psiClass.isImported(context.containingFile as PsiJavaFile)) {
val qualifier = constructNestedClassReferenceIdentifier(outerClass, context)?.name ?: outerClass.getName()!! val qualifier = constructNestedClassReferenceIdentifier(outerClass, context)?.name ?: outerClass.name!!
return Identifier(Identifier.toKotlin(qualifier) + "." + Identifier.toKotlin(psiClass.getName()!!)).assignNoPrototype() return Identifier(Identifier.toKotlin(qualifier) + "." + Identifier.toKotlin(psiClass.name!!)).assignNoPrototype()
} }
return null return null
} }
@@ -643,12 +643,12 @@ class Converter private constructor(
public fun convertIdentifier(identifier: PsiIdentifier?): Identifier { public fun convertIdentifier(identifier: PsiIdentifier?): Identifier {
if (identifier == null) return Identifier.Empty if (identifier == null) return Identifier.Empty
return Identifier(identifier.getText()!!).assignPrototype(identifier) return Identifier(identifier.text!!).assignPrototype(identifier)
} }
public fun convertModifiers(owner: PsiModifierListOwner, isMethodInOpenClass: Boolean): Modifiers { public fun convertModifiers(owner: PsiModifierListOwner, isMethodInOpenClass: Boolean): Modifiers {
var modifiers = Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }) var modifiers = Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second })
.assignPrototype(owner.getModifierList(), CommentsAndSpacesInheritance.NO_SPACES) .assignPrototype(owner.modifierList, CommentsAndSpacesInheritance.NO_SPACES)
if (owner is PsiMethod) { if (owner is PsiMethod) {
val isOverride = isOverride(owner) val isOverride = isOverride(owner)
@@ -682,7 +682,7 @@ class Converter private constructor(
public fun convertAnonymousClassBody(anonymousClass: PsiAnonymousClass): AnonymousClassBody { public fun convertAnonymousClassBody(anonymousClass: PsiAnonymousClass): AnonymousClassBody {
return AnonymousClassBody(ClassBodyConverter(anonymousClass, ClassKind.ANONYMOUS_OBJECT, this).convertBody(), return AnonymousClassBody(ClassBodyConverter(anonymousClass, ClassKind.ANONYMOUS_OBJECT, this).convertBody(),
anonymousClass.getBaseClassType().resolve()?.isInterface() ?: false).assignPrototype(anonymousClass) anonymousClass.baseClassType.resolve()?.isInterface ?: false).assignPrototype(anonymousClass)
} }
private val MODIFIERS_MAP = listOf( private val MODIFIERS_MAP = listOf(
@@ -694,10 +694,10 @@ class Converter private constructor(
) )
private fun convertThrows(method: PsiMethod): Annotations { private fun convertThrows(method: PsiMethod): Annotations {
val throwsList = method.getThrowsList() val throwsList = method.throwsList
val types = throwsList.getReferencedTypes() val types = throwsList.referencedTypes
val refElements = throwsList.getReferenceElements() val refElements = throwsList.referenceElements
assert(types.size() == refElements.size()) assert(types.size == refElements.size)
if (types.isEmpty()) return Annotations.Empty if (types.isEmpty()) return Annotations.Empty
val arguments = types.indices.map { index -> val arguments = types.indices.map { index ->
val convertedType = typeConverter.convertType(types[index], Nullability.NotNull) val convertedType = typeConverter.convertType(types[index], Nullability.NotNull)
@@ -30,8 +30,8 @@ object EmptyDocCommentConverter: DocCommentConverter {
} }
fun PsiDocTag.content(): String = fun PsiDocTag.content(): String =
getChildren() children
.dropWhile { it.getNode().getElementType() == JavaDocTokenType.DOC_TAG_NAME } .dropWhile { it.node.elementType == JavaDocTokenType.DOC_TAG_NAME }
.dropWhile { it is PsiWhiteSpace } .dropWhile { it is PsiWhiteSpace }
.filterNot { it.getNode().getElementType() == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } .filterNot { it.node.elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS }
.joinToString("") { it.getText() } .joinToString("") { it.text }
@@ -68,26 +68,26 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
override fun visitArrayAccessExpression(expression: PsiArrayAccessExpression) { override fun visitArrayAccessExpression(expression: PsiArrayAccessExpression) {
val assignment = expression.getStrictParentOfType<PsiAssignmentExpression>() val assignment = expression.getStrictParentOfType<PsiAssignmentExpression>()
val lvalue = assignment != null && expression == assignment.getLExpression(); val lvalue = assignment != null && expression == assignment.lExpression;
result = ArrayAccessExpression(codeConverter.convertExpression(expression.getArrayExpression()), result = ArrayAccessExpression(codeConverter.convertExpression(expression.arrayExpression),
codeConverter.convertExpression(expression.getIndexExpression()), codeConverter.convertExpression(expression.indexExpression),
lvalue) lvalue)
} }
override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression) { override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression) {
val arrayType = expression.getType() val arrayType = expression.type
val componentType = (arrayType as? PsiArrayType)?.getComponentType() val componentType = (arrayType as? PsiArrayType)?.componentType
val expressionType = typeConverter.convertType(arrayType) val expressionType = typeConverter.convertType(arrayType)
assert(expressionType is ArrayType) { "Array initializer must have array type: expressionType = $expressionType expression = $expression" } assert(expressionType is ArrayType) { "Array initializer must have array type: expressionType = $expressionType expression = $expression" }
result = createArrayInitializerExpression(expressionType as ArrayType, result = createArrayInitializerExpression(expressionType as ArrayType,
expression.getInitializers().map { codeConverter.convertExpression(it, componentType) }) expression.initializers.map { codeConverter.convertExpression(it, componentType) })
} }
override fun visitAssignmentExpression(expression: PsiAssignmentExpression) { override fun visitAssignmentExpression(expression: PsiAssignmentExpression) {
val tokenType = expression.getOperationSign().getTokenType() val tokenType = expression.operationSign.tokenType
val lhs = codeConverter.convertExpression(expression.getLExpression()) val lhs = codeConverter.convertExpression(expression.lExpression)
val rhs = codeConverter.convertExpression(expression.getRExpression()!!, expression.getLExpression().getType()) val rhs = codeConverter.convertExpression(expression.rExpression!!, expression.lExpression.type)
val secondOp = when(tokenType) { val secondOp = when(tokenType) {
JavaTokenType.GTGTEQ, JavaTokenType.LTLTEQ, JavaTokenType.GTGTGTEQ, JavaTokenType.GTGTEQ, JavaTokenType.LTLTEQ, JavaTokenType.GTGTGTEQ,
@@ -106,12 +106,12 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
override fun visitBinaryExpression(expression: PsiBinaryExpression) { override fun visitBinaryExpression(expression: PsiBinaryExpression) {
val left = expression.getLOperand() val left = expression.lOperand
val right = expression.getROperand() val right = expression.rOperand
var leftConverted = codeConverter.convertExpression(left, null) var leftConverted = codeConverter.convertExpression(left, null)
var rightConverted = codeConverter.convertExpression(right, null) var rightConverted = codeConverter.convertExpression(right, null)
val operationTokenType = expression.getOperationTokenType() val operationTokenType = expression.operationTokenType
if (operationTokenType in NON_NULL_OPERAND_OPS) { if (operationTokenType in NON_NULL_OPERAND_OPS) {
leftConverted = BangBangExpression.surroundIfNullable(leftConverted) leftConverted = BangBangExpression.surroundIfNullable(leftConverted)
rightConverted = BangBangExpression.surroundIfNullable(rightConverted) rightConverted = BangBangExpression.surroundIfNullable(rightConverted)
@@ -133,18 +133,18 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
private fun canKeepEqEq(left: PsiExpression, right: PsiExpression?): Boolean { private fun canKeepEqEq(left: PsiExpression, right: PsiExpression?): Boolean {
if (left.isNullLiteral() || (right?.isNullLiteral() ?: false)) return true if (left.isNullLiteral() || (right?.isNullLiteral() ?: false)) return true
val type = left.getType() val type = left.type
when (type) { when (type) {
is PsiPrimitiveType, is PsiArrayType -> return true is PsiPrimitiveType, is PsiArrayType -> return true
is PsiClassType -> { is PsiClassType -> {
val psiClass = type.resolve() ?: return false val psiClass = type.resolve() ?: return false
if (!psiClass.hasModifierProperty(PsiModifier.FINAL)) return false if (!psiClass.hasModifierProperty(PsiModifier.FINAL)) return false
if (psiClass.isEnum()) return true if (psiClass.isEnum) return true
val equalsSignature = getEqualsSignature(converter.project, GlobalSearchScope.allScope(converter.project)) val equalsSignature = getEqualsSignature(converter.project, GlobalSearchScope.allScope(converter.project))
val equalsMethod = MethodSignatureUtil.findMethodBySignature(psiClass, equalsSignature, true) val equalsMethod = MethodSignatureUtil.findMethodBySignature(psiClass, equalsSignature, true)
if (equalsMethod != null && equalsMethod.getContainingClass()?.getQualifiedName() != CommonClassNames.JAVA_LANG_OBJECT) return false if (equalsMethod != null && equalsMethod.containingClass?.qualifiedName != CommonClassNames.JAVA_LANG_OBJECT) return false
return true return true
} }
@@ -172,11 +172,11 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
JavaTokenType.GTGTGT) JavaTokenType.GTGTGT)
override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression) { override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression) {
val operand = expression.getOperand() val operand = expression.operand
val typeName = operand.getType().getCanonicalText() val typeName = operand.type.canonicalText
val primitiveType = JvmPrimitiveType.values().firstOrNull { it.getJavaKeywordName() == typeName } val primitiveType = JvmPrimitiveType.values.firstOrNull { it.javaKeywordName == typeName }
val wrapperTypeName = if (primitiveType != null) { val wrapperTypeName = if (primitiveType != null) {
primitiveType.getWrapperFqName() primitiveType.wrapperFqName
} }
else if (typeName == "void") { // by unknown reason it's not in JvmPrimitiveType enum else if (typeName == "void") { // by unknown reason it's not in JvmPrimitiveType enum
FqName("java.lang.Void") FqName("java.lang.Void")
@@ -198,30 +198,30 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
override fun visitConditionalExpression(expression: PsiConditionalExpression) { override fun visitConditionalExpression(expression: PsiConditionalExpression) {
val condition = expression.getCondition() val condition = expression.condition
val type = condition.getType() val type = condition.type
val expr = if (type != null) val expr = if (type != null)
codeConverter.convertExpression(condition, type) codeConverter.convertExpression(condition, type)
else else
codeConverter.convertExpression(condition) codeConverter.convertExpression(condition)
result = IfStatement(expr, result = IfStatement(expr,
codeConverter.convertExpression(expression.getThenExpression()), codeConverter.convertExpression(expression.thenExpression),
codeConverter.convertExpression(expression.getElseExpression()), codeConverter.convertExpression(expression.elseExpression),
expression.isInSingleLine()) expression.isInSingleLine())
} }
override fun visitInstanceOfExpression(expression: PsiInstanceOfExpression) { override fun visitInstanceOfExpression(expression: PsiInstanceOfExpression) {
val checkType = expression.getCheckType() val checkType = expression.checkType
result = IsOperator(codeConverter.convertExpression(expression.getOperand()), result = IsOperator(codeConverter.convertExpression(expression.operand),
converter.convertTypeElement(checkType, Nullability.NotNull)) converter.convertTypeElement(checkType, Nullability.NotNull))
} }
override fun visitLiteralExpression(expression: PsiLiteralExpression) { override fun visitLiteralExpression(expression: PsiLiteralExpression) {
val value = expression.getValue() val value = expression.value
var text = expression.getText()!! var text = expression.text!!
val type = expression.getType() val type = expression.type
if (type != null) { if (type != null) {
val typeStr = type.getCanonicalText() val typeStr = type.canonicalText
if (typeStr == "double") { if (typeStr == "double") {
text = text.replace("D", "").replace("d", "") text = text.replace("D", "").replace("d", "")
if (!text.contains(".")) { if (!text.contains(".")) {
@@ -247,8 +247,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
val methodExpr = expression.getMethodExpression() val methodExpr = expression.methodExpression
val arguments = expression.getArgumentList().getExpressions() val arguments = expression.argumentList.expressions
val target = methodExpr.resolve() val target = methodExpr.resolve()
val isNullable = if (target is PsiMethod) typeConverter.methodNullability(target).isNullable(codeConverter.settings) else false val isNullable = if (target is PsiMethod) typeConverter.methodNullability(target).isNullable(codeConverter.settings) else false
val typeArguments = convertTypeArguments(expression) val typeArguments = convertTypeArguments(expression)
@@ -258,12 +258,12 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val isTopLevel = origin?.getStrictParentOfType<KtClassOrObject>() == null val isTopLevel = origin?.getStrictParentOfType<KtClassOrObject>() == null
if (origin is KtProperty || origin is KtPropertyAccessor || origin is KtParameter) { if (origin is KtProperty || origin is KtPropertyAccessor || origin is KtParameter) {
val property = if (origin is KtPropertyAccessor) val property = if (origin is KtPropertyAccessor)
origin.getParent() as KtProperty origin.parent as KtProperty
else else
origin as KtNamedDeclaration origin as KtNamedDeclaration
val parameterCount = target.getParameterList().getParameters().size() val parameterCount = target.parameterList.parameters.size
if (parameterCount == arguments.size()) { if (parameterCount == arguments.size) {
val propertyName = Identifier(property.getName()!!, isNullable).assignNoPrototype() val propertyName = Identifier(property.name!!, isNullable).assignNoPrototype()
val isExtension = property.isExtensionDeclaration() val isExtension = property.isExtensionDeclaration()
val propertyAccess = if (isTopLevel) { val propertyAccess = if (isTopLevel) {
if (isExtension) if (isExtension)
@@ -272,7 +272,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
propertyName propertyName
} }
else { else {
QualifiedExpression(codeConverter.convertExpression(methodExpr.getQualifierExpression()), propertyName).assignNoPrototype() QualifiedExpression(codeConverter.convertExpression(methodExpr.qualifierExpression), propertyName).assignNoPrototype()
} }
when(if (isExtension) parameterCount - 1 else parameterCount) { when(if (isExtension) parameterCount - 1 else parameterCount) {
@@ -294,14 +294,14 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
result = if (origin.isExtensionDeclaration()) { result = if (origin.isExtensionDeclaration()) {
val qualifier = codeConverter.convertExpression(arguments.firstOrNull()) val qualifier = codeConverter.convertExpression(arguments.firstOrNull())
MethodCallExpression.build(qualifier, MethodCallExpression.build(qualifier,
origin.getName()!!, origin.name!!,
convertArguments(expression, isExtension = true), convertArguments(expression, isExtension = true),
typeArguments, typeArguments,
isNullable) isNullable)
} }
else { else {
MethodCallExpression.build(null, MethodCallExpression.build(null,
origin.getName()!!, origin.name!!,
convertArguments(expression), convertArguments(expression),
typeArguments, typeArguments,
isNullable) isNullable)
@@ -312,9 +312,9 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
if (target is PsiMethod) { if (target is PsiMethod) {
val specialMethod = SpecialMethod.match(target, arguments.size(), converter.services) val specialMethod = SpecialMethod.match(target, arguments.size, converter.services)
if (specialMethod != null) { if (specialMethod != null) {
val converted = specialMethod.convertCall(methodExpr.getQualifierExpression(), arguments, typeArguments, codeConverter) val converted = specialMethod.convertCall(methodExpr.qualifierExpression, arguments, typeArguments, codeConverter)
if (converted != null) { if (converted != null) {
result = converted result = converted
return return
@@ -329,17 +329,17 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
private fun convertTypeArguments(call: PsiCallExpression): List<Type> { private fun convertTypeArguments(call: PsiCallExpression): List<Type> {
var typeArgs = call.getTypeArguments().toList() var typeArgs = call.typeArguments.toList()
// always add explicit type arguments and remove them if they are redundant later // always add explicit type arguments and remove them if they are redundant later
if (typeArgs.size() == 0) { if (typeArgs.size == 0) {
val resolve = call.resolveMethodGenerics() val resolve = call.resolveMethodGenerics()
if (resolve.isValidResult()) { if (resolve.isValidResult) {
val method = resolve.getElement() as? PsiMethod val method = resolve.element as? PsiMethod
if (method != null) { if (method != null) {
val typeParameters = method.getTypeParameters() val typeParameters = method.typeParameters
if (typeParameters.isNotEmpty()) { if (typeParameters.isNotEmpty()) {
val map = resolve.getSubstitutor().getSubstitutionMap() val map = resolve.substitutor.substitutionMap
typeArgs = typeParameters.map { map[it] ?: return listOf() } typeArgs = typeParameters.map { map[it] ?: return listOf() }
} }
} }
@@ -351,13 +351,13 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
override fun visitNewExpression(expression: PsiNewExpression) { override fun visitNewExpression(expression: PsiNewExpression) {
val type = expression.type val type = expression.type
if (expression.getArrayInitializer() != null) { if (expression.arrayInitializer != null) {
result = codeConverter.convertExpression(expression.getArrayInitializer()) result = codeConverter.convertExpression(expression.arrayInitializer)
} }
else if (expression.getArrayDimensions().size() > 0 && expression.getType() is PsiArrayType) { else if (expression.arrayDimensions.size > 0 && expression.type is PsiArrayType) {
result = ArrayWithoutInitializationExpression( result = ArrayWithoutInitializationExpression(
typeConverter.convertType(expression.type, Nullability.NotNull) as ArrayType, typeConverter.convertType(expression.type, Nullability.NotNull) as ArrayType,
codeConverter.convertExpressions(expression.getArrayDimensions())) codeConverter.convertExpressions(expression.arrayDimensions))
} }
else { else {
if (type?.canonicalText in PsiPrimitiveType.getAllBoxedTypeNames()) { if (type?.canonicalText in PsiPrimitiveType.getAllBoxedTypeNames()) {
@@ -368,8 +368,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
} }
val qualifier = expression.getQualifier() val qualifier = expression.qualifier
val classRef = expression.getClassOrAnonymousClassReference() val classRef = expression.classOrAnonymousClassReference
val classRefConverted = if (classRef != null) converter.convertCodeReferenceElement(classRef, hasExternalQualifier = qualifier != null) else null val classRefConverted = if (classRef != null) converter.convertCodeReferenceElement(classRef, hasExternalQualifier = qualifier != null) else null
result = NewClassExpression(classRefConverted, result = NewClassExpression(classRefConverted,
convertArguments(expression), convertArguments(expression),
@@ -379,17 +379,17 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression) { override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression) {
result = ParenthesizedExpression(codeConverter.convertExpression(expression.getExpression())) result = ParenthesizedExpression(codeConverter.convertExpression(expression.expression))
} }
override fun visitPostfixExpression(expression: PsiPostfixExpression) { override fun visitPostfixExpression(expression: PsiPostfixExpression) {
result = PostfixExpression(Operator(expression.getOperationSign().getTokenType()).assignPrototype(expression.operationSign), result = PostfixExpression(Operator(expression.operationSign.tokenType).assignPrototype(expression.operationSign),
codeConverter.convertExpression(expression.getOperand())) codeConverter.convertExpression(expression.operand))
} }
override fun visitPrefixExpression(expression: PsiPrefixExpression) { override fun visitPrefixExpression(expression: PsiPrefixExpression) {
val operand = codeConverter.convertExpression(expression.getOperand(), expression.getOperand()!!.getType()) val operand = codeConverter.convertExpression(expression.operand, expression.operand!!.type)
val token = expression.getOperationTokenType() val token = expression.operationTokenType
if (token == JavaTokenType.TILDE) { if (token == JavaTokenType.TILDE) {
result = MethodCallExpression.buildNotNull(operand, "inv") result = MethodCallExpression.buildNotNull(operand, "inv")
} }
@@ -403,22 +403,22 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
override fun visitReferenceExpression(expression: PsiReferenceExpression) { override fun visitReferenceExpression(expression: PsiReferenceExpression) {
// to avoid quoting of 'this' and 'super' in calls to this/super class constructors // to avoid quoting of 'this' and 'super' in calls to this/super class constructors
if (expression.getText() == "this") { if (expression.text == "this") {
result = ThisExpression(Identifier.Empty) result = ThisExpression(Identifier.Empty)
return return
} }
if (expression.getText() == "super") { if (expression.text == "super") {
result = SuperExpression(Identifier.Empty) result = SuperExpression(Identifier.Empty)
return return
} }
val referenceName = expression.getReferenceName()!! val referenceName = expression.referenceName!!
val target = expression.resolve() val target = expression.resolve()
val isNullable = target is PsiVariable && typeConverter.variableNullability(target).isNullable(codeConverter.settings) val isNullable = target is PsiVariable && typeConverter.variableNullability(target).isNullable(codeConverter.settings)
val qualifier = expression.getQualifierExpression() val qualifier = expression.qualifierExpression
var identifier = Identifier(referenceName, isNullable).assignNoPrototype() var identifier = Identifier(referenceName, isNullable).assignNoPrototype()
if (qualifier != null && qualifier.getType() is PsiArrayType && referenceName == "length") { if (qualifier != null && qualifier.type is PsiArrayType && referenceName == "length") {
identifier = Identifier("size", isNullable).assignNoPrototype() identifier = Identifier("size", isNullable).assignNoPrototype()
} }
else if (qualifier != null) { else if (qualifier != null) {
@@ -429,8 +429,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
else { else {
if (target is PsiClass) { if (target is PsiClass) {
if (PrimitiveType.values().any { it.getTypeName().asString() == target.getName() }) { if (PrimitiveType.values().any { it.typeName.asString() == target.name }) {
result = Identifier(target.getQualifiedName()!!, false) result = Identifier(target.qualifiedName!!, false)
return return
} }
} }
@@ -439,14 +439,14 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val context = converter.specialContext ?: expression val context = converter.specialContext ?: expression
if (target is PsiMember if (target is PsiMember
&& target.hasModifierProperty(PsiModifier.STATIC) && target.hasModifierProperty(PsiModifier.STATIC)
&& target.getContainingClass() != null && target.containingClass != null
&& !PsiTreeUtil.isAncestor(target.getContainingClass(), context, true) && !PsiTreeUtil.isAncestor(target.containingClass, context, true)
&& !target.isImported(context.getContainingFile() as PsiJavaFile)) { && !target.isImported(context.containingFile as PsiJavaFile)) {
var member: PsiMember = target var member: PsiMember = target
var code = Identifier.toKotlin(referenceName) var code = Identifier.toKotlin(referenceName)
while (true) { while (true) {
val containingClass = member.getContainingClass() ?: break val containingClass = member.containingClass ?: break
code = Identifier.toKotlin(containingClass.getName()!!) + "." + code code = Identifier.toKotlin(containingClass.name!!) + "." + code
member = containingClass member = containingClass
} }
result = Identifier(code, false, false) result = Identifier(code, false, false)
@@ -458,22 +458,22 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
override fun visitSuperExpression(expression: PsiSuperExpression) { override fun visitSuperExpression(expression: PsiSuperExpression) {
val psiQualifier = expression.getQualifier() val psiQualifier = expression.qualifier
val qualifier = psiQualifier?.getReferenceName() val qualifier = psiQualifier?.referenceName
result = SuperExpression(if (qualifier != null) Identifier(qualifier).assignPrototype(psiQualifier) else Identifier.Empty) result = SuperExpression(if (qualifier != null) Identifier(qualifier).assignPrototype(psiQualifier) else Identifier.Empty)
} }
override fun visitThisExpression(expression: PsiThisExpression) { override fun visitThisExpression(expression: PsiThisExpression) {
val psiQualifier = expression.getQualifier() val psiQualifier = expression.qualifier
val qualifier = psiQualifier?.getReferenceName() val qualifier = psiQualifier?.referenceName
result = ThisExpression(if (qualifier != null) Identifier(qualifier).assignPrototype(psiQualifier) else Identifier.Empty) result = ThisExpression(if (qualifier != null) Identifier(qualifier).assignPrototype(psiQualifier) else Identifier.Empty)
} }
override fun visitTypeCastExpression(expression: PsiTypeCastExpression) { override fun visitTypeCastExpression(expression: PsiTypeCastExpression) {
val castType = expression.getCastType() ?: return val castType = expression.castType ?: return
val operand = expression.getOperand() val operand = expression.operand
val operandType = operand?.getType() val operandType = operand?.type
val typeText = castType.getType().getCanonicalText() val typeText = castType.type.canonicalText
val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText] val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText]
val operandConverted = codeConverter.convertExpression(operand) val operandConverted = codeConverter.convertExpression(operand)
if (operandType is PsiPrimitiveType && typeConversion != null) { if (operandType is PsiPrimitiveType && typeConversion != null) {
@@ -500,10 +500,10 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
override fun visitPolyadicExpression(expression: PsiPolyadicExpression) { override fun visitPolyadicExpression(expression: PsiPolyadicExpression) {
val commentsAndSpacesInheritance = CommentsAndSpacesInheritance.LINE_BREAKS val commentsAndSpacesInheritance = CommentsAndSpacesInheritance.LINE_BREAKS
val args = expression.getOperands().map { val args = expression.operands.map {
codeConverter.convertExpression(it, expression.getType()).assignPrototype(it, commentsAndSpacesInheritance) codeConverter.convertExpression(it, expression.type).assignPrototype(it, commentsAndSpacesInheritance)
} }
val operators = expression.getOperands().map { val operators = expression.operands.map {
expression.getTokenBeforeOperand(it)?.let { expression.getTokenBeforeOperand(it)?.let {
Operator(it.tokenType).assignPrototype(it, commentsAndSpacesInheritance) Operator(it.tokenType).assignPrototype(it, commentsAndSpacesInheritance)
} }
@@ -513,21 +513,21 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
private fun convertArguments(expression: PsiCallExpression, isExtension: Boolean = false): List<Expression> { private fun convertArguments(expression: PsiCallExpression, isExtension: Boolean = false): List<Expression> {
var arguments = expression.getArgumentList()?.getExpressions()?.toList() ?: listOf() var arguments = expression.argumentList?.expressions?.toList() ?: listOf()
if (isExtension && arguments.isNotEmpty()) { if (isExtension && arguments.isNotEmpty()) {
arguments = arguments.drop(1) arguments = arguments.drop(1)
} }
val resolved = expression.resolveMethod() val resolved = expression.resolveMethod()
val parameters = resolved?.getParameterList()?.getParameters() val parameters = resolved?.parameterList?.parameters
val expectedTypes = parameters?.map { it.getType() } ?: listOf() val expectedTypes = parameters?.map { it.type } ?: listOf()
val commentsAndSpacesInheritance = CommentsAndSpacesInheritance.LINE_BREAKS val commentsAndSpacesInheritance = CommentsAndSpacesInheritance.LINE_BREAKS
return if (arguments.size() == expectedTypes.size()) { return if (arguments.size == expectedTypes.size) {
arguments.mapIndexed { i, argument -> arguments.mapIndexed { i, argument ->
val converted = codeConverter.convertExpression(argument, expectedTypes[i]) val converted = codeConverter.convertExpression(argument, expectedTypes[i])
val result = if (parameters != null && i == arguments.lastIndex && parameters[i].isVarArgs() && argument.getType() is PsiArrayType) val result = if (parameters != null && i == arguments.lastIndex && parameters[i].isVarArgs && argument.type is PsiArrayType)
StarExpression(converted) StarExpression(converted)
else else
converted converted
@@ -630,7 +630,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
} }
val lambdaParameterList = ParameterList( val lambdaParameterList = ParameterList(
if (parameters.size() == 1 && !isKotlinFunctionType) { if (parameters.size == 1 && !isKotlinFunctionType) {
// for lambdas all parameters with types should be present // for lambdas all parameters with types should be present
emptyList() emptyList()
} else { } else {
@@ -690,7 +690,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
newParameters.add(Identifier(it.name ?: "p", false).assignNoPrototype() to parameterType) newParameters.add(Identifier(it.name ?: "p", false).assignNoPrototype() to parameterType)
} }
if (newParameters.size() == 1 && !isKotlinFunctionType) { if (newParameters.size == 1 && !isKotlinFunctionType) {
newParameters.clear() newParameters.clear()
newParameters.add(Identifier("it", false).assignNoPrototype() to null) newParameters.add(Identifier("it", false).assignNoPrototype() to null)
} }
@@ -31,19 +31,19 @@ class ForConverter(
private val settings = codeConverter.settings private val settings = codeConverter.settings
private val project = codeConverter.converter.project private val project = codeConverter.converter.project
private val initialization = statement.getInitialization() private val initialization = statement.initialization
private val update = statement.getUpdate() private val update = statement.update
private val condition = statement.getCondition() private val condition = statement.condition
private val body = statement.getBody() private val body = statement.body
public fun execute(): Statement { public fun execute(): Statement {
val foreach = convertToForeach() val foreach = convertToForeach()
if (foreach != null) return foreach if (foreach != null) return foreach
val initialization = statement.getInitialization() val initialization = statement.initialization
val update = statement.getUpdate() val update = statement.update
val condition = statement.getCondition() val condition = statement.condition
val body = statement.getBody() val body = statement.body
val initializationConverted = codeConverter.convertStatement(initialization) val initializationConverted = codeConverter.convertStatement(initialization)
val updateConverted = codeConverter.convertStatement(update) val updateConverted = codeConverter.convertStatement(update)
@@ -60,7 +60,7 @@ class ForConverter(
val continueConverted = this@ForConverter.codeConverter.convertStatement(statement) val continueConverted = this@ForConverter.codeConverter.convertStatement(statement)
val statements = listOf(updateConverted, continueConverted) val statements = listOf(updateConverted, continueConverted)
if (statement.getParent() is PsiCodeBlock) { if (statement.parent is PsiCodeBlock) {
// generate fictive statement which will generate multiple statements // generate fictive statement which will generate multiple statements
return object : Statement() { return object : Statement() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
@@ -75,10 +75,10 @@ class ForConverter(
}) })
if (body is PsiBlockStatement) { if (body is PsiBlockStatement) {
val nameConflict = initialization is PsiDeclarationStatement && initialization.getDeclaredElements().any { loopVar -> val nameConflict = initialization is PsiDeclarationStatement && initialization.declaredElements.any { loopVar ->
loopVar is PsiNamedElement && body.getCodeBlock().getStatements().any { statement -> loopVar is PsiNamedElement && body.codeBlock.statements.any { statement ->
statement is PsiDeclarationStatement && statement.getDeclaredElements().any { statement is PsiDeclarationStatement && statement.declaredElements.any {
it is PsiNamedElement && it.getName() == loopVar.getName() it is PsiNamedElement && it.name == loopVar.name
} }
} }
} }
@@ -88,7 +88,7 @@ class ForConverter(
Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype() Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
} }
else { else {
val block = codeConverterToUse.convertBlock(body.getCodeBlock(), true) val block = codeConverterToUse.convertBlock(body.codeBlock, true)
Block(block.statements + listOf(updateConverted), block.lBrace, block.rBrace, true).assignPrototypesFrom(block) Block(block.statements + listOf(updateConverted), block.lBrace, block.rBrace, true).assignPrototypesFrom(block)
} }
} }
@@ -147,23 +147,23 @@ class ForConverter(
private fun convertToForeach(): ForeachStatement? { private fun convertToForeach(): ForeachStatement? {
if (initialization is PsiDeclarationStatement) { if (initialization is PsiDeclarationStatement) {
val loopVar = initialization.getDeclaredElements().singleOrNull() as? PsiLocalVariable ?: return null val loopVar = initialization.declaredElements.singleOrNull() as? PsiLocalVariable ?: return null
if (!loopVar.hasWriteAccesses(referenceSearcher, body) if (!loopVar.hasWriteAccesses(referenceSearcher, body)
&& !loopVar.hasWriteAccesses(referenceSearcher, condition) && !loopVar.hasWriteAccesses(referenceSearcher, condition)
&& condition is PsiBinaryExpression) { && condition is PsiBinaryExpression) {
val left = condition.getLOperand() as? PsiReferenceExpression ?: return null val left = condition.lOperand as? PsiReferenceExpression ?: return null
val right = condition.getROperand() ?: return null val right = condition.rOperand ?: return null
if (left.resolve() == loopVar) { if (left.resolve() == loopVar) {
val start = loopVar.getInitializer() ?: return null val start = loopVar.initializer ?: return null
val operationType = (update as? PsiExpressionStatement)?.getExpression()?.isVariableIncrementOrDecrement(loopVar) val operationType = (update as? PsiExpressionStatement)?.expression?.isVariableIncrementOrDecrement(loopVar)
val reversed = when (operationType) { val reversed = when (operationType) {
JavaTokenType.PLUSPLUS -> false JavaTokenType.PLUSPLUS -> false
JavaTokenType.MINUSMINUS -> true JavaTokenType.MINUSMINUS -> true
else -> return null else -> return null
} }
val inclusive = when (condition.getOperationTokenType()) { val inclusive = when (condition.operationTokenType) {
JavaTokenType.LT -> if (reversed) return null else false JavaTokenType.LT -> if (reversed) return null else false
JavaTokenType.LE -> if (reversed) return null else true JavaTokenType.LE -> if (reversed) return null else true
JavaTokenType.GT -> if (reversed) false else return null JavaTokenType.GT -> if (reversed) false else return null
@@ -187,8 +187,8 @@ class ForConverter(
private fun PsiElement.isVariableIncrementOrDecrement(variable: PsiVariable): IElementType? { private fun PsiElement.isVariableIncrementOrDecrement(variable: PsiVariable): IElementType? {
//TODO: simplify code when KT-5453 fixed //TODO: simplify code when KT-5453 fixed
val pair = when (this) { val pair = when (this) {
is PsiPostfixExpression -> getOperationTokenType() to getOperand() is PsiPostfixExpression -> operationTokenType to operand
is PsiPrefixExpression -> getOperationTokenType() to getOperand() is PsiPrefixExpression -> operationTokenType to operand
else -> return null else -> return null
} }
if ((pair.second as? PsiReferenceExpression)?.resolve() != variable) return null if ((pair.second as? PsiReferenceExpression)?.resolve() != variable) return null
@@ -210,16 +210,16 @@ class ForConverter(
val collectionSize = if (reversed) { val collectionSize = if (reversed) {
if (!inclusiveComparison) return null if (!inclusiveComparison) return null
if ((bound as? PsiLiteralExpression)?.getValue() != 0) return null if ((bound as? PsiLiteralExpression)?.value != 0) return null
if (start !is PsiBinaryExpression) return null if (start !is PsiBinaryExpression) return null
if (start.getOperationTokenType() != JavaTokenType.MINUS) return null if (start.operationTokenType != JavaTokenType.MINUS) return null
if ((start.getROperand() as? PsiLiteralExpression)?.getValue() != 1) return null if ((start.rOperand as? PsiLiteralExpression)?.value != 1) return null
start.getLOperand() start.lOperand
} }
else { else {
if (inclusiveComparison) return null if (inclusiveComparison) return null
if ((start as? PsiLiteralExpression)?.getValue() != 0) return null if ((start as? PsiLiteralExpression)?.value != 0) return null
bound bound
} }
@@ -227,13 +227,13 @@ class ForConverter(
var indices: Expression? = null var indices: Expression? = null
// check if it's iteration through list indices // check if it's iteration through list indices
if (collectionSize is PsiMethodCallExpression && collectionSize.getArgumentList().getExpressions().isEmpty()) { if (collectionSize is PsiMethodCallExpression && collectionSize.argumentList.expressions.isEmpty()) {
val methodExpr = collectionSize.getMethodExpression() val methodExpr = collectionSize.methodExpression
if (methodExpr is PsiReferenceExpression && methodExpr.getReferenceName() == "size") { if (methodExpr is PsiReferenceExpression && methodExpr.referenceName == "size") {
val qualifier = methodExpr.getQualifierExpression() val qualifier = methodExpr.qualifierExpression
if (qualifier is PsiReferenceExpression /* we don't convert to .indices if qualifier is method call or something because of possible side effects */) { if (qualifier is PsiReferenceExpression /* we don't convert to .indices if qualifier is method call or something because of possible side effects */) {
val collectionType = PsiElementFactory.SERVICE.getInstance(project).createTypeByFQClassName(CommonClassNames.JAVA_UTIL_COLLECTION) val collectionType = PsiElementFactory.SERVICE.getInstance(project).createTypeByFQClassName(CommonClassNames.JAVA_UTIL_COLLECTION)
val qualifierType = qualifier.getType() val qualifierType = qualifier.type
if (qualifierType != null && collectionType.isAssignableFrom(qualifierType)) { if (qualifierType != null && collectionType.isAssignableFrom(qualifierType)) {
indices = QualifiedExpression(codeConverter.convertExpression(qualifier), Identifier("indices", false).assignNoPrototype()) indices = QualifiedExpression(codeConverter.convertExpression(qualifier), Identifier("indices", false).assignNoPrototype())
} }
@@ -242,9 +242,9 @@ class ForConverter(
} }
// check if it's iteration through array indices // check if it's iteration through array indices
else if (collectionSize is PsiReferenceExpression /* we don't convert to .indices if qualifier is method call or something because of possible side effects */ else if (collectionSize is PsiReferenceExpression /* we don't convert to .indices if qualifier is method call or something because of possible side effects */
&& collectionSize.getReferenceName() == "length") { && collectionSize.referenceName == "length") {
val qualifier = collectionSize.getQualifierExpression() val qualifier = collectionSize.qualifierExpression
if (qualifier is PsiReferenceExpression && qualifier.getType() is PsiArrayType) { if (qualifier is PsiReferenceExpression && qualifier.type is PsiArrayType) {
indices = QualifiedExpression(codeConverter.convertExpression(qualifier), Identifier("indices", false).assignNoPrototype()) indices = QualifiedExpression(codeConverter.convertExpression(qualifier), Identifier("indices", false).assignNoPrototype())
} }
} }
@@ -263,7 +263,7 @@ class ForConverter(
} }
if (bound is PsiLiteralExpression) { if (bound is PsiLiteralExpression) {
val value = bound.getValue() val value = bound.value
if (value is Int) { if (value is Int) {
return LiteralExpression((value + correction).toString()).assignPrototype(bound) return LiteralExpression((value + correction).toString()).assignPrototype(bound)
} }
@@ -277,13 +277,13 @@ class ForConverter(
private fun PsiStatement.toContinuedLoop(): PsiLoopStatement? { private fun PsiStatement.toContinuedLoop(): PsiLoopStatement? {
return when (this) { return when (this) {
is PsiLoopStatement -> this is PsiLoopStatement -> this
is PsiLabeledStatement -> this.getStatement()?.toContinuedLoop() is PsiLabeledStatement -> this.statement?.toContinuedLoop()
else -> null else -> null
} }
} }
private fun hasNameConflict(): Boolean { private fun hasNameConflict(): Boolean {
val names = statement.getInitialization()?.declaredVariableNames() ?: return false val names = statement.initialization?.declaredVariableNames() ?: return false
if (names.isEmpty()) return false if (names.isEmpty()) return false
val factory = PsiElementFactory.SERVICE.getInstance(project) val factory = PsiElementFactory.SERVICE.getInstance(project)
@@ -315,8 +315,8 @@ class ForConverter(
private fun PsiStatement.declaredVariableNames(): Collection<String> { private fun PsiStatement.declaredVariableNames(): Collection<String> {
val declarationStatement = this as? PsiDeclarationStatement ?: return listOf() val declarationStatement = this as? PsiDeclarationStatement ?: return listOf()
return declarationStatement.getDeclaredElements() return declarationStatement.declaredElements
.filterIsInstance<PsiVariable>() .filterIsInstance<PsiVariable>()
.map { it.getName()!! } .map { it.name!! }
} }
} }
@@ -76,7 +76,7 @@ public class JavaToKotlinConverter(
AfterConversionPass(project, postProcessor).run(kotlinFile, range = null) AfterConversionPass(project, postProcessor).run(kotlinFile, range = null)
kotlinFile.getText() kotlinFile.text
} }
catch(e: ProcessCanceledException) { catch(e: ProcessCanceledException) {
throw e throw e
@@ -150,7 +150,7 @@ public class JavaToKotlinConverter(
): ExternalCodeProcessing? { ): ExternalCodeProcessing? {
if (usageProcessings.isEmpty()) return null if (usageProcessings.isEmpty()) return null
val map: Map<PsiElement, Collection<UsageProcessing>> = usageProcessings.values() val map: Map<PsiElement, Collection<UsageProcessing>> = usageProcessings.values
.flatMap { it } .flatMap { it }
.filter { it.javaCodeProcessor != null || it.kotlinCodeProcessor != null } .filter { it.javaCodeProcessor != null || it.kotlinCodeProcessor != null }
.groupBy { it.targetElement } .groupBy { it.targetElement }
@@ -160,13 +160,13 @@ public class JavaToKotlinConverter(
override fun prepareWriteOperation(progress: ProgressIndicator): () -> Unit { override fun prepareWriteOperation(progress: ProgressIndicator): () -> Unit {
val refs = ArrayList<ReferenceInfo>() val refs = ArrayList<ReferenceInfo>()
progress.setText("Searching usages to update...") progress.text = "Searching usages to update..."
for ((i, entry) in map.entrySet().withIndex()) { for ((i, entry) in map.entries.withIndex()) {
val psiElement = entry.key val psiElement = entry.key
val processings = entry.value val processings = entry.value
progress.setText2((psiElement as? PsiNamedElement)?.getName() ?: "") progress.text2 = (psiElement as? PsiNamedElement)?.name ?: ""
progress.checkCanceled() progress.checkCanceled()
ProgressManager.getInstance().runProcess( ProgressManager.getInstance().runProcess(
@@ -174,10 +174,10 @@ public class JavaToKotlinConverter(
val searchJava = processings.any { it.javaCodeProcessor != null } val searchJava = processings.any { it.javaCodeProcessor != null }
val searchKotlin = processings.any { it.kotlinCodeProcessor != null } val searchKotlin = processings.any { it.kotlinCodeProcessor != null }
services.referenceSearcher.findUsagesForExternalCodeProcessing(psiElement, searchJava, searchKotlin) services.referenceSearcher.findUsagesForExternalCodeProcessing(psiElement, searchJava, searchKotlin)
.filterNot { inConversionScope(it.getElement()) } .filterNot { inConversionScope(it.element) }
.mapTo(refs) { ReferenceInfo(it, psiElement, it.getElement().getContainingFile(), processings) } .mapTo(refs) { ReferenceInfo(it, psiElement, it.element.containingFile, processings) }
}, },
ProgressPortionReporter(progress, i / map.size().toDouble(), 1.0 / map.size())) ProgressPortionReporter(progress, i / map.size.toDouble(), 1.0 / map.size))
} }
@@ -187,10 +187,10 @@ public class JavaToKotlinConverter(
} }
private fun processUsages(refs: Collection<ReferenceInfo>) { private fun processUsages(refs: Collection<ReferenceInfo>) {
for (fileRefs in refs.groupBy { it.file }.values()) { // group by file for faster sorting for (fileRefs in refs.groupBy { it.file }.values) { // group by file for faster sorting
ReferenceLoop@ ReferenceLoop@
for ((reference, target, file, processings) in fileRefs.sortedWith(ReferenceComparator)) { for ((reference, target, file, processings) in fileRefs.sortedWith(ReferenceComparator)) {
val processors = when (reference.getElement().getLanguage()) { val processors = when (reference.element.language) {
JavaLanguage.INSTANCE -> processings.mapNotNull { it.javaCodeProcessor } JavaLanguage.INSTANCE -> processings.mapNotNull { it.javaCodeProcessor }
KotlinLanguage.INSTANCE -> processings.mapNotNull { it.kotlinCodeProcessor } KotlinLanguage.INSTANCE -> processings.mapNotNull { it.kotlinCodeProcessor }
else -> continue@ReferenceLoop else -> continue@ReferenceLoop
@@ -208,8 +208,8 @@ public class JavaToKotlinConverter(
} }
private fun checkReferenceValid(reference: PsiReference, afterProcessor: ExternalCodeProcessor?) { private fun checkReferenceValid(reference: PsiReference, afterProcessor: ExternalCodeProcessor?) {
val element = reference.getElement() val element = reference.element
assert(element.isValid() && element.getContainingFile() !is DummyHolder) { assert(element.isValid && element.containingFile !is DummyHolder) {
"Reference $reference got invalidated" + (if (afterProcessor != null) " after processing with $afterProcessor" else "") "Reference $reference got invalidated" + (if (afterProcessor != null) " after processing with $afterProcessor" else "")
} }
} }
@@ -233,7 +233,7 @@ public class JavaToKotlinConverter(
} }
private val progressText = "Converting Java to Kotlin" private val progressText = "Converting Java to Kotlin"
private val fileCount = files?.size() ?: 0 private val fileCount = files?.size ?: 0
private val fileCountText = fileCount.toString() + " " + if (fileCount > 1) "files" else "file" private val fileCountText = fileCount.toString() + " " + if (fileCount > 1) "files" else "file"
private var fraction = 0.0 private var fraction = 0.0
private var pass = 1 private var pass = 1
@@ -247,13 +247,13 @@ public class JavaToKotlinConverter(
// we use special process with EmptyProgressIndicator to avoid changing text in our progress by inheritors search inside etc // we use special process with EmptyProgressIndicator to avoid changing text in our progress by inheritors search inside etc
ProgressManager.getInstance().runProcess( ProgressManager.getInstance().runProcess(
{ {
progress?.setText("$progressText ($fileCountText) - pass $pass of 3") progress?.text = "$progressText ($fileCountText) - pass $pass of 3"
for ((i, item) in inputItems.withIndex()) { for ((i, item) in inputItems.withIndex()) {
progress?.checkCanceled() progress?.checkCanceled()
progress?.setFraction(fraction + fractionPortion * i / fileCount) progress?.fraction = fraction + fractionPortion * i / fileCount
progress?.setText2(files!![i].getVirtualFile().getPresentableUrl()) progress?.text2 = files!![i].virtualFile.presentableUrl
outputItems.add(processItem(item)) outputItems.add(processItem(item))
} }
@@ -273,15 +273,15 @@ public class JavaToKotlinConverter(
) : DelegatingProgressIndicator(indicator) { ) : DelegatingProgressIndicator(indicator) {
init { init {
setFraction(0.0) fraction = 0.0
} }
override fun start() { override fun start() {
setFraction(0.0) fraction = 0.0
} }
override fun stop() { override fun stop() {
setFraction(portion) fraction = portion
} }
override fun setFraction(fraction: Double) { override fun setFraction(fraction: Double) {
@@ -45,7 +45,7 @@ public object JavaToKotlinTranslator {
public fun generateKotlinCode(javaCode: String, project: Project): String { public fun generateKotlinCode(javaCode: String, project: Project): String {
val file = createFile(javaCode, project) val file = createFile(javaCode, project)
if (file is PsiJavaFile) { if (file is PsiJavaFile) {
val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, EmptyJavaToKotlinServices) val converter = JavaToKotlinConverter(file.project, ConverterSettings.defaultSettings, EmptyJavaToKotlinServices)
return prettify(converter.elementsToKotlin(listOf(file)).results.single()!!.text) //TODO: imports return prettify(converter.elementsToKotlin(listOf(file)).results.single()!!.text) //TODO: imports
} }
return "" return ""
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.j2k
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.j2k.ast.*
import java.util.ArrayList import java.util.*
import java.util.HashMap
import java.util.HashSet
class OverloadReducer( class OverloadReducer(
private val methods: Collection<PsiMethod>, private val methods: Collection<PsiMethod>,
@@ -39,8 +37,8 @@ class OverloadReducer(
public fun parameterDefault(method: PsiMethod, parameterIndex: Int): PsiExpression? { public fun parameterDefault(method: PsiMethod, parameterIndex: Int): PsiExpression? {
val defaults = methodToLastParameterDefaults[method] ?: return null val defaults = methodToLastParameterDefaults[method] ?: return null
val index = method.getParameterList().getParametersCount() - parameterIndex - 1 val index = method.parameterList.parametersCount - parameterIndex - 1
return if (index < defaults.size()) defaults[index] else null return if (index < defaults.size) defaults[index] else null
} }
private class EquivalentOverloadInfo( private class EquivalentOverloadInfo(
@@ -55,15 +53,15 @@ class OverloadReducer(
private fun buildOverloadEquivalenceMap(): Map<PsiMethod, EquivalentOverloadInfo> { private fun buildOverloadEquivalenceMap(): Map<PsiMethod, EquivalentOverloadInfo> {
val overloadGroups = methods val overloadGroups = methods
.groupBy { listOf(if (it.isConstructor()) null else it.getName(), .groupBy { listOf(if (it.isConstructor) null else it.name,
it.accessModifier(), it.accessModifier(),
it.getReturnType(), it.returnType,
it.hasModifierProperty(PsiModifier.STATIC), it.hasModifierProperty(PsiModifier.STATIC),
getAnnotationsFingerprint(it)) } getAnnotationsFingerprint(it)) }
.values() .values
.filter { it.size() > 1 } .filter { it.size > 1 }
.map { it.filterNot { shouldSkipOverload(it) } } .map { it.filterNot { shouldSkipOverload(it) } }
.filter { it.size() > 1 } .filter { it.size > 1 }
val map = HashMap<PsiMethod, EquivalentOverloadInfo>() val map = HashMap<PsiMethod, EquivalentOverloadInfo>()
for (group in overloadGroups) { for (group in overloadGroups) {
@@ -79,7 +77,7 @@ class OverloadReducer(
} }
map[method] = resultOverloadInfo map[method] = resultOverloadInfo
for (entry in map.entrySet()) { for (entry in map.entries) {
if (entry.value.method == method) { if (entry.value.method == method) {
val newParameterDefaults = entry.value.parameterDefaults + resultOverloadInfo.parameterDefaults val newParameterDefaults = entry.value.parameterDefaults + resultOverloadInfo.parameterDefaults
entry.setValue(EquivalentOverloadInfo(resultOverloadInfo.method, newParameterDefaults)) entry.setValue(EquivalentOverloadInfo(resultOverloadInfo.method, newParameterDefaults))
@@ -93,27 +91,27 @@ class OverloadReducer(
} }
private fun shouldSkipOverload(method: PsiMethod): Boolean { private fun shouldSkipOverload(method: PsiMethod): Boolean {
if (method.isConstructor()) return false if (method.isConstructor) return false
if (method.hasModifierProperty(PsiModifier.ABSTRACT)) return true if (method.hasModifierProperty(PsiModifier.ABSTRACT)) return true
if (method.hasModifierProperty(PsiModifier.NATIVE)) return true if (method.hasModifierProperty(PsiModifier.NATIVE)) return true
if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) return true if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) return true
if (method.getHierarchicalMethodSignature().getSuperSignatures().isNotEmpty()) return true if (method.hierarchicalMethodSignature.superSignatures.isNotEmpty()) return true
if (isOpenClass && referenceSearcher.hasOverrides(method)) return true if (isOpenClass && referenceSearcher.hasOverrides(method)) return true
return false return false
} }
private fun findEquivalentOverload(method: PsiMethod, overloads: Collection<PsiMethod>): EquivalentOverloadInfo? { private fun findEquivalentOverload(method: PsiMethod, overloads: Collection<PsiMethod>): EquivalentOverloadInfo? {
val statement = method.getBody()?.getStatements()?.singleOrNull() ?: return null val statement = method.body?.statements?.singleOrNull() ?: return null
val methodCall = when (statement) { val methodCall = when (statement) {
is PsiExpressionStatement -> statement.getExpression() is PsiExpressionStatement -> statement.expression
is PsiReturnStatement -> statement.getReturnValue() is PsiReturnStatement -> statement.returnValue
else -> null else -> null
} as? PsiMethodCallExpression ?: return null } as? PsiMethodCallExpression ?: return null
val expectedMethodName = if (method.isConstructor()) "this" else method.getName() val expectedMethodName = if (method.isConstructor) "this" else method.name
val refExpr = methodCall.getMethodExpression() val refExpr = methodCall.methodExpression
if (refExpr.isQualified() || refExpr.getReferenceName() != expectedMethodName) return null if (refExpr.isQualified || refExpr.referenceName != expectedMethodName) return null
val target = refExpr.resolve() as? PsiMethod ?: return null val target = refExpr.resolve() as? PsiMethod ?: return null
if (target !in overloads) return null if (target !in overloads) return null
@@ -123,21 +121,21 @@ class OverloadReducer(
} }
private fun calcTargetParameterDefaults(method: PsiMethod, target: PsiMethod, targetCall: PsiMethodCallExpression): List<PsiExpression>? { private fun calcTargetParameterDefaults(method: PsiMethod, target: PsiMethod, targetCall: PsiMethodCallExpression): List<PsiExpression>? {
val parameters = method.getParameterList().getParameters() val parameters = method.parameterList.parameters
val targetParameters = target.getParameterList().getParameters() val targetParameters = target.parameterList.parameters
if (parameters.size() >= targetParameters.size()) return null if (parameters.size >= targetParameters.size) return null
val args = targetCall.getArgumentList().getExpressions() val args = targetCall.argumentList.expressions
if (args.size() != targetParameters.size()) return null // incorrect code if (args.size != targetParameters.size) return null // incorrect code
for (i in parameters.indices) { for (i in parameters.indices) {
val parameter = parameters[i] val parameter = parameters[i]
val targetParameter = targetParameters[i] val targetParameter = targetParameters[i]
if (parameter.getName() != targetParameter.getName() || parameter.getType() != targetParameter.getType()) return null if (parameter.name != targetParameter.name || parameter.type != targetParameter.type) return null
val arg = args[i] val arg = args[i]
if (arg !is PsiReferenceExpression || arg.resolve() != parameter) return null if (arg !is PsiReferenceExpression || arg.resolve() != parameter) return null
} }
return args.drop(parameters.size()) return args.drop(parameters.size)
} }
private fun dropOverloadsForDefaultValues(equivalenceMap: Map<PsiMethod, EquivalentOverloadInfo>) { private fun dropOverloadsForDefaultValues(equivalenceMap: Map<PsiMethod, EquivalentOverloadInfo>) {
@@ -147,19 +145,19 @@ class OverloadReducer(
DropCandidatesLoop@ DropCandidatesLoop@
for (method in dropCandidates) { for (method in dropCandidates) {
val paramCount = method.getParameterList().getParametersCount() val paramCount = method.parameterList.parametersCount
val targetInfo = equivalenceMap[method]!! val targetInfo = equivalenceMap[method]!!
val targetParamCount = targetInfo.method.getParameterList().getParametersCount() val targetParamCount = targetInfo.method.parameterList.parametersCount
assert(paramCount < targetParamCount) assert(paramCount < targetParamCount)
val defaults = targetInfo.parameterDefaults val defaults = targetInfo.parameterDefaults
assert(defaults.size() == targetParamCount - paramCount) assert(defaults.size == targetParamCount - paramCount)
val targetDefaults = methodToLastParameterDefaults.getOrPut(targetInfo.method, { ArrayList() }) val targetDefaults = methodToLastParameterDefaults.getOrPut(targetInfo.method, { ArrayList() })
for (i in defaults.indices) { for (i in defaults.indices) {
val default = defaults[defaults.size() - i - 1] val default = defaults[defaults.size - i - 1]
if (i < targetDefaults.size()) { // default for this parameter has already been assigned if (i < targetDefaults.size) { // default for this parameter has already been assigned
if (targetDefaults[i].getText() != default.getText()) continue@DropCandidatesLoop if (targetDefaults[i].text != default.text) continue@DropCandidatesLoop
} }
else { else {
targetDefaults.add(default) targetDefaults.add(default)
@@ -171,7 +169,7 @@ class OverloadReducer(
} }
private fun getAnnotationsFingerprint(method: PsiMethod): Any { private fun getAnnotationsFingerprint(method: PsiMethod): Any {
return method.getModifierList().getAnnotations().map { it.getText() } return method.modifierList.annotations.map { it.text }
} }
} }
@@ -181,13 +179,13 @@ public fun Converter.convertParameterList(
convertParameter: (parameter: PsiParameter, default: DeferredElement<Expression>?) -> FunctionParameter = { parameter, default -> convertParameter(parameter, defaultValue = default) }, convertParameter: (parameter: PsiParameter, default: DeferredElement<Expression>?) -> FunctionParameter = { parameter, default -> convertParameter(parameter, defaultValue = default) },
correctCodeConverter: CodeConverter.() -> CodeConverter = { this } correctCodeConverter: CodeConverter.() -> CodeConverter = { this }
): ParameterList { ): ParameterList {
val parameterList = method.getParameterList() val parameterList = method.parameterList
val params = parameterList.getParameters() val params = parameterList.parameters
return ParameterList(params.indices.map { i -> return ParameterList(params.indices.map { i ->
val parameter = params[i] val parameter = params[i]
val defaultValue = overloadReducer?.parameterDefault(method, i) val defaultValue = overloadReducer?.parameterDefault(method, i)
val defaultValueConverted = if (defaultValue != null) val defaultValueConverted = if (defaultValue != null)
deferredElement { codeConverter -> codeConverter.correctCodeConverter().convertExpression(defaultValue, parameter.getType()) } deferredElement { codeConverter -> codeConverter.correctCodeConverter().convertExpression(defaultValue, parameter.type) }
else else
null null
convertParameter(parameter, defaultValueConverted) convertParameter(parameter, defaultValueConverted)
@@ -33,8 +33,8 @@ public fun ReferenceSearcher.findVariableUsages(variable: PsiVariable, scope: Ps
public fun ReferenceSearcher.findMethodCalls(method: PsiMethod, scope: PsiElement): Collection<PsiMethodCallExpression> { public fun ReferenceSearcher.findMethodCalls(method: PsiMethod, scope: PsiElement): Collection<PsiMethodCallExpression> {
return findLocalUsages(method, scope).mapNotNull { return findLocalUsages(method, scope).mapNotNull {
if (it is PsiReferenceExpression) { if (it is PsiReferenceExpression) {
val methodCall = it.getParent() as? PsiMethodCallExpression val methodCall = it.parent as? PsiMethodCallExpression
if (methodCall?.getMethodExpression() == it) methodCall else null if (methodCall?.methodExpression == it) methodCall else null
} }
else { else {
null null
@@ -45,14 +45,14 @@ public fun ReferenceSearcher.findMethodCalls(method: PsiMethod, scope: PsiElemen
public fun PsiField.isVar(searcher: ReferenceSearcher): Boolean { public fun PsiField.isVar(searcher: ReferenceSearcher): Boolean {
if (hasModifierProperty(PsiModifier.FINAL)) return false if (hasModifierProperty(PsiModifier.FINAL)) return false
if (!hasModifierProperty(PsiModifier.PRIVATE)) return true if (!hasModifierProperty(PsiModifier.PRIVATE)) return true
val containingClass = getContainingClass() ?: return true val containingClass = containingClass ?: return true
val writes = searcher.findVariableUsages(this, containingClass).filter { PsiUtil.isAccessedForWriting(it) } val writes = searcher.findVariableUsages(this, containingClass).filter { PsiUtil.isAccessedForWriting(it) }
if (writes.size() == 0) return false if (writes.size == 0) return false
if (writes.size() > 1) return true if (writes.size > 1) return true
val write = writes.single() val write = writes.single()
val parent = write.getParent() val parent = write.parent
if (parent is PsiAssignmentExpression if (parent is PsiAssignmentExpression
&& parent.getOperationSign().getTokenType() == JavaTokenType.EQ && parent.operationSign.tokenType == JavaTokenType.EQ
&& write.isQualifierEmptyOrThis() && write.isQualifierEmptyOrThis()
) { ) {
val constructor = write.getContainingConstructor() val constructor = write.getContainingConstructor()
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.j2k package org.jetbrains.kotlin.j2k
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
public interface ResolverForConverter { public interface ResolverForConverter {
public fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor? public fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor?
@@ -131,7 +131,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
OBJECT_EQUALS(null, "equals", 1) { OBJECT_EQUALS(null, "equals", 1) {
override fun matches(method: PsiMethod, superMethodsSearcher: SuperMethodsSearcher): Boolean override fun matches(method: PsiMethod, superMethodsSearcher: SuperMethodsSearcher): Boolean
= super.matches(method, superMethodsSearcher) && method.getParameterList().getParameters().single().getType().getCanonicalText() == JAVA_LANG_OBJECT = super.matches(method, superMethodsSearcher) && method.parameterList.parameters.single().type.canonicalText == JAVA_LANG_OBJECT
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? { override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
if (qualifier == null || qualifier is PsiSuperExpression) return null if (qualifier == null || qualifier is PsiSuperExpression) return null
@@ -253,7 +253,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
= super.matches(method, superMethodsSearcher) && method.parameterList.let { it.parametersCount == 2 && it.parameters.last().isVarArgs } = super.matches(method, superMethodsSearcher) && method.parameterList.let { it.parametersCount == 2 && it.parameters.last().isVarArgs }
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? { override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
if (arguments.size() == 2 && arguments.last().isAssignableToCharSequenceArray()) { if (arguments.size == 2 && arguments.last().isAssignableToCharSequenceArray()) {
return STRING_JOIN.convertCall(qualifier, arguments, typeArgumentsConverted, codeConverter) return STRING_JOIN.convertCall(qualifier, arguments, typeArgumentsConverted, codeConverter)
} }
else { else {
@@ -305,7 +305,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
method.parameterList.parameters.let { it.first().type.canonicalText == "java.util.Locale" && it.last().isVarArgs } method.parameterList.parameters.let { it.first().type.canonicalText == "java.util.Locale" && it.last().isVarArgs }
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? { override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
if (arguments.size() < 2) return null // incorrect call if (arguments.size < 2) return null // incorrect call
return MethodCallExpression.build(codeConverter.convertExpression(arguments[1]), "format", codeConverter.convertExpressions(listOf(arguments[0]) + arguments.drop(2)), emptyList(), false) return MethodCallExpression.build(codeConverter.convertExpression(arguments[1]), "format", codeConverter.convertExpressions(listOf(arguments[0]) + arguments.drop(2)), emptyList(), false)
} }
}, },
@@ -404,9 +404,9 @@ private fun convertSystemOutMethodCall(
codeConverter: CodeConverter codeConverter: CodeConverter
): Expression? { ): Expression? {
if (qualifier !is PsiReferenceExpression) return null if (qualifier !is PsiReferenceExpression) return null
val qqualifier = qualifier.getQualifierExpression() as? PsiReferenceExpression ?: return null val qqualifier = qualifier.qualifierExpression as? PsiReferenceExpression ?: return null
if (qqualifier.getCanonicalText() != "java.lang.System") return null if (qqualifier.canonicalText != "java.lang.System") return null
if (qualifier.getReferenceName() != "out") return null if (qualifier.referenceName != "out") return null
if (typeArgumentsConverted.isNotEmpty()) return null if (typeArgumentsConverted.isNotEmpty()) return null
return MethodCallExpression.build(null, methodName, arguments.map { codeConverter.convertExpression(it) }, emptyList(), false) return MethodCallExpression.build(null, methodName, arguments.map { codeConverter.convertExpression(it) }, emptyList(), false)
} }
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.j2k
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.j2k.ast.*
import java.util.ArrayList import java.util.*
interface StatementConverter { interface StatementConverter {
fun convertStatement(statement: PsiStatement, codeConverter: CodeConverter): Statement fun convertStatement(statement: PsiStatement, codeConverter: CodeConverter): Statement
@@ -51,8 +51,8 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
} }
override fun visitAssertStatement(statement: PsiAssertStatement) { override fun visitAssertStatement(statement: PsiAssertStatement) {
val descriptionExpr = statement.getAssertDescription() val descriptionExpr = statement.assertDescription
val condition = codeConverter.convertExpression(statement.getAssertCondition()) val condition = codeConverter.convertExpression(statement.assertCondition)
if (descriptionExpr == null) { if (descriptionExpr == null) {
result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition)) result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition))
} }
@@ -65,30 +65,30 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
} }
override fun visitBlockStatement(statement: PsiBlockStatement) { override fun visitBlockStatement(statement: PsiBlockStatement) {
val block = codeConverter.convertBlock(statement.getCodeBlock()) val block = codeConverter.convertBlock(statement.codeBlock)
result = MethodCallExpression.build(null, "run", listOf(LambdaExpression(null, block).assignNoPrototype()), listOf(), false) result = MethodCallExpression.build(null, "run", listOf(LambdaExpression(null, block).assignNoPrototype()), listOf(), false)
} }
override fun visitBreakStatement(statement: PsiBreakStatement) { override fun visitBreakStatement(statement: PsiBreakStatement) {
if (statement.getLabelIdentifier() == null) { if (statement.labelIdentifier == null) {
result = BreakStatement(Identifier.Empty) result = BreakStatement(Identifier.Empty)
} }
else { else {
result = BreakStatement(converter.convertIdentifier(statement.getLabelIdentifier())) result = BreakStatement(converter.convertIdentifier(statement.labelIdentifier))
} }
} }
override fun visitContinueStatement(statement: PsiContinueStatement) { override fun visitContinueStatement(statement: PsiContinueStatement) {
if (statement.getLabelIdentifier() == null) { if (statement.labelIdentifier == null) {
result = ContinueStatement(Identifier.Empty) result = ContinueStatement(Identifier.Empty)
} }
else { else {
result = ContinueStatement(converter.convertIdentifier(statement.getLabelIdentifier())) result = ContinueStatement(converter.convertIdentifier(statement.labelIdentifier))
} }
} }
override fun visitDeclarationStatement(statement: PsiDeclarationStatement) { override fun visitDeclarationStatement(statement: PsiDeclarationStatement) {
result = DeclarationStatement(statement.getDeclaredElements().map { result = DeclarationStatement(statement.declaredElements.map {
when (it) { when (it) {
is PsiLocalVariable -> codeConverter.convertLocalVariable(it) is PsiLocalVariable -> codeConverter.convertLocalVariable(it)
is PsiClass -> converter.convertClass(it) is PsiClass -> converter.convertClass(it)
@@ -98,20 +98,20 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
} }
override fun visitDoWhileStatement(statement: PsiDoWhileStatement) { override fun visitDoWhileStatement(statement: PsiDoWhileStatement) {
val condition = statement.getCondition() val condition = statement.condition
val expression = if (condition != null && condition.getType() != null) val expression = if (condition != null && condition.type != null)
codeConverter.convertExpression(condition, condition.getType()) codeConverter.convertExpression(condition, condition.type)
else else
codeConverter.convertExpression(condition) codeConverter.convertExpression(condition)
result = DoWhileStatement(expression, codeConverter.convertStatementOrBlock(statement.getBody()), statement.isInSingleLine()) result = DoWhileStatement(expression, codeConverter.convertStatementOrBlock(statement.body), statement.isInSingleLine())
} }
override fun visitExpressionStatement(statement: PsiExpressionStatement) { override fun visitExpressionStatement(statement: PsiExpressionStatement) {
result = codeConverter.convertExpression(statement.getExpression()) result = codeConverter.convertExpression(statement.expression)
} }
override fun visitExpressionListStatement(statement: PsiExpressionListStatement) { override fun visitExpressionListStatement(statement: PsiExpressionListStatement) {
result = ExpressionListStatement(codeConverter.convertExpressions(statement.getExpressionList().getExpressions())) result = ExpressionListStatement(codeConverter.convertExpressions(statement.expressionList.expressions))
} }
override fun visitForStatement(statement: PsiForStatement) { override fun visitForStatement(statement: PsiForStatement) {
@@ -119,28 +119,28 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
} }
override fun visitForeachStatement(statement: PsiForeachStatement) { override fun visitForeachStatement(statement: PsiForeachStatement) {
val iteratorExpr = codeConverter.convertExpression(statement.getIteratedValue()) val iteratorExpr = codeConverter.convertExpression(statement.iteratedValue)
val iterator = BangBangExpression.surroundIfNullable(iteratorExpr) val iterator = BangBangExpression.surroundIfNullable(iteratorExpr)
val iterationParameter = statement.getIterationParameter() val iterationParameter = statement.iterationParameter
result = ForeachStatement(iterationParameter.declarationIdentifier(), result = ForeachStatement(iterationParameter.declarationIdentifier(),
if (codeConverter.settings.specifyLocalVariableTypeByDefault) codeConverter.typeConverter.convertVariableType(iterationParameter) else null, if (codeConverter.settings.specifyLocalVariableTypeByDefault) codeConverter.typeConverter.convertVariableType(iterationParameter) else null,
iterator, iterator,
codeConverter.convertStatementOrBlock(statement.getBody()), codeConverter.convertStatementOrBlock(statement.body),
statement.isInSingleLine()) statement.isInSingleLine())
} }
override fun visitIfStatement(statement: PsiIfStatement) { override fun visitIfStatement(statement: PsiIfStatement) {
val condition = statement.getCondition() val condition = statement.condition
val expression = codeConverter.convertExpression(condition, PsiType.BOOLEAN) val expression = codeConverter.convertExpression(condition, PsiType.BOOLEAN)
result = IfStatement(expression, result = IfStatement(expression,
codeConverter.convertStatementOrBlock(statement.getThenBranch()), codeConverter.convertStatementOrBlock(statement.thenBranch),
codeConverter.convertStatementOrBlock(statement.getElseBranch()), codeConverter.convertStatementOrBlock(statement.elseBranch),
statement.isInSingleLine()) statement.isInSingleLine())
} }
override fun visitLabeledStatement(statement: PsiLabeledStatement) { override fun visitLabeledStatement(statement: PsiLabeledStatement) {
val statementConverted = codeConverter.convertStatement(statement.getStatement()) val statementConverted = codeConverter.convertStatement(statement.statement)
val identifier = converter.convertIdentifier(statement.getLabelIdentifier()) val identifier = converter.convertIdentifier(statement.labelIdentifier)
if (statementConverted is ForConverter.WhileWithInitializationPseudoStatement) { // special case - if our loop gets converted to while with initialization we should move the label to the loop if (statementConverted is ForConverter.WhileWithInitializationPseudoStatement) { // special case - if our loop gets converted to while with initialization we should move the label to the loop
val labeledLoop = LabeledStatement(identifier, statementConverted.loop).assignPrototype(statement) val labeledLoop = LabeledStatement(identifier, statementConverted.loop).assignPrototype(statement)
result = ForConverter.WhileWithInitializationPseudoStatement(statementConverted.initialization, labeledLoop, statementConverted.kind) result = ForConverter.WhileWithInitializationPseudoStatement(statementConverted.initialization, labeledLoop, statementConverted.kind)
@@ -151,10 +151,10 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
} }
override fun visitSwitchLabelStatement(statement: PsiSwitchLabelStatement) { override fun visitSwitchLabelStatement(statement: PsiSwitchLabelStatement) {
result = if (statement.isDefaultCase()) result = if (statement.isDefaultCase)
ElseWhenEntrySelector() ElseWhenEntrySelector()
else else
ValueWhenEntrySelector(codeConverter.convertExpression(statement.getCaseValue())) ValueWhenEntrySelector(codeConverter.convertExpression(statement.caseValue))
} }
override fun visitSwitchStatement(statement: PsiSwitchStatement) { override fun visitSwitchStatement(statement: PsiSwitchStatement) {
@@ -162,22 +162,22 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
} }
override fun visitSynchronizedStatement(statement: PsiSynchronizedStatement) { override fun visitSynchronizedStatement(statement: PsiSynchronizedStatement) {
result = SynchronizedStatement(codeConverter.convertExpression(statement.getLockExpression()), result = SynchronizedStatement(codeConverter.convertExpression(statement.lockExpression),
codeConverter.convertBlock(statement.getBody())) codeConverter.convertBlock(statement.body))
} }
override fun visitThrowStatement(statement: PsiThrowStatement) { override fun visitThrowStatement(statement: PsiThrowStatement) {
result = ThrowStatement(codeConverter.convertExpression(statement.getException())) result = ThrowStatement(codeConverter.convertExpression(statement.exception))
} }
override fun visitTryStatement(tryStatement: PsiTryStatement) { override fun visitTryStatement(tryStatement: PsiTryStatement) {
val tryBlock = tryStatement.getTryBlock() val tryBlock = tryStatement.tryBlock
val catchesConverted = convertCatches(tryStatement) val catchesConverted = convertCatches(tryStatement)
val finallyConverted = codeConverter.convertBlock(tryStatement.getFinallyBlock()) val finallyConverted = codeConverter.convertBlock(tryStatement.finallyBlock)
val resourceList = tryStatement.getResourceList() val resourceList = tryStatement.resourceList
if (resourceList != null) { if (resourceList != null) {
val variables = resourceList.getResourceVariables() val variables = resourceList.resourceVariables
if (variables.isNotEmpty()) { if (variables.isNotEmpty()) {
result = convertTryWithResources(tryBlock, variables, catchesConverted, finallyConverted) result = convertTryWithResources(tryBlock, variables, catchesConverted, finallyConverted)
return return
@@ -189,12 +189,12 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
private fun convertCatches(tryStatement: PsiTryStatement): List<CatchStatement> { private fun convertCatches(tryStatement: PsiTryStatement): List<CatchStatement> {
val catches = ArrayList<CatchStatement>() val catches = ArrayList<CatchStatement>()
for ((block, parameter) in tryStatement.getCatchBlocks().zip(tryStatement.getCatchBlockParameters())) { for ((block, parameter) in tryStatement.catchBlocks.zip(tryStatement.catchBlockParameters)) {
val blockConverted = codeConverter.convertBlock(block) val blockConverted = codeConverter.convertBlock(block)
val annotations = converter.convertAnnotations(parameter) val annotations = converter.convertAnnotations(parameter)
val parameterType = parameter.getType() val parameterType = parameter.type
val types = if (parameterType is PsiDisjunctionType) val types = if (parameterType is PsiDisjunctionType)
parameterType.getDisjunctions() parameterType.disjunctions
else else
listOf(parameterType) listOf(parameterType)
for (t in types) { for (t in types) {
@@ -220,7 +220,7 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
val parameter = LambdaParameter(Identifier(variable.name!!).assignNoPrototype(), null).assignNoPrototype() val parameter = LambdaParameter(Identifier(variable.name!!).assignNoPrototype(), null).assignNoPrototype()
val parameterList = ParameterList(listOf(parameter)).assignNoPrototype() val parameterList = ParameterList(listOf(parameter)).assignNoPrototype()
val lambda = LambdaExpression(parameterList, block) val lambda = LambdaExpression(parameterList, block)
expression = MethodCallExpression.build(codeConverter.convertExpression(variable.getInitializer()), "use", listOf(lambda), listOf(), false) expression = MethodCallExpression.build(codeConverter.convertExpression(variable.initializer), "use", listOf(lambda), listOf(), false)
expression.assignNoPrototype() expression.assignNoPrototype()
block = Block(listOf(expression), LBrace().assignNoPrototype(), RBrace().assignNoPrototype()).assignNoPrototype() block = Block(listOf(expression), LBrace().assignNoPrototype(), RBrace().assignNoPrototype()).assignNoPrototype()
} }
@@ -229,21 +229,21 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
return wrapResultStatement(expression) return wrapResultStatement(expression)
} }
block = Block(listOf(wrapResultStatement(expression)), LBrace().assignPrototype(tryBlock?.getLBrace()), RBrace().assignPrototype(tryBlock?.getRBrace()), true) block = Block(listOf(wrapResultStatement(expression)), LBrace().assignPrototype(tryBlock?.lBrace), RBrace().assignPrototype(tryBlock?.rBrace), true)
return TryStatement(block.assignPrototype(tryBlock), catchesConverted, finallyConverted) return TryStatement(block.assignPrototype(tryBlock), catchesConverted, finallyConverted)
} }
override fun visitWhileStatement(statement: PsiWhileStatement) { override fun visitWhileStatement(statement: PsiWhileStatement) {
val condition = statement.getCondition() val condition = statement.condition
val expression = if (condition?.getType() != null) val expression = if (condition?.type != null)
codeConverter.convertExpression(condition, condition!!.getType()) codeConverter.convertExpression(condition, condition!!.type)
else else
codeConverter.convertExpression(condition) codeConverter.convertExpression(condition)
result = WhileStatement(expression, codeConverter.convertStatementOrBlock(statement.getBody()), statement.isInSingleLine()) result = WhileStatement(expression, codeConverter.convertStatementOrBlock(statement.body), statement.isInSingleLine())
} }
override fun visitReturnStatement(statement: PsiReturnStatement) { override fun visitReturnStatement(statement: PsiReturnStatement) {
val returnValue = statement.getReturnValue() val returnValue = statement.returnValue
val methodReturnType = codeConverter.methodReturnType val methodReturnType = codeConverter.methodReturnType
val expression = if (returnValue != null && methodReturnType != null) val expression = if (returnValue != null && methodReturnType != null)
codeConverter.convertExpression(returnValue, methodReturnType) codeConverter.convertExpression(returnValue, methodReturnType)
@@ -260,7 +260,7 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
fun CodeConverter.convertStatementOrBlock(statement: PsiStatement?): Statement { fun CodeConverter.convertStatementOrBlock(statement: PsiStatement?): Statement {
return if (statement is PsiBlockStatement) return if (statement is PsiBlockStatement)
convertBlock(statement.getCodeBlock()) convertBlock(statement.codeBlock)
else else
convertStatement(statement) convertStatement(statement)
} }
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.j2k
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.j2k.ast.*
import java.util.ArrayList import java.util.*
class SwitchConverter(private val codeConverter: CodeConverter) { class SwitchConverter(private val codeConverter: CodeConverter) {
public fun convert(statement: PsiSwitchStatement): WhenStatement public fun convert(statement: PsiSwitchStatement): WhenStatement
= WhenStatement(codeConverter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody())) = WhenStatement(codeConverter.convertExpression(statement.expression), switchBodyToWhenEntries(statement.body))
private class Case(val label: PsiSwitchLabelStatement?, val statements: List<PsiStatement>) private class Case(val label: PsiSwitchLabelStatement?, val statements: List<PsiStatement>)
@@ -59,7 +59,7 @@ class SwitchConverter(private val codeConverter: CodeConverter) {
} }
} }
for (statement in body.getStatements()) { for (statement in body.statements) {
if (statement is PsiSwitchLabelStatement) { if (statement is PsiSwitchLabelStatement) {
flushCurrentCase() flushCurrentCase()
currentLabel = statement currentLabel = statement
@@ -78,10 +78,10 @@ class SwitchConverter(private val codeConverter: CodeConverter) {
private fun convertCaseStatements(statements: List<PsiStatement>, allowBlock: Boolean = true): List<Statement> { private fun convertCaseStatements(statements: List<PsiStatement>, allowBlock: Boolean = true): List<Statement> {
val statementsToKeep = statements.filter { !isSwitchBreak(it) } val statementsToKeep = statements.filter { !isSwitchBreak(it) }
if (allowBlock && statementsToKeep.size() == 1) { if (allowBlock && statementsToKeep.size == 1) {
val block = statementsToKeep.single() as? PsiBlockStatement val block = statementsToKeep.single() as? PsiBlockStatement
if (block != null) { if (block != null) {
return listOf(codeConverter.convertBlock(block.getCodeBlock(), true, { !isSwitchBreak(it) })) return listOf(codeConverter.convertBlock(block.codeBlock, true, { !isSwitchBreak(it) }))
} }
} }
return statementsToKeep.map { codeConverter.convertStatement(it) } return statementsToKeep.map { codeConverter.convertStatement(it) }
@@ -94,7 +94,7 @@ class SwitchConverter(private val codeConverter: CodeConverter) {
} }
else { else {
val block = case.statements.singleOrNull() as? PsiBlockStatement val block = case.statements.singleOrNull() as? PsiBlockStatement
val statements = if (block != null) block.getCodeBlock().getStatements().toList() else case.statements val statements = if (block != null) block.codeBlock.statements.toList() else case.statements
!statements.any { it is PsiBreakStatement || it is PsiContinueStatement || it is PsiReturnStatement || it is PsiThrowStatement } !statements.any { it is PsiBreakStatement || it is PsiContinueStatement || it is PsiReturnStatement || it is PsiThrowStatement }
} }
return if (fallsThrough) // we fall through into the next case return if (fallsThrough) // we fall through into the next case
@@ -105,11 +105,11 @@ class SwitchConverter(private val codeConverter: CodeConverter) {
private fun convertCaseStatementsToBody(cases: List<Case>, caseIndex: Int): Statement { private fun convertCaseStatementsToBody(cases: List<Case>, caseIndex: Int): Statement {
val statements = convertCaseStatements(cases, caseIndex) val statements = convertCaseStatements(cases, caseIndex)
return if (statements.size() == 1) return if (statements.size == 1)
statements.single() statements.single()
else else
Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype() Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
} }
private fun isSwitchBreak(statement: PsiStatement) = statement is PsiBreakStatement && statement.getLabelIdentifier() == null private fun isSwitchBreak(statement: PsiStatement) = statement is PsiBreakStatement && statement.labelIdentifier == null
} }
@@ -25,8 +25,7 @@ import org.jetbrains.kotlin.j2k.ast.*
import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import java.util.HashMap import java.util.*
import java.util.HashSet
class TypeConverter(val converter: Converter) { class TypeConverter(val converter: Converter) {
private val typesBeingConverted = HashSet<PsiType>() private val typesBeingConverted = HashSet<PsiType>()
@@ -64,13 +63,13 @@ class TypeConverter(val converter: Converter) {
converter.settings).assignNoPrototype() converter.settings).assignNoPrototype()
} }
else { else {
convertType(variable.getType(), variableNullability(variable), variableMutability(variable)) convertType(variable.type, variableNullability(variable), variableMutability(variable))
} }
return result.assignPrototype(variable.getTypeElement()) return result.assignPrototype(variable.typeElement)
} }
public fun convertMethodReturnType(method: PsiMethod): Type public fun convertMethodReturnType(method: PsiMethod): Type
= convertType(method.getReturnType(), methodNullability(method), methodMutability(method)).assignPrototype(method.getReturnTypeElement()) = convertType(method.returnType, methodNullability(method), methodMutability(method)).assignPrototype(method.returnTypeElement)
public fun variableNullability(variable: PsiVariable): Nullability public fun variableNullability(variable: PsiVariable): Nullability
= nullabilityFlavor.forVariableType(variable) = nullabilityFlavor.forVariableType(variable)
@@ -84,13 +83,13 @@ class TypeConverter(val converter: Converter) {
public fun methodMutability(method: PsiMethod): Mutability public fun methodMutability(method: PsiMethod): Mutability
= mutabilityFlavor.forMethodReturnType(method) = mutabilityFlavor.forMethodReturnType(method)
private fun PsiVariable.isMainMethodParameter() = this is PsiParameter && (getDeclarationScope() as? PsiMethod)?.isMainMethod() ?: false private fun PsiVariable.isMainMethodParameter() = this is PsiParameter && (declarationScope as? PsiMethod)?.isMainMethod() ?: false
private fun searchScope(element: PsiElement): PsiElement? { private fun searchScope(element: PsiElement): PsiElement? {
return when(element) { return when(element) {
is PsiParameter -> element.getDeclarationScope() is PsiParameter -> element.declarationScope
is PsiField -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.getContainingClass() else element.getContainingFile() is PsiField -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.containingClass else element.containingFile
is PsiMethod -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.getContainingClass() else element.getContainingFile() is PsiMethod -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.containingClass else element.containingFile
is PsiLocalVariable -> element.getContainingMethod() is PsiLocalVariable -> element.getContainingMethod()
else -> null else -> null
} }
@@ -100,7 +99,7 @@ class TypeConverter(val converter: Converter) {
if (hasModifierProperty(PsiModifier.FINAL)) return true if (hasModifierProperty(PsiModifier.FINAL)) return true
return when(this) { return when(this) {
is PsiLocalVariable -> !hasWriteAccesses(converter.referenceSearcher, getContainingMethod()) is PsiLocalVariable -> !hasWriteAccesses(converter.referenceSearcher, getContainingMethod())
is PsiField -> if (hasModifierProperty(PsiModifier.PRIVATE)) !hasWriteAccesses(converter.referenceSearcher, getContainingClass()) else false is PsiField -> if (hasModifierProperty(PsiModifier.PRIVATE)) !hasWriteAccesses(converter.referenceSearcher, containingClass) else false
else -> false else -> false
} }
} }
@@ -129,7 +128,7 @@ class TypeConverter(val converter: Converter) {
private fun forVariableTypeNoCache(variable: PsiVariable): T { private fun forVariableTypeNoCache(variable: PsiVariable): T {
if (variable is PsiEnumConstant) return forEnumConstant if (variable is PsiEnumConstant) return forEnumConstant
val variableType = variable.getType() val variableType = variable.type
var value = fromType(variableType) var value = fromType(variableType)
if (value != default) return value if (value != default) return value
@@ -137,14 +136,14 @@ class TypeConverter(val converter: Converter) {
if (value != default) return value if (value != default) return value
if (variable is PsiParameter) { if (variable is PsiParameter) {
val scope = variable.getDeclarationScope() val scope = variable.declarationScope
if (scope is PsiMethod) { if (scope is PsiMethod) {
val paramIndex = scope.getParameterList().getParameters().indexOf(variable) val paramIndex = scope.parameterList.parameters.indexOf(variable)
assert(paramIndex >= 0) assert(paramIndex >= 0)
val superSignatures = scope.getHierarchicalMethodSignature().getSuperSignatures() val superSignatures = scope.hierarchicalMethodSignature.superSignatures
value = superSignatures.map { signature -> value = superSignatures.map { signature ->
val params = signature.getMethod().getParameterList().getParameters() val params = signature.method.parameterList.parameters
if (paramIndex < params.size()) forVariableType(params[paramIndex]) else default if (paramIndex < params.size) forVariableType(params[paramIndex]) else default
}.firstOrNull { it != default } ?: default }.firstOrNull { it != default } ?: default
if (value != default) return value if (value != default) return value
} }
@@ -179,7 +178,7 @@ class TypeConverter(val converter: Converter) {
} }
private fun forMethodReturnTypeNoCache(method: PsiMethod): T { private fun forMethodReturnTypeNoCache(method: PsiMethod): T {
val returnType = method.getReturnType() ?: return default val returnType = method.returnType ?: return default
var value = fromType(returnType) var value = fromType(returnType)
if (value != default) return value if (value != default) return value
@@ -187,8 +186,8 @@ class TypeConverter(val converter: Converter) {
value = fromAnnotations(method) value = fromAnnotations(method)
if (value != default) return value if (value != default) return value
val superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures() val superSignatures = method.hierarchicalMethodSignature.superSignatures
value = superSignatures.map { forMethodReturnType(it.getMethod()) }.firstOrNull { it != default } ?: default value = superSignatures.map { forMethodReturnType(it.method) }.firstOrNull { it != default } ?: default
if (value != default) return value if (value != default) return value
value = fromTypeHeuristics(returnType) value = fromTypeHeuristics(returnType)
@@ -196,7 +195,7 @@ class TypeConverter(val converter: Converter) {
if (!converter.inConversionScope(method)) return default // do not analyze body and usages of methods out of our conversion scope if (!converter.inConversionScope(method)) return default // do not analyze body and usages of methods out of our conversion scope
val body = method.getBody() val body = method.body
if (body != null) { if (body != null) {
value = fromMethodBody(body) value = fromMethodBody(body)
if (value != default) return value if (value != default) return value
@@ -230,7 +229,7 @@ class TypeConverter(val converter: Converter) {
override fun fromType(type: PsiType) = if (type is PsiPrimitiveType) Nullability.NotNull else Nullability.Default override fun fromType(type: PsiType) = if (type is PsiPrimitiveType) Nullability.NotNull else Nullability.Default
override fun fromAnnotations(owner: PsiModifierListOwner): Nullability { override fun fromAnnotations(owner: PsiModifierListOwner): Nullability {
val manager = NullableNotNullManager.getInstance(owner.getProject()) val manager = NullableNotNullManager.getInstance(owner.project)
return if (manager.isNotNull(owner, false/* we do not check bases because they are checked by callers of this method*/)) return if (manager.isNotNull(owner, false/* we do not check bases because they are checked by callers of this method*/))
Nullability.NotNull Nullability.NotNull
else if (manager.isNullable(owner, false)) else if (manager.isNullable(owner, false))
@@ -240,7 +239,7 @@ class TypeConverter(val converter: Converter) {
} }
override fun forVariableTypeBeforeUsageSearch(variable: PsiVariable): Nullability { override fun forVariableTypeBeforeUsageSearch(variable: PsiVariable): Nullability {
val initializer = variable.getInitializer() val initializer = variable.initializer
if (initializer != null) { if (initializer != null) {
val initializerNullability = initializer.nullability() val initializerNullability = initializer.nullability()
if (initializerNullability != Nullability.Default) { if (initializerNullability != Nullability.Default) {
@@ -259,8 +258,8 @@ class TypeConverter(val converter: Converter) {
if (variable is PsiParameter) { if (variable is PsiParameter) {
// Object.equals corresponds to Any.equals which has nullable parameter: // Object.equals corresponds to Any.equals which has nullable parameter:
val scope = variable.getDeclarationScope() val scope = variable.declarationScope
if (scope is PsiMethod && scope.getName() == "equals" && scope.getContainingClass()?.getQualifiedName() == JAVA_LANG_OBJECT) { if (scope is PsiMethod && scope.name == "equals" && scope.containingClass?.qualifiedName == JAVA_LANG_OBJECT) {
return Nullability.Nullable return Nullability.Nullable
} }
} }
@@ -276,25 +275,25 @@ class TypeConverter(val converter: Converter) {
} }
// variables of types like Integer are most likely nullable // variables of types like Integer are most likely nullable
override fun fromTypeHeuristics(type: PsiType) = if (type.getCanonicalText() in boxingTypes) Nullability.Nullable else Nullability.Default override fun fromTypeHeuristics(type: PsiType) = if (type.canonicalText in boxingTypes) Nullability.Nullable else Nullability.Default
override fun fromUsage(usage: PsiExpression): Nullability { override fun fromUsage(usage: PsiExpression): Nullability {
return if (isNullableFromUsage(usage)) Nullability.Nullable else Nullability.Default return if (isNullableFromUsage(usage)) Nullability.Nullable else Nullability.Default
} }
private fun isNullableFromUsage(usage: PsiExpression): Boolean { private fun isNullableFromUsage(usage: PsiExpression): Boolean {
val parent = usage.getParent() val parent = usage.parent
if (parent is PsiAssignmentExpression && parent.getOperationTokenType() == JavaTokenType.EQ && usage == parent.getLExpression()) { if (parent is PsiAssignmentExpression && parent.operationTokenType == JavaTokenType.EQ && usage == parent.lExpression) {
return parent.getRExpression()?.nullability() == Nullability.Nullable return parent.rExpression?.nullability() == Nullability.Nullable
} }
else if (parent is PsiBinaryExpression) { else if (parent is PsiBinaryExpression) {
val operationType = parent.getOperationTokenType() val operationType = parent.operationTokenType
if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) { if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) {
val otherOperand = if (usage == parent.getLOperand()) parent.getROperand() else parent.getLOperand() val otherOperand = if (usage == parent.lOperand) parent.rOperand else parent.lOperand
return otherOperand?.isNullLiteral() ?: false return otherOperand?.isNullLiteral() ?: false
} }
} }
else if (parent is PsiVariable && usage == parent.getInitializer() && parent.isEffectivelyFinal()) { else if (parent is PsiVariable && usage == parent.initializer && parent.isEffectivelyFinal()) {
return variableNullability(parent) == Nullability.Nullable return variableNullability(parent) == Nullability.Nullable
} }
return false return false
@@ -302,15 +301,15 @@ class TypeConverter(val converter: Converter) {
override fun forVariableTypeAfterUsageSearch(variable: PsiVariable): Nullability { override fun forVariableTypeAfterUsageSearch(variable: PsiVariable): Nullability {
if (variable is PsiParameter) { if (variable is PsiParameter) {
val method = variable.getDeclarationScope() as? PsiMethod val method = variable.declarationScope as? PsiMethod
if (method != null) { if (method != null) {
val scope = searchScope(method) val scope = searchScope(method)
if (scope != null) { if (scope != null) {
val parameters = method.getParameterList().getParameters() val parameters = method.parameterList.parameters
val parameterIndex = parameters.indexOf(variable) val parameterIndex = parameters.indexOf(variable)
for (call in converter.referenceSearcher.findMethodCalls(method, scope)) { for (call in converter.referenceSearcher.findMethodCalls(method, scope)) {
val args = call.getArgumentList().getExpressions() val args = call.argumentList.expressions
if (args.size() == parameters.size()) { if (args.size == parameters.size) {
if (args[parameterIndex].nullability() == Nullability.Nullable) { if (args[parameterIndex].nullability() == Nullability.Nullable) {
return Nullability.Nullable return Nullability.Nullable
} }
@@ -326,7 +325,7 @@ class TypeConverter(val converter: Converter) {
var isNullable = false var isNullable = false
body.accept(object: JavaRecursiveElementVisitor() { body.accept(object: JavaRecursiveElementVisitor() {
override fun visitReturnStatement(statement: PsiReturnStatement) { override fun visitReturnStatement(statement: PsiReturnStatement) {
if (statement.getReturnValue()?.nullability() == Nullability.Nullable) { if (statement.returnValue?.nullability() == Nullability.Nullable) {
isNullable = true isNullable = true
} }
} }
@@ -340,20 +339,20 @@ class TypeConverter(val converter: Converter) {
private fun PsiExpression.nullability(): Nullability { private fun PsiExpression.nullability(): Nullability {
return when (this) { return when (this) {
is PsiLiteralExpression -> if (getType() != PsiType.NULL) Nullability.NotNull else Nullability.Nullable is PsiLiteralExpression -> if (type != PsiType.NULL) Nullability.NotNull else Nullability.Nullable
is PsiNewExpression -> Nullability.NotNull is PsiNewExpression -> Nullability.NotNull
is PsiConditionalExpression -> { is PsiConditionalExpression -> {
val nullability1 = getThenExpression()?.nullability() val nullability1 = thenExpression?.nullability()
if (nullability1 == Nullability.Nullable) return Nullability.Nullable if (nullability1 == Nullability.Nullable) return Nullability.Nullable
val nullability2 = getElseExpression()?.nullability() val nullability2 = elseExpression?.nullability()
if (nullability2 == Nullability.Nullable) return Nullability.Nullable if (nullability2 == Nullability.Nullable) return Nullability.Nullable
if (nullability1 == Nullability.NotNull && nullability2 == Nullability.NotNull) return Nullability.NotNull if (nullability1 == Nullability.NotNull && nullability2 == Nullability.NotNull) return Nullability.NotNull
Nullability.Default Nullability.Default
} }
is PsiParenthesizedExpression -> getExpression()?.nullability() ?: Nullability.Default is PsiParenthesizedExpression -> expression?.nullability() ?: Nullability.Default
//TODO: some other cases //TODO: some other cases
@@ -368,7 +367,7 @@ class TypeConverter(val converter: Converter) {
override fun fromType(type: PsiType): Mutability { override fun fromType(type: PsiType): Mutability {
val target = (type as? PsiClassType)?.resolve() ?: return Mutability.NonMutable val target = (type as? PsiClassType)?.resolve() ?: return Mutability.NonMutable
if (target.getQualifiedName() !in TypeVisitor.toKotlinMutableTypesMap.keySet()) return Mutability.NonMutable if (!TypeVisitor.toKotlinMutableTypesMap.keys.containsRaw(target.qualifiedName)) return Mutability.NonMutable
return Mutability.Default return Mutability.Default
} }
@@ -376,7 +375,7 @@ class TypeConverter(val converter: Converter) {
if (owner is KtLightElement<*, *>) { if (owner is KtLightElement<*, *>) {
val jetDeclaration = owner.getOrigin() as? KtCallableDeclaration ?: return Mutability.Default val jetDeclaration = owner.getOrigin() as? KtCallableDeclaration ?: return Mutability.Default
val descriptor = converter.services.resolverForConverter.resolveToDescriptor(jetDeclaration) as? CallableDescriptor ?: return Mutability.Default val descriptor = converter.services.resolverForConverter.resolveToDescriptor(jetDeclaration) as? CallableDescriptor ?: return Mutability.Default
val type = descriptor.getReturnType() ?: return Mutability.Default val type = descriptor.returnType ?: return Mutability.Default
val classDescriptor = TypeUtils.getClassDescriptor(type) ?: return Mutability.Default val classDescriptor = TypeUtils.getClassDescriptor(type) ?: return Mutability.Default
return if (DescriptorUtils.getFqName(classDescriptor).asString() in mutableKotlinClasses) return if (DescriptorUtils.getFqName(classDescriptor).asString() in mutableKotlinClasses)
Mutability.Mutable Mutability.Mutable
@@ -385,30 +384,30 @@ class TypeConverter(val converter: Converter) {
} }
//TODO: Kotlin compiled elements //TODO: Kotlin compiled elements
return super<TypeFlavor>.fromAnnotations(owner) //TODO: ReadOnly annotation return super.fromAnnotations(owner) //TODO: ReadOnly annotation
} }
override fun fromUsage(usage: PsiExpression) override fun fromUsage(usage: PsiExpression)
= if (isMutableFromUsage(usage)) Mutability.Mutable else Mutability.Default = if (isMutableFromUsage(usage)) Mutability.Mutable else Mutability.Default
private fun isMutableFromUsage(usage: PsiExpression): Boolean { private fun isMutableFromUsage(usage: PsiExpression): Boolean {
val parent = usage.getParent() val parent = usage.parent
if (parent is PsiReferenceExpression && usage == parent.getQualifierExpression() && parent.getParent() is PsiMethodCallExpression) { if (parent is PsiReferenceExpression && usage == parent.qualifierExpression && parent.parent is PsiMethodCallExpression) {
return parent.getReferenceName() in modificationMethodNames return modificationMethodNames.containsRaw(parent.referenceName)
} }
else if (parent is PsiExpressionList) { else if (parent is PsiExpressionList) {
val call = parent.getParent() as? PsiCall ?: return false val call = parent.parent as? PsiCall ?: return false
val method = call.resolveMethod() ?: return false val method = call.resolveMethod() ?: return false
val paramIndex = parent.getExpressions().indexOf(usage) val paramIndex = parent.expressions.indexOf(usage)
val parameterList = method.getParameterList() val parameterList = method.parameterList
if (paramIndex >= parameterList.getParametersCount()) return false if (paramIndex >= parameterList.parametersCount) return false
return variableMutability(parameterList.getParameters()[paramIndex]) == Mutability.Mutable return variableMutability(parameterList.parameters[paramIndex]) == Mutability.Mutable
} }
else if (parent is PsiVariable && usage == parent.getInitializer()) { else if (parent is PsiVariable && usage == parent.initializer) {
return variableMutability(parent) == Mutability.Mutable return variableMutability(parent) == Mutability.Mutable
} }
else if (parent is PsiAssignmentExpression && parent.getOperationTokenType() == JavaTokenType.EQ && usage == parent.getRExpression()) { else if (parent is PsiAssignmentExpression && parent.operationTokenType == JavaTokenType.EQ && usage == parent.rExpression) {
val leftSideVar = (parent.getLExpression() as? PsiReferenceExpression)?.resolve() as? PsiVariable ?: return false val leftSideVar = (parent.lExpression as? PsiReferenceExpression)?.resolve() as? PsiVariable ?: return false
return variableMutability(leftSideVar) == Mutability.Mutable return variableMutability(leftSideVar) == Mutability.Mutable
} }
return false return false
@@ -431,6 +430,6 @@ class TypeConverter(val converter: Converter) {
"add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll" "add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll"
) )
private val mutableKotlinClasses = TypeVisitor.toKotlinMutableTypesMap.values().toSet() private val mutableKotlinClasses = TypeVisitor.toKotlinMutableTypesMap.values.toSet()
} }
} }
+15 -15
View File
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.j2k.ast.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getJavaKeywordName() } private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.javaKeywordName }
class TypeVisitor( class TypeVisitor(
private val converter: Converter, private val converter: Converter,
@@ -38,7 +38,7 @@ class TypeVisitor(
override fun visitType(type: PsiType) = ErrorType() override fun visitType(type: PsiType) = ErrorType()
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type { override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
val name = primitiveType.getCanonicalText() val name = primitiveType.canonicalText
return if (name == "void") { return if (name == "void") {
UnitType() UnitType()
} }
@@ -54,7 +54,7 @@ class TypeVisitor(
} }
override fun visitArrayType(arrayType: PsiArrayType): Type { override fun visitArrayType(arrayType: PsiArrayType): Type {
return ArrayType(typeConverter.convertType(arrayType.getComponentType(), inAnnotationType = inAnnotationType), Nullability.Default, converter.settings) return ArrayType(typeConverter.convertType(arrayType.componentType, inAnnotationType = inAnnotationType), Nullability.Default, converter.settings)
} }
override fun visitClassType(classType: PsiClassType): Type { override fun visitClassType(classType: PsiClassType): Type {
@@ -68,7 +68,7 @@ class TypeVisitor(
val psiClass = classType.resolve() val psiClass = classType.resolve()
if (psiClass != null) { if (psiClass != null) {
val javaClassName = psiClass.getQualifiedName() val javaClassName = psiClass.qualifiedName
val kotlinClassName = (if (mutability.isMutable(converter.settings)) toKotlinMutableTypesMap[javaClassName] else null) val kotlinClassName = (if (mutability.isMutable(converter.settings)) toKotlinMutableTypesMap[javaClassName] else null)
?: toKotlinTypesMap[javaClassName] ?: toKotlinTypesMap[javaClassName]
if (kotlinClassName != null) { if (kotlinClassName != null) {
@@ -77,35 +77,35 @@ class TypeVisitor(
if (inAnnotationType && javaClassName == "java.lang.Class") { if (inAnnotationType && javaClassName == "java.lang.Class") {
val fqName = FqName("kotlin.reflect.KClass") val fqName = FqName("kotlin.reflect.KClass")
val identifier = Identifier(fqName.shortName().getIdentifier(), imports = listOf(fqName)).assignNoPrototype() val identifier = Identifier(fqName.shortName().identifier, imports = listOf(fqName)).assignNoPrototype()
return ReferenceElement(identifier, typeArgs).assignNoPrototype() return ReferenceElement(identifier, typeArgs).assignNoPrototype()
} }
} }
if (classType is PsiClassReferenceType) { if (classType is PsiClassReferenceType) {
return converter.convertCodeReferenceElement(classType.getReference(), hasExternalQualifier = false, typeArgsConverted = typeArgs) return converter.convertCodeReferenceElement(classType.reference, hasExternalQualifier = false, typeArgsConverted = typeArgs)
} }
return ReferenceElement(Identifier(classType.getClassName() ?: "").assignNoPrototype(), typeArgs).assignNoPrototype() return ReferenceElement(Identifier(classType.className ?: "").assignNoPrototype(), typeArgs).assignNoPrototype()
} }
private fun getShortName(className: String): String = className.substringAfterLast('.', className) private fun getShortName(className: String): String = className.substringAfterLast('.', className)
private fun convertTypeArgs(classType: PsiClassType): List<Type> { private fun convertTypeArgs(classType: PsiClassType): List<Type> {
if (classType.getParameterCount() == 0) { if (classType.parameterCount == 0) {
return createTypeArgsForRawTypeUsage(classType, Mutability.Default) return createTypeArgsForRawTypeUsage(classType, Mutability.Default)
} }
else { else {
return typeConverter.convertTypes(classType.getParameters()) return typeConverter.convertTypes(classType.parameters)
} }
} }
private fun createTypeArgsForRawTypeUsage(classType: PsiClassType, mutability: Mutability): List<Type> { private fun createTypeArgsForRawTypeUsage(classType: PsiClassType, mutability: Mutability): List<Type> {
if (classType is PsiClassReferenceType) { if (classType is PsiClassReferenceType) {
val targetClass = classType.getReference().resolve() as? PsiClass val targetClass = classType.reference.resolve() as? PsiClass
if (targetClass != null) { if (targetClass != null) {
return targetClass.getTypeParameters().map { return targetClass.typeParameters.map {
val superType = it.getSuperTypes().first() // there must be at least one super type always val superType = it.superTypes.first() // there must be at least one super type always
typeConverter.convertType(superType, Nullability.Default, mutability, inAnnotationType).assignNoPrototype() typeConverter.convertType(superType, Nullability.Default, mutability, inAnnotationType).assignNoPrototype()
} }
} }
@@ -115,14 +115,14 @@ class TypeVisitor(
override fun visitWildcardType(wildcardType: PsiWildcardType): Type { override fun visitWildcardType(wildcardType: PsiWildcardType): Type {
return when { return when {
wildcardType.isExtends() -> OutProjectionType(typeConverter.convertType(wildcardType.getExtendsBound())) wildcardType.isExtends -> OutProjectionType(typeConverter.convertType(wildcardType.extendsBound))
wildcardType.isSuper() -> InProjectionType(typeConverter.convertType(wildcardType.getSuperBound())) wildcardType.isSuper -> InProjectionType(typeConverter.convertType(wildcardType.superBound))
else -> StarProjectionType() else -> StarProjectionType()
} }
} }
override fun visitEllipsisType(ellipsisType: PsiEllipsisType): Type { override fun visitEllipsisType(ellipsisType: PsiEllipsisType): Type {
return VarArgType(typeConverter.convertType(ellipsisType.getComponentType(), inAnnotationType = inAnnotationType)) return VarArgType(typeConverter.convertType(ellipsisType.componentType, inAnnotationType = inAnnotationType))
} }
companion object { companion object {
+16 -16
View File
@@ -47,46 +47,46 @@ fun shouldGenerateDefaultInitializer(searcher: ReferenceSearcher, field: PsiFiel
= field.initializer == null && (field.isVar(searcher) || !field.hasWriteAccesses(searcher, field.containingClass)) = field.initializer == null && (field.isVar(searcher) || !field.hasWriteAccesses(searcher, field.containingClass))
fun PsiReferenceExpression.isQualifierEmptyOrThis(): Boolean { fun PsiReferenceExpression.isQualifierEmptyOrThis(): Boolean {
val qualifier = getQualifierExpression() val qualifier = qualifierExpression
return qualifier == null || (qualifier is PsiThisExpression && qualifier.getQualifier() == null) return qualifier == null || (qualifier is PsiThisExpression && qualifier.qualifier == null)
} }
fun PsiReferenceExpression.isQualifierEmptyOrClass(psiClass: PsiClass): Boolean { fun PsiReferenceExpression.isQualifierEmptyOrClass(psiClass: PsiClass): Boolean {
val qualifier = getQualifierExpression() val qualifier = qualifierExpression
return qualifier == null || (qualifier is PsiReferenceExpression && qualifier.isReferenceTo(psiClass)) return qualifier == null || (qualifier is PsiReferenceExpression && qualifier.isReferenceTo(psiClass))
} }
fun PsiElement.isInSingleLine(): Boolean { fun PsiElement.isInSingleLine(): Boolean {
if (this is PsiWhiteSpace) { if (this is PsiWhiteSpace) {
val text = getText()!! val text = text!!
return text.indexOf('\n') < 0 && text.indexOf('\r') < 0 return text.indexOf('\n') < 0 && text.indexOf('\r') < 0
} }
var child = getFirstChild() var child = firstChild
while (child != null) { while (child != null) {
if (!child.isInSingleLine()) return false if (!child.isInSingleLine()) return false
child = child.getNextSibling() child = child.nextSibling
} }
return true return true
} }
//TODO: check for variables that are definitely assigned in constructors //TODO: check for variables that are definitely assigned in constructors
fun PsiElement.getContainingMethod(): PsiMethod? { fun PsiElement.getContainingMethod(): PsiMethod? {
var context = getContext() var context = context
while (context != null) { while (context != null) {
val _context = context val _context = context
if (_context is PsiMethod) return _context if (_context is PsiMethod) return _context
context = _context.getContext() context = _context.context
} }
return null return null
} }
fun PsiElement.getContainingConstructor(): PsiMethod? { fun PsiElement.getContainingConstructor(): PsiMethod? {
val method = getContainingMethod() val method = getContainingMethod()
return if (method?.isConstructor() == true) method else null return if (method?.isConstructor == true) method else null
} }
fun PsiMember.isConstructor(): Boolean = this is PsiMethod && this.isConstructor() fun PsiMember.isConstructor(): Boolean = this is PsiMethod && this.isConstructor
fun PsiModifierListOwner.accessModifier(): String = when { fun PsiModifierListOwner.accessModifier(): String = when {
hasModifierProperty(PsiModifier.PUBLIC) -> PsiModifier.PUBLIC hasModifierProperty(PsiModifier.PUBLIC) -> PsiModifier.PUBLIC
@@ -99,18 +99,18 @@ fun PsiMethod.isMainMethod(): Boolean = PsiMethodUtil.isMainMethod(this)
fun PsiMember.isImported(file: PsiJavaFile): Boolean { fun PsiMember.isImported(file: PsiJavaFile): Boolean {
if (this is PsiClass) { if (this is PsiClass) {
val fqName = getQualifiedName() val fqName = qualifiedName
val index = fqName?.lastIndexOf('.') ?: -1 val index = fqName?.lastIndexOf('.') ?: -1
val parentName = if (index >= 0) fqName!!.substring(0, index) else null val parentName = if (index >= 0) fqName!!.substring(0, index) else null
return file.getImportList()?.getAllImportStatements()?.any { return file.importList?.allImportStatements?.any {
it.getImportReference()?.getQualifiedName() == (if (it.isOnDemand()) parentName else fqName) it.importReference?.qualifiedName == (if (it.isOnDemand) parentName else fqName)
} ?: false } ?: false
} }
else { else {
return getContainingClass() != null && file.getImportList()?.getImportStaticStatements()?.any { return containingClass != null && file.importList?.importStaticStatements?.any {
it.resolveTargetClass() == getContainingClass() && (it.isOnDemand() || it.getReferenceName() == getName()) it.resolveTargetClass() == containingClass && (it.isOnDemand || it.referenceName == name)
} ?: false } ?: false
} }
} }
fun PsiExpression.isNullLiteral() = this is PsiLiteralExpression && getType() == PsiType.NULL fun PsiExpression.isNullLiteral() = this is PsiLiteralExpression && type == PsiType.NULL
@@ -44,15 +44,15 @@ class ArrayWithoutInitializationExpression(val type: ArrayType, val expressions:
} }
fun constructInnerType(hostType: ArrayType, expressions: List<Expression>): CodeBuilder { fun constructInnerType(hostType: ArrayType, expressions: List<Expression>): CodeBuilder {
if (expressions.size() == 1) { if (expressions.size == 1) {
return oneDim(hostType, expressions[0]) return oneDim(hostType, expressions[0])
} }
val innerType = hostType.elementType val innerType = hostType.elementType
if (expressions.size() > 1 && innerType is ArrayType) { if (expressions.size > 1 && innerType is ArrayType) {
return oneDim(hostType, expressions[0], { return oneDim(hostType, expressions[0], {
builder.append("{") builder.append("{")
constructInnerType(innerType, expressions.subList(1, expressions.size())) constructInnerType(innerType, expressions.subList(1, expressions.size))
builder.append("}") builder.append("}")
}) })
} }
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class Block(val statements: List<Statement>, val lBrace: LBrace, val rBrace: RBrace, val notEmpty: Boolean = false) : Statement() { class Block(val statements: List<Statement>, val lBrace: LBrace, val rBrace: RBrace, val notEmpty: Boolean = false) : Statement() {
override val isEmpty: Boolean override val isEmpty: Boolean
@@ -59,7 +59,7 @@ open class Class(
} }
private fun baseClassSignatureWithParams(builder: CodeBuilder): List<() -> CodeBuilder> { private fun baseClassSignatureWithParams(builder: CodeBuilder): List<() -> CodeBuilder> {
if (keyword.equals("class") && extendsTypes.size() == 1 && baseClassParams != null) { if (keyword.equals("class") && extendsTypes.size == 1 && baseClassParams != null) {
return listOf({ return listOf({
builder append extendsTypes[0] append "(" builder append extendsTypes[0] append "("
builder.append(baseClassParams, ", ") builder.append(baseClassParams, ", ")
@@ -16,8 +16,11 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.*
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.CodeConverter
import org.jetbrains.kotlin.j2k.Converter
import org.jetbrains.kotlin.j2k.EmptyDocCommentConverter
fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?, inheritance: CommentsAndSpacesInheritance = CommentsAndSpacesInheritance()): TElement { fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?, inheritance: CommentsAndSpacesInheritance = CommentsAndSpacesInheritance()): TElement {
prototypes = if (prototype != null) listOf(PrototypeInfo(prototype, inheritance)) else listOf() prototypes = if (prototype != null) listOf(PrototypeInfo(prototype, inheritance)) else listOf()
+1 -1
View File
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
class Enum( class Enum(
name: Identifier, name: Identifier,
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
class EnumConstant( class EnumConstant(
val identifier: Identifier, val identifier: Identifier,
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.CodeBuilder import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.CodeConverter
abstract class Expression : Statement() { abstract class Expression : Statement() {
open val isNullable: Boolean get() = false open val isNullable: Boolean get() = false
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class ExpressionList(val expressions: List<Expression>) : Expression() { class ExpressionList(val expressions: List<Expression>) : Expression() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
@@ -201,7 +201,7 @@ class LambdaExpression(val parameterList: ParameterList?, val block: Block) : Ex
if (parameterList != null && !parameterList.parameters.isEmpty()) { if (parameterList != null && !parameterList.parameters.isEmpty()) {
builder.append(parameterList) builder.append(parameterList)
.append("->") .append("->")
.append(if (block.statements.size() > 1) "\n" else " ") .append(if (block.statements.size > 1) "\n" else " ")
.append(block.statements, "\n") .append(block.statements, "\n")
} }
else { else {
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
fun PsiNameIdentifierOwner.declarationIdentifier(): Identifier { fun PsiNameIdentifierOwner.declarationIdentifier(): Identifier {
val name = getName() val name = name
return if (name != null) Identifier(name, false).assignPrototype(getNameIdentifier()!!) else Identifier.Empty return if (name != null) Identifier(name, false).assignPrototype(nameIdentifier!!) else Identifier.Empty
} }
class Identifier( class Identifier(
@@ -51,14 +51,14 @@ class Identifier(
imports.forEach { builder.addImport(it) } imports.forEach { builder.addImport(it) }
} }
private fun quote(str: String): String = "`" + str + "`" private fun quote(str: String): String = "`$str`"
override fun toString() = if (isNullable) "$name?" else name override fun toString() = if (isNullable) "$name?" else name
companion object { companion object {
val Empty = Identifier("") val Empty = Identifier("")
private val KEYWORDS = KtTokens.KEYWORDS.getTypes().map { (it as KtKeywordToken).getValue() }.toSet() private val KEYWORDS = KtTokens.KEYWORDS.types.map { (it as KtKeywordToken).value }.toSet()
fun toKotlin(name: String): String = Identifier(name).toKotlin() fun toKotlin(name: String): String = Identifier(name).toKotlin()
} }
@@ -16,13 +16,16 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import com.intellij.psi.PsiImportStatementBase
import org.jetbrains.kotlin.j2k.*
import com.intellij.psi.PsiImportList import com.intellij.psi.PsiImportList
import org.jetbrains.kotlin.name.FqName import com.intellij.psi.PsiImportStatementBase
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import com.intellij.psi.PsiJavaCodeReferenceElement import com.intellij.psi.PsiJavaCodeReferenceElement
import org.jetbrains.kotlin.asJava.KtLightClassForFacade import org.jetbrains.kotlin.asJava.KtLightClassForFacade
import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.Converter
import org.jetbrains.kotlin.j2k.append
import org.jetbrains.kotlin.j2k.quoteKeywords
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
class Import(val name: String) : Element() { class Import(val name: String) : Element() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
@@ -40,14 +43,13 @@ class ImportList(public var imports: List<Import>) : Element() {
} }
public fun Converter.convertImportList(importList: PsiImportList): ImportList = public fun Converter.convertImportList(importList: PsiImportList): ImportList =
ImportList(importList.getAllImportStatements().mapNotNull { convertImport(it, true) }).assignPrototype(importList) ImportList(importList.allImportStatements.mapNotNull { convertImport(it, true) }).assignPrototype(importList)
public fun Converter.convertImport(anImport: PsiImportStatementBase, filter: Boolean): Import? { public fun Converter.convertImport(anImport: PsiImportStatementBase, filter: Boolean): Import? {
fun doConvert(): Import? { fun doConvert(): Import? {
val reference = anImport.getImportReference() val reference = anImport.importReference ?: return null
if (reference == null) return null val qualifiedName = quoteKeywords(reference.qualifiedName!!)
val qualifiedName = quoteKeywords(reference.getQualifiedName()!!) if (anImport.isOnDemand) {
if (anImport.isOnDemand()) {
return Import(qualifiedName + ".*") return Import(qualifiedName + ".*")
} }
else { else {
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
class Initializer(val body: DeferredElement<Block>, modifiers: Modifiers) : Member(Annotations.Empty, modifiers) { class Initializer(val body: DeferredElement<Block>, modifiers: Modifiers) : Member(Annotations.Empty, modifiers) {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.j2k.CodeBuilder import org.jetbrains.kotlin.j2k.CodeBuilder
class LocalVariable( class LocalVariable(
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class MethodCallExpression( class MethodCallExpression(
val methodExpression: Expression, val methodExpression: Expression,
@@ -43,7 +43,7 @@ class Modifiers(modifiers: Collection<Modifier>) : Element() {
else else
modifiers.filter { it != Modifier.PUBLIC } modifiers.filter { it != Modifier.PUBLIC }
val text = modifiersToInclude val text = modifiersToInclude
.sortedBy { it.ordinal() } .sortedBy { it.ordinal }
.map { it.toKotlin() } .map { it.toKotlin() }
.joinToString(" ") .joinToString(" ")
builder.append(text) builder.append(text)
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class NewClassExpression( class NewClassExpression(
val name: ReferenceElement?, val name: ReferenceElement?,
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class ParameterList(val parameters: List<Parameter>) : Element() { class ParameterList(val parameters: List<Parameter>) : Element() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class ReferenceElement(val name: Identifier, val typeArgs: List<Element>) : Element() { class ReferenceElement(val name: Identifier, val typeArgs: List<Element>) : Element() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
abstract class Statement : Element() { abstract class Statement : Element() {
object Empty : Statement() { object Empty : Statement() {
@@ -17,11 +17,14 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import com.intellij.psi.PsiTypeParameter import com.intellij.psi.PsiTypeParameter
import org.jetbrains.kotlin.j2k.*
import com.intellij.psi.PsiTypeParameterList import com.intellij.psi.PsiTypeParameterList
import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.Converter
import org.jetbrains.kotlin.j2k.append
import org.jetbrains.kotlin.j2k.buildList
class TypeParameter(val name: Identifier, val extendsTypes: List<Type>) : Element() { class TypeParameter(val name: Identifier, val extendsTypes: List<Type>) : Element() {
fun hasWhere(): Boolean = extendsTypes.size() > 1 fun hasWhere(): Boolean = extendsTypes.size > 1
fun whereToKotlin(builder: CodeBuilder) { fun whereToKotlin(builder: CodeBuilder) {
if (hasWhere()) { if (hasWhere()) {
@@ -64,12 +67,12 @@ class TypeParameterList(val parameters: List<TypeParameter>) : Element() {
private fun Converter.convertTypeParameter(typeParameter: PsiTypeParameter): TypeParameter { private fun Converter.convertTypeParameter(typeParameter: PsiTypeParameter): TypeParameter {
return TypeParameter(typeParameter.declarationIdentifier(), return TypeParameter(typeParameter.declarationIdentifier(),
typeParameter.getExtendsListTypes().map { typeConverter.convertType(it) }).assignPrototype(typeParameter) typeParameter.extendsListTypes.map { typeConverter.convertType(it) }).assignPrototype(typeParameter)
} }
fun Converter.convertTypeParameterList(typeParameterList: PsiTypeParameterList?): TypeParameterList { fun Converter.convertTypeParameterList(typeParameterList: PsiTypeParameterList?): TypeParameterList {
return if (typeParameterList != null) return if (typeParameterList != null)
TypeParameterList(typeParameterList.getTypeParameters()!!.toList().map { convertTypeParameter(it) }).assignPrototype(typeParameterList) TypeParameterList(typeParameterList.typeParameters!!.toList().map { convertTypeParameter(it) }).assignPrototype(typeParameterList)
else else
TypeParameterList.Empty TypeParameterList.Empty
} }
@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.j2k.ast package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.ConverterSettings
fun Type.isUnit(): Boolean = this is UnitType fun Type.isUnit(): Boolean = this is UnitType
@@ -18,9 +18,6 @@ package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.CodeBuilder import org.jetbrains.kotlin.j2k.CodeBuilder
fun String.withSuffix(suffix: String): String = if (isEmpty()) "" else this + suffix
fun String.withPrefix(prefix: String): String = if (isEmpty()) "" else prefix + this
fun CodeBuilder.appendWithPrefix(element: Element, prefix: String): CodeBuilder = if (!element.isEmpty) this append prefix append element else this fun CodeBuilder.appendWithPrefix(element: Element, prefix: String): CodeBuilder = if (!element.isEmpty) this append prefix append element else this
fun CodeBuilder.appendWithSuffix(element: Element, suffix: String): CodeBuilder = if (!element.isEmpty) this append element append suffix else this fun CodeBuilder.appendWithSuffix(element: Element, suffix: String): CodeBuilder = if (!element.isEmpty) this append element append suffix else this
@@ -114,9 +114,9 @@ private class PropertyDetector(
val propertyNameToGetterInfo = detectGetters(methodsToCheck, prohibitedPropertyNames, propertyNamesWithConflict) val propertyNameToGetterInfo = detectGetters(methodsToCheck, prohibitedPropertyNames, propertyNamesWithConflict)
val propertyNameToSetterInfo = detectSetters(methodsToCheck, prohibitedPropertyNames, propertyNameToGetterInfo.keySet(), propertyNamesWithConflict) val propertyNameToSetterInfo = detectSetters(methodsToCheck, prohibitedPropertyNames, propertyNameToGetterInfo.keys, propertyNamesWithConflict)
val propertyNames = propertyNameToGetterInfo.keySet() + propertyNameToSetterInfo.keySet() val propertyNames = propertyNameToGetterInfo.keys + propertyNameToSetterInfo.keys
val memberToPropertyInfo = HashMap<PsiMember, PropertyInfo>() val memberToPropertyInfo = HashMap<PsiMember, PropertyInfo>()
for (propertyName in propertyNames) { for (propertyName in propertyNames) {
@@ -246,7 +246,7 @@ private class PropertyDetector(
} }
private fun dropPropertiesWithConflictingAccessors(memberToPropertyInfo: MutableMap<PsiMember, PropertyInfo>) { private fun dropPropertiesWithConflictingAccessors(memberToPropertyInfo: MutableMap<PsiMember, PropertyInfo>) {
val propertyInfos = memberToPropertyInfo.values().distinct() val propertyInfos = memberToPropertyInfo.values.distinct()
val mappedMethods = propertyInfos.mapNotNull { it.getMethod }.toSet() + propertyInfos.mapNotNull { it.setMethod }.toSet() val mappedMethods = propertyInfos.mapNotNull { it.getMethod }.toSet() + propertyInfos.mapNotNull { it.setMethod }.toSet()
@@ -413,25 +413,25 @@ private class PropertyDetector(
} }
private fun fieldFromGetterBody(getter: PsiMethod): PsiField? { private fun fieldFromGetterBody(getter: PsiMethod): PsiField? {
val body = getter.getBody() ?: return null val body = getter.body ?: return null
val returnStatement = (body.getStatements().singleOrNull() as? PsiReturnStatement) ?: return null val returnStatement = (body.statements.singleOrNull() as? PsiReturnStatement) ?: return null
val isStatic = getter.hasModifierProperty(PsiModifier.STATIC) val isStatic = getter.hasModifierProperty(PsiModifier.STATIC)
val field = fieldByExpression(returnStatement.getReturnValue(), isStatic) ?: return null val field = fieldByExpression(returnStatement.returnValue, isStatic) ?: return null
if (field.getType() != getter.getReturnType()) return null if (field.type != getter.returnType) return null
if (converter.typeConverter.variableMutability(field) != converter.typeConverter.methodMutability(getter)) return null if (converter.typeConverter.variableMutability(field) != converter.typeConverter.methodMutability(getter)) return null
return field return field
} }
private fun fieldFromSetterBody(setter: PsiMethod): PsiField? { private fun fieldFromSetterBody(setter: PsiMethod): PsiField? {
val body = setter.getBody() ?: return null val body = setter.body ?: return null
val statement = (body.getStatements().singleOrNull() as? PsiExpressionStatement) ?: return null val statement = (body.statements.singleOrNull() as? PsiExpressionStatement) ?: return null
val assignment = statement.getExpression() as? PsiAssignmentExpression ?: return null val assignment = statement.expression as? PsiAssignmentExpression ?: return null
if (assignment.getOperationTokenType() != JavaTokenType.EQ) return null if (assignment.operationTokenType != JavaTokenType.EQ) return null
val isStatic = setter.hasModifierProperty(PsiModifier.STATIC) val isStatic = setter.hasModifierProperty(PsiModifier.STATIC)
val field = fieldByExpression(assignment.getLExpression(), isStatic) ?: return null val field = fieldByExpression(assignment.lExpression, isStatic) ?: return null
val parameter = setter.getParameterList().getParameters().single() val parameter = setter.parameterList.parameters.single()
if ((assignment.getRExpression() as? PsiReferenceExpression)?.resolve() != parameter) return null if ((assignment.rExpression as? PsiReferenceExpression)?.resolve() != parameter) return null
if (field.getType() != parameter.getType()) return null if (field.type != parameter.type) return null
return field return field
} }
@@ -444,7 +444,7 @@ private class PropertyDetector(
if (!refExpr.isQualifierEmptyOrThis()) return null if (!refExpr.isQualifierEmptyOrThis()) return null
} }
val field = refExpr.resolve() as? PsiField ?: return null val field = refExpr.resolve() as? PsiField ?: return null
if (field.getContainingClass() != psiClass || field.hasModifierProperty(PsiModifier.STATIC) != static) return null if (field.containingClass != psiClass || field.hasModifierProperty(PsiModifier.STATIC) != static) return null
return field return field
} }
} }
@@ -29,18 +29,18 @@ class AccessorToPropertyProcessing(val accessorMethod: PsiMethod, val accessorKi
override fun convertMethodUsage(methodCall: PsiMethodCallExpression, codeConverter: CodeConverter): Expression? { override fun convertMethodUsage(methodCall: PsiMethodCallExpression, codeConverter: CodeConverter): Expression? {
val isNullable = codeConverter.typeConverter.methodNullability(accessorMethod).isNullable(codeConverter.settings) val isNullable = codeConverter.typeConverter.methodNullability(accessorMethod).isNullable(codeConverter.settings)
val methodExpr = methodCall.getMethodExpression() val methodExpr = methodCall.methodExpression
val arguments = methodCall.getArgumentList().getExpressions() val arguments = methodCall.argumentList.expressions
val propertyName = Identifier(propertyName, isNullable).assignNoPrototype() val propertyName = Identifier(propertyName, isNullable).assignNoPrototype()
val propertyAccess = QualifiedExpression(codeConverter.convertExpression(methodExpr.getQualifierExpression()), propertyName).assignNoPrototype() val propertyAccess = QualifiedExpression(codeConverter.convertExpression(methodExpr.qualifierExpression), propertyName).assignNoPrototype()
if (accessorKind == AccessorKind.GETTER) { if (accessorKind == AccessorKind.GETTER) {
if (arguments.size() != 0) return null // incorrect call if (arguments.size != 0) return null // incorrect call
return propertyAccess return propertyAccess
} }
else { else {
if (arguments.size() != 1) return null // incorrect call if (arguments.size != 1) return null // incorrect call
val argument = codeConverter.convertExpression(arguments[0]) val argument = codeConverter.convertExpression(arguments[0])
return AssignmentExpression(propertyAccess, argument, Operator.EQ) return AssignmentExpression(propertyAccess, argument, Operator.EQ)
} }
@@ -54,34 +54,34 @@ class AccessorToPropertyProcessing(val accessorMethod: PsiMethod, val accessorKi
else else
object : ExternalCodeProcessor { object : ExternalCodeProcessor {
override fun processUsage(reference: PsiReference): Array<PsiReference>? { override fun processUsage(reference: PsiReference): Array<PsiReference>? {
val nameExpr = reference.getElement() as? KtSimpleNameExpression ?: return null val nameExpr = reference.element as? KtSimpleNameExpression ?: return null
val callExpr = nameExpr.getParent() as? KtCallExpression ?: return null val callExpr = nameExpr.parent as? KtCallExpression ?: return null
val arguments = callExpr.getValueArguments() val arguments = callExpr.valueArguments
val factory = KtPsiFactory(nameExpr.getProject()) val factory = KtPsiFactory(nameExpr.project)
var propertyNameExpr = factory.createSimpleName(propertyName) var propertyNameExpr = factory.createSimpleName(propertyName)
if (accessorKind == AccessorKind.GETTER) { if (accessorKind == AccessorKind.GETTER) {
if (arguments.size() != 0) return null // incorrect call if (arguments.size != 0) return null // incorrect call
propertyNameExpr = callExpr.replace(propertyNameExpr) as KtSimpleNameExpression propertyNameExpr = callExpr.replace(propertyNameExpr) as KtSimpleNameExpression
return propertyNameExpr.getReferences() return propertyNameExpr.references
} }
else { else {
val value = arguments.singleOrNull()?.getArgumentExpression() ?: return null val value = arguments.singleOrNull()?.getArgumentExpression() ?: return null
var assignment = factory.createExpression("a = b") as KtBinaryExpression var assignment = factory.createExpression("a = b") as KtBinaryExpression
assignment.getRight()!!.replace(value) assignment.right!!.replace(value)
val qualifiedExpression = callExpr.getParent() as? KtQualifiedExpression val qualifiedExpression = callExpr.parent as? KtQualifiedExpression
if (qualifiedExpression != null && qualifiedExpression.getSelectorExpression() == callExpr) { if (qualifiedExpression != null && qualifiedExpression.selectorExpression == callExpr) {
callExpr.replace(propertyNameExpr) callExpr.replace(propertyNameExpr)
assignment.getLeft()!!.replace(qualifiedExpression) assignment.left!!.replace(qualifiedExpression)
assignment = qualifiedExpression.replace(assignment) as KtBinaryExpression assignment = qualifiedExpression.replace(assignment) as KtBinaryExpression
return (assignment.getLeft() as KtQualifiedExpression).getSelectorExpression()!!.getReferences() return (assignment.left as KtQualifiedExpression).selectorExpression!!.references
} }
else { else {
assignment.getLeft()!!.replace(propertyNameExpr) assignment.left!!.replace(propertyNameExpr)
assignment = callExpr.replace(assignment) as KtBinaryExpression assignment = callExpr.replace(assignment) as KtBinaryExpression
return assignment.getLeft()!!.getReferences() return assignment.left!!.references
} }
} }
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.j2k.usageProcessing package org.jetbrains.kotlin.j2k.usageProcessing
import com.intellij.psi.PsiReference import com.intellij.psi.PsiReference
import org.jetbrains.kotlin.j2k.ResolverForConverter
class ElementRenamedCodeProcessor(private val newName: String) : ExternalCodeProcessor { class ElementRenamedCodeProcessor(private val newName: String) : ExternalCodeProcessor {
override fun processUsage(reference: PsiReference): Array<PsiReference>? { override fun processUsage(reference: PsiReference): Array<PsiReference>? {
@@ -21,37 +21,35 @@ import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.j2k.AccessorKind import org.jetbrains.kotlin.j2k.AccessorKind
import org.jetbrains.kotlin.j2k.CodeConverter import org.jetbrains.kotlin.j2k.CodeConverter
import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.j2k.ast.*
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, val isNullable: Boolean) : UsageProcessing { class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, val isNullable: Boolean) : UsageProcessing {
override val targetElement: PsiElement get() = this.field override val targetElement: PsiElement get() = this.field
override val convertedCodeProcessor: ConvertedCodeProcessor? = override val convertedCodeProcessor: ConvertedCodeProcessor? =
if (field.getName() != propertyName) MyConvertedCodeProcessor() else null if (field.name != propertyName) MyConvertedCodeProcessor() else null
override var javaCodeProcessor = if (field.hasModifierProperty(PsiModifier.PRIVATE)) override var javaCodeProcessor = if (field.hasModifierProperty(PsiModifier.PRIVATE))
null null
else if (!field.hasModifierProperty(PsiModifier.STATIC)) else if (!field.hasModifierProperty(PsiModifier.STATIC))
UseAccessorsJavaCodeProcessor() UseAccessorsJavaCodeProcessor()
else if (field.getName() != propertyName) else if (field.name != propertyName)
ElementRenamedCodeProcessor(propertyName) ElementRenamedCodeProcessor(propertyName)
else else
null null
override val kotlinCodeProcessor = if (field.getName() != propertyName) ElementRenamedCodeProcessor(propertyName) else null override val kotlinCodeProcessor = if (field.name != propertyName) ElementRenamedCodeProcessor(propertyName) else null
private inner class MyConvertedCodeProcessor : ConvertedCodeProcessor { private inner class MyConvertedCodeProcessor : ConvertedCodeProcessor {
override fun convertVariableUsage(expression: PsiReferenceExpression, codeConverter: CodeConverter): Expression? { override fun convertVariableUsage(expression: PsiReferenceExpression, codeConverter: CodeConverter): Expression? {
val identifier = Identifier(propertyName, isNullable).assignNoPrototype() val identifier = Identifier(propertyName, isNullable).assignNoPrototype()
val qualifier = expression.getQualifierExpression() val qualifier = expression.qualifierExpression
if (qualifier != null) { if (qualifier != null) {
return QualifiedExpression(codeConverter.convertExpression(qualifier), identifier) return QualifiedExpression(codeConverter.convertExpression(qualifier), identifier)
} }
else { else {
// check if field name is shadowed // check if field name is shadowed
val elementFactory = PsiElementFactory.SERVICE.getInstance(expression.getProject()) val elementFactory = PsiElementFactory.SERVICE.getInstance(expression.project)
val refExpr = try { val refExpr = try {
elementFactory.createExpressionFromText(propertyName, expression) as? PsiReferenceExpression ?: return identifier elementFactory.createExpressionFromText(propertyName, expression) as? PsiReferenceExpression ?: return identifier
} }
@@ -67,25 +65,25 @@ class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, v
} }
private inner class UseAccessorsJavaCodeProcessor : ExternalCodeProcessor { private inner class UseAccessorsJavaCodeProcessor : ExternalCodeProcessor {
private val factory = PsiElementFactory.SERVICE.getInstance(field.getProject()) private val factory = PsiElementFactory.SERVICE.getInstance(field.project)
override fun processUsage(reference: PsiReference): Array<PsiReference>? { override fun processUsage(reference: PsiReference): Array<PsiReference>? {
val refExpr = reference.getElement() as? PsiReferenceExpression ?: return null val refExpr = reference.element as? PsiReferenceExpression ?: return null
val qualifier = refExpr.getQualifierExpression() val qualifier = refExpr.qualifierExpression
val parent = refExpr.getParent() val parent = refExpr.parent
when (parent) { when (parent) {
is PsiAssignmentExpression -> { is PsiAssignmentExpression -> {
if (refExpr == parent.getLExpression()) { if (refExpr == parent.lExpression) {
if (parent.getOperationTokenType() == JavaTokenType.EQ) { if (parent.operationTokenType == JavaTokenType.EQ) {
val callExpr = parent.replace(generateSetterCall(qualifier, parent.getRExpression() ?: return null)) as PsiMethodCallExpression val callExpr = parent.replace(generateSetterCall(qualifier, parent.rExpression ?: return null)) as PsiMethodCallExpression
return arrayOf(callExpr.getMethodExpression()) return arrayOf(callExpr.methodExpression)
} }
else { else {
val assignmentOpText = parent.getOperationSign().getText() val assignmentOpText = parent.operationSign.text
assert(assignmentOpText.endsWith("=")) assert(assignmentOpText.endsWith("="))
val opText = assignmentOpText.substring(0, assignmentOpText.length() - 1) val opText = assignmentOpText.substring(0, assignmentOpText.length - 1)
return parent.replaceWithModificationCalls(qualifier, opText, parent.getRExpression() ?: return null) return parent.replaceWithModificationCalls(qualifier, opText, parent.rExpression ?: return null)
} }
} }
} }
@@ -93,9 +91,9 @@ class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, v
is PsiPrefixExpression, is PsiPostfixExpression -> { is PsiPrefixExpression, is PsiPostfixExpression -> {
//TODO: what if it's used as value? //TODO: what if it's used as value?
val operationType = if (parent is PsiPrefixExpression) val operationType = if (parent is PsiPrefixExpression)
parent.getOperationTokenType() parent.operationTokenType
else else
(parent as PsiPostfixExpression).getOperationTokenType() (parent as PsiPostfixExpression).operationTokenType
val opText = when (operationType) { val opText = when (operationType) {
JavaTokenType.PLUSPLUS -> "+" JavaTokenType.PLUSPLUS -> "+"
JavaTokenType.MINUSMINUS -> "-" JavaTokenType.MINUSMINUS -> "-"
@@ -108,7 +106,7 @@ class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, v
} }
val callExpr = refExpr.replace(generateGetterCall(qualifier)) as PsiMethodCallExpression val callExpr = refExpr.replace(generateGetterCall(qualifier)) as PsiMethodCallExpression
return arrayOf(callExpr.getMethodExpression()) return arrayOf(callExpr.methodExpression)
} }
//TODO: what if qualifier has side effects? //TODO: what if qualifier has side effects?
@@ -116,31 +114,31 @@ class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, v
var getCall = generateGetterCall(qualifier) var getCall = generateGetterCall(qualifier)
var binary = factory.createExpressionFromText("x $op y", null) as PsiBinaryExpression var binary = factory.createExpressionFromText("x $op y", null) as PsiBinaryExpression
binary.getLOperand().replace(getCall) binary.lOperand.replace(getCall)
binary.getROperand()!!.replace(value) binary.rOperand!!.replace(value)
var setCall = generateSetterCall(qualifier, binary) as PsiMethodCallExpression var setCall = generateSetterCall(qualifier, binary) as PsiMethodCallExpression
setCall = this.replace(setCall) as PsiMethodCallExpression setCall = this.replace(setCall) as PsiMethodCallExpression
binary = setCall.getArgumentList().getExpressions().single() as PsiBinaryExpression binary = setCall.argumentList.expressions.single() as PsiBinaryExpression
getCall = binary.getLOperand() as PsiMethodCallExpression getCall = binary.lOperand as PsiMethodCallExpression
return arrayOf(getCall.getMethodExpression(), setCall.getMethodExpression()) return arrayOf(getCall.methodExpression, setCall.methodExpression)
} }
private fun generateGetterCall(qualifier: PsiExpression?): PsiMethodCallExpression { private fun generateGetterCall(qualifier: PsiExpression?): PsiMethodCallExpression {
val text = accessorName(AccessorKind.GETTER) + "()" val text = accessorName(AccessorKind.GETTER) + "()"
val expressionText = if (qualifier != null) val expressionText = if (qualifier != null)
"${qualifier.getText()}.$text" "${qualifier.text}.$text"
else else
text text
return factory.createExpressionFromText(expressionText, null) as PsiMethodCallExpression return factory.createExpressionFromText(expressionText, null) as PsiMethodCallExpression
} }
private fun generateSetterCall(qualifier: PsiExpression?, value: PsiExpression): PsiExpression { private fun generateSetterCall(qualifier: PsiExpression?, value: PsiExpression): PsiExpression {
val text = accessorName(AccessorKind.SETTER) + "(" + value.getText() + ")" val text = accessorName(AccessorKind.SETTER) + "(" + value.text + ")"
val expressionText = if (qualifier != null) val expressionText = if (qualifier != null)
"${qualifier.getText()}.$text" "${qualifier.text}.$text"
else else
text text
return factory.createExpressionFromText(expressionText, null) return factory.createExpressionFromText(expressionText, null)
@@ -25,16 +25,16 @@ public class MethodIntoObjectProcessing(private val method: PsiMethod, private v
override val javaCodeProcessor = object: ExternalCodeProcessor { override val javaCodeProcessor = object: ExternalCodeProcessor {
override fun processUsage(reference: PsiReference): Array<PsiReference>? { override fun processUsage(reference: PsiReference): Array<PsiReference>? {
val refExpr = reference.getElement() as? PsiReferenceExpression ?: return null val refExpr = reference.element as? PsiReferenceExpression ?: return null
val qualifier = refExpr.getQualifierExpression() val qualifier = refExpr.qualifierExpression
val factory = PsiElementFactory.SERVICE.getInstance(method.getProject()) val factory = PsiElementFactory.SERVICE.getInstance(method.project)
if (qualifier != null) { if (qualifier != null) {
val newQualifier = factory.createExpressionFromText(qualifier.getText() + "." + objectName, null) val newQualifier = factory.createExpressionFromText(qualifier.text + "." + objectName, null)
qualifier.replace(newQualifier) qualifier.replace(newQualifier)
return arrayOf(reference) return arrayOf(reference)
} }
else { else {
var qualifiedExpr = factory.createExpressionFromText(objectName + "." + refExpr.getText(), null) as PsiReferenceExpression var qualifiedExpr = factory.createExpressionFromText(objectName + "." + refExpr.text, null) as PsiReferenceExpression
qualifiedExpr = refExpr.replace(qualifiedExpr) as PsiReferenceExpression qualifiedExpr = refExpr.replace(qualifiedExpr) as PsiReferenceExpression
return arrayOf(qualifiedExpr) return arrayOf(qualifiedExpr)
} }
@@ -26,9 +26,9 @@ class ToObjectWithOnlyMethodsProcessing(private val psiClass: PsiClass) : UsageP
override val javaCodeProcessor = object: ExternalCodeProcessor { override val javaCodeProcessor = object: ExternalCodeProcessor {
override fun processUsage(reference: PsiReference): Array<PsiReference>? { override fun processUsage(reference: PsiReference): Array<PsiReference>? {
val refExpr = reference.getElement() as? PsiReferenceExpression ?: return null val refExpr = reference.element as? PsiReferenceExpression ?: return null
val factory = PsiElementFactory.SERVICE.getInstance(psiClass.getProject()) val factory = PsiElementFactory.SERVICE.getInstance(psiClass.project)
var qualifiedExpr = factory.createExpressionFromText(refExpr.getText() + "." + JvmAbi.INSTANCE_FIELD, null) as PsiReferenceExpression var qualifiedExpr = factory.createExpressionFromText(refExpr.text + "." + JvmAbi.INSTANCE_FIELD, null) as PsiReferenceExpression
qualifiedExpr = refExpr.replace(qualifiedExpr) as PsiReferenceExpression qualifiedExpr = refExpr.replace(qualifiedExpr) as PsiReferenceExpression
return arrayOf(qualifiedExpr) return arrayOf(qualifiedExpr)
} }
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.j2k.usageProcessing package org.jetbrains.kotlin.j2k.usageProcessing
import com.google.common.collect.Multimap
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.CodeConverter import org.jetbrains.kotlin.j2k.CodeConverter
import org.jetbrains.kotlin.j2k.SpecialExpressionConverter import org.jetbrains.kotlin.j2k.SpecialExpressionConverter
@@ -55,7 +54,7 @@ class UsageProcessingExpressionConverter(val processings: Map<PsiElement, Collec
} }
is PsiMethodCallExpression -> { is PsiMethodCallExpression -> {
val target = expression.getMethodExpression().resolve() as? PsiMethod ?: return null val target = expression.methodExpression.resolve() as? PsiMethod ?: return null
val forTarget = processings[target] ?: return null val forTarget = processings[target] ?: return null
for (processing in forTarget) { for (processing in forTarget) {
val converted = processing.convertedCodeProcessor?.convertMethodUsage(expression, codeConverter) val converted = processing.convertedCodeProcessor?.convertMethodUsage(expression, codeConverter)
@@ -25,10 +25,12 @@ import com.intellij.core.JavaCoreProjectEnvironment
import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionsArea import com.intellij.openapi.extensions.ExtensionsArea
import com.intellij.openapi.fileTypes.FileTypeExtensionPoint import com.intellij.openapi.fileTypes.FileTypeExtensionPoint
import junit.framework.TestCase
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.intellij.psi.* import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.FileContextProvider
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.augment.PsiAugmentProvider import com.intellij.psi.augment.PsiAugmentProvider
import com.intellij.psi.compiled.ClassFileDecompilers import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.impl.JavaClassSupersImpl import com.intellij.psi.impl.JavaClassSupersImpl
@@ -37,6 +39,7 @@ import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy
import com.intellij.psi.meta.MetaDataContributor import com.intellij.psi.meta.MetaDataContributor
import com.intellij.psi.stubs.BinaryFileStubBuilders import com.intellij.psi.stubs.BinaryFileStubBuilders
import com.intellij.psi.util.JavaClassSupers import com.intellij.psi.util.JavaClassSupers
import junit.framework.TestCase
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import java.io.File import java.io.File
import java.net.URLClassLoader import java.net.URLClassLoader
@@ -48,7 +51,7 @@ public abstract class AbstractJavaToKotlinConverterForWebDemoTest : TestCase() {
try { try {
val fileContents = FileUtil.loadFile(File(javaPath), true) val fileContents = FileUtil.loadFile(File(javaPath), true)
val javaCoreEnvironment: JavaCoreProjectEnvironment = setUpJavaCoreEnvironment() val javaCoreEnvironment: JavaCoreProjectEnvironment = setUpJavaCoreEnvironment()
translateToKotlin(fileContents, javaCoreEnvironment.getProject()) translateToKotlin(fileContents, javaCoreEnvironment.project)
} }
finally { finally {
Disposer.dispose(DISPOSABLE) Disposer.dispose(DISPOSABLE)
@@ -64,19 +67,19 @@ public abstract class AbstractJavaToKotlinConverterForWebDemoTest : TestCase() {
val applicationEnvironment = JavaCoreApplicationEnvironment(DISPOSABLE) val applicationEnvironment = JavaCoreApplicationEnvironment(DISPOSABLE)
val javaCoreEnvironment = object : JavaCoreProjectEnvironment(DISPOSABLE, applicationEnvironment) { val javaCoreEnvironment = object : JavaCoreProjectEnvironment(DISPOSABLE, applicationEnvironment) {
override fun preregisterServices() { override fun preregisterServices() {
val projectArea = Extensions.getArea(getProject()) val projectArea = Extensions.getArea(project)
CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiTreeChangePreprocessor.EP_NAME, javaClass<PsiTreeChangePreprocessor>()) CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class.java)
CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiElementFinder.EP_NAME, javaClass<PsiElementFinder>()) CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiElementFinder.EP_NAME, PsiElementFinder::class.java)
} }
}; };
javaCoreEnvironment.getProject().registerService(javaClass<NullableNotNullManager>(), object : NullableNotNullManager() { javaCoreEnvironment.project.registerService(NullableNotNullManager::class.java, object : NullableNotNullManager() {
override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases) override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases)
override fun isNotNull(owner: PsiModifierListOwner, checkBases: Boolean) = true override fun isNotNull(owner: PsiModifierListOwner, checkBases: Boolean) = true
override fun hasHardcodedContracts(element: PsiElement): Boolean = false override fun hasHardcodedContracts(element: PsiElement): Boolean = false
}) })
applicationEnvironment.getApplication().registerService(javaClass<JavaClassSupers>(), javaClass<JavaClassSupersImpl>()) applicationEnvironment.application.registerService(JavaClassSupers::class.java, JavaClassSupersImpl::class.java)
for (root in PathUtil.getJdkClassesRoots()) { for (root in PathUtil.getJdkClassesRoots()) {
javaCoreEnvironment.addJarToClassPath(root) javaCoreEnvironment.addJarToClassPath(root)
@@ -89,30 +92,30 @@ public abstract class AbstractJavaToKotlinConverterForWebDemoTest : TestCase() {
} }
private fun registerExtensionPoints(area: ExtensionsArea) { private fun registerExtensionPoints(area: ExtensionsArea) {
CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, javaClass<FileTypeExtensionPoint<Any>>()) CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, javaClass<FileContextProvider>()) CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, javaClass<MetaDataContributor>()) CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, javaClass<PsiAugmentProvider>()) CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, javaClass<JavaMainMethodProvider>()) CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, javaClass<ContainerProvider>()) CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, ClsCustomNavigationPolicy.EP_NAME, javaClass<ClsCustomNavigationPolicy>()) CoreApplicationEnvironment.registerExtensionPoint(area, ClsCustomNavigationPolicy.EP_NAME, ClsCustomNavigationPolicy::class.java)
CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, javaClass<ClassFileDecompilers.Decompiler>()) CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class.java)
} }
fun findAnnotations(): File? { fun findAnnotations(): File? {
var classLoader = javaClass<JavaToKotlinTranslator>().getClassLoader() var classLoader = JavaToKotlinTranslator::class.java.classLoader
while (classLoader != null) { while (classLoader != null) {
val loader = classLoader val loader = classLoader
if (loader is URLClassLoader) { if (loader is URLClassLoader) {
for (url in loader.getURLs()) { for (url in loader.urLs) {
if ("file" == url.getProtocol() && url.getFile()!!.endsWith("/annotations.jar")) { if ("file" == url.protocol && url.file!!.endsWith("/annotations.jar")) {
return File(url.getFile()!!) return File(url.file!!)
} }
} }
} }
classLoader = classLoader.getParent() classLoader = classLoader.parent
} }
return null return null
} }
@@ -22,16 +22,14 @@ import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.testFramework.LightPlatformTestCase import com.intellij.testFramework.LightPlatformTestCase
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.dumpTextWithErrors import org.jetbrains.kotlin.idea.test.dumpTextWithErrors
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File import java.io.File
import java.util.ArrayList import java.util.*
public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaToKotlinConverterTest() { public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaToKotlinConverterTest() {
public fun doTest(dirPath: String) { public fun doTest(dirPath: String) {
@@ -61,12 +59,12 @@ public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaT
val process = externalCodeProcessor?.prepareWriteOperation(EmptyProgressIndicator()) val process = externalCodeProcessor?.prepareWriteOperation(EmptyProgressIndicator())
project.executeWriteCommand("") { process?.invoke() } project.executeWriteCommand("") { process?.invoke() }
fun expectedResultFile(i: Int) = File(filesToConvert[i].getPath().replace(".java", ".kt")) fun expectedResultFile(i: Int) = File(filesToConvert[i].path.replace(".java", ".kt"))
val resultFiles = ArrayList<KtFile>() val resultFiles = ArrayList<KtFile>()
for ((i, javaFile) in psiFilesToConvert.withIndex()) { for ((i, javaFile) in psiFilesToConvert.withIndex()) {
deleteFile(javaFile.getVirtualFile()) deleteFile(javaFile.virtualFile)
val virtualFile = addFile(results[i], expectedResultFile(i).getName(), "test") val virtualFile = addFile(results[i], expectedResultFile(i).name, "test")
resultFiles.add(psiManager.findFile(virtualFile) as KtFile) resultFiles.add(psiManager.findFile(virtualFile) as KtFile)
} }
@@ -75,13 +73,13 @@ public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaT
} }
for ((externalFile, externalPsiFile) in externalFiles.zip(externalPsiFiles)) { for ((externalFile, externalPsiFile) in externalFiles.zip(externalPsiFiles)) {
val expectedFile = File(externalFile.getPath() + ".expected") val expectedFile = File(externalFile.path + ".expected")
var resultText = if (externalPsiFile is KtFile) { var resultText = if (externalPsiFile is KtFile) {
externalPsiFile.dumpTextWithErrors() externalPsiFile.dumpTextWithErrors()
} }
else { else {
//TODO: errors dump for java files too //TODO: errors dump for java files too
externalPsiFile.getText() externalPsiFile.text
} }
KotlinTestUtils.assertEqualsToFile(expectedFile, resultText) KotlinTestUtils.assertEqualsToFile(expectedFile, resultText)
} }
@@ -96,7 +96,7 @@ public abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJava
CodeStyleManager.getInstance(project)!!.reformat(convertedFile) CodeStyleManager.getInstance(project)!!.reformat(convertedFile)
} }
val reformattedText = convertedFile.getText()!! val reformattedText = convertedFile.text!!
return if (inFunContext) return if (inFunContext)
reformattedText.removeFirstLine().removeLastLine().trimIndent() reformattedText.removeFirstLine().removeLastLine().trimIndent()
@@ -111,17 +111,17 @@ public abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJava
} }
private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String { private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val result = fileToKotlin("final class C {" + text + "}", settings, project).replace("internal class C {", "").replace("internal object C {", "") val result = fileToKotlin("final class C {$text}", settings, project).replace("internal class C {", "").replace("internal object C {", "")
return result.substring(0, (result.lastIndexOf("}"))).trim() return result.substring(0, (result.lastIndexOf("}"))).trim()
} }
private fun statementToKotlin(text: String, settings: ConverterSettings, project: Project): String { private fun statementToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val result = methodToKotlin("void main() {" + text + "}", settings, project) val result = methodToKotlin("void main() {$text}", settings, project)
return result.substring(0, result.lastIndexOf("}")).replaceFirst("fun main() {", "").trim() return result.substring(0, result.lastIndexOf("}")).replaceFirst("fun main() {", "").trim()
} }
private fun expressionToKotlin(code: String, settings: ConverterSettings, project: Project): String { private fun expressionToKotlin(code: String, settings: ConverterSettings, project: Project): String {
val result = statementToKotlin("final Object o =" + code + "}", settings, project) val result = statementToKotlin("final Object o =$code}", settings, project)
return result.replaceFirst("val o:Any? = ", "").replaceFirst("val o:Any = ", "").replaceFirst("val o = ", "").trim() return result.replaceFirst("val o:Any? = ", "").replaceFirst("val o:Any = ", "").replaceFirst("val o = ", "").trim()
} }
@@ -48,7 +48,7 @@ public abstract class AbstractJavaToKotlinConverterTest : LightCodeInsightFixtur
} }
protected fun addFile(file: File, dirName: String): VirtualFile { protected fun addFile(file: File, dirName: String): VirtualFile {
return addFile(FileUtil.loadFile(file, true), file.getName(), dirName) return addFile(FileUtil.loadFile(file, true), file.name, dirName)
} }
protected fun addFile(text: String, fileName: String, dirName: String): VirtualFile { protected fun addFile(text: String, fileName: String, dirName: String): VirtualFile {