J2K: correct conversion of nested class references
#KT-5294 Fixed #KT-5400 Fixed
This commit is contained in:
@@ -183,8 +183,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
|||||||
var body = postProcessBody(bodyConverter.convertBlock(constructor.getBody()))
|
var body = postProcessBody(bodyConverter.convertBlock(constructor.getBody()))
|
||||||
val containingClass = constructor.getContainingClass()
|
val containingClass = constructor.getContainingClass()
|
||||||
val typeParameterList = converter.convertTypeParameterList(containingClass?.getTypeParameterList())
|
val typeParameterList = converter.convertTypeParameterList(containingClass?.getTypeParameterList())
|
||||||
val factoryFunctionType = ClassType(containingClass?.declarationIdentifier() ?: Identifier.Empty,
|
val factoryFunctionType = ClassType(ReferenceElement(containingClass?.declarationIdentifier() ?: Identifier.Empty, typeParameterList.parameters).assignNoPrototype(),
|
||||||
typeParameterList.parameters,
|
|
||||||
Nullability.NotNull,
|
Nullability.NotNull,
|
||||||
converter.settings).assignNoPrototype()
|
converter.settings).assignNoPrototype()
|
||||||
return FactoryFunction(constructor.declarationIdentifier(), annotations, correctFactoryFunctionAccess(modifiers),
|
return FactoryFunction(constructor.declarationIdentifier(), annotations, correctFactoryFunctionAccess(modifiers),
|
||||||
@@ -201,13 +200,14 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
|||||||
val body = primaryConstructor.getBody()
|
val body = primaryConstructor.getBody()
|
||||||
|
|
||||||
val parameterUsageReplacementMap = HashMap<String, String>()
|
val parameterUsageReplacementMap = HashMap<String, String>()
|
||||||
|
val correctedTypeConverter = converter.withSpecialContext(psiClass).typeConverter /* to correct nested class references */
|
||||||
val block = if (body != null) {
|
val block = if (body != null) {
|
||||||
val statementsToRemove = HashSet<PsiStatement>()
|
val statementsToRemove = HashSet<PsiStatement>()
|
||||||
for (parameter in params) {
|
for (parameter in params) {
|
||||||
val (field, initializationStatement) = findBackingFieldForConstructorParameter(parameter, primaryConstructor) ?: continue
|
val (field, initializationStatement) = findBackingFieldForConstructorParameter(parameter, primaryConstructor) ?: continue
|
||||||
|
|
||||||
val fieldType = typeConverter.convertVariableType(field)
|
val fieldType = correctedTypeConverter.convertVariableType(field)
|
||||||
val parameterType = typeConverter.convertVariableType(parameter)
|
val parameterType = correctedTypeConverter.convertVariableType(parameter)
|
||||||
// types can be different only in nullability
|
// types can be different only in nullability
|
||||||
val `type` = if (fieldType == parameterType) {
|
val `type` = if (fieldType == parameterType) {
|
||||||
fieldType
|
fieldType
|
||||||
@@ -244,6 +244,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
|||||||
|
|
||||||
// we need to replace renamed parameter usages in base class constructor arguments and in default values
|
// we need to replace renamed parameter usages in base class constructor arguments and in default values
|
||||||
val correctedConverter = converter.withExpressionVisitor { ReplacingExpressionVisitor(this, parameterUsageReplacementMap, it) }
|
val correctedConverter = converter.withExpressionVisitor { ReplacingExpressionVisitor(this, parameterUsageReplacementMap, it) }
|
||||||
|
.withSpecialContext(psiClass) /* to correct nested class references */
|
||||||
|
|
||||||
val statement = primaryConstructor.getBody()?.getStatements()?.firstOrNull()
|
val statement = primaryConstructor.getBody()?.getStatements()?.firstOrNull()
|
||||||
val methodCall = (statement as? PsiExpressionStatement)?.getExpression() as? PsiMethodCallExpression
|
val methodCall = (statement as? PsiExpressionStatement)?.getExpression() as? PsiMethodCallExpression
|
||||||
@@ -259,7 +260,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
if (!parameterToField.containsKey(parameter)) {
|
if (!parameterToField.containsKey(parameter)) {
|
||||||
converter.convertParameter(parameter, defaultValue = defaultValue)
|
correctedConverter.convertParameter(parameter, defaultValue = defaultValue)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val (field, `type`) = parameterToField[parameter]!!
|
val (field, `type`) = parameterToField[parameter]!!
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.intellij.psi.CommonClassNames.*
|
|||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions.*
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions.*
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.util.PsiMethodUtil
|
import com.intellij.psi.util.PsiMethodUtil
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
|
||||||
public trait ConversionScope {
|
public trait ConversionScope {
|
||||||
public fun contains(element: PsiElement): Boolean
|
public fun contains(element: PsiElement): Boolean
|
||||||
@@ -34,29 +35,53 @@ public class FilesConversionScope(val files: Collection<PsiJavaFile>) : Conversi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Converter private(val project: Project, val settings: ConverterSettings, val conversionScope: ConversionScope, val state: Converter.State) {
|
public class Converter private(val project: Project, val settings: ConverterSettings, val conversionScope: ConversionScope, val state: Converter.State) {
|
||||||
private class State(val typeConverter: TypeConverter,
|
private class State(val methodReturnType: PsiType?,
|
||||||
val methodReturnType: PsiType?,
|
|
||||||
val expressionVisitorFactory: (Converter) -> ExpressionVisitor,
|
val expressionVisitorFactory: (Converter) -> ExpressionVisitor,
|
||||||
val statementVisitorFactory: (Converter) -> StatementVisitor)
|
val statementVisitorFactory: (Converter) -> StatementVisitor,
|
||||||
val typeConverter: TypeConverter = state.typeConverter
|
val specialContext: PsiElement?,
|
||||||
|
val importList: ImportList?,
|
||||||
|
val importsToAdd: MutableCollection<String>?)
|
||||||
|
|
||||||
|
val typeConverter: TypeConverter = TypeConverter(this)
|
||||||
|
|
||||||
val methodReturnType: PsiType? = state.methodReturnType
|
val methodReturnType: PsiType? = state.methodReturnType
|
||||||
|
val specialContext: PsiElement? = state.specialContext
|
||||||
|
val importNames: Set<String> = state.importList?.imports?.mapTo(HashSet<String>()) { it.name } ?: setOf()
|
||||||
|
val importsToAdd: MutableCollection<String>? = state.importsToAdd
|
||||||
|
|
||||||
private val expressionVisitor = state.expressionVisitorFactory(this)
|
private val expressionVisitor = state.expressionVisitorFactory(this)
|
||||||
private val statementVisitor = state.statementVisitorFactory(this)
|
private val statementVisitor = state.statementVisitorFactory(this)
|
||||||
|
|
||||||
class object {
|
class object {
|
||||||
public fun create(project: Project, settings: ConverterSettings, conversionScope: ConversionScope): Converter
|
public fun create(project: Project, settings: ConverterSettings, conversionScope: ConversionScope): Converter {
|
||||||
= Converter(project, settings, conversionScope, State(TypeConverter(settings, conversionScope), null, { ExpressionVisitor(it) }, { StatementVisitor(it) }))
|
val state = State(null, { ExpressionVisitor(it) }, { StatementVisitor(it) }, null, null, null)
|
||||||
|
return Converter(project, settings, conversionScope, state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withMethodReturnType(methodReturnType: PsiType?): Converter
|
fun withMethodReturnType(methodReturnType: PsiType?): Converter
|
||||||
= Converter(project, settings, conversionScope, State(typeConverter, methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory))
|
= Converter(project, settings, conversionScope,
|
||||||
|
State(methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, state.importList, state.importsToAdd))
|
||||||
|
|
||||||
fun withExpressionVisitor(factory: (Converter) -> ExpressionVisitor): Converter
|
fun withExpressionVisitor(factory: (Converter) -> ExpressionVisitor): Converter
|
||||||
= Converter(project, settings, conversionScope, State(typeConverter, state.methodReturnType, factory, state.statementVisitorFactory))
|
= Converter(project, settings, conversionScope,
|
||||||
|
State(state.methodReturnType, factory, state.statementVisitorFactory, state.specialContext, state.importList, state.importsToAdd))
|
||||||
|
|
||||||
fun withStatementVisitor(factory: (Converter) -> StatementVisitor): Converter
|
fun withStatementVisitor(factory: (Converter) -> StatementVisitor): Converter
|
||||||
= Converter(project, settings, conversionScope, State(typeConverter, state.methodReturnType, state.expressionVisitorFactory, factory))
|
= Converter(project, settings, conversionScope,
|
||||||
|
State(state.methodReturnType, state.expressionVisitorFactory, factory, state.specialContext, state.importList, state.importsToAdd))
|
||||||
|
|
||||||
|
fun withSpecialContext(context: PsiElement): Converter
|
||||||
|
= Converter(project, settings, conversionScope,
|
||||||
|
State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, context, state.importList, state.importsToAdd))
|
||||||
|
|
||||||
|
private fun withImportList(importList: ImportList): Converter
|
||||||
|
= Converter(project, settings, conversionScope,
|
||||||
|
State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, importList, state.importsToAdd))
|
||||||
|
|
||||||
|
private fun withImportsToAdd(importsToAdd: MutableCollection<String>): Converter
|
||||||
|
= Converter(project, settings, conversionScope,
|
||||||
|
State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, state.importList, importsToAdd))
|
||||||
|
|
||||||
public fun elementToKotlin(element: PsiElement): String {
|
public fun elementToKotlin(element: PsiElement): String {
|
||||||
val converted = convertTopElement(element) ?: return ""
|
val converted = convertTopElement(element) ?: return ""
|
||||||
@@ -80,21 +105,22 @@ public class Converter private(val project: Project, val settings: ConverterSett
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun convertFile(javaFile: PsiJavaFile): File {
|
private fun convertFile(javaFile: PsiJavaFile): File {
|
||||||
|
val importsToAdd = LinkedHashSet<String>()
|
||||||
|
var converter = this.withImportsToAdd(importsToAdd)
|
||||||
var convertedChildren = javaFile.getChildren().map {
|
var convertedChildren = javaFile.getChildren().map {
|
||||||
if (it is PsiImportList) {
|
if (it is PsiImportList) {
|
||||||
val importList = convertImportList(it)
|
val importList = convertImportList(it)
|
||||||
typeConverter.importList = importList
|
converter = converter.withImportList(importList)
|
||||||
importList
|
importList
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
convertTopElement(it)
|
converter.convertTopElement(it)
|
||||||
}
|
}
|
||||||
}.filterNotNull()
|
}.filterNotNull()
|
||||||
|
|
||||||
typeConverter.importList = null
|
if (importsToAdd.isNotEmpty()) {
|
||||||
if (typeConverter.importsToAdd.isNotEmpty()) {
|
|
||||||
val importList = convertedChildren.filterIsInstance(javaClass<ImportList>()).first()
|
val importList = convertedChildren.filterIsInstance(javaClass<ImportList>()).first()
|
||||||
val newImportList = ImportList(importList.imports + typeConverter.importsToAdd).assignPrototypesFrom(importList)
|
val newImportList = ImportList(importList.imports + importsToAdd.map { Import(it).assignNoPrototype() }).assignPrototypesFrom(importList)
|
||||||
convertedChildren = convertedChildren.map { if (it == importList) newImportList else it }
|
convertedChildren = convertedChildren.map { if (it == importList) newImportList else it }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,6 +418,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
|
|||||||
return expressionVisitor.result.assignPrototype(expression)
|
return expressionVisitor.result.assignPrototype(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: drop this method - it has unclear semantics
|
||||||
fun convertElement(element: PsiElement?): Element {
|
fun convertElement(element: PsiElement?): Element {
|
||||||
if (element == null) return Element.Empty
|
if (element == null) return Element.Empty
|
||||||
|
|
||||||
@@ -400,6 +427,46 @@ public class Converter private(val project: Project, val settings: ConverterSett
|
|||||||
return elementVisitor.result.assignPrototype(element)
|
return elementVisitor.result.assignPrototype(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun convertCodeReferenceElement(element: PsiJavaCodeReferenceElement, hasExternalQualifier: Boolean, typeArgsConverted: List<Element>? = null): ReferenceElement {
|
||||||
|
val typeArgs = typeArgsConverted ?: typeConverter.convertTypes(element.getTypeParameters())
|
||||||
|
|
||||||
|
if (element.isQualified()) {
|
||||||
|
var result = Identifier.toKotlin(element.getReferenceName()!!)
|
||||||
|
var qualifier = element.getQualifier()
|
||||||
|
while (qualifier != null) {
|
||||||
|
val codeRefElement = qualifier as PsiJavaCodeReferenceElement
|
||||||
|
result = Identifier.toKotlin(codeRefElement.getReferenceName()!!) + "." + result
|
||||||
|
qualifier = codeRefElement.getQualifier()
|
||||||
|
}
|
||||||
|
return ReferenceElement(Identifier(result).assignNoPrototype(), typeArgs).assignPrototype(element)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!hasExternalQualifier) {
|
||||||
|
// references to nested classes may need correction
|
||||||
|
val targetClass = element.resolve() as? PsiClass
|
||||||
|
if (targetClass != null) {
|
||||||
|
val identifier = constructNestedClassReferenceIdentifier(targetClass, specialContext ?: element)
|
||||||
|
if (identifier != null) {
|
||||||
|
return ReferenceElement(identifier, typeArgs).assignPrototype(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReferenceElement(Identifier(element.getReferenceName()!!).assignNoPrototype(), typeArgs).assignPrototype(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun constructNestedClassReferenceIdentifier(psiClass: PsiClass, context: PsiElement): Identifier? {
|
||||||
|
val outerClass = psiClass.getContainingClass()
|
||||||
|
if (outerClass != null
|
||||||
|
&& !PsiTreeUtil.isAncestor(outerClass, context, true)
|
||||||
|
&& !psiClass.isImported(context.getContainingFile() as PsiJavaFile)) {
|
||||||
|
val qualifier = constructNestedClassReferenceIdentifier(outerClass, context)?.name ?: outerClass.getName()!!
|
||||||
|
return Identifier(Identifier.toKotlin(qualifier) + "." + Identifier.toKotlin(psiClass.getName()!!)).assignNoPrototype()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
fun convertTypeElement(element: PsiTypeElement?): TypeElement
|
fun convertTypeElement(element: PsiTypeElement?): TypeElement
|
||||||
= TypeElement(if (element == null) ErrorType().assignNoPrototype() else typeConverter.convertType(element.getType())).assignPrototype(element)
|
= TypeElement(if (element == null) ErrorType().assignNoPrototype() else typeConverter.convertType(element.getType())).assignPrototype(element)
|
||||||
|
|
||||||
|
|||||||
@@ -31,27 +31,16 @@ import org.jetbrains.jet.j2k.ast.ErrorType
|
|||||||
import com.intellij.codeInsight.NullableNotNullManager
|
import com.intellij.codeInsight.NullableNotNullManager
|
||||||
import org.jetbrains.jet.j2k.ast.ArrayType
|
import org.jetbrains.jet.j2k.ast.ArrayType
|
||||||
import org.jetbrains.jet.j2k.ast.ClassType
|
import org.jetbrains.jet.j2k.ast.ClassType
|
||||||
|
import org.jetbrains.jet.j2k.ast.ReferenceElement
|
||||||
import org.jetbrains.jet.j2k.ast.Identifier
|
import org.jetbrains.jet.j2k.ast.Identifier
|
||||||
|
|
||||||
class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) {
|
class TypeConverter(val converter: Converter) {
|
||||||
private val nullabilityCache = HashMap<PsiElement, Nullability>()
|
private val nullabilityCache = HashMap<PsiElement, Nullability>()
|
||||||
private val classesToImport = HashSet<String>()
|
|
||||||
|
|
||||||
public var importList: ImportList? = null
|
|
||||||
set(value) {
|
|
||||||
$importList = value
|
|
||||||
importNames = importList?.imports?.mapTo(HashSet<String>()) { it.name } ?: setOf()
|
|
||||||
|
|
||||||
}
|
|
||||||
private var importNames: Set<String> = setOf()
|
|
||||||
|
|
||||||
public val importsToAdd: Collection<Import>
|
|
||||||
get() = classesToImport.map { Import(it).assignNoPrototype() }
|
|
||||||
|
|
||||||
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
|
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
|
||||||
if (`type` == null) return ErrorType().assignNoPrototype()
|
if (`type` == null) return ErrorType().assignNoPrototype()
|
||||||
|
|
||||||
val result = `type`.accept<Type>(TypeVisitor(this, importNames, classesToImport))!!.assignNoPrototype()
|
val result = `type`.accept<Type>(TypeVisitor(converter))!!.assignNoPrototype()
|
||||||
return when (nullability) {
|
return when (nullability) {
|
||||||
Nullability.NotNull -> result.toNotNullType()
|
Nullability.NotNull -> result.toNotNullType()
|
||||||
Nullability.Nullable -> result.toNullableType()
|
Nullability.Nullable -> result.toNullableType()
|
||||||
@@ -64,9 +53,9 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
|
|||||||
|
|
||||||
public fun convertVariableType(variable: PsiVariable): Type {
|
public fun convertVariableType(variable: PsiVariable): Type {
|
||||||
val result = if (variable.isMainMethodParameter()) {
|
val result = if (variable.isMainMethodParameter()) {
|
||||||
ArrayType(ClassType(Identifier("String").assignNoPrototype(), listOf(), Nullability.NotNull, settings).assignNoPrototype(),
|
ArrayType(ClassType(ReferenceElement(Identifier("String").assignNoPrototype(), listOf()).assignNoPrototype(), Nullability.NotNull, converter.settings).assignNoPrototype(),
|
||||||
Nullability.NotNull,
|
Nullability.NotNull,
|
||||||
settings)
|
converter.settings).assignNoPrototype()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
convertType(variable.getType(), variableNullability(variable))
|
convertType(variable.getType(), variableNullability(variable))
|
||||||
@@ -124,7 +113,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
|
|||||||
return Nullability.NotNull
|
return Nullability.NotNull
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conversionScope.contains(variable)) { // do not analyze usages out of our conversion scope
|
if (!converter.conversionScope.contains(variable)) { // do not analyze usages out of our conversion scope
|
||||||
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.getDeclarationScope()
|
||||||
@@ -203,7 +192,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
|
|||||||
return Nullability.Nullable
|
return Nullability.Nullable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conversionScope.contains(method)) return nullability // do not analyze body and usages of methods out of our conversion scope
|
if (!converter.conversionScope.contains(method)) return nullability // do not analyze body and usages of methods out of our conversion scope
|
||||||
|
|
||||||
if (nullability == Nullability.Default) {
|
if (nullability == Nullability.Default) {
|
||||||
method.getBody()?.accept(object: JavaRecursiveElementVisitor() {
|
method.getBody()?.accept(object: JavaRecursiveElementVisitor() {
|
||||||
|
|||||||
@@ -139,3 +139,20 @@ fun PsiMethod.isMainMethod(): Boolean = PsiMethodUtil.isMainMethod(this)
|
|||||||
|
|
||||||
fun <T: Any> List<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
|
fun <T: Any> List<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
|
||||||
fun <T: Any> Array<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
|
fun <T: Any> Array<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
|
||||||
|
|
||||||
|
fun PsiMember.isImported(file: PsiJavaFile): Boolean {
|
||||||
|
if (this is PsiClass) {
|
||||||
|
val fqName = getQualifiedName()
|
||||||
|
val index = fqName?.lastIndexOf('.') ?: -1
|
||||||
|
val parentName = if (index >= 0) fqName!!.substring(0, index) else null
|
||||||
|
return file.getImportList()?.getAllImportStatements()?.any {
|
||||||
|
it.getImportReference()?.getQualifiedName() == (if (it.isOnDemand()) parentName else fqName)
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return getContainingClass() != null && file.getImportList()?.getImportStaticStatements()?.any {
|
||||||
|
it.resolveTargetClass() == getContainingClass() && (it.isOnDemand() || it.getReferenceName() == getName())
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast
|
|||||||
import org.jetbrains.jet.j2k.*
|
import org.jetbrains.jet.j2k.*
|
||||||
|
|
||||||
class NewClassExpression(
|
class NewClassExpression(
|
||||||
val name: Element,
|
val name: ReferenceElement?,
|
||||||
val arguments: List<Expression>,
|
val arguments: List<Expression>,
|
||||||
val qualifier: Expression = Expression.Empty,
|
val qualifier: Expression = Expression.Empty,
|
||||||
val anonymousClass: AnonymousClassBody? = null
|
val anonymousClass: AnonymousClassBody? = null
|
||||||
@@ -34,7 +34,9 @@ class NewClassExpression(
|
|||||||
builder.append(qualifier).append(if (qualifier.isNullable) "!!." else ".")
|
builder.append(qualifier).append(if (qualifier.isNullable) "!!." else ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append(name)
|
if (name != null) {
|
||||||
|
builder.append(name)
|
||||||
|
}
|
||||||
|
|
||||||
if (anonymousClass == null || !anonymousClass.extendsTrait) {
|
if (anonymousClass == null || !anonymousClass.extendsTrait) {
|
||||||
builder.append("(").append(arguments, ", ").append(")")
|
builder.append("(").append(arguments, ", ").append(")")
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package org.jetbrains.jet.j2k.ast
|
|||||||
|
|
||||||
import org.jetbrains.jet.j2k.*
|
import org.jetbrains.jet.j2k.*
|
||||||
|
|
||||||
class ReferenceElement(val reference: Identifier, val types: List<Type>) : Element() {
|
class ReferenceElement(val name: Identifier, val typeArgs: List<Element>) : Element() {
|
||||||
override fun generateCode(builder: CodeBuilder) {
|
override fun generateCode(builder: CodeBuilder) {
|
||||||
builder.append(reference).append(types, ", ", "<", ">")
|
builder.append(name).append(typeArgs, ", ", "<", ">")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,15 +78,15 @@ class ErrorType : NotNullType() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassType(val name: Identifier, val typeArgs: List<Element>, nullability: Nullability, settings: ConverterSettings)
|
class ClassType(val referenceElement: ReferenceElement, nullability: Nullability, settings: ConverterSettings)
|
||||||
: MayBeNullableType(nullability, settings) {
|
: MayBeNullableType(nullability, settings) {
|
||||||
|
|
||||||
override fun generateCode(builder: CodeBuilder) {
|
override fun generateCode(builder: CodeBuilder) {
|
||||||
builder.append(name).append(typeArgs, ", ", "<", ">").append(isNullableStr)
|
builder append referenceElement append isNullableStr
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toNotNullType(): Type = ClassType(name, typeArgs, Nullability.NotNull, settings).assignPrototypesFrom(this)
|
override fun toNotNullType(): Type = ClassType(referenceElement, Nullability.NotNull, settings).assignPrototypesFrom(this)
|
||||||
override fun toNullableType(): Type = ClassType(name, typeArgs, Nullability.Nullable, settings).assignPrototypesFrom(this)
|
override fun toNullableType(): Type = ClassType(referenceElement, Nullability.Nullable, settings).assignPrototypesFrom(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings)
|
class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings)
|
||||||
|
|||||||
@@ -42,23 +42,6 @@ class ElementVisitor(private val converter: Converter) : JavaElementVisitor() {
|
|||||||
result = ExpressionList(converter.convertExpressions(list.getExpressions()))
|
result = ExpressionList(converter.convertExpressions(list.getExpressions()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReferenceElement(reference: PsiJavaCodeReferenceElement) {
|
|
||||||
val types = typeConverter.convertTypes(reference.getTypeParameters())
|
|
||||||
if (!reference.isQualified()) {
|
|
||||||
result = ReferenceElement(Identifier(reference.getReferenceName()!!).assignNoPrototype(), types)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var code = Identifier.toKotlin(reference.getReferenceName()!!)
|
|
||||||
var qualifier = reference.getQualifier()
|
|
||||||
while (qualifier != null) {
|
|
||||||
val p = qualifier as PsiJavaCodeReferenceElement
|
|
||||||
code = Identifier.toKotlin(p.getReferenceName()!!) + "." + code
|
|
||||||
qualifier = p.getQualifier()
|
|
||||||
}
|
|
||||||
result = ReferenceElement(Identifier(code).assignNoPrototype(), types)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTypeElement(`type`: PsiTypeElement) {
|
override fun visitTypeElement(`type`: PsiTypeElement) {
|
||||||
result = TypeElement(typeConverter.convertType(`type`.getType()))
|
result = TypeElement(typeConverter.convertType(`type`.getType()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,19 +254,17 @@ open class ExpressionVisitor(private val converter: Converter) : JavaElementVisi
|
|||||||
converter.convertExpressions(expression.getArrayDimensions()))
|
converter.convertExpressions(expression.getArrayDimensions()))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = createNewClassExpression(expression)
|
val anonymousClass = expression.getAnonymousClass()
|
||||||
|
val qualifier = expression.getQualifier()
|
||||||
|
val classRef = expression.getClassOrAnonymousClassReference()
|
||||||
|
val classRefConverted = if (classRef != null) converter.convertCodeReferenceElement(classRef, hasExternalQualifier = qualifier != null) else null
|
||||||
|
result = NewClassExpression(classRefConverted,
|
||||||
|
convertArguments(expression),
|
||||||
|
converter.convertExpression(qualifier),
|
||||||
|
if (anonymousClass != null) converter.convertAnonymousClassBody(anonymousClass) else null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNewClassExpression(expression: PsiNewExpression): Expression {
|
|
||||||
val anonymousClass = expression.getAnonymousClass()
|
|
||||||
val classReference = expression.getClassOrAnonymousClassReference()
|
|
||||||
return NewClassExpression(converter.convertElement(classReference),
|
|
||||||
convertArguments(expression),
|
|
||||||
converter.convertExpression(expression.getQualifier()),
|
|
||||||
if (anonymousClass != null) converter.convertAnonymousClassBody(anonymousClass) else null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression) {
|
override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression) {
|
||||||
result = ParenthesizedExpression(converter.convertExpression(expression.getExpression()))
|
result = ParenthesizedExpression(converter.convertExpression(expression.getExpression()))
|
||||||
}
|
}
|
||||||
@@ -317,16 +315,18 @@ open class ExpressionVisitor(private val converter: Converter) : JavaElementVisi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add qualification for static members from base classes and also this works for enum constants in switch
|
// add qualification for static members from base classes and also this works for enum constants in switch
|
||||||
|
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.getContainingClass() != null
|
||||||
&& !PsiTreeUtil.isAncestor(target.getContainingClass(), expression, true)
|
&& !PsiTreeUtil.isAncestor(target.getContainingClass(), context, true)
|
||||||
&& !isStaticallyImported(target, expression)) {
|
&& !target.isImported(context.getContainingFile() as PsiJavaFile)) {
|
||||||
var member: PsiMember = target
|
var member: PsiMember = target
|
||||||
var code = Identifier.toKotlin(referenceName)
|
var code = Identifier.toKotlin(referenceName)
|
||||||
while (member.getContainingClass() != null) {
|
while (true) {
|
||||||
code = Identifier.toKotlin(member.getContainingClass()!!.getName()!!) + "." + code
|
val containingClass = member.getContainingClass() ?: break
|
||||||
member = member.getContainingClass()!!
|
code = Identifier.toKotlin(containingClass.getName()!!) + "." + code
|
||||||
|
member = containingClass
|
||||||
}
|
}
|
||||||
result = Identifier(code, false, false)
|
result = Identifier(code, false, false)
|
||||||
return
|
return
|
||||||
@@ -433,23 +433,4 @@ open class ExpressionVisitor(private val converter: Converter) : JavaElementVisi
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isStaticallyImported(member: PsiMember, context: PsiElement): Boolean {
|
|
||||||
val containingFile = context.getContainingFile()
|
|
||||||
val targetContainingClass = member.getContainingClass()
|
|
||||||
if (containingFile is PsiJavaFile && targetContainingClass != null) {
|
|
||||||
val importList = containingFile.getImportList();
|
|
||||||
if (importList != null) {
|
|
||||||
return importList.getImportStaticStatements().any { importResolvesTo(it, member) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun importResolvesTo(importStatement: PsiImportStaticStatement, member: PsiMember): Boolean {
|
|
||||||
val targetContainingClass = member.getContainingClass()
|
|
||||||
val importedClass = importStatement.resolveTargetClass()
|
|
||||||
return importedClass == targetContainingClass
|
|
||||||
&& (importStatement.isOnDemand() || importStatement.getReferenceName() == member.getName())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,19 @@ package org.jetbrains.jet.j2k.visitors
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.source.PsiClassReferenceType
|
import com.intellij.psi.impl.source.PsiClassReferenceType
|
||||||
import org.jetbrains.jet.j2k.ast.*
|
import org.jetbrains.jet.j2k.ast.*
|
||||||
import java.util.LinkedList
|
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import java.util.ArrayList
|
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType
|
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType
|
||||||
import org.jetbrains.jet.j2k.TypeConverter
|
import org.jetbrains.jet.j2k.TypeConverter
|
||||||
|
import java.util.ArrayList
|
||||||
|
import org.jetbrains.jet.j2k.singleOrNull2
|
||||||
|
import org.jetbrains.jet.j2k.Converter
|
||||||
|
|
||||||
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
|
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
|
||||||
|
|
||||||
class TypeVisitor(private val converter: TypeConverter, private val importNames: Set<String>, private val classesToImport: MutableSet<String>) : PsiTypeVisitor<Type>() {
|
class TypeVisitor(private val converter: Converter) : PsiTypeVisitor<Type>() {
|
||||||
|
|
||||||
|
private val typeConverter: TypeConverter = converter.typeConverter
|
||||||
|
|
||||||
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
||||||
val name = primitiveType.getCanonicalText()
|
val name = primitiveType.getCanonicalText()
|
||||||
return if (name == "void") {
|
return if (name == "void") {
|
||||||
@@ -45,100 +49,86 @@ class TypeVisitor(private val converter: TypeConverter, private val importNames:
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitArrayType(arrayType: PsiArrayType): Type {
|
override fun visitArrayType(arrayType: PsiArrayType): Type {
|
||||||
return ArrayType(converter.convertType(arrayType.getComponentType()), Nullability.Default, converter.settings)
|
return ArrayType(typeConverter.convertType(arrayType.getComponentType()), Nullability.Default, converter.settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassType(classType: PsiClassType): Type {
|
override fun visitClassType(classType: PsiClassType): Type {
|
||||||
val identifier = constructClassTypeIdentifier(classType)
|
val refElement = constructReferenceElement(classType)
|
||||||
val resolvedClassTypeParams = createRawTypesForResolvedReference(classType)
|
return ClassType(refElement, Nullability.Default, converter.settings)
|
||||||
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
|
||||||
val starParamList = ArrayList<Type>()
|
|
||||||
if (resolvedClassTypeParams.size() == 1) {
|
|
||||||
if ((resolvedClassTypeParams.single() as ClassType).name.name == "Any") {
|
|
||||||
starParamList.add(StarProjectionType())
|
|
||||||
return ClassType(identifier, starParamList, Nullability.Default, converter.settings)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ClassType(identifier, resolvedClassTypeParams, Nullability.Default, converter.settings)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ClassType(identifier, resolvedClassTypeParams, Nullability.Default, converter.settings)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ClassType(identifier, converter.convertTypes(classType.getParameters()), Nullability.Default, converter.settings)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun constructClassTypeIdentifier(classType: PsiClassType): Identifier {
|
private fun constructReferenceElement(classType: PsiClassType): ReferenceElement {
|
||||||
|
val typeArgs = convertTypeArgs(classType)
|
||||||
|
|
||||||
val psiClass = classType.resolve()
|
val psiClass = classType.resolve()
|
||||||
if (psiClass != null) {
|
if (psiClass != null) {
|
||||||
val javaClassName = psiClass.getQualifiedName()
|
val javaClassName = psiClass.getQualifiedName()
|
||||||
val kotlinClassName = toKotlinTypesMap[javaClassName]
|
val kotlinClassName = toKotlinTypesMap[javaClassName]
|
||||||
if (kotlinClassName != null) {
|
if (kotlinClassName != null) {
|
||||||
val kotlinShortName = getShortName(kotlinClassName)
|
val kotlinShortName = getShortName(kotlinClassName)
|
||||||
if (kotlinShortName == getShortName(javaClassName!!) && importNames.contains(getPackageName(javaClassName) + ".*")) {
|
if (kotlinShortName == getShortName(javaClassName!!) && converter.importNames.contains(getPackageName(javaClassName) + ".*")) {
|
||||||
classesToImport.add(kotlinClassName)
|
converter.importsToAdd?.add(kotlinClassName)
|
||||||
}
|
}
|
||||||
return Identifier(kotlinShortName).assignNoPrototype()
|
return ReferenceElement(Identifier(kotlinShortName).assignNoPrototype(), typeArgs).assignNoPrototype()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classType is PsiClassReferenceType) {
|
if (classType is PsiClassReferenceType) {
|
||||||
val reference = classType.getReference()
|
return converter.convertCodeReferenceElement(classType.getReference(), hasExternalQualifier = false, typeArgsConverted = typeArgs)
|
||||||
if (reference.isQualified()) {
|
|
||||||
var result = Identifier.toKotlin(reference.getReferenceName()!!)
|
|
||||||
var qualifier = reference.getQualifier()
|
|
||||||
while (qualifier != null) {
|
|
||||||
val codeRefElement = qualifier as PsiJavaCodeReferenceElement
|
|
||||||
result = Identifier.toKotlin(codeRefElement.getReferenceName()!!) + "." + result
|
|
||||||
qualifier = codeRefElement.getQualifier()
|
|
||||||
}
|
|
||||||
return Identifier(result).assignNoPrototype()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Identifier(classType.getClassName() ?: "").assignNoPrototype()
|
return ReferenceElement(Identifier(classType.getClassName() ?: "").assignNoPrototype(), typeArgs).assignNoPrototype()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPackageName(className: String): String = className.substring(0, className.lastIndexOf('.'))
|
private fun getPackageName(className: String): String = className.substring(0, className.lastIndexOf('.'))
|
||||||
private fun getShortName(className: String): String = className.substring(className.lastIndexOf('.') + 1)
|
private fun getShortName(className: String): String = className.substring(className.lastIndexOf('.') + 1)
|
||||||
|
|
||||||
|
private fun convertTypeArgs(classType: PsiClassType): List<Type> {
|
||||||
|
val resolvedClassTypeParams = createRawTypesForResolvedReference(classType)
|
||||||
|
|
||||||
|
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
||||||
|
if ((resolvedClassTypeParams.singleOrNull2() as? ClassType)?.referenceElement?.name?.name == "Any") {
|
||||||
|
return listOf(StarProjectionType().assignNoPrototype())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return resolvedClassTypeParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return typeConverter.convertTypes(classType.getParameters())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createRawTypesForResolvedReference(classType: PsiClassType): List<Type> {
|
private fun createRawTypesForResolvedReference(classType: PsiClassType): List<Type> {
|
||||||
val typeParams = LinkedList<Type>()
|
val typeArgs = ArrayList<Type>()
|
||||||
if (classType is PsiClassReferenceType) {
|
if (classType is PsiClassReferenceType) {
|
||||||
val resolve = classType.getReference().resolve()
|
val resolve = classType.getReference().resolve()
|
||||||
if (resolve is PsiClass) {
|
if (resolve is PsiClass) {
|
||||||
for (typeParam in resolve.getTypeParameters()) {
|
for (typeParam in resolve.getTypeParameters()) {
|
||||||
val superTypes = typeParam.getSuperTypes()
|
val superTypes = typeParam.getSuperTypes()
|
||||||
val boundType = if (superTypes.size > 0) {
|
val boundType = if (superTypes.size > 0) {
|
||||||
ClassType(constructClassTypeIdentifier(superTypes[0]),
|
ClassType(constructReferenceElement(superTypes.first()), Nullability.Default, converter.settings)
|
||||||
converter.convertTypes(superTypes[0].getParameters()),
|
|
||||||
Nullability.Default,
|
|
||||||
converter.settings)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
StarProjectionType()
|
StarProjectionType()
|
||||||
}
|
}
|
||||||
typeParams.add(boundType)
|
typeArgs.add(boundType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return typeArgs
|
||||||
return typeParams
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWildcardType(wildcardType: PsiWildcardType): Type {
|
override fun visitWildcardType(wildcardType: PsiWildcardType): Type {
|
||||||
return when {
|
return when {
|
||||||
wildcardType.isExtends() -> OutProjectionType(converter.convertType(wildcardType.getExtendsBound()))
|
wildcardType.isExtends() -> OutProjectionType(typeConverter.convertType(wildcardType.getExtendsBound()))
|
||||||
wildcardType.isSuper() -> InProjectionType(converter.convertType(wildcardType.getSuperBound()))
|
wildcardType.isSuper() -> InProjectionType(typeConverter.convertType(wildcardType.getSuperBound()))
|
||||||
else -> StarProjectionType()
|
else -> StarProjectionType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEllipsisType(ellipsisType: PsiEllipsisType): Type {
|
override fun visitEllipsisType(ellipsisType: PsiEllipsisType): Type {
|
||||||
return VarArgType(converter.convertType(ellipsisType.getComponentType()))
|
return VarArgType(typeConverter.convertType(ellipsisType.getComponentType()))
|
||||||
}
|
}
|
||||||
|
|
||||||
class object {
|
class object {
|
||||||
|
|||||||
@@ -891,6 +891,31 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
|||||||
doTest("j2k/tests/testData/ast/constructors/methodCallInFactoryFun.java");
|
doTest("j2k/tests/testData/ast/constructors/methodCallInFactoryFun.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedClassNameInParameterDefaults.java")
|
||||||
|
public void testNestedClassNameInParameterDefaults() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/nestedClassNameInParameterDefaults.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedClassNameInParameterDefaults2.java")
|
||||||
|
public void testNestedClassNameInParameterDefaults2() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/nestedClassNameInParameterDefaults2.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedClassNameInParameterDefaults3.java")
|
||||||
|
public void testNestedClassNameInParameterDefaults3() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/nestedClassNameInParameterDefaults3.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedClassNameInParameterDefaults4.java")
|
||||||
|
public void testNestedClassNameInParameterDefaults4() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/nestedClassNameInParameterDefaults4.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedClassNameInSuperParameters.java")
|
||||||
|
public void testNestedClassNameInSuperParameters() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/nestedClassNameInSuperParameters.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noPrimary.java")
|
@TestMetadata("noPrimary.java")
|
||||||
public void testNoPrimary() throws Exception {
|
public void testNoPrimary() throws Exception {
|
||||||
doTest("j2k/tests/testData/ast/constructors/noPrimary.java");
|
doTest("j2k/tests/testData/ast/constructors/noPrimary.java");
|
||||||
@@ -1732,6 +1757,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
|||||||
doTest("j2k/tests/testData/ast/issues/kt-1074.java");
|
doTest("j2k/tests/testData/ast/issues/kt-1074.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt-5294.java")
|
||||||
|
public void testKt_5294() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/issues/kt-5294.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt-5400.java")
|
||||||
|
public void testKt_5400() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/issues/kt-5400.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt-543.java")
|
@TestMetadata("kt-543.java")
|
||||||
public void testKt_543() throws Exception {
|
public void testKt_543() throws Exception {
|
||||||
doTest("j2k/tests/testData/ast/issues/kt-543.java");
|
doTest("j2k/tests/testData/ast/issues/kt-543.java");
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class A {
|
||||||
|
A(Nested nested) {
|
||||||
|
}
|
||||||
|
|
||||||
|
A() {
|
||||||
|
this(new Nested(Nested.FIELD));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Nested {
|
||||||
|
Nested(int p){}
|
||||||
|
|
||||||
|
public static final int FIELD = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class A(nested: A.Nested = A.Nested(A.Nested.FIELD)) {
|
||||||
|
|
||||||
|
class Nested(p: Int) {
|
||||||
|
class object {
|
||||||
|
|
||||||
|
public val FIELD: Int = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import A.Nested;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
A(Nested nested) {
|
||||||
|
}
|
||||||
|
|
||||||
|
A() {
|
||||||
|
this(new Nested(Nested.FIELD));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Nested {
|
||||||
|
Nested(int p){}
|
||||||
|
|
||||||
|
public static final int FIELD = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
Nested nested;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import A.Nested
|
||||||
|
|
||||||
|
class A(nested: Nested = Nested(Nested.FIELD)) {
|
||||||
|
|
||||||
|
class Nested(p: Int) {
|
||||||
|
class object {
|
||||||
|
|
||||||
|
public val FIELD: Int = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
var nested: Nested
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package pack;
|
||||||
|
|
||||||
|
import static pack.A.Nested;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
A(Nested nested) {
|
||||||
|
}
|
||||||
|
|
||||||
|
A() {
|
||||||
|
this(new Nested(Nested.FIELD));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Nested {
|
||||||
|
Nested(int p){}
|
||||||
|
|
||||||
|
public static final int FIELD = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
Nested nested;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package pack
|
||||||
|
|
||||||
|
import pack.A.Nested
|
||||||
|
|
||||||
|
class A(nested: Nested = Nested(Nested.FIELD)) {
|
||||||
|
|
||||||
|
class Nested(p: Int) {
|
||||||
|
class object {
|
||||||
|
|
||||||
|
public val FIELD: Int = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
var nested: Nested
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package pack;
|
||||||
|
|
||||||
|
import static pack.A.*;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
A(Nested nested) {
|
||||||
|
}
|
||||||
|
|
||||||
|
A() {
|
||||||
|
this(new Nested(Nested.FIELD));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Nested {
|
||||||
|
Nested(int p){}
|
||||||
|
|
||||||
|
public static final int FIELD = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
Nested nested;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package pack
|
||||||
|
|
||||||
|
import pack.A.*
|
||||||
|
|
||||||
|
class A(nested: Nested = Nested(Nested.FIELD)) {
|
||||||
|
|
||||||
|
class Nested(p: Int) {
|
||||||
|
class object {
|
||||||
|
|
||||||
|
public val FIELD: Int = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
var nested: Nested
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
class Base {
|
||||||
|
Base(Nested nested){}
|
||||||
|
|
||||||
|
static class Nested {
|
||||||
|
Nested(int p){}
|
||||||
|
|
||||||
|
public static final int FIELD = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived extends Base {
|
||||||
|
Derived() {
|
||||||
|
super(new Nested(Nested.FIELD));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class Base(nested: Base.Nested) {
|
||||||
|
|
||||||
|
class Nested(p: Int) {
|
||||||
|
class object {
|
||||||
|
|
||||||
|
public val FIELD: Int = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived : Base(Base.Nested(Base.Nested.FIELD))
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class X {
|
||||||
|
private final List<Y> list;
|
||||||
|
|
||||||
|
X(List<Y> list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Y{}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class X(private val list: List<X.Y>) {
|
||||||
|
|
||||||
|
inner class Y
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Base {
|
||||||
|
class Nested{}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived extends Base {
|
||||||
|
Nested field;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Base {
|
||||||
|
inner class Nested
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived : Base() {
|
||||||
|
var field: Base.Nested
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.List
|
|
||||||
import kotlin.Iterator
|
import kotlin.Iterator
|
||||||
|
import kotlin.List
|
||||||
|
|
||||||
trait I<T : List<Iterator<String>>>
|
trait I<T : List<Iterator<String>>>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user