Prepare repository for merge into master

This commit is contained in:
Pavel V. Talanov
2013-10-28 15:20:07 +04:00
parent 8537254b6f
commit 375951798e
801 changed files with 63 additions and 3680 deletions
+3
View File
@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: org.jetbrains.jet.j2k.JavaToKotlinCli
+879
View File
@@ -0,0 +1,879 @@
package org.jetbrains.jet.j2k
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableSet
import com.google.common.collect.Sets
import com.intellij.psi.*
import org.jetbrains.jet.j2k.ast.*
import org.jetbrains.jet.j2k.ast.types.ClassType
import org.jetbrains.jet.j2k.ast.types.EmptyType
import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.j2k.visitors.*
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import java.util.*
import com.intellij.psi.CommonClassNames.*
import org.jetbrains.jet.lang.types.expressions.OperatorConventions.*
import com.intellij.openapi.util.Pair
import java.text.MessageFormat
import com.intellij.psi.util.PsiUtil
import org.jetbrains.jet.config.CompilerConfiguration
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment
import com.intellij.openapi.Disposable
import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.util.QualifiedNamesUtil
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap
public open class Converter() {
private var classIdentifiersSet: MutableSet<String> = Sets.newHashSet()!!
private val dispatcher: Dispatcher = Dispatcher(this)
private val flags: MutableSet<J2KConverterFlags?>? = Sets.newHashSet()
private val jetCoreEnvironment = JetCoreEnvironment(
object : Disposable {
public override fun dispose() {
}
}, CompilerConfiguration())
private val project = jetCoreEnvironment.getProject();
private val javaToKotlinClassMap: JavaToKotlinClassMap = JavaToKotlinClassMap.getInstance()
public open var methodReturnType: PsiType? = null
private set
public open fun addFlag(flag: J2KConverterFlags): Boolean {
return flags?.add(flag)!!
}
public open fun hasFlag(flag: J2KConverterFlags): Boolean {
return flags?.contains(flag)!!
}
public open fun setClassIdentifiers(identifiers: MutableSet<String>) {
classIdentifiersSet = identifiers
}
public open fun getClassIdentifiers(): Set<String> {
return Collections.unmodifiableSet(classIdentifiersSet)
}
public open fun clearClassIdentifiers(): Unit {
classIdentifiersSet.clear()
}
public open fun elementToKotlin(element: PsiElement): String {
val kElement = topElementToElement(element)
return kElement?.toKotlin() ?: ""
}
public open fun topElementToElement(element: PsiElement?): Node? = when(element) {
is PsiJavaFile -> fileToFile(element)
is PsiClass -> classToClass(element)
is PsiMethod -> methodToFunction(element)
is PsiField -> fieldToField(element, element.getContainingClass())
is PsiStatement -> statementToStatement(element)
is PsiExpression -> expressionToExpression(element)
is PsiComment -> Comment(element.getText()!!)
else -> null
}
public open fun fileToFile(javaFile: PsiJavaFile): File {
return fileToFile(javaFile, Collections.emptyList<String>())
}
public open fun fileToFileWithCompatibilityImport(javaFile: PsiJavaFile): File {
return fileToFile(javaFile, Collections.singletonList("kotlin.compatibility.*"))
}
private fun fileToFile(javaFile: PsiJavaFile, additionalImports: List<String>): File {
val importList: PsiImportList? = javaFile.getImportList()
val imports: MutableList<Import> = (if (importList == null)
arrayListOf()
else
ArrayList(importsToImportList(importList.getAllImportStatements()) filter {
// If name is invalid, like with star imports, don't try to filter
if (!QualifiedNamesUtil.isValidJavaFqName(it.name))
true
else {
// If imported class has a kotlin analog, drop the import
val kotlinAnalogsForClass = javaToKotlinClassMap.mapPlatformClass(FqName(it.name))
kotlinAnalogsForClass.isEmpty()
}
}))
for (i : String in additionalImports)
imports.add(Import(i))
val body: ArrayList<Node> = arrayListOf()
for(element in javaFile.getChildren()) {
if (element !is PsiImportStatementBase) {
val node = topElementToElement(element)
if (node != null) {
body.add(node)
}
}
}
return File(quoteKeywords(javaFile.getPackageName()), imports, body, createMainFunction(javaFile))
}
public open fun anonymousClassToAnonymousClass(anonymousClass: PsiAnonymousClass): AnonymousClass {
return AnonymousClass(this, getMembers(anonymousClass))
}
private fun getMembers(psiClass: PsiClass): MutableList<Node> {
val members = ArrayList<Node>()
val lbraceOffset = psiClass.getLBrace()?.getTextRange()?.getStartOffset() ?: 0
for (e : PsiElement? in psiClass.getChildren()) {
val isDocComment = e?.getTextRange()?.getStartOffset() ?: 0 < lbraceOffset
if (isDocComment) continue
val converted = memberToMember(e, psiClass)
if (converted != null) members.add(converted)
}
return members
}
private fun getDocComments(element: PsiElement): List<Node> {
val comments = ArrayList<Node>()
val textOffset = element.getTextOffset()
for (e : PsiElement? in element.getChildren()) {
if (e is PsiComment && e.getTextRange()?.getStartOffset() ?: 0 < textOffset) {
comments.add(Comment(e.getText()!!));
}
}
return comments
}
private fun memberToMember(e: PsiElement?, containingClass: PsiClass): Node? = when(e) {
is PsiMethod -> methodToFunction(e, true)
is PsiField -> fieldToField(e, containingClass)
is PsiClass -> classToClass(e)
is PsiClassInitializer -> initializerToInitializer(e)
is PsiComment -> Comment(e.getText()!!)
else -> null
}
private fun classToClass(psiClass: PsiClass): Class {
val modifiers: Set<Modifier> = modifiersListToModifiersSet(psiClass.getModifierList())
val fields: List<Field> = fieldsToFieldList(psiClass.getFields(), psiClass)
val typeParameters: List<Element> = elementsToElementList(psiClass.getTypeParameters())
val implementsTypes: List<Type> = typesToNotNullableTypeList(psiClass.getImplementsListTypes())
val extendsTypes: List<Type> = typesToNotNullableTypeList(psiClass.getExtendsListTypes())
val name: Identifier = Identifier(psiClass.getName()!!)
val baseClassParams= ArrayList<Expression>()
val members = getMembers(psiClass)
val docComments = getDocComments(psiClass)
val visitor: SuperVisitor = SuperVisitor()
psiClass.accept(visitor)
val resolvedSuperCallParameters = visitor.resolvedSuperCallParameters
if (resolvedSuperCallParameters.size() == 1) {
val psiExpressionList = resolvedSuperCallParameters.iterator().next()
baseClassParams.addAll(expressionsToExpressionList(psiExpressionList.getExpressions()))
}
if (!psiClass.isEnum() && !psiClass.isInterface() && psiClass.getConstructors().size > 1 &&
getPrimaryConstructorForThisCase(psiClass) == null) {
val finalOrWithEmptyInitializer: List<Field> = getFinalOrWithEmptyInitializer(fields)
val initializers = HashMap<String, String>()
for (m in members) {
if (m is Constructor) {
if (!m.isPrimary) {
for (fo in finalOrWithEmptyInitializer){
val init: String = getDefaultInitializer(fo)
initializers.put(fo.identifier.toKotlin(), init)
}
val newStatements = ArrayList<Element>()
for (s in m.block!!.statements) {
var isRemoved: Boolean = false
if (s is AssignmentExpression) {
val assignee = s.left
if (assignee is CallChainExpression) {
for (fo : Field in finalOrWithEmptyInitializer) {
val id: String = fo.identifier.toKotlin()
if (assignee.identifier.toKotlin().endsWith("." + id)) {
initializers.put(id, s.right.toKotlin())
isRemoved = true
}
}
}
}
if (!isRemoved) {
newStatements.add(s)
}
}
newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(name.toKotlin(), finalOrWithEmptyInitializer, initializers)))
m.block = Block(newStatements)
}
}
}
members.add(Constructor(Identifier.EMPTY_IDENTIFIER, arrayListOf(), Collections.emptySet<Modifier>(),
ClassType(name, Collections.emptyList<Element>(), false),
Collections.emptyList<Element>(),
ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
true))
}
if (psiClass.isInterface()) {
return Trait(this, name, docComments, modifiers, typeParameters, extendsTypes, Collections.emptyList<Expression>(), implementsTypes, members)
}
if (psiClass.isEnum()) {
return Enum(this, name, docComments, modifiers, typeParameters, Collections.emptyList<Type>(), Collections.emptyList<Expression>(), implementsTypes, members)
}
return Class(this, name, docComments, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members)
}
private fun initializerToInitializer(i: PsiClassInitializer): Initializer {
return Initializer(blockToBlock(i.getBody(), true), modifiersListToModifiersSet(i.getModifierList()))
}
private fun fieldsToFieldList(fields: Array<PsiField>, psiClass: PsiClass): List<Field> {
return fields.map { fieldToField(it, psiClass) }
}
private fun fieldToField(field: PsiField, psiClass: PsiClass?): Field {
val modifiers = modifiersListToModifiersSet(field.getModifierList())
val docComments = getDocComments(field)
if (field is PsiEnumConstant) {
return EnumConstant(Identifier(field.getName()!!),
docComments,
modifiers,
typeToType(field.getType()),
elementToElement(field.getArgumentList()))
}
var kType = typeToType(field.getType(), isAnnotatedAsNotNull(field.getModifierList()))
if (field.hasModifierProperty(PsiModifier.FINAL) && isDefinitelyNotNull(field.getInitializer())) {
kType = kType.convertedToNotNull();
}
return Field(Identifier(field.getName()!!),
docComments,
modifiers,
kType,
expressionToExpression(field.getInitializer(), field.getType()),
countWritingAccesses(field, psiClass))
}
private fun methodToFunction(method: PsiMethod): Function {
return methodToFunction(method, true)
}
private fun methodToFunction(method: PsiMethod, notEmpty: Boolean): Function {
if (isOverrideObjectDirect(method)) {
dispatcher.expressionVisitor = ExpressionVisitorForDirectObjectInheritors(this)
}
else {
dispatcher.expressionVisitor = ExpressionVisitor(this)
}
methodReturnType = method.getReturnType()
val identifier: Identifier = Identifier(method.getName())
val returnType: Type = typeToType(method.getReturnType(), isAnnotatedAsNotNull(method.getModifierList()))
val body: Block = (if (hasFlag(J2KConverterFlags.SKIP_BODIES))
Block.EMPTY_BLOCK
else
blockToBlock(method.getBody(), notEmpty))
val params: Element = createFunctionParameters(method)
val typeParameters = elementsToElementList(method.getTypeParameters())
val modifiers = modifiersListToModifiersSet(method.getModifierList())
val docComments = getDocComments(method)
if (isOverrideAnyMethodExceptMethodsFromObject(method)) {
modifiers.add(Modifier.OVERRIDE)
}
val containingClass = method.getContainingClass()
if (containingClass != null && containingClass.isInterface()) {
modifiers.remove(Modifier.ABSTRACT)
}
if (isNotOpenMethod(method)) {
modifiers.add(Modifier.NOT_OPEN)
}
if (method.isConstructor()) {
val isPrimary: Boolean = isConstructorPrimary(method)
return Constructor(identifier, docComments, modifiers, returnType, typeParameters, params,
Block(removeEmpty(body.statements), false), isPrimary)
}
return Function(identifier, docComments, modifiers, returnType, typeParameters, params, body)
}
private fun createFunctionParameters(method: PsiMethod): ParameterList {
val result = ArrayList<Parameter>()
for (parameter : PsiParameter? in method.getParameterList().getParameters()) {
result.add(Parameter(Identifier(parameter?.getName()!!),
typeToType(parameter?.getType(),
isAnnotatedAsNotNull(parameter?.getModifierList())),
isReadOnly(parameter, method.getBody())))
}
return ParameterList(result)
}
private fun isOverrideAnyMethodExceptMethodsFromObject(method: PsiMethod): Boolean {
var counter: Boolean = normalCase(method)
if (counter)
{
return true
}
if (isInheritFromObject(method))
{
return caseForObject(method)
}
return false
}
private fun caseForObject(method: PsiMethod): Boolean {
val containing: PsiClass? = method.getContainingClass()
if (containing != null) {
for (s : PsiClassType? in containing.getSuperTypes()) {
val canonicalText: String? = s?.getCanonicalText()
if (canonicalText != JAVA_LANG_OBJECT && !getClassIdentifiers().contains(canonicalText)) {
return true
}
}
}
return false
}
public open fun blockToBlock(block: PsiCodeBlock?, notEmpty: Boolean): Block {
if (block == null)
return Block.EMPTY_BLOCK
return Block(removeEmpty(statementsToStatementList(block.getChildren())), notEmpty)
}
public open fun blockToBlock(block: PsiCodeBlock?): Block {
return blockToBlock(block, true)
}
public open fun statementsToStatementList(statements: Array<PsiElement>): List<Element> {
return statements.filterNot { it is PsiWhiteSpace }.map { statementToStatement(it) }
}
public open fun statementsToStatementList(statements: List<PsiElement>): List<Element> {
return statements.filterNot { it is PsiWhiteSpace }.map { statementToStatement(it) }
}
public open fun statementToStatement(s: PsiElement?): Element {
if (s == null)
return Statement.EMPTY_STATEMENT
val statementVisitor: StatementVisitor = StatementVisitor(this)
s.accept(statementVisitor)
return statementVisitor.getResult()
}
public open fun expressionsToExpressionList(expressions: Array<PsiExpression>): List<Expression> {
val result = ArrayList<Expression>()
for (e : PsiExpression? in expressions)
result.add(expressionToExpression(e))
return result
}
public open fun expressionToExpression(e: PsiExpression?): Expression {
if (e == null)
return Expression.EMPTY_EXPRESSION
val expressionVisitor: ExpressionVisitor = dispatcher.expressionVisitor
e.accept(expressionVisitor)
return expressionVisitor.getResult()
}
public open fun elementToElement(e: PsiElement?): Element {
if (e == null)
return Element.EMPTY_ELEMENT
val elementVisitor: ElementVisitor = ElementVisitor(this)
e.accept(elementVisitor)
return elementVisitor.getResult()
}
public open fun elementsToElementList(elements: Array<out PsiElement?>): List<Element> {
val result = ArrayList<Element>()
for(element in elements) {
result.add(elementToElement(element))
}
return result
}
public open fun typeElementToTypeElement(element: PsiTypeElement?): TypeElement {
return TypeElement(if (element == null)
EmptyType()
else
typeToType(element.getType()))
}
public open fun typeToType(`type`: PsiType?): Type {
if (`type` == null)
return EmptyType()
val typeVisitor: TypeVisitor = TypeVisitor(this)
`type`.accept<Type>(typeVisitor)
return typeVisitor.getResult()
}
public open fun typesToTypeList(types: Array<PsiType>): List<Type> {
return types.map { typeToType(it) }
}
public open fun typeToType(`type`: PsiType?, notNull: Boolean): Type {
val result: Type = typeToType(`type`)
if (notNull) {
return result.convertedToNotNull()
}
return result
}
private fun typesToNotNullableTypeList(types: Array<out PsiType?>): List<Type> {
val result = ArrayList<Type>()
for(aType in types) {
result.add(typeToType(aType).convertedToNotNull())
}
return result
}
public open fun parametersToParameterList(parameters: Array<PsiParameter>): List<Parameter?> {
return parameters.map { parameterToParameter(it) }
}
public open fun parameterToParameter(parameter: PsiParameter, forceNotNull: Boolean = false): Parameter {
return Parameter(Identifier(parameter.getName()!!),
typeToType(parameter.getType(),
forceNotNull || isAnnotatedAsNotNull(parameter.getModifierList())), true)
}
public open fun argumentsToExpressionList(expression: PsiCallExpression): List<Expression> {
val argumentList: PsiExpressionList? = expression.getArgumentList()
val arguments: Array<PsiExpression> = (if (argumentList != null)
argumentList.getExpressions()
else
PsiExpression.EMPTY_ARRAY)
val result = ArrayList<Expression>()
val resolved: PsiMethod? = expression.resolveMethod()
val expectedTypes = ArrayList<PsiType?>()
if (resolved != null) {
for (p : PsiParameter? in resolved.getParameterList().getParameters())
expectedTypes.add(p?.getType())
}
if (arguments.size == expectedTypes.size()) {
for (i in 0..expectedTypes.size() - 1) result.add(expressionToExpression(arguments[i], expectedTypes.get(i)))
}
else {
for (argument : PsiExpression? in arguments) {
result.add(expressionToExpression(argument))
}
}
return result
}
public open fun expressionToExpression(argument: PsiExpression?, expectedType: PsiType?): Expression {
if (argument == null)
return Identifier.EMPTY_IDENTIFIER
var expression: Expression = expressionToExpression(argument)
val actualType: PsiType? = argument.getType()
val isPrimitiveTypeOrNull: Boolean = actualType == null || actualType is PsiPrimitiveType
if (isPrimitiveTypeOrNull && expression.isNullable()) {
expression = BangBangExpression(expression)
}
else if (expectedType is PsiPrimitiveType && actualType is PsiClassType) {
if (PsiPrimitiveType.getUnboxedType(actualType) == expectedType) {
expression = BangBangExpression(expression)
}
}
if (actualType != null) {
if (isConversionNeeded(actualType, expectedType) && !(expression is LiteralExpression))
{
val conversion: String? = PRIMITIVE_TYPE_CONVERSIONS.get(expectedType?.getCanonicalText())
if (conversion != null) {
expression = MethodCallExpression.build(expression, conversion)
}
}
}
return expression
}
class object {
public val NOT_NULL_ANNOTATIONS: Set<String> = ImmutableSet.of<String>("org.jetbrains.annotations.NotNull", "com.sun.istack.internal.NotNull", "javax.annotation.Nonnull")!!
public val PRIMITIVE_TYPE_CONVERSIONS: Map<String, String> = ImmutableMap.builder<String, String>()
?.put("byte", BYTE.asString())
?.put("short", SHORT.asString())
?.put("int", INT.asString())
?.put("long", LONG.asString())
?.put("float", FLOAT.asString())
?.put("double", DOUBLE.asString())
?.put("char", CHAR.asString())
?.put(JAVA_LANG_BYTE, BYTE.asString())
?.put(JAVA_LANG_SHORT, SHORT.asString())
?.put(JAVA_LANG_INTEGER, INT.asString())
?.put(JAVA_LANG_LONG, LONG.asString())
?.put(JAVA_LANG_FLOAT, FLOAT.asString())
?.put(JAVA_LANG_DOUBLE, DOUBLE.asString())
?.put(JAVA_LANG_CHARACTER, CHAR.asString())
?.build()!!
private fun quoteKeywords(packageName: String): String {
return packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".")
}
private fun getFinalOrWithEmptyInitializer(fields: List<Field>): List<Field> {
val result = ArrayList<Field>()
for (f : Field in fields)
if (f.isVal() || f.initializer.toKotlin().isEmpty()) {
result.add(f)
}
return result
}
private fun createParametersFromFields(fields: List<Field>): List<Parameter> {
return fields.map { Parameter(Identifier("_" + it.identifier.name), it.`type`, true) }
}
private fun createInitStatementsFromFields(fields: List<Field>): List<Element> {
val result = ArrayList<Element>()
for (f : Field in fields) {
val identifierToKotlin: String? = f.identifier.toKotlin()
result.add(DummyStringExpression(identifierToKotlin + " = " + "_" + identifierToKotlin))
}
return result
}
private fun createPrimaryConstructorInvocation(s: String, fields: List<Field>, initializers: Map<String, String>): String {
return s + "(" + fields.map { initializers[it.identifier.toKotlin()] }.makeString(", ") + ")"
}
public open fun getDefaultInitializer(f: Field): String {
if (f.`type`.nullable) {
return "null"
}
else {
val typeToKotlin: String = f.`type`.toKotlin()
if (typeToKotlin.equals("Boolean"))
return "false"
if (typeToKotlin.equals("Char"))
return "' '"
if (typeToKotlin.equals("Double"))
return "0." + OperatorConventions.DOUBLE + "()"
if (typeToKotlin.equals("Float"))
return "0." + OperatorConventions.FLOAT + "()"
return "0"
}
}
private fun getPrimaryConstructorForThisCase(psiClass: PsiClass): PsiMethod? {
val tv = ThisVisitor()
psiClass.accept(tv)
return tv.getPrimaryConstructor()
}
public open fun isConstructorPrimary(constructor: PsiMethod): Boolean {
val parent = constructor.getParent()
if (parent is PsiClass) {
if (parent.getConstructors().size == 1) {
return true
}
else {
val c: PsiMethod? = getPrimaryConstructorForThisCase(parent)
if (c != null && c.hashCode() == constructor.hashCode()) {
return true
}
}
}
return false
}
private fun removeEmpty(statements: List<Element>): List<Element> {
return statements.filterNot { it == Statement.EMPTY_STATEMENT ||
it == Expression.EMPTY_EXPRESSION ||
it == Element.EMPTY_ELEMENT }
}
private fun isNotOpenMethod(method: PsiMethod): Boolean {
val parent = method.getParent()
if (parent is PsiClass) {
val parentModifierList: PsiModifierList? = parent.getModifierList()
if ((parentModifierList != null && parentModifierList.hasExplicitModifier(PsiModifier.FINAL)) || parent.isEnum()) {
return true
}
}
return false
}
private fun normalCase(method: PsiMethod): Boolean {
var counter: Int = 0
for (s : HierarchicalMethodSignature? in method.getHierarchicalMethodSignature().getSuperSignatures())
{
var containingClass: PsiClass? = s?.getMethod()?.getContainingClass()
var qualifiedName: String? = (if (containingClass != null)
containingClass?.getQualifiedName()
else
"")
if (qualifiedName != null && !qualifiedName.equals(JAVA_LANG_OBJECT))
{
counter++
}
}
return counter > 0
}
private fun isInheritFromObject(method: PsiMethod): Boolean {
var superSignatures: List<HierarchicalMethodSignature?> = method.getHierarchicalMethodSignature().getSuperSignatures()
for (s : HierarchicalMethodSignature? in superSignatures) {
var containingClass: PsiClass? = s?.getMethod()?.getContainingClass()
var qualifiedName: String? = (if (containingClass != null)
containingClass?.getQualifiedName()
else
"")
if (qualifiedName == JAVA_LANG_OBJECT) {
return true
}
}
return false
}
private fun isOverrideObjectDirect(method: PsiMethod): Boolean {
var superSignatures: List<HierarchicalMethodSignature?>? = method.getHierarchicalMethodSignature().getSuperSignatures()
if (superSignatures?.size()!! == 1)
{
val containingClass: PsiClass? = superSignatures?.get(0)?.getMethod()?.getContainingClass()
val qualifiedName: String? = (if (containingClass != null)
containingClass.getQualifiedName()
else
"")
if (qualifiedName == JAVA_LANG_OBJECT) {
return true
}
}
return false
}
private fun importsToImportList(imports: Array<PsiImportStatementBase>): List<Import> {
val result = ArrayList<Import>()
for (i : PsiImportStatementBase? in imports) {
if (i == null) continue
val anImport: Import = importToImport(i)
val name: String = anImport.name
if (!name.isEmpty() && !NOT_NULL_ANNOTATIONS.contains(name)) {
result.add(anImport)
}
}
return result
}
private fun importToImport(i: PsiImportStatementBase): Import {
val reference: PsiJavaCodeReferenceElement? = i.getImportReference()
if (reference != null) {
return Import(quoteKeywords(reference.getQualifiedName()!!) + ((if (i.isOnDemand())
".*"
else
"")))
}
return Import("")
}
public open fun identifierToIdentifier(identifier: PsiIdentifier?): Identifier {
if (identifier == null)
return Identifier.EMPTY_IDENTIFIER
return Identifier(identifier.getText()!!)
}
public open fun modifiersListToModifiersSet(modifierList: PsiModifierList?): MutableSet<Modifier> {
val modifiersSet: HashSet<Modifier> = hashSetOf()
if (modifierList != null) {
if (modifierList.hasExplicitModifier(PsiModifier.ABSTRACT))
modifiersSet.add(Modifier.ABSTRACT)
if (modifierList.hasModifierProperty(PsiModifier.FINAL))
modifiersSet.add(Modifier.FINAL)
if (modifierList.hasModifierProperty(PsiModifier.STATIC))
modifiersSet.add(Modifier.STATIC)
if (modifierList.hasExplicitModifier(PsiModifier.PUBLIC))
modifiersSet.add(Modifier.PUBLIC)
if (modifierList.hasExplicitModifier(PsiModifier.PROTECTED))
modifiersSet.add(Modifier.PROTECTED)
if (modifierList.hasExplicitModifier(PsiModifier.PACKAGE_LOCAL))
modifiersSet.add(Modifier.INTERNAL)
if (modifierList.hasExplicitModifier(PsiModifier.PRIVATE))
modifiersSet.add(Modifier.PRIVATE)
}
return modifiersSet
}
private fun isConversionNeeded(actual: PsiType?, expected: PsiType?): Boolean {
if (actual == null || expected == null) {
return false
}
val typeMap = HashMap<String, String>()
typeMap.put(JAVA_LANG_BYTE, "byte")
typeMap.put(JAVA_LANG_SHORT, "short")
typeMap.put(JAVA_LANG_INTEGER, "int")
typeMap.put(JAVA_LANG_LONG, "long")
typeMap.put(JAVA_LANG_FLOAT, "float")
typeMap.put(JAVA_LANG_DOUBLE, "double")
typeMap.put(JAVA_LANG_CHARACTER, "char")
val expectedStr: String? = expected.getCanonicalText()
val actualStr: String? = actual.getCanonicalText()
val o1: Boolean = expectedStr == typeMap[actualStr]
val o2: Boolean = actualStr == typeMap[expectedStr]
return actualStr != expectedStr && (!(o1 xor o2))
}
}
}
public fun createMainFunction(file: PsiFile): String {
val classNamesWithMains = ArrayList<Pair<String?, PsiMethod?>?>()
for (c : PsiClass? in (file as PsiJavaFile).getClasses()) {
var main: PsiMethod? = findMainMethod(c)
if (main != null) {
classNamesWithMains.add(Pair<String?, PsiMethod?>(c?.getName(), main))
}
}
if (classNamesWithMains.size() > 0) {
var className: String? = classNamesWithMains.get(0)?.getFirst()
return MessageFormat.format("fun main(args : Array<String>) = {0}.main(args as Array<String?>?)", className)
}
return ""
}
private fun findMainMethod(aClass: PsiClass?): PsiMethod? {
if (isMainClass(aClass)) {
val mainMethods: Array<PsiMethod>? = aClass?.findMethodsByName("main", false)
if (mainMethods != null) {
return findMainMethod(mainMethods)
}
}
return null
}
private fun isMainClass(psiClass: PsiClass?): Boolean {
if (psiClass == null || psiClass is PsiAnonymousClass)
return false
if (psiClass.isInterface())
return false
return psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC)
}
private fun findMainMethod(mainMethods: Array<PsiMethod>): PsiMethod? {
return mainMethods.find { isMainMethod(it) }
}
public fun isMainMethod(method: PsiMethod?): Boolean {
if (method == null || method.getContainingClass() == null)
return false
if (PsiType.VOID != method.getReturnType())
return false
if (!method.hasModifierProperty(PsiModifier.STATIC))
return false
if (!method.hasModifierProperty(PsiModifier.PUBLIC))
return false
val parameters: Array<PsiParameter>? = method.getParameterList().getParameters()
if (parameters?.size!! != 1)
return false
val `type`: PsiType? = parameters!![0].getType()
if (`type` !is PsiArrayType)
return false
val componentType: PsiType? = `type`.getComponentType()
return componentType?.equalsToText("java.lang.String")!!
}
public fun countWritingAccesses(element: PsiElement?, container: PsiElement?): Int {
var counter: Int = 0
if (container != null) {
val visitor: ReferenceCollector = ReferenceCollector()
container.accept(visitor)
for (e : PsiReferenceExpression in visitor.getCollectedReferences())
if (e.isReferenceTo(element) && PsiUtil.isAccessedForWriting(e)) {
counter++
}
}
return counter
}
open class ReferenceCollector(): JavaRecursiveElementVisitor() {
private val myCollectedReferences = ArrayList<PsiReferenceExpression>()
public open fun getCollectedReferences(): List<PsiReferenceExpression> {
return myCollectedReferences
}
public override fun visitReferenceExpression(expression: PsiReferenceExpression?): Unit {
super.visitReferenceExpression(expression)
if (expression != null) {
myCollectedReferences.add(expression)
}
}
}
public fun isReadOnly(element: PsiElement?, container: PsiElement?): Boolean {
return countWritingAccesses(element, container) == 0
}
public fun isAnnotatedAsNotNull(modifierList: PsiModifierList?): Boolean {
if (modifierList != null) {
val annotations: Array<PsiAnnotation> = modifierList.getAnnotations()
for (a : PsiAnnotation in annotations) {
val qualifiedName: String? = a.getQualifiedName()
if (qualifiedName != null && Converter.NOT_NULL_ANNOTATIONS.contains(qualifiedName)) {
return true
}
}
}
return false
}
public fun isDefinitelyNotNull(element: PsiElement?): Boolean = when(element) {
is PsiLiteralExpression -> element.getValue() != null
is PsiNewExpression -> true
else -> false
}
@@ -0,0 +1,8 @@
package org.jetbrains.jet.j2k
public enum class J2KConverterFlags {
FULLY_QUALIFIED_TYPE_NAMES
SKIP_BODIES
SKIP_NON_PUBLIC_MEMBERS
}
@@ -0,0 +1,144 @@
//package org.jetbrains.jet.j2k;
//
//import com.intellij.psi.PsiFile;
//import com.intellij.psi.PsiJavaFile;
//import org.apache.commons.cli.*;
//import org.jetbrains.annotations.NotNull;
//import org.jetbrains.annotations.Nullable;
//
//import java.io.File;
//import java.io.FileNotFoundException;
//import java.io.IOException;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.List;
//import java.util.logging.Logger;
//import java.util.regex.Pattern;
//
//import static org.apache.commons.io.FileUtils.readFileToString;
//import static org.apache.commons.io.FileUtils.writeStringToFile;
//
//@SuppressWarnings({"CallToPrintStackTrace", "UseOfSystemOutOrSystemErr"})
//public class JavaToKotlinCli {
// private static final Logger myLogger = Logger.getAnonymousLogger();
//
// private JavaToKotlinCli() {
// }
//
// public static void main(String[] args) {
// CommandLineParser parser = new BasicParser();
// Options options = new Options()
// .addOption("h", "help", false, "Print usage information")
// .addOption("f", "from", true, "Directory with Java sources")
// .addOption("t", "to", true, "Directory with Kotlin sources")
// .addOption("p", "public-only", false, "Only public and protected members")
// .addOption("fqn", "fqn", false, "Full qualified names")
// .addOption("d", "declarations-only", false, "Declarations only")
// ;
//
// try {
// CommandLine commandLine = parser.parse(options, args);
//
// if (commandLine.hasOption("help"))
// showHelpAndExit();
//
// if (commandLine.hasOption("from") && commandLine.hasOption("to")) {
// String from = commandLine.getOptionValue("from");
// String to = commandLine.getOptionValue("to");
//
// for (Option o : commandLine.getOptions()) {
// Converter.addFlag(o.getLongOpt());
// }
//
// if (!from.isEmpty() && !to.isEmpty())
// convertSourceTree(from, to);
// else
// showHelpAndExit();
// } else
// showHelpAndExit();
// } catch (ParseException e) {
// e.printStackTrace();
// }
// }
//
// @SuppressWarnings("ResultOfMethodCallIgnored")
// private static void convertSourceTree(String javaPath, String kotlinPath) {
// try {
// File javaDir = new File(javaPath);
// File kotlinDir = new File(kotlinPath);
//
// if (kotlinDir.exists())
// kotlinDir.delete();
//
// if (!kotlinDir.exists() && !kotlinDir.mkdir())
// myLogger.warning("Creation failed: " + kotlinDir.getAbsolutePath());
//
// for (File f : getJavaFiles(javaDir.getAbsolutePath())) {
// String relative = javaDir.toURI().relativize(f.toURI()).getPath().replace(".java", ".kt");
// File file = new File(kotlinPath, relative);
//
// if (file.exists())
// file.delete();
//
// if (f.isDirectory())
// if (!file.exists() && !file.mkdir())
// myLogger.warning("Creation failed: " + file.getAbsolutePath());
//
// if (f.isFile()) {
// writeStringToFile(file, fileToKotlin(f));
// }
// }
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
// @NotNull
// private static String fileToKotlin(File f) throws IOException {
// final String javaCode = readJavaFileToString(f);
// return generateKotlinCode(JavaToKotlinTranslator.createFile(JavaToKotlinTranslator.setUpJavaCoreEnvironment(), javaCode));
// }
//
// @NotNull
// private static String generateKotlinCode(@Nullable PsiFile file) {
// if (file != null && file instanceof PsiJavaFile) {
// JavaToKotlinTranslator.setClassIdentifiers(file);
// return JavaToKotlinTranslator.prettify(Converter.fileToFile((PsiJavaFile) file).toKotlin());
// }
// return "";
// }
//
// @NotNull
// private static String readJavaFileToString(@NotNull File javaFile) throws IOException {
// return Pattern.compile("\\s*/\\*.*\\*/", Pattern.DOTALL).matcher(readFileToString(javaFile)).replaceAll("");
// }
//
// private static void showHelpAndExit() {
// System.err.println("Usage: java -jar java2kotlin.jar -f <from> -t <to>");
// System.exit(1);
// }
//
// static public List<File> getJavaFiles(String startDirName) throws FileNotFoundException {
// return getJavaFiles(new File(startDirName));
// }
//
// private static List<File> getJavaFiles(File start) throws FileNotFoundException {
// List<File> result = new ArrayList<File>();
//
// if (start.isFile())
// return Arrays.asList(start);
//
// for (File file : Arrays.asList(start.listFiles())) {
// if ((file.isFile() && file.getName().endsWith(".java")) || file.isDirectory())
// result.add(file);
//
// if (file.isDirectory()) {
// List<File> deeperList = getJavaFiles(file);
// result.addAll(deeperList);
// }
// }
// return result;
// }
//}
@@ -0,0 +1,160 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.j2k;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.core.JavaCoreProjectEnvironment;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.Disposable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.PsiJavaFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.j2k.visitors.ClassVisitor;
import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLClassLoader;
public class JavaToKotlinTranslator {
private JavaToKotlinTranslator() {
}
private static final Converter CONVERTER = new Converter();
@Nullable
private static PsiFile createFile(@NotNull String text) {
JavaCoreProjectEnvironment javaCoreEnvironment = setUpJavaCoreEnvironment();
return PsiFileFactory.getInstance(javaCoreEnvironment.getProject()).createFileFromText(
"test.java", JavaLanguage.INSTANCE, text
);
}
@Nullable
static PsiFile createFile(@NotNull JavaCoreProjectEnvironment javaCoreEnvironment, @NotNull String text) {
return PsiFileFactory.getInstance(javaCoreEnvironment.getProject()).createFileFromText(
"test.java", JavaLanguage.INSTANCE, text
);
}
@NotNull
static JavaCoreProjectEnvironment setUpJavaCoreEnvironment() {
Disposable parentDisposable = new Disposable() {
@Override
public void dispose() {
}
};
JavaCoreApplicationEnvironment applicationEnvironment = new JavaCoreApplicationEnvironment(parentDisposable);
JavaCoreProjectEnvironment javaCoreEnvironment = new JavaCoreProjectEnvironment(parentDisposable, applicationEnvironment);
javaCoreEnvironment.addJarToClassPath(PathUtil.findRtJar());
File annotations = findAnnotations();
if (annotations != null && annotations.exists()) {
javaCoreEnvironment.addJarToClassPath(annotations);
}
return javaCoreEnvironment;
}
@NotNull
static String prettify(@Nullable String code) {
if (code == null) {
return "";
}
return code
.trim()
.replaceAll("\r\n", "\n")
.replaceAll(" \n", "\n")
.replaceAll("\n ", "\n")
.replaceAll("\n+", "\n")
.replaceAll(" +", " ")
.trim()
;
}
@Nullable
private static File findAnnotations() {
ClassLoader classLoader = JavaToKotlinTranslator.class.getClassLoader();
while (classLoader != null) {
if (classLoader instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) classLoader;
for (URL url : loader.getURLs())
if ("file".equals(url.getProtocol()) && url.getFile().endsWith("/annotations.jar")) {
return new File(url.getFile());
}
}
classLoader = classLoader.getParent();
}
return null;
}
static void setClassIdentifiers(@NotNull Converter converter, @NotNull PsiElement psiFile) {
ClassVisitor c = new ClassVisitor();
psiFile.accept(c);
converter.clearClassIdentifiers();
converter.setClassIdentifiers(c.getClassIdentifiers());
}
@NotNull
static String generateKotlinCode(@NotNull String javaCode) {
PsiFile file = createFile(javaCode);
if (file != null && file instanceof PsiJavaFile) {
setClassIdentifiers(CONVERTER, file);
return prettify(CONVERTER.fileToFile((PsiJavaFile) file).toKotlin());
}
return "";
}
@NotNull
static String generateKotlinCodeWithCompatibilityImport(@NotNull String javaCode) {
PsiFile file = createFile(javaCode);
if (file != null && file instanceof PsiJavaFile) {
setClassIdentifiers(CONVERTER, file);
return prettify(CONVERTER.fileToFileWithCompatibilityImport((PsiJavaFile) file).toKotlin());
}
return "";
}
public static void main(@NotNull String[] args) throws IOException {
//noinspection UseOfSystemOutOrSystemErr
final PrintStream out = System.out;
if (args.length == 1) {
String kotlinCode = "";
try {
kotlinCode = generateKotlinCode(args[0]);
} catch (Exception e) {
out.println("EXCEPTION: " + e.getMessage());
}
if (kotlinCode.isEmpty()) {
out.println("EXCEPTION: generated code is empty.");
}
else {
out.println(kotlinCode);
}
}
else {
out.println("EXCEPTION: wrong number of arguments (should be 1).");
}
}
public static String translateToKotlin(String code) {
return generateKotlinCode(code);
}
}
@@ -0,0 +1,20 @@
package org.jetbrains.jet.j2k
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public open class SetupJavaCoreEnvironmentException(s: String?): RuntimeException() {
}
@@ -0,0 +1,43 @@
//package org.jetbrains.jet.j2k.actions
//
//import com.intellij.openapi.actionSystem.AnAction
//import com.intellij.openapi.actionSystem.AnActionEvent
//import org.jetbrains.jet.j2k.Converter
//import com.intellij.openapi.actionSystem.PlatformDataKeys
//import com.intellij.openapi.actionSystem.LangDataKeys
//import com.intellij.psi.PsiJavaFile
//import com.intellij.openapi.util.io.FileUtil
//import com.intellij.openapi.fileEditor.FileDocumentManager
//import com.intellij.psi.PsiDocumentManager
//import com.intellij.openapi.command.WriteCommandAction
//import com.intellij.openapi.application.ApplicationManager
//import com.intellij.psi.codeStyle.CodeStyleManager
//
//class JavaToKotlinAction(): AnAction() {
// public override fun actionPerformed(event : AnActionEvent?) {
// val converter = Converter()
// val psiFile = event!!.getData(LangDataKeys.PSI_FILE)!!
// ApplicationManager.getApplication()?.runWriteAction(object : Runnable {
// public override fun run() {
// val result = converter.fileToFile(psiFile as PsiJavaFile).toKotlin()
// val newName = FileUtil.getNameWithoutExtension(psiFile.getName()) + ".kt"
// val newFile = psiFile.getContainingDirectory()?.createFile(newName)!!
// val project = psiFile.getProject()
// val psiDocumentManager = PsiDocumentManager.getInstance(project)!!
// val document = psiDocumentManager.getDocument(newFile)!!
// document.setText(result)
// psiDocumentManager.doPostponedOperationsAndUnblockDocument(document)
// psiDocumentManager.commitDocument(document)
// CodeStyleManager.getInstance(project)!!.reformat(newFile)
// psiFile.setName(psiFile.getName() + ".old")
// newFile.navigate(true)
// }
// })
// }
//
//
// public override fun update(e : AnActionEvent?) {
// val psiFile = e!!.getData(LangDataKeys.PSI_FILE)
// e.getPresentation().setEnabled(psiFile is PsiJavaFile)
// }
//}
@@ -0,0 +1,17 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.types.Type
import java.util.Collections
public open class AnonymousClass(converter : Converter, members : List<Node>)
: Class(converter,
Identifier("anonClass"),
arrayList(),
Collections.emptySet<Modifier>(),
Collections.emptyList<Element>(),
Collections.emptyList<Type>(),
Collections.emptyList<Expression>(),
Collections.emptyList<Type>(), members) {
public override fun toKotlin() = bodyToKotlin()
}
@@ -0,0 +1,60 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import java.util.*
import com.intellij.openapi.util.text.StringUtil
public open class ArrayInitializerExpression(val `type` : Type, val initializers : List<Expression>) : Expression() {
public override fun toKotlin() : String {
return createArrayFunction() + "(" + createInitializers() + ")"
}
private fun createInitializers(): String {
return initializers.map { explicitConvertIfNeeded(it) }.makeString(", ")
}
private fun createArrayFunction() : String {
var sType : String? = innerTypeStr()
if (Node.PRIMITIVE_TYPES.contains(sType)) {
return sType + "Array"
}
return StringUtil.decapitalize(`type`.convertedToNotNull().toKotlin())!!
}
private fun innerTypeStr() : String {
return `type`.convertedToNotNull().toKotlin().replace("Array", "").toLowerCase()
}
private fun explicitConvertIfNeeded(i : Expression) : String {
val doubleOrFloatTypes = hashSet("double", "float", "java.lang.double", "java.lang.float")
val afterReplace : String = innerTypeStr().replace(">", "").replace("<", "").replace("?", "")
if (doubleOrFloatTypes.contains(afterReplace))
{
if (i is LiteralExpression) {
if (i.toKotlin().contains(".")) {
return i.toKotlin()
}
return i.toKotlin() + ".0"
}
return "(" + i.toKotlin() + ")" + getConversion(afterReplace)
}
return i.toKotlin()
}
class object {
private open fun getConversion(afterReplace : String) : String {
if (afterReplace.contains("double"))
return "." + OperatorConventions.DOUBLE + "()"
if (afterReplace.contains("float"))
return "." + OperatorConventions.FLOAT + "()"
return ""
}
}
}
@@ -0,0 +1,55 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.ArrayType
import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.j2k.ast.types.PrimitiveType
public open class ArrayWithoutInitializationExpression(val `type` : Type, val expressions : List<Expression>) : Expression() {
public override fun toKotlin() : String {
if (`type` is ArrayType) {
return constructInnerType(`type`, expressions)
}
return getConstructorName(`type`, expressions.size() != 0)
}
private fun constructInnerType(hostType : ArrayType, expressions: List<Expression>) : String {
if (expressions.size() == 1) {
return oneDim(hostType, expressions[0])
}
val innerType = hostType.elementType
if (expressions.size() > 1 && innerType is ArrayType) {
return oneDim(hostType, expressions[0], "{" + constructInnerType(innerType, expressions.subList(1, expressions.size())) + "}")
}
return getConstructorName(hostType, expressions.size() != 0)
}
class object {
private open fun oneDim(`type` : Type, size : Expression) : String {
return oneDim(`type`, size, "")
}
private open fun oneDim(`type` : Type, size : Expression, init : String) : String {
return getConstructorName(`type`, !init.isEmpty()) + "(" + size.toKotlin() + init.withPrefix(", ") + ")"
}
private open fun getConstructorName(`type` : Type, hasInit : Boolean) : String {
return if (`type` is ArrayType)
when (`type`.elementType) {
is PrimitiveType ->
`type`.convertedToNotNull().toKotlin()
is ArrayType ->
if (hasInit)
`type`.convertedToNotNull().toKotlin()
else
"arrayOfNulls<" + `type`.elementType.toKotlin() + ">"
else ->
"arrayOfNulls<" + `type`.elementType.toKotlin() + ">"
}
else
`type`.convertedToNotNull().toKotlin()
}
}
}
@@ -0,0 +1,12 @@
package org.jetbrains.jet.j2k.ast
public open class AssertStatement(val condition : Expression, val detail : Expression) : Statement() {
public override fun toKotlin() : String {
var detail : String? = (if (detail != Expression.EMPTY_EXPRESSION)
"(" + detail.toKotlin() + ")"
else
"")
return "assert" + detail + " {" + condition.toKotlin() + "}"
}
}
@@ -0,0 +1,21 @@
package org.jetbrains.jet.j2k.ast
import java.util.LinkedList
public open class Block(val statements: List<Element>, val notEmpty: Boolean = false): Statement() {
public override fun isEmpty(): Boolean {
return !notEmpty && (statements.size() == 0 || statements.all { it == Statement.EMPTY_STATEMENT })
}
public override fun toKotlin(): String {
if (!isEmpty()) {
return "{\n" + statements.toKotlin("\n") + "\n}"
}
return ""
}
class object {
public val EMPTY_BLOCK: Block = Block(arrayList())
}
}
@@ -0,0 +1,16 @@
package org.jetbrains.jet.j2k.ast
public open class CallChainExpression(val expression : Expression, val identifier : Expression) : Expression() {
public override fun isNullable() : Boolean {
if (!expression.isEmpty() && expression.isNullable()) return true
return identifier.isNullable()
}
public override fun toKotlin() : String {
if (!expression.isEmpty()) {
return expression.toKotlin() + (if (expression.isNullable()) "?." else ".") + identifier.toKotlin()
}
return identifier.toKotlin()
}
}
+152
View File
@@ -0,0 +1,152 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.annotations.Nullable
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.J2KConverterFlags
import org.jetbrains.jet.j2k.ast.types.ClassType
import org.jetbrains.jet.j2k.ast.types.Type
import java.util.HashSet
import java.util.LinkedList
import java.util.ArrayList
public open class Class(converter : Converter,
val name : Identifier,
val docComments: List<Node>,
modifiers : Set<Modifier>,
val typeParameters : List<Element>,
val extendsTypes : List<Type>,
val baseClassParams : List<Expression>,
val implementsTypes : List<Type>,
members : List<Node>) : Member(modifiers) {
val members = getMembers(members, converter)
open val TYPE: String
get() = "class"
private fun getPrimaryConstructor() : Constructor? {
return members.find { it is Constructor && it.isPrimary } as Constructor?
}
open fun primaryConstructorSignatureToKotlin() : String {
val maybeConstructor : Constructor? = getPrimaryConstructor()
return if (maybeConstructor != null) maybeConstructor.primarySignatureToKotlin() else "()"
}
open fun primaryConstructorBodyToKotlin() : String? {
val maybeConstructor : Constructor? = getPrimaryConstructor()
if (maybeConstructor != null && !(maybeConstructor.block?.isEmpty() ?: true)) {
return maybeConstructor.primaryBodyToKotlin()
}
return ""
}
private fun hasWhere() : Boolean = typeParameters.any { it is TypeParameter && it.hasWhere() }
open fun typeParameterWhereToKotlin() : String {
if (hasWhere()) {
val wheres = typeParameters.filter { it is TypeParameter }.map { (it as TypeParameter).getWhereToKotlin() }
return " where " + wheres.makeString(", ") + " "
}
return ""
}
open fun membersExceptConstructors() : List<Node> = members.filterNot { it is Constructor }
open fun secondaryConstructorsAsStaticInitFunction() : List<Function> {
return members.filter { it is Constructor && !it.isPrimary }.map { constructorToInit(it as Function) }
}
private fun constructorToInit(f: Function): Function {
val modifiers = HashSet<Modifier>(f.modifiers)
modifiers.add(Modifier.STATIC)
val statements = ArrayList<Element>(f.block?.statements ?: listOf())
statements.add(ReturnStatement(Identifier("__")))
val block = Block(statements)
val constructorTypeParameters = ArrayList<Element>()
constructorTypeParameters.addAll(typeParameters)
constructorTypeParameters.addAll(f.typeParameters)
return Function(Identifier("init"), arrayList(), modifiers, ClassType(name, constructorTypeParameters, false),
constructorTypeParameters, f.params, block)
}
open fun typeParametersToKotlin() : String = typeParameters.toKotlin(", ", "<", ">")
open fun baseClassSignatureWithParams() : List<String> {
if (TYPE.equals("class") && extendsTypes.size() == 1) {
val baseParams = baseClassParams.toKotlin(", ")
return arrayList(extendsTypes[0].toKotlin() + "(" + baseParams + ")")
}
return extendsTypes.map { it.toKotlin() }
}
open fun implementTypesToKotlin() : String {
val allTypes = ArrayList<String>()
allTypes.addAll(baseClassSignatureWithParams())
allTypes.addAll(implementsTypes.map { it.toKotlin() })
return if (allTypes.size() == 0)
""
else
" : " + allTypes.makeString(", ")
}
open fun modifiersToKotlin() : String {
val modifierList = ArrayList<Modifier>()
val modifier = accessModifier()
if (modifier != null) {
modifierList.add(modifier)
}
if (needAbstractModifier()) {
modifierList.add(Modifier.ABSTRACT)
}
if (needOpenModifier()) {
modifierList.add(Modifier.OPEN)
}
return modifierList.toKotlin()
}
open fun needOpenModifier() = !modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.ABSTRACT)
open fun needAbstractModifier() = isAbstract()
open fun bodyToKotlin() : String {
return " {\n" + getNonStatic(membersExceptConstructors()).toKotlin("\n") + "\n" + primaryConstructorBodyToKotlin() + "\n" + classObjectToKotlin() + "\n}"
}
private fun classObjectToKotlin() : String {
val staticMembers = ArrayList<Node>()
staticMembers.addAll(secondaryConstructorsAsStaticInitFunction())
staticMembers.addAll(getStatic(membersExceptConstructors()))
return staticMembers.toKotlin("\n", "class object {\n", "\n}")
}
public override fun toKotlin() : String =
docComments.toKotlin("\n", "", "\n") +
modifiersToKotlin() +
TYPE + " " + name.toKotlin() +
typeParametersToKotlin() +
primaryConstructorSignatureToKotlin() +
implementTypesToKotlin() +
typeParameterWhereToKotlin() +
bodyToKotlin()
class object {
open fun getMembers(members : List<Node>, converter : Converter) : List<Node> {
if (converter.hasFlag(J2KConverterFlags.SKIP_NON_PUBLIC_MEMBERS)) {
return members.filter { it is Comment ||
(it as Member).accessModifier() == Modifier.PUBLIC ||
(it as Member).accessModifier() == Modifier.PROTECTED }
}
return members
}
private fun getStatic(members : List<Node>) : List<Node> {
return members.filter { it is Member && it.isStatic() }
}
private fun getNonStatic(members : List<Node>) : List<Node> {
return members.filterNot { it is Member && it.isStatic() }
}
}
}
@@ -0,0 +1,21 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class Constructor(identifier : Identifier,
docComments: List<Node>,
modifiers : Set<Modifier>,
`type` : Type,
typeParameters : List<Element>,
params : Element,
block : Block,
val isPrimary : Boolean) : Function(identifier, docComments, modifiers, `type`, typeParameters, params, block) {
public open fun primarySignatureToKotlin() : String {
return "(" + params.toKotlin() + ")"
}
public open fun primaryBodyToKotlin() : String {
return block!!.toKotlin()
}
}
@@ -0,0 +1,6 @@
package org.jetbrains.jet.j2k.ast
public open class DummyStringExpression(val string: String): Expression() {
public override fun toKotlin(): String = string
}
@@ -0,0 +1,17 @@
package org.jetbrains.jet.j2k.ast
public abstract class Element(): Node() {
public open fun isEmpty(): Boolean = false
class object {
public val EMPTY_ELEMENT: Element = object : Element() {
override fun toKotlin() = ""
override fun isEmpty() = true
}
}
}
public class Comment(val text: String): Element() {
override fun toKotlin() = text
}
+35
View File
@@ -0,0 +1,35 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.types.Type
public open class Enum(converter : Converter,
name : Identifier,
docComments: List<Node>,
modifiers : Set<Modifier>,
typeParameters : List<Element>,
extendsTypes : List<Type>,
baseClassParams : List<Expression>,
implementsTypes : List<Type>,
members : List<Node>) : Class(converter, name, docComments, modifiers, typeParameters,
extendsTypes, baseClassParams, implementsTypes, members) {
override fun primaryConstructorSignatureToKotlin() : String {
val s : String = super.primaryConstructorSignatureToKotlin()
return if (s.equals("()")) "" else s
}
override fun needOpenModifier() = false
public override fun toKotlin() : String {
val primaryConstructorBody = primaryConstructorBodyToKotlin() ?: ""
return modifiersToKotlin() +
"enum class " + name.toKotlin() +
primaryConstructorSignatureToKotlin() +
typeParametersToKotlin() +
implementTypesToKotlin() +
" {\n" + membersExceptConstructors().toKotlin("\n") + "\n" +
(if (primaryConstructorBody.isEmpty()) "" else primaryConstructorBody + "\n") +
"}"
}
}
@@ -0,0 +1,20 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class EnumConstant(identifier : Identifier,
docComments: List<Node>,
modifiers : Set<Modifier>,
`type` : Type,
params : Element) : Field(identifier, docComments, modifiers, `type`.convertedToNotNull(), params, 0) {
public override fun toKotlin() : String {
if (initializer.toKotlin().isEmpty()) {
return identifier.toKotlin()
}
return identifier.toKotlin() + " : " + `type`.toKotlin() + "(" + initializer.toKotlin() + ")"
}
}
@@ -0,0 +1,15 @@
package org.jetbrains.jet.j2k.ast
public abstract class Expression(): Statement() {
public open fun isNullable(): Boolean {
return false
}
class object {
public val EMPTY_EXPRESSION: Expression = object: Expression() {
public override fun toKotlin()= ""
public override fun isEmpty() = true
}
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class ExpressionList(val expressions: List<Expression>): Expression() {
public override fun toKotlin(): String = expressions.map { it.toKotlin() }.makeString(", ")
}
@@ -0,0 +1,58 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class ArrayAccessExpression(val expression: Expression, val index: Expression, val lvalue: Boolean) : Expression() {
override fun toKotlin() = expression.toKotlin() +
(if (!lvalue && expression.isNullable()) "!!" else "") +
"[" + index.toKotlin() + "]"
}
public open class AssignmentExpression(val left : Expression, val right : Expression, val op : String) : Expression() {
override fun toKotlin() = left.toKotlin() + " "+ op + " "+ right.toKotlin()
}
public class BangBangExpression(val expr: Expression): Expression() {
override fun toKotlin() = expr.toKotlin() + "!!"
}
public open class BinaryExpression(val left: Expression, val right: Expression, val op: String): Expression() {
override fun toKotlin() = left.toKotlin() + " " + op + " " + right.toKotlin()
}
public open class ClassObjectAccessExpression(val typeElement: TypeElement): Expression() {
override fun toKotlin() = "javaClass<" + typeElement.toKotlinNotNull() + ">()"
}
public open class IsOperator(val expression: Expression, val typeElement: TypeElement): Expression() {
override fun toKotlin() = expression.toKotlin() + " is " + typeElement.toKotlinNotNull()
}
public open class TypeCastExpression(val `type` : Type, val expression : Expression) : Expression() {
override fun toKotlin() = "(" + expression.toKotlin() + " as " + `type`.toKotlin() + ")"
}
public open class LiteralExpression(val literalText: String): Expression() {
override fun toKotlin() = literalText
}
public open class ParenthesizedExpression(val expression : Expression) : Expression() {
override fun toKotlin() = "(" + expression.toKotlin() + ")"
}
public open class PrefixOperator(val op: String, val expression: Expression): Expression() {
override fun toKotlin() = op + expression.toKotlin()
override fun isNullable() = expression.isNullable()
}
public open class PostfixOperator(val op: String, val expression: Expression): Expression() {
override fun toKotlin() = expression.toKotlin() + op
}
public open class ThisExpression(val identifier: Identifier) : Expression() {
override fun toKotlin() = "this" + identifier.withPrefix("@")
}
public open class SuperExpression(val identifier : Identifier) : Expression() {
override fun toKotlin() = "super" + identifier.withPrefix("@")
}
@@ -0,0 +1,44 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
import java.util.LinkedList
import org.jetbrains.jet.j2k.Converter
import java.util.ArrayList
public open class Field(val identifier : Identifier,
val docComments: List<Node>,
modifiers : Set<Modifier>,
val `type` : Type,
val initializer : Element,
val writingAccesses : Int) : Member(modifiers) {
open fun modifiersToKotlin() : String {
val modifierList = ArrayList<Modifier>()
if (isAbstract()) {
modifierList.add(Modifier.ABSTRACT)
}
val modifier = accessModifier()
if (modifier != null) {
modifierList.add(modifier)
}
return modifierList.toKotlin() + (if (isVal()) "val " else "var ")
}
public open fun isVal() : Boolean = modifiers.contains(Modifier.FINAL)
public override fun isStatic() : Boolean = modifiers.contains(Modifier.STATIC)
public override fun toKotlin() : String {
val declaration : String = docComments.toKotlin("\n", "", "\n") +
modifiersToKotlin() + identifier.toKotlin() + " : " + `type`.toKotlin()
if (initializer.isEmpty()) {
return declaration + ((if (isVal() && !isStatic() && writingAccesses != 0)
""
else
" = " + Converter.getDefaultInitializer(this)))
}
return declaration + " = " + initializer.toKotlin()
}
}
+16
View File
@@ -0,0 +1,16 @@
package org.jetbrains.jet.j2k.ast
public open class File(val packageName: String,
val imports: MutableList<Import>,
val body: MutableList<Node>,
val mainFunction: String): Node() {
public override fun toKotlin(): String {
val common: String = imports.toKotlin("\n") + "\n\n" + body.toKotlin("\n") + "\n" + mainFunction
if (packageName.isEmpty()) {
return common
}
return "package " + packageName + "\n" + common
}
}
@@ -0,0 +1,71 @@
package org.jetbrains.jet.j2k.ast
import java.util.LinkedList
import org.jetbrains.jet.j2k.ast.types.Type
import java.util.ArrayList
public open class Function(val name : Identifier,
val docComments: List<Node>,
modifiers : Set<Modifier>,
val `type` : Type,
val typeParameters : List<Element>,
val params : Element,
var block : Block?) : Member(modifiers) {
private fun typeParametersToKotlin() : String {
return (if (typeParameters.size() > 0)
"<" + typeParameters.map { it.toKotlin() }.makeString(", ") + ">"
else
"")
}
private fun hasWhere() : Boolean = typeParameters.any { it is TypeParameter && it.hasWhere() }
private fun typeParameterWhereToKotlin() : String {
if (hasWhere())
{
val wheres = typeParameters.filter { it is TypeParameter }.map { ((it as TypeParameter).getWhereToKotlin() )}
return " where " + wheres.makeString(", ") + " "
}
return ""
}
open fun modifiersToKotlin() : String {
val modifierList = ArrayList<Modifier>()
val accessModifier = accessModifier()
if (accessModifier != null) {
modifierList.add(accessModifier)
}
if (isAbstract()) {
modifierList.add(Modifier.ABSTRACT)
}
if (modifiers.contains(Modifier.OVERRIDE)) {
modifierList.add(Modifier.OVERRIDE)
}
if (!modifiers.contains(Modifier.ABSTRACT) &&
!modifiers.contains(Modifier.OVERRIDE) &&
!modifiers.contains(Modifier.FINAL) &&
!modifiers.contains(Modifier.PRIVATE)) {
modifierList.add(Modifier.OPEN)
}
if (modifiers.contains(Modifier.NOT_OPEN)) {
modifierList.remove(Modifier.OPEN)
}
return modifierList.toKotlin()
}
public override fun toKotlin() : String {
return docComments.toKotlin("\n", "", "\n") +
modifiersToKotlin() +
"fun " + name.toKotlin() +
typeParametersToKotlin() +
"(" + params.toKotlin() + ") : " +
`type`.toKotlin() + " "+ typeParameterWhereToKotlin() +
block?.toKotlin()
}
}
@@ -0,0 +1,31 @@
package org.jetbrains.jet.j2k.ast
public open class Identifier(val name: String,
val myNullable: Boolean = true,
val quotingNeeded: Boolean = true): Expression() {
public override fun isEmpty() = name.length() == 0
private open fun ifNeedQuote(): String {
if (quotingNeeded && (ONLY_KOTLIN_KEYWORDS.contains(name)) || name.contains("$")) {
return quote(name)
}
return name
}
public override fun toKotlin(): String = ifNeedQuote()
public override fun isNullable(): Boolean = myNullable
class object {
public val EMPTY_IDENTIFIER: Identifier = Identifier("")
private open fun quote(str: String): String {
return "`" + str + "`"
}
public val ONLY_KOTLIN_KEYWORDS: Set<String> = hashSet(
"package", "as", "type", "val", "var", "fun", "is", "in", "object", "when", "trait", "This"
);
}
}
@@ -0,0 +1,6 @@
package org.jetbrains.jet.j2k.ast
public open class Import(val name: String): Node() {
public override fun toKotlin() = "import " + name
}
@@ -0,0 +1,8 @@
package org.jetbrains.jet.j2k.ast
public open class Initializer(val block : Block, modifiers : Set<Modifier>) : Member(modifiers) {
public override fun toKotlin() : String {
return block.toKotlin()
}
}
@@ -0,0 +1,19 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class LocalVariable(val identifier: Identifier,
val modifiersSet: Set<Modifier>,
val `type`: Type,
val initializer: Expression): Expression() {
public open fun hasModifier(modifier: Modifier): Boolean = modifiersSet.contains(modifier)
public override fun toKotlin(): String {
if (initializer.isEmpty()) {
return identifier.toKotlin() + " : " + `type`.toKotlin()
}
return identifier.toKotlin() + " : " + `type`.toKotlin() + " = " + initializer.toKotlin()
}
}
@@ -0,0 +1,10 @@
package org.jetbrains.jet.j2k.ast
public abstract class Member(val modifiers : Set<Modifier>) : Node() {
open fun accessModifier() : Modifier? {
return modifiers.find { m -> m == Modifier.PUBLIC || m == Modifier.PROTECTED || m == Modifier.PRIVATE }
}
public open fun isAbstract() : Boolean = modifiers.contains(Modifier.ABSTRACT)
public open fun isStatic() : Boolean = modifiers.contains(Modifier.STATIC)
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class MethodCallExpression(val methodCall: Expression,
val arguments: List<Expression>,
val typeParameters: List<Type>,
val resultIsNullable: Boolean = false): Expression() {
public override fun isNullable(): Boolean = methodCall.isNullable() || resultIsNullable
public override fun toKotlin(): String {
val typeParamsToKotlin: String = typeParameters.toKotlin(", ", "<", ">")
val argumentsMapped = arguments.map { it.toKotlin() }
return methodCall.toKotlin() + typeParamsToKotlin + "(" + argumentsMapped.makeString(", ") + ")"
}
class object {
fun build(receiver: Expression, methodName: String, arguments: List<Expression> = arrayList()): MethodCallExpression {
return MethodCallExpression(CallChainExpression(receiver, Identifier(methodName, false)),
arguments,
arrayList(), false)
}
}
}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.j2k.ast
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public enum class Modifier(val name: String) {
PUBLIC: Modifier("public")
PROTECTED: Modifier("protected")
PRIVATE: Modifier("private")
INTERNAL: Modifier("internal")
STATIC: Modifier("static")
ABSTRACT: Modifier("abstract")
FINAL: Modifier("final")
OPEN: Modifier("open")
NOT_OPEN: Modifier("not open")
OVERRIDE: Modifier("override")
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.annotations.Nullable
public open class NewClassExpression(val name: Element,
val arguments: List<Expression>,
val qualifier: Expression = Expression.EMPTY_EXPRESSION,
val anonymousClass: AnonymousClass? = null): Expression() {
public override fun toKotlin(): String {
val callOperator: String? = (if (qualifier.isNullable())
"?."
else
".")
val qualifier: String? = (if (qualifier.isEmpty())
""
else
qualifier.toKotlin() + callOperator)
val appliedArguments: String = arguments.toKotlin(", ")
return (if (anonymousClass != null)
"object : " + qualifier + name.toKotlin() + "(" + appliedArguments + ")" + anonymousClass.toKotlin()
else
qualifier + name.toKotlin() + "(" + appliedArguments + ")")
}
}
+11
View File
@@ -0,0 +1,11 @@
package org.jetbrains.jet.j2k.ast
public abstract class Node() {
public abstract fun toKotlin(): String
class object {
public val PRIMITIVE_TYPES: Set<String> = hashSet(
"double", "float", "long", "int", "short", "byte", "boolean", "char")
}
}
@@ -0,0 +1,18 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.j2k.ast.types.VarArg
public open class Parameter(val identifier : Identifier, val `type` : Type, val readOnly: Boolean = true) : Expression() {
public override fun toKotlin() : String {
val vararg : String = (if (`type` is VarArg)
"vararg "
else
"")
val `var` : String? = (if (readOnly)
""
else
"var ")
return vararg + `var` + identifier.toKotlin() + " : " + `type`.toKotlin()
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.j2k.ast
public open class ParameterList(val parameters : List<Parameter>) : Expression() {
public override fun toKotlin() = parameters.map { it.toKotlin() }.makeString(", ")
}
@@ -0,0 +1,9 @@
package org.jetbrains.jet.j2k.ast
public open class PolyadicExpression(val expressions: List<Expression>, val token: String): Expression() {
public override fun toKotlin(): String {
val expressionsWithConversions = expressions.map { it.toKotlin() }
return expressionsWithConversions.makeString(" " + token + " ")
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class ReferenceElement(val reference : Identifier, val types : List<Type>) : Element() {
public override fun toKotlin() = reference.toKotlin() + types.toKotlin(", ", "<", ">")
}
@@ -0,0 +1,132 @@
package org.jetbrains.jet.j2k.ast
public abstract class Statement(): Element() {
class object {
public val EMPTY_STATEMENT: Statement = object : Statement() {
public override fun toKotlin() = ""
}
}
}
public open class DeclarationStatement(val elements: List<Element>): Statement() {
public override fun toKotlin(): String {
return elements.filter { it is LocalVariable }.map { convertDeclaration(it as LocalVariable) }.makeString("\n")
}
private fun convertDeclaration(v: LocalVariable): String {
val varKeyword: String? = (if (v.hasModifier(Modifier.FINAL))
"val"
else
"var")
return varKeyword + " " + v.toKotlin()
}
}
public open class ExpressionListStatement(val expressions: List<Expression>): Expression() {
public override fun toKotlin() = expressions.toKotlin("\n")
}
public open class LabelStatement(val name: Identifier, val statement: Element): Statement() {
public override fun toKotlin(): String = "@" + name.toKotlin() + " " + statement.toKotlin()
}
public open class ReturnStatement(val expression: Expression): Statement() {
public override fun toKotlin() = "return " + expression.toKotlin()
}
public open class IfStatement(val condition: Expression,
val thenStatement: Element,
val elseStatement: Element): Expression() {
public override fun toKotlin(): String {
val result: String = "if (" + condition.toKotlin() + ")\n" + thenStatement.toKotlin() + "\n"
if (elseStatement != Statement.EMPTY_STATEMENT) {
return result + "else\n" + elseStatement.toKotlin()
}
return result
}
}
// Loops --------------------------------------------------------------------------------------------------
public open class WhileStatement(val condition: Expression, val body: Element): Statement() {
public override fun toKotlin() = "while (" + condition.toKotlin() + ")\n" + body.toKotlin()
}
public open class DoWhileStatement(condition: Expression, body: Element): WhileStatement(condition, body) {
public override fun toKotlin() = "do\n" + body.toKotlin() + "\nwhile (" + condition.toKotlin() + ")"
}
public open class ForeachStatement(val variable: Parameter,
val expression: Expression,
val body: Element): Statement() {
public override fun toKotlin() = "for (" + variable.toKotlin() + " in " +
expression.toKotlin() + ")\n" + body.toKotlin()
}
public open class ForeachWithRangeStatement(val identifier: Identifier,
val start: Expression,
val end: Expression,
val body: Element): Statement() {
public override fun toKotlin() = "for (" + identifier.toKotlin() + " in " +
start.toKotlin() + ".." + end.toKotlin() + ") " + body.toKotlin()
}
public open class BreakStatement(val label: Identifier = Identifier.EMPTY_IDENTIFIER) : Statement() {
public override fun toKotlin() = "break" + label.withPrefix("@")
}
public open class ContinueStatement(val label: Identifier = Identifier.EMPTY_IDENTIFIER): Statement() {
public override fun toKotlin() = "continue" + label.withPrefix("@")
}
// Exceptions ----------------------------------------------------------------------------------------------
public open class TryStatement(val block: Block, val catches: List<CatchStatement>, val finallyBlock: Block): Statement() {
public override fun toKotlin(): String {
return "try\n" + block.toKotlin() + "\n" + catches.toKotlin("\n") + "\n" + (if (finallyBlock.isEmpty())
""
else
"finally\n" + finallyBlock.toKotlin())
}
}
public open class ThrowStatement(val expression: Expression): Expression() {
public override fun toKotlin() = "throw " + expression.toKotlin()
}
public open class CatchStatement(val variable: Parameter, val block: Block): Statement() {
public override fun toKotlin(): String = "catch (" + variable.toKotlin() + ") " + block.toKotlin()
}
// Switch --------------------------------------------------------------------------------------------------
public open class SwitchContainer(val expression: Expression, val caseContainers: List<CaseContainer>): Statement() {
public override fun toKotlin() = "when (" + expression.toKotlin() + ") {\n" + caseContainers.toKotlin("\n") + "\n}"
}
public open class CaseContainer(val caseStatement: List<Element>, statements: List<Element>): Statement() {
private val myBlock: Block
{
val newStatements = statements.filterNot { it is BreakStatement || it is ContinueStatement }
myBlock = Block(newStatements, true)
}
public override fun toKotlin() = caseStatement.toKotlin(", ") + " -> " + myBlock.toKotlin()
}
public open class SwitchLabelStatement(val expression: Expression): Statement() {
public override fun toKotlin() = expression.toKotlin()
}
public open class DefaultSwitchLabelStatement(): Statement() {
public override fun toKotlin() = "else"
}
// Other ------------------------------------------------------------------------------------------------------
public open class SynchronizedStatement(val expression: Expression, val block: Block): Statement() {
public override fun toKotlin() = "synchronized (" + expression.toKotlin() + ") "+ block.toKotlin()
}
@@ -0,0 +1,22 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.types.Type
public open class Trait(converter : Converter,
name : Identifier,
docComments: List<Node>,
modifiers : Set<Modifier>,
typeParameters : List<Element>,
extendsTypes : List<Type>,
baseClassParams : List<Expression>,
implementsTypes : List<Type>,
members : List<Node>) : Class(converter, name, docComments, modifiers, typeParameters,
extendsTypes, baseClassParams, implementsTypes, members) {
override val TYPE: String
get() = "trait"
override fun primaryConstructorSignatureToKotlin() = ""
override fun needOpenModifier() = false
}
@@ -0,0 +1,9 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class TypeElement(val `type` : Type) : Element() {
override fun toKotlin() = `type`.toKotlin()
public fun toKotlinNotNull(): String = `type`.convertedToNotNull().toKotlin()
}
@@ -0,0 +1,22 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type
public open class TypeParameter(val name : Identifier, val extendsTypes : List<Type>) : Element() {
public open fun hasWhere() : Boolean = extendsTypes.size() > 1
public open fun getWhereToKotlin() : String {
if (hasWhere()) {
return name.toKotlin() + " : " + extendsTypes.get(1).toKotlin()
}
return ""
}
public override fun toKotlin() : String {
if (extendsTypes.size() > 0) {
return name.toKotlin() + " : " + extendsTypes [0].toKotlin()
}
return name.toKotlin()
}
}
+28
View File
@@ -0,0 +1,28 @@
package org.jetbrains.jet.j2k.ast
fun List<Node>.toKotlin(separator: String, prefix: String = "", suffix: String = ""): String {
val result = StringBuilder()
if (size() > 0) {
result.append(prefix)
var first = true
for(x in this) {
if (!first) result.append(separator)
first = false
result.append(x.toKotlin())
}
result.append(suffix)
}
return result.toString()
}
fun Collection<Modifier>.toKotlin(separator: String = " "): String {
val result = StringBuilder()
for(x in this) {
result.append(x.name)
result.append(separator)
}
return result.toString()
}
fun String.withPrefix(prefix: String) = if (isEmpty()) "" else prefix + this
fun Expression.withPrefix(prefix: String) = if (isEmpty()) "" else prefix + toKotlin()
@@ -0,0 +1,13 @@
package org.jetbrains.jet.j2k.ast.types
public open class ArrayType(val elementType : Type, nullable: Boolean) : Type(nullable) {
public override fun toKotlin() : String {
if (elementType is PrimitiveType) {
return elementType.toKotlin() + "Array" + isNullableStr()
}
return "Array<" + elementType.toKotlin() + ">" + isNullableStr()
}
public override fun convertedToNotNull() : Type = ArrayType(elementType, false)
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.Element
import org.jetbrains.jet.j2k.ast.Identifier
import java.util.Collections
import java.util.ArrayList
public open class ClassType(val `type` : Identifier, val parameters : List<Element>, nullable : Boolean) : Type(nullable) {
public override fun toKotlin() : String {
// TODO change to map() when KT-2051 is fixed
val parametersToKotlin = ArrayList<String>()
for(param in parameters) {
parametersToKotlin.add(param.toKotlin())
}
var params : String = if (parametersToKotlin.size() == 0)
""
else
"<" + parametersToKotlin.makeString(", ") + ">"
return `type`.toKotlin() + params + isNullableStr()
}
public override fun convertedToNotNull() : Type = ClassType(`type`, parameters, false)
}
@@ -0,0 +1,5 @@
package org.jetbrains.jet.j2k.ast.types
public open class EmptyType() : Type(false) {
public override fun toKotlin() : String = "UNRESOLVED_TYPE"
}
@@ -0,0 +1,5 @@
package org.jetbrains.jet.j2k.ast.types
public open class InProjectionType(val bound : Type) : Type(false) {
public override fun toKotlin() : String = "in " + bound.toKotlin()
}
@@ -0,0 +1,5 @@
package org.jetbrains.jet.j2k.ast.types
public open class OutProjectionType(val bound : Type) : Type(false) {
public override fun toKotlin() : String = "out " + bound.toKotlin()
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.Identifier
public open class PrimitiveType(val `type` : Identifier) : Type(false) {
public override fun toKotlin() : String = `type`.toKotlin()
}
@@ -0,0 +1,5 @@
package org.jetbrains.jet.j2k.ast.types
public open class StarProjectionType() : Type(false) {
public override fun toKotlin() : String = "*"
}
@@ -0,0 +1,17 @@
package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.Element
public abstract class Type(val nullable: Boolean) : Element() {
public open fun convertedToNotNull() : Type {
if (nullable) throw UnsupportedOperationException("convertedToNotNull must be defined")
return this
}
public open fun isNullableStr() : String? {
return (if (nullable)
"?"
else
"")
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.types.Type
public open class VarArg(val `type` : Type) : Type(false) {
public override fun toKotlin() : String = `type`.toKotlin()
}
@@ -0,0 +1,21 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.JavaRecursiveElementVisitor
import com.intellij.psi.PsiClass
import java.util.HashSet
public open class ClassVisitor(): JavaRecursiveElementVisitor() {
private val myClassIdentifiers = HashSet<String>()
public open fun getClassIdentifiers(): Set<String> {
return HashSet<String>(myClassIdentifiers)
}
public override fun visitClass(aClass: PsiClass?): Unit {
val qName = aClass?.getQualifiedName()
if (qName != null) {
myClassIdentifiers.add(qName)
}
super.visitClass(aClass)
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.j2k.visitors
import org.jetbrains.jet.j2k.Converter
public open class Dispatcher(converter: Converter) {
public var expressionVisitor: ExpressionVisitor = ExpressionVisitor(converter)
}
@@ -0,0 +1,72 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.*
import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.j2k.isAnnotatedAsNotNull
import org.jetbrains.jet.j2k.isDefinitelyNotNull
public open class ElementVisitor(val myConverter : Converter) : JavaElementVisitor() {
protected var myResult : Element = Element.EMPTY_ELEMENT
public fun getConverter() : Converter {
return myConverter
}
public open fun getResult() : Element {
return myResult
}
public override fun visitLocalVariable(variable : PsiLocalVariable?) : Unit {
val theVariable = variable!!
var kType = myConverter.typeToType(theVariable.getType(), isAnnotatedAsNotNull(theVariable.getModifierList()))
if (theVariable.hasModifierProperty(PsiModifier.FINAL) && isDefinitelyNotNull(theVariable.getInitializer())) {
kType = kType.convertedToNotNull();
}
myResult = LocalVariable(Identifier(theVariable.getName()!!),
Converter.modifiersListToModifiersSet(theVariable.getModifierList()),
kType,
myConverter.expressionToExpression(theVariable.getInitializer(), theVariable.getType()))
}
public override fun visitExpressionList(list : PsiExpressionList?) : Unit {
myResult = ExpressionList(myConverter.expressionsToExpressionList(list!!.getExpressions()))
}
public override fun visitReferenceElement(reference : PsiJavaCodeReferenceElement?) : Unit {
val theReference = reference!!
val types : List<Type> = myConverter.typesToTypeList(theReference.getTypeParameters())
if (!theReference.isQualified()) {
myResult = ReferenceElement(Identifier(theReference.getReferenceName()!!), types)
}
else {
var result : String = Identifier(reference.getReferenceName()!!).toKotlin()
var qualifier : PsiElement? = theReference.getQualifier()
while (qualifier != null)
{
val p : PsiJavaCodeReferenceElement = (qualifier as PsiJavaCodeReferenceElement)
result = Identifier(p.getReferenceName()!!).toKotlin() + "." + result
qualifier = p.getQualifier()
}
myResult = ReferenceElement(Identifier(result), types)
}
}
public override fun visitTypeElement(`type` : PsiTypeElement?) : Unit {
myResult = TypeElement(myConverter.typeToType(`type`!!.getType()))
}
public override fun visitTypeParameter(classParameter : PsiTypeParameter?) : Unit {
myResult = TypeParameter(Identifier(classParameter!!.getName()!!),
classParameter.getExtendsListTypes().map { myConverter.typeToType(it) } )
}
public override fun visitParameterList(list : PsiParameterList?) : Unit {
myResult = ParameterList(myConverter.parametersToParameterList(list!!.getParameters()).requireNoNulls())
}
public override fun visitComment(comment: PsiComment?) {
myResult = Comment(comment?.getText()!!)
}
}
@@ -0,0 +1,512 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import com.intellij.psi.tree.IElementType
import org.jetbrains.annotations.Nullable
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.*
import org.jetbrains.jet.j2k.ast.types.EmptyType
import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import java.util.ArrayList
import java.util.Collections
import com.intellij.psi.CommonClassNames.*
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.jet.lang.types.lang.PrimitiveType
import org.jetbrains.jet.j2k.isAnnotatedAsNotNull
public open class ExpressionVisitor(converter: Converter): StatementVisitor(converter) {
{
myResult = Expression.EMPTY_EXPRESSION
}
public override fun getResult(): Expression {
return myResult as Expression
}
public override fun visitArrayAccessExpression(expression: PsiArrayAccessExpression?): Unit {
val assignment = PsiTreeUtil.getParentOfType(expression, javaClass<PsiAssignmentExpression>())
val lvalue = assignment != null && expression == assignment.getLExpression();
myResult = ArrayAccessExpression(getConverter().expressionToExpression(expression?.getArrayExpression()),
getConverter().expressionToExpression(expression?.getIndexExpression()),
lvalue)
}
public override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression?): Unit {
myResult = ArrayInitializerExpression(getConverter().typeToType(expression?.getType()),
getConverter().expressionsToExpressionList(expression?.getInitializers()!!))
}
public override fun visitAssignmentExpression(expression: PsiAssignmentExpression?): Unit {
val tokenType: IElementType = expression?.getOperationSign()?.getTokenType()!!
val secondOp: String = when(tokenType) {
JavaTokenType.GTGTEQ -> "shr"
JavaTokenType.LTLTEQ -> "shl"
JavaTokenType.XOREQ -> "xor"
JavaTokenType.ANDEQ -> "and"
JavaTokenType.OREQ -> "or"
JavaTokenType.GTGTGTEQ -> "ushr"
else -> ""
}
val lhs = getConverter().expressionToExpression(expression?.getLExpression()!!)
val rhs = getConverter().expressionToExpression(expression?.getRExpression()!!, expression?.getLExpression()?.getType())
if (!secondOp.isEmpty()) {
myResult = AssignmentExpression(lhs, BinaryExpression(lhs, rhs, secondOp), "=")
}
else {
myResult = AssignmentExpression(lhs, rhs, expression?.getOperationSign()?.getText()!!)
}
}
public override fun visitBinaryExpression(expression: PsiBinaryExpression?): Unit {
val lhs = getConverter().expressionToExpression(expression?.getLOperand()!!, expression?.getType())
val rhs = getConverter().expressionToExpression(expression?.getROperand(), expression?.getType())
if (expression?.getOperationSign()?.getTokenType() == JavaTokenType.GTGTGT) {
myResult = MethodCallExpression.build(lhs, "ushr", arrayList(rhs))
}
else {
myResult = BinaryExpression(lhs, rhs,
getOperatorString(expression?.getOperationSign()?.getTokenType()!!))
}
}
public override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression?): Unit {
myResult = ClassObjectAccessExpression(getConverter().typeElementToTypeElement(expression?.getOperand()))
}
public override fun visitConditionalExpression(expression: PsiConditionalExpression?): Unit {
val condition: PsiExpression? = expression?.getCondition()
val `type`: PsiType? = condition?.getType()
val e: Expression = (if (`type` != null)
getConverter().expressionToExpression(condition, `type`)
else
getConverter().expressionToExpression(condition))
myResult = ParenthesizedExpression(IfStatement(e,
getConverter().expressionToExpression(expression?.getThenExpression()),
getConverter().expressionToExpression(expression?.getElseExpression())))
}
public override fun visitExpressionList(list: PsiExpressionList?): Unit {
myResult = ExpressionList(getConverter().expressionsToExpressionList(list!!.getExpressions()))
}
public override fun visitInstanceOfExpression(expression: PsiInstanceOfExpression?): Unit {
val checkType: PsiTypeElement? = expression?.getCheckType()
myResult = IsOperator(getConverter().expressionToExpression(expression?.getOperand()),
myConverter.typeElementToTypeElement(checkType))
}
public override fun visitLiteralExpression(expression: PsiLiteralExpression?): Unit {
val value: Any? = expression?.getValue()
var text: String = expression?.getText()!!
val `type`: PsiType? = expression?.getType()
if (`type` != null) {
val canonicalTypeStr: String? = `type`.getCanonicalText()
if (canonicalTypeStr?.equals("double")!! || canonicalTypeStr?.equals(JAVA_LANG_DOUBLE)!!) {
text = text.replace("D", "").replace("d", "")
if (!text.contains(".")) {
text += ".0"
}
}
if (canonicalTypeStr?.equals("float")!! || canonicalTypeStr?.equals(JAVA_LANG_FLOAT)!!) {
text = text.replace("F", "").replace("f", "") + "." + OperatorConventions.FLOAT + "()"
}
if (canonicalTypeStr?.equals("long")!! || canonicalTypeStr?.equals(JAVA_LANG_LONG)!!) {
text = text.replace("L", "").replace("l", "")
}
if (canonicalTypeStr?.equals("int")!! || canonicalTypeStr?.equals(JAVA_LANG_INTEGER)!!) {
text = (if (value != null) value.toString() else text)
}
}
myResult = LiteralExpression(text)
}
public override fun visitMethodCallExpression(expression: PsiMethodCallExpression?): Unit {
convertMethodCallExpression(expression!!)
}
protected fun convertMethodCallExpression(expression: PsiMethodCallExpression) {
if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
myResult = MethodCallExpression(getConverter().expressionToExpression(expression.getMethodExpression()),
getConverter().argumentsToExpressionList(expression),
getConverter().typesToTypeList(expression.getTypeArguments()),
getConverter().typeToType(expression.getType()).nullable)
}
}
public override fun visitNewExpression(expression: PsiNewExpression?): Unit {
if (expression?.getArrayInitializer() != null)
{
myResult = createNewEmptyArray(expression)
}
else
if (expression?.getArrayDimensions()?.size!! > 0) {
myResult = createNewEmptyArrayWithoutInitialization(expression!!)
}
else
{
myResult = createNewClassExpression(expression)
}
}
private fun createNewClassExpression(expression: PsiNewExpression?): Expression {
val anonymousClass: PsiAnonymousClass? = expression?.getAnonymousClass()
val constructor: PsiMethod? = expression?.resolveMethod()
var classReference: PsiJavaCodeReferenceElement? = expression?.getClassOrAnonymousClassReference()
val isNotConvertedClass: Boolean = classReference != null && !getConverter().getClassIdentifiers().contains(classReference?.getQualifiedName())
var argumentList: PsiExpressionList? = expression?.getArgumentList()
var arguments: Array<PsiExpression> = (if (argumentList != null)
argumentList?.getExpressions()!!
else
array<PsiExpression>())
if (constructor == null || Converter.isConstructorPrimary(constructor) || isNotConvertedClass)
{
return NewClassExpression(getConverter().elementToElement(classReference),
getConverter().argumentsToExpressionList(expression!!),
getConverter().expressionToExpression(expression.getQualifier()),
(if (anonymousClass != null)
getConverter().anonymousClassToAnonymousClass(anonymousClass)
else
null))
}
val reference: PsiJavaCodeReferenceElement? = expression?.getClassReference()
val typeParameters: List<Type> = (if (reference != null)
getConverter().typesToTypeList(reference.getTypeParameters())
else
Collections.emptyList<Type>())
return CallChainExpression(Identifier(constructor.getName(), false),
MethodCallExpression(Identifier("init"), getConverter().expressionsToExpressionList(arguments), typeParameters, false))
}
private fun createNewEmptyArrayWithoutInitialization(expression: PsiNewExpression): Expression {
return ArrayWithoutInitializationExpression(
getConverter().typeToType(expression.getType(), true),
getConverter().expressionsToExpressionList(expression.getArrayDimensions()))
}
private fun createNewEmptyArray(expression: PsiNewExpression?): Expression {
return getConverter().expressionToExpression(expression?.getArrayInitializer())
}
public override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression?): Unit {
myResult = ParenthesizedExpression(getConverter().expressionToExpression(expression?.getExpression()))
}
public override fun visitPostfixExpression(expression: PsiPostfixExpression?): Unit {
myResult = PostfixOperator(getOperatorString(expression!!.getOperationSign().getTokenType()!!),
getConverter().expressionToExpression(expression.getOperand()))
}
public override fun visitPrefixExpression(expression: PsiPrefixExpression?): Unit {
val operand = getConverter().expressionToExpression(expression?.getOperand(), expression?.getOperand()!!.getType())
val token = expression?.getOperationTokenType()!!
if (token == JavaTokenType.TILDE) {
myResult = MethodCallExpression.build(ParenthesizedExpression(operand), "inv", arrayList())
}
else {
myResult = PrefixOperator(getOperatorString(token), operand)
}
}
public override fun visitReferenceExpression(expression: PsiReferenceExpression?): Unit {
val isFieldReference: Boolean = isFieldReference(expression!!, getContainingClass(expression))
val insideSecondaryConstructor: Boolean = isInsideSecondaryConstructor(expression)
val hasReceiver: Boolean = isFieldReference && insideSecondaryConstructor
val isThis: Boolean = isThisExpression(expression)
val notNull = isResolvedToNotNull(expression)
val isNullable: Boolean = getConverter().typeToType(expression.getType(), notNull).nullable
val className: String = getClassNameWithConstructor(expression)
val referencedName = expression.getReferenceName()!!
var identifier: Expression = Identifier(referencedName, isNullable)
val __: String = "__"
val qualifier = expression.getQualifierExpression()
if (hasReceiver){
identifier = CallChainExpression(Identifier(__, false), Identifier(referencedName, isNullable))
}
else if (insideSecondaryConstructor && isThis) {
identifier = Identifier("val __ = " + className)
}
else if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") {
identifier = Identifier("size", isNullable)
}
else if (qualifier == null) {
val resolved = expression.getReference()?.resolve()
if (resolved is PsiClass) {
val clazz = resolved as PsiClass
if (PrimitiveType.values() any { it.getTypeName().asString() == clazz.getName() }) {
myResult = Identifier(clazz.getQualifiedName()!!, false)
return
}
}
if (resolved is PsiMember && resolved.hasModifierProperty(PsiModifier.STATIC) &&
resolved.getContainingClass() != null &&
PsiTreeUtil.getParentOfType(expression, javaClass<PsiClass>()) != resolved.getContainingClass() &&
!isStaticallyImported(resolved, expression)) {
var member = resolved as PsiMember
var result = Identifier(referencedName).toKotlin()
while(member.getContainingClass() != null) {
result = Identifier(member.getContainingClass()!!.getName()!!).toKotlin() + "." + result
member = member.getContainingClass()!!
}
myResult = Identifier(result, false, false)
return
}
}
myResult = CallChainExpression(getConverter().expressionToExpression(qualifier), identifier)
}
private fun isResolvedToNotNull(expression: PsiReference): Boolean {
val target = expression.resolve()
if (target is PsiEnumConstant) {
return true;
}
if (target is PsiModifierListOwner) {
return isAnnotatedAsNotNull(target.getModifierList());
}
return false;
}
public override fun visitSuperExpression(expression: PsiSuperExpression?): Unit {
val qualifier: PsiJavaCodeReferenceElement? = expression?.getQualifier()
myResult = SuperExpression((if (qualifier != null)
Identifier(qualifier.getQualifiedName()!!)
else
Identifier.EMPTY_IDENTIFIER))
}
public override fun visitThisExpression(expression: PsiThisExpression?): Unit {
val qualifier: PsiJavaCodeReferenceElement? = expression?.getQualifier()
myResult = ThisExpression((if (qualifier != null)
Identifier(qualifier.getQualifiedName()!!)
else
Identifier.EMPTY_IDENTIFIER))
}
public override fun visitTypeCastExpression(expression: PsiTypeCastExpression?): Unit {
val castType: PsiTypeElement? = expression?.getCastType()
if (castType != null) {
val operand = expression?.getOperand()
val operandType = operand?.getType()
val typeText = castType.getType().getCanonicalText()
val typeConversion = Converter.PRIMITIVE_TYPE_CONVERSIONS[typeText]
if (operandType is PsiPrimitiveType && typeConversion != null) {
myResult = MethodCallExpression.build(getConverter().expressionToExpression(operand), typeConversion)
}
else {
myResult = TypeCastExpression(getConverter().typeToType(castType.getType()),
getConverter().expressionToExpression(operand))
}
}
}
public override fun visitPolyadicExpression(expression: PsiPolyadicExpression?): Unit {
var parameters = ArrayList<Expression>()
for (operand : PsiExpression in expression?.getOperands()!!) {
parameters.add(getConverter().expressionToExpression(operand, expression?.getType()))
}
myResult = PolyadicExpression(parameters, getOperatorString(expression?.getOperationTokenType()!!))
}
class object {
private fun getOperatorString(tokenType: IElementType): String {
if (tokenType == JavaTokenType.PLUS)
return "+"
if (tokenType == JavaTokenType.MINUS)
return "-"
if (tokenType == JavaTokenType.ASTERISK)
return "*"
if (tokenType == JavaTokenType.DIV)
return "/"
if (tokenType == JavaTokenType.PERC)
return "%"
if (tokenType == JavaTokenType.GTGT)
return "shr"
if (tokenType == JavaTokenType.LTLT)
return "shl"
if (tokenType == JavaTokenType.XOR)
return "xor"
if (tokenType == JavaTokenType.AND)
return "and"
if (tokenType == JavaTokenType.OR)
return "or"
if (tokenType == JavaTokenType.GTGTGT)
return "ushr"
if (tokenType == JavaTokenType.GT)
return ">"
if (tokenType == JavaTokenType.LT)
return "<"
if (tokenType == JavaTokenType.GE)
return ">="
if (tokenType == JavaTokenType.LE)
return "<="
if (tokenType == JavaTokenType.EQEQ)
return "=="
if (tokenType == JavaTokenType.NE)
return "!="
if (tokenType == JavaTokenType.ANDAND)
return "&&"
if (tokenType == JavaTokenType.OROR)
return "||"
if (tokenType == JavaTokenType.PLUSPLUS)
return "++"
if (tokenType == JavaTokenType.MINUSMINUS)
return "--"
if (tokenType == JavaTokenType.EXCL)
return "!"
// System.out.println("UNSUPPORTED TOKEN TYPE: " + tokenType?.toString())
return ""
}
private fun getClassNameWithConstructor(expression: PsiReferenceExpression): String {
var context: PsiElement? = expression.getContext()
while (context != null) {
if (context is PsiMethod && ((context as PsiMethod)).isConstructor()) {
val containingClass: PsiClass? = ((context as PsiMethod)).getContainingClass()
if (containingClass != null) {
val identifier: PsiIdentifier? = containingClass.getNameIdentifier()
if (identifier != null) {
return identifier.getText()!!
}
}
}
context = context?.getContext()
}
return ""
}
open fun getClassName(expression: PsiExpression): String {
var context: PsiElement? = expression.getContext()
while (context != null)
{
if ((context is PsiClass?)) {
val containingClass: PsiClass? = (context as PsiClass?)
val identifier: PsiIdentifier? = containingClass?.getNameIdentifier()
if (identifier != null) {
return identifier.getText()!!
}
}
context = context?.getContext()
}
return ""
}
private fun isFieldReference(expression: PsiReferenceExpression, currentClass: PsiClass?): Boolean {
val reference: PsiReference? = expression.getReference()
if (reference != null) {
val resolvedReference: PsiElement? = reference.resolve()
if (resolvedReference is PsiField) {
return (resolvedReference as PsiField).getContainingClass() == currentClass
}
}
return false
}
private fun isInsideSecondaryConstructor(expression: PsiReferenceExpression): Boolean {
var context: PsiElement? = expression.getContext()
while (context != null) {
if (context is PsiMethod && (context as PsiMethod).isConstructor()) {
return !Converter.isConstructorPrimary((context as PsiMethod))
}
context = context?.getContext()
}
return false
}
private fun isInsidePrimaryConstructor(expression: PsiExpression): Boolean {
var context: PsiElement? = expression.getContext()
while (context != null) {
if (context is PsiMethod && (context as PsiMethod).isConstructor()) {
return Converter.isConstructorPrimary(context as PsiMethod)
}
context = context?.getContext()
}
return false
}
private fun getContainingClass(expression: PsiExpression): PsiClass? {
var context: PsiElement? = expression.getContext()
while (context != null)
{
if (context is PsiMethod && (context as PsiMethod).isConstructor())
{
return (context as PsiMethod).getContainingClass()
}
context = context?.getContext()
}
return null
}
private fun isThisExpression(expression: PsiReferenceExpression): Boolean {
for (r : PsiReference? in expression.getReferences())
if (r?.getCanonicalText()?.equals("this")!!)
{
val res: PsiElement? = r?.resolve()
if (res is PsiMethod && res.isConstructor()) {
return true
}
}
return false
}
}
}
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) {
val importStatics = importList.getImportStaticStatements();
return importStatics.any { importResolvesTo(it, member) }
}
}
return false
}
private fun importResolvesTo(stmt: PsiImportStaticStatement?, member: PsiMember): Boolean {
val targetContainingClass = member.getContainingClass()
var importedClass = stmt?.resolveTargetClass()
return importedClass == targetContainingClass && (stmt?.isOnDemand() ?: false ||
stmt?.getReferenceName() == member.getName())
}
@@ -0,0 +1,41 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.DummyStringExpression
import org.jetbrains.jet.j2k.ast.Identifier
import com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT
import org.jetbrains.jet.j2k.ast.MethodCallExpression
public open class ExpressionVisitorForDirectObjectInheritors(converter: Converter): ExpressionVisitor(converter) {
public override fun visitMethodCallExpression(expression: PsiMethodCallExpression?): Unit {
val methodExpression = expression?.getMethodExpression()!!
if (superMethodInvocation(methodExpression, "hashCode")) {
myResult = MethodCallExpression.build(Identifier("System", false), "identityHashCode", arrayList(Identifier("this")))
}
else if (superMethodInvocation(methodExpression, "equals")) {
myResult = MethodCallExpression.build(Identifier("this", false), "identityEquals", getConverter().argumentsToExpressionList(expression!!))
}
else if (superMethodInvocation(methodExpression, "toString")) {
myResult = DummyStringExpression(java.lang.String.format("getJavaClass<%s>.getName() + '@' + Integer.toHexString(hashCode())",
ExpressionVisitor.getClassName(methodExpression)))
}
else {
convertMethodCallExpression(expression!!)
}
}
class object {
private fun superMethodInvocation(expression: PsiReferenceExpression, methodName: String?): Boolean {
val referenceName: String? = expression.getReferenceName()
val qualifierExpression: PsiExpression? = expression.getQualifierExpression()
if (referenceName == methodName && qualifierExpression is PsiSuperExpression) {
val `type`: PsiType? = qualifierExpression.getType()
if (`type` != null && `type`.getCanonicalText() == JAVA_LANG_OBJECT) {
return true
}
}
return false
}
}
}
@@ -0,0 +1,283 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import com.intellij.psi.tree.IElementType
import org.jetbrains.annotations.Nullable
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.ast.*
import java.util.Arrays
import java.util.Collections
import java.util.LinkedList
import org.jetbrains.jet.j2k.countWritingAccesses
import java.util.ArrayList
public open class StatementVisitor(converter: Converter): ElementVisitor(converter) {
public override fun visitAssertStatement(statement: PsiAssertStatement?): Unit {
myResult = AssertStatement(getConverter().expressionToExpression(statement?.getAssertCondition()),
getConverter().expressionToExpression(statement?.getAssertDescription()))
}
public override fun visitBlockStatement(statement: PsiBlockStatement?): Unit {
myResult = myConverter.blockToBlock(statement?.getCodeBlock(), true)
}
public override fun visitBreakStatement(statement: PsiBreakStatement?): Unit {
if (statement?.getLabelIdentifier() == null) {
myResult = BreakStatement(Identifier.EMPTY_IDENTIFIER)
}
else
{
myResult = BreakStatement(Converter.identifierToIdentifier(statement?.getLabelIdentifier()))
}
}
public override fun visitContinueStatement(statement: PsiContinueStatement?): Unit {
if (statement?.getLabelIdentifier() == null)
{
myResult = ContinueStatement(Identifier.EMPTY_IDENTIFIER)
}
else
{
myResult = ContinueStatement(Converter.identifierToIdentifier(statement?.getLabelIdentifier()))
}
}
public override fun visitDeclarationStatement(statement: PsiDeclarationStatement?): Unit {
myResult = DeclarationStatement(getConverter().elementsToElementList(statement?.getDeclaredElements()!!))
}
public override fun visitDoWhileStatement(statement: PsiDoWhileStatement?): Unit {
val condition: PsiExpression? = statement?.getCondition()
val expression: Expression = (if (condition != null && condition.getType() != null)
getConverter().expressionToExpression(condition, condition.getType())
else
getConverter().expressionToExpression(condition))
myResult = DoWhileStatement(expression, getConverter().statementToStatement(statement?.getBody()))
}
public override fun visitExpressionStatement(statement: PsiExpressionStatement?): Unit {
myResult = getConverter().expressionToExpression(statement?.getExpression())
}
public override fun visitExpressionListStatement(statement: PsiExpressionListStatement?): Unit {
myResult = ExpressionListStatement(getConverter().expressionsToExpressionList(
statement?.getExpressionList()?.getExpressions()!!))
}
public override fun visitForStatement(statement: PsiForStatement?): Unit {
val initialization: PsiStatement? = statement?.getInitialization()
val update: PsiStatement? = statement?.getUpdate()
val condition: PsiExpression? = statement?.getCondition()
val body: PsiStatement? = statement?.getBody()
val firstChild: PsiLocalVariable? = (if (initialization != null && (initialization.getFirstChild() is PsiLocalVariable))
(initialization.getFirstChild() as PsiLocalVariable)
else
null)
var bodyWriteCount: Int = countWritingAccesses(firstChild, body)
var conditionWriteCount: Int = countWritingAccesses(firstChild, condition)
var updateWriteCount: Int = countWritingAccesses(firstChild, update)
val onceWritableIterator: Boolean = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0
val operationTokenType: IElementType? = (if (condition is PsiBinaryExpression)
condition.getOperationTokenType()
else
null)
if (initialization is PsiDeclarationStatement && initialization.getFirstChild() == initialization.getLastChild() &&
condition != null && update != null && update.getChildren().size == 1 &&
(isPlusPlusExpression(update.getChildren()[0])) && (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE) &&
initialization.getFirstChild() != null && (initialization.getFirstChild() is PsiLocalVariable) &&
firstChild != null && firstChild.getNameIdentifier() != null && onceWritableIterator) {
val end: Expression = getConverter().expressionToExpression((condition as PsiBinaryExpression).getROperand())
val endExpression: Expression = (if (operationTokenType == JavaTokenType.LT)
BinaryExpression(end, Identifier("1"), "-")
else
end)
myResult = ForeachWithRangeStatement(Identifier(firstChild.getName()!!),
getConverter().expressionToExpression(firstChild.getInitializer()),
endExpression,
getConverter().statementToStatement(body))
}
else {
var forStatements = ArrayList<Element>()
forStatements.add(getConverter().statementToStatement(initialization))
forStatements.add(WhileStatement(
if (condition == null)
LiteralExpression("true")
else
getConverter().expressionToExpression(condition),
Block(arrayListOf(getConverter().statementToStatement(body),
Block(arrayListOf(getConverter().statementToStatement(update)), false)), false)))
myResult = Block(forStatements, false)
}
}
public override fun visitForeachStatement(statement: PsiForeachStatement?): Unit {
val iterator = {
val iteratorExpr = getConverter().expressionToExpression(statement?.getIteratedValue())
if (iteratorExpr.isNullable())
BangBangExpression(iteratorExpr)
else
iteratorExpr
}()
myResult = ForeachStatement(getConverter().parameterToParameter(statement?.getIterationParameter()!!),
iterator,
getConverter().statementToStatement(statement?.getBody()))
}
public override fun visitIfStatement(statement: PsiIfStatement?): Unit {
val condition: PsiExpression? = statement?.getCondition()
val expression: Expression = getConverter().expressionToExpression(condition, PsiType.BOOLEAN)
myResult = IfStatement(expression,
getConverter().statementToStatement(statement?.getThenBranch()),
getConverter().statementToStatement(statement?.getElseBranch()))
}
public override fun visitLabeledStatement(statement: PsiLabeledStatement?): Unit {
myResult = LabelStatement(Converter.identifierToIdentifier(statement?.getLabelIdentifier()),
getConverter().statementToStatement(statement?.getStatement()))
}
public override fun visitSwitchLabelStatement(statement: PsiSwitchLabelStatement?): Unit {
myResult = (if (statement?.isDefaultCase()!!)
DefaultSwitchLabelStatement()
else
SwitchLabelStatement(getConverter().expressionToExpression(statement?.getCaseValue())))
}
public override fun visitSwitchStatement(statement: PsiSwitchStatement?): Unit {
myResult = SwitchContainer(getConverter().expressionToExpression(statement?.getExpression()),
switchBodyToCases(statement?.getBody()))
}
private open fun switchBodyToCases(body: PsiCodeBlock?): List<CaseContainer> {
val cases: List<List<PsiElement>> = splitToCases(body)
val allSwitchStatements = ArrayList<PsiElement>()
if (body != null) {
// TODO Arrays.asList()
for(s in body.getStatements()) allSwitchStatements.add(s)
}
val result = ArrayList<CaseContainer>()
var pendingLabels = ArrayList<Element>()
var i: Int = 0
var hasDefaultCase: Boolean = false
for (ls in cases) {
// TODO assert {(ls?.size()).sure() > 0}
if (ls.size() > 0) {
var label = ls[0]
hasDefaultCase = hasDefaultCase || (label as PsiSwitchLabelStatement).isDefaultCase()
// TODO assert {(label is PsiSwitchLabelStatement?)}
// TODO assert("not a right index") {allSwitchStatements?.get(i) == label}
if (ls.size() > 1) {
pendingLabels.add(getConverter().statementToStatement(label))
val slice: List<PsiElement> = ls.subList(1, (ls.size()))
if (!containsBreak(slice)) {
val statements = ArrayList(getConverter().statementsToStatementList(slice))
statements.addAll(getConverter().statementsToStatementList(getAllToNextBreak(allSwitchStatements, i + ls.size())))
result.add(CaseContainer(pendingLabels, statements))
pendingLabels = ArrayList()
}
else {
result.add(CaseContainer(pendingLabels, getConverter().statementsToStatementList(slice)))
pendingLabels = ArrayList()
}
}
else {
pendingLabels.add(getConverter().statementToStatement(label))
}
i += ls.size()
}
}
if (!hasDefaultCase)
result.add(CaseContainer(listOf(DefaultSwitchLabelStatement()), ArrayList()))
return result
}
public override fun visitSynchronizedStatement(statement: PsiSynchronizedStatement?): Unit {
myResult = SynchronizedStatement(getConverter().expressionToExpression(statement?.getLockExpression()),
getConverter().blockToBlock(statement?.getBody()))
}
public override fun visitThrowStatement(statement: PsiThrowStatement?): Unit {
myResult = ThrowStatement(getConverter().expressionToExpression(statement?.getException()))
}
public override fun visitTryStatement(statement: PsiTryStatement?): Unit {
val catches = ArrayList<CatchStatement>()
val catchBlocks = statement?.getCatchBlocks()!!
val catchBlockParameters = statement?.getCatchBlockParameters()!!
for (i in 0..catchBlocks.size - 1) {
catches.add(CatchStatement(getConverter().parameterToParameter(catchBlockParameters[i], true),
getConverter().blockToBlock(catchBlocks[i], true)))
}
myResult = TryStatement(getConverter().blockToBlock(statement?.getTryBlock(), true),
catches, getConverter().blockToBlock(statement?.getFinallyBlock(), true))
}
public override fun visitWhileStatement(statement: PsiWhileStatement?): Unit {
var condition: PsiExpression? = statement?.getCondition()
val expression: Expression = (if (condition != null && condition?.getType() != null)
this.getConverter().expressionToExpression(condition, condition?.getType())
else
getConverter().expressionToExpression(condition))
myResult = WhileStatement(expression, getConverter().statementToStatement(statement?.getBody()))
}
public override fun visitReturnStatement(statement: PsiReturnStatement?): Unit {
val returnValue: PsiExpression? = statement?.getReturnValue()
val methodReturnType: PsiType? = getConverter().methodReturnType
val expression: Expression = (if (returnValue != null && methodReturnType != null)
this.getConverter().expressionToExpression(returnValue, methodReturnType)
else
getConverter().expressionToExpression(returnValue))
myResult = ReturnStatement(expression)
}
class object {
private open fun isPlusPlusExpression(psiElement: PsiElement): Boolean {
return (psiElement is PsiPostfixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS) ||
(psiElement is PsiPrefixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS)
}
private fun containsBreak(slice: List<PsiElement?>) = slice.any { it is PsiBreakStatement }
private open fun getAllToNextBreak(allStatements: List<PsiElement>, start: Int): List<PsiElement> {
val result = ArrayList<PsiElement>()
for (i in start..allStatements.size() - 1) {
val s = allStatements.get(i)
if (s is PsiBreakStatement || s is PsiReturnStatement) {
return result
}
if (!(s is PsiSwitchLabelStatement)) {
result.add(s)
}
}
return result
}
private open fun splitToCases(body: PsiCodeBlock?): List<List<PsiElement>> {
val cases = ArrayList<List<PsiElement>>()
var currentCaseStatements = ArrayList<PsiElement>()
var isFirst: Boolean = true
if (body != null) {
for (s in body.getChildren()) {
if (s !is PsiStatement && s !is PsiComment) continue
if (s is PsiSwitchLabelStatement) {
if (isFirst) {
isFirst = false
}
else {
cases.add(currentCaseStatements)
currentCaseStatements = ArrayList()
}
}
currentCaseStatements.add(s)
}
cases.add(currentCaseStatements)
}
return cases
}
}
}
@@ -0,0 +1,26 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import java.util.HashSet
public open class SuperVisitor(): JavaRecursiveElementVisitor() {
public val resolvedSuperCallParameters: HashSet<PsiExpressionList> = hashSet()
public override fun visitMethodCallExpression(expression: PsiMethodCallExpression?): Unit {
if (expression != null && isSuper(expression.getMethodExpression())) {
resolvedSuperCallParameters.add(expression.getArgumentList())
}
}
class object {
open fun isSuper(r: PsiReference): Boolean {
if (r.getCanonicalText().equals("super")) {
val baseConstructor: PsiElement? = r.resolve()
if (baseConstructor != null && baseConstructor is PsiMethod && baseConstructor.isConstructor()) {
return true
}
}
return false
}
}
}
@@ -0,0 +1,33 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import org.jetbrains.annotations.Nullable
import java.util.LinkedHashSet
public open class ThisVisitor(): JavaRecursiveElementVisitor() {
private val myResolvedConstructors = LinkedHashSet<PsiMethod>()
public override fun visitReferenceExpression(expression: PsiReferenceExpression?): Unit {
for (r : PsiReference? in expression?.getReferences()!!) {
if (r?.getCanonicalText() == "this") {
val res: PsiElement? = r?.resolve()
if (res is PsiMethod && res.isConstructor()) {
myResolvedConstructors.add(res)
}
}
}
}
public open fun getPrimaryConstructor(): PsiMethod? {
if (myResolvedConstructors.size() > 0) {
val first: PsiMethod = myResolvedConstructors.iterator().next()
for (m in myResolvedConstructors)
if (m.hashCode() != first.hashCode()) {
return null
}
return first
}
return null
}
}
@@ -0,0 +1,179 @@
package org.jetbrains.jet.j2k.visitors
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType
import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.J2KConverterFlags
import org.jetbrains.jet.j2k.ast.*
import org.jetbrains.jet.j2k.ast.types.*
import java.util.LinkedList
import com.intellij.openapi.util.text.StringUtil
import java.util.ArrayList
public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisitor<Type>() {
private var myResult : Type = EmptyType()
public open fun getResult() : Type {
return myResult
}
public override fun visitPrimitiveType(primitiveType: PsiPrimitiveType?) : Type {
val name : String = primitiveType?.getCanonicalText()!!
if (name == "void") {
myResult = PrimitiveType(Identifier("Unit"))
}
else if (Node.PRIMITIVE_TYPES.contains(name)) {
myResult = PrimitiveType(Identifier(StringUtil.capitalize(name)))
}
else {
myResult = PrimitiveType(Identifier(name))
}
return myResult
}
public override fun visitArrayType(arrayType: PsiArrayType?) : Type {
if (myResult is EmptyType) {
myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true)
}
return myResult
}
public override fun visitClassType(classType : PsiClassType?) : Type {
if (classType == null) return myResult
val identifier : Identifier = constructClassTypeIdentifier(classType)
val resolvedClassTypeParams : List<Type> = createRawTypesForResolvedReference(classType)
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
val starParamList : ArrayList<Type> = ArrayList<Type>()
if (resolvedClassTypeParams.size() == 1) {
if ((resolvedClassTypeParams.get(0) as ClassType).`type`.name == "Any") {
starParamList.add(StarProjectionType())
myResult = ClassType(identifier, starParamList, true)
}
else {
myResult = ClassType(identifier, resolvedClassTypeParams, true)
}
}
else {
myResult = ClassType(identifier, resolvedClassTypeParams, true)
}
}
else {
myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()), true)
}
return myResult
}
private fun constructClassTypeIdentifier(classType : PsiClassType) : Identifier {
val psiClass : PsiClass? = classType.resolve()
if (psiClass != null) {
val qualifiedName: String? = psiClass.getQualifiedName()
if (qualifiedName != null) {
if (!qualifiedName.equals("java.lang.Object") && myConverter.hasFlag(J2KConverterFlags.FULLY_QUALIFIED_TYPE_NAMES)) {
return Identifier(qualifiedName)
}
if (qualifiedName.equals(CommonClassNames.JAVA_LANG_ITERABLE)) {
return Identifier(CommonClassNames.JAVA_LANG_ITERABLE)
}
if (qualifiedName.equals(CommonClassNames.JAVA_UTIL_ITERATOR)) {
return Identifier(CommonClassNames.JAVA_UTIL_ITERATOR)
}
if (qualifiedName.equals(CommonClassNames.JAVA_UTIL_LIST)) {
return Identifier("MutableList")
}
}
}
val classTypeName = createQualifiedName(classType)
if (classTypeName.isEmpty()) {
return Identifier(getClassTypeName(classType))
}
return Identifier(classTypeName)
}
private fun createRawTypesForResolvedReference(classType : PsiClassType) : List<Type> {
val typeParams = LinkedList<Type>()
if (classType is PsiClassReferenceType) {
val reference : PsiJavaCodeReferenceElement? = (classType as PsiClassReferenceType).getReference()
val resolve : PsiElement? = reference?.resolve()
if (resolve is PsiClass) {
for (p : PsiTypeParameter? in (resolve as PsiClass).getTypeParameters()) {
val superTypes = p!!.getSuperTypes()
val boundType : Type = (if (superTypes.size > 0)
ClassType(Identifier(getClassTypeName(superTypes[0])),
myConverter.typesToTypeList(superTypes[0].getParameters()),
true)
else
StarProjectionType())
typeParams.add(boundType)
}
}
}
return typeParams
}
public override fun visitWildcardType(wildcardType : PsiWildcardType?) : Type {
if (wildcardType!!.isExtends()) {
myResult = OutProjectionType(myConverter.typeToType(wildcardType.getExtendsBound()))
}
else
if (wildcardType.isSuper()) {
myResult = InProjectionType(myConverter.typeToType(wildcardType.getSuperBound()))
}
else {
myResult = StarProjectionType()
}
return myResult
}
public override fun visitEllipsisType(ellipsisType : PsiEllipsisType?) : Type {
myResult = VarArg(myConverter.typeToType(ellipsisType?.getComponentType()))
return myResult
}
class object {
private fun createQualifiedName(classType : PsiClassType) : String {
if (classType is PsiClassReferenceType)
{
val reference : PsiJavaCodeReferenceElement? = (classType as PsiClassReferenceType).getReference()
if (reference != null && reference.isQualified()) {
var result : String = Identifier(reference.getReferenceName()!!).toKotlin()
var qualifier : PsiElement? = reference.getQualifier()
while (qualifier != null)
{
val p : PsiJavaCodeReferenceElement = (qualifier as PsiJavaCodeReferenceElement)
result = Identifier(p.getReferenceName()!!).toKotlin() + "." + result
qualifier = p.getQualifier()
}
return result
}
}
return ""
}
private fun getClassTypeName(classType : PsiClassType) : String {
var canonicalTypeStr : String? = classType.getCanonicalText()
return when(canonicalTypeStr) {
CommonClassNames.JAVA_LANG_OBJECT -> "Any"
CommonClassNames.JAVA_LANG_BYTE -> "Byte"
CommonClassNames.JAVA_LANG_CHARACTER -> "Char"
CommonClassNames.JAVA_LANG_DOUBLE -> "Double"
CommonClassNames.JAVA_LANG_FLOAT -> "Float"
CommonClassNames.JAVA_LANG_INTEGER -> "Int"
CommonClassNames.JAVA_LANG_LONG -> "Long"
CommonClassNames.JAVA_LANG_SHORT -> "Short"
CommonClassNames.JAVA_LANG_BOOLEAN -> "Boolean"
else -> (if (classType.getClassName() != null)
classType.getClassName()!!
else
classType.getCanonicalText())!!
}
}
}
}
@@ -0,0 +1,175 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.j2k;
import com.intellij.core.JavaCoreProjectEnvironment;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
public class StandaloneJavaToKotlinConverterTest extends TestCase {
private final String myDataPath;
private final String myName;
@NotNull
private final static JavaCoreProjectEnvironment myJavaCoreEnvironment = JavaToKotlinTranslator.setUpJavaCoreEnvironment();
public StandaloneJavaToKotlinConverterTest(String dataPath, String name) {
myDataPath = dataPath;
myName = name;
}
@Override
protected void runTest() throws Throwable {
Converter converter = new Converter();
String javaPath = "tests/testData/" + getTestFilePath();
String kotlinPath = javaPath.replace(".jav", ".kt");
final File kotlinFile = new File(kotlinPath);
if (!kotlinFile.exists()) {
FileUtil.writeToFile(kotlinFile, "");
}
final String expected = StringUtil.convertLineSeparators(FileUtil.loadFile(kotlinFile));
final File javaFile = new File(javaPath);
final String javaCode = FileUtil.loadFile(javaFile);
String actual = "";
String parentFileName = javaFile.getParentFile().getName();
if (parentFileName.equals("expression")) {
actual = expressionToKotlin(converter, javaCode);
}
else if (parentFileName.equals("statement")) {
actual = statementToKotlin(converter, javaCode);
}
else if (parentFileName.equals("method")) {
actual = methodToKotlin(converter, javaCode);
}
else if (parentFileName.equals("class")) {
actual = fileToKotlin(converter, javaCode);
}
else if (parentFileName.equals("file")) {
actual = fileToKotlin(converter, javaCode);
}
else if (parentFileName.equals("comp")) actual = fileToFileWithCompatibilityImport(javaCode);
actual = StringUtil.convertLineSeparators(actual);
assert !actual.isEmpty() : "Specify what is it: file, class, method, statement or expression: " + javaPath + " parent: " + parentFileName;
final File tmp = new File(kotlinPath + ".tmp");
if (!expected.equals(actual)) FileUtil.writeToFile(tmp, actual);
if (expected.equals(actual) && tmp.exists()) //noinspection ResultOfMethodCallIgnored
{
tmp.delete();
}
Assert.assertEquals(expected, actual);
}
@NotNull
String getTestFilePath() {
return myDataPath + "/" + myName + ".jav";
}
@NotNull
@Override
public String getName() {
return "test_" + myName;
}
@NotNull
public static Test suite() {
TestSuite suite = new TestSuite();
// suite.addTest(new StandaloneJavaToKotlinConverterTest("ast/class/file", "kt-639"));
suite.addTest(TestCaseBuilder.suiteForDirectory("tests/testData", "/ast", new TestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new StandaloneJavaToKotlinConverterTest(dataPath, name);
}
}));
return suite;
}
@NotNull
private static String fileToFileWithCompatibilityImport(@NotNull String text) {
return JavaToKotlinTranslator.generateKotlinCodeWithCompatibilityImport(text);
}
@NotNull
private String fileToKotlin(Converter converter, @NotNull String text) {
return generateKotlinCode(converter, JavaToKotlinTranslator.createFile(myJavaCoreEnvironment, text));
}
@NotNull
private static String generateKotlinCode(@NotNull Converter converter, @Nullable PsiFile file) {
if (file != null && file instanceof PsiJavaFile) {
JavaToKotlinTranslator.setClassIdentifiers(converter, file);
return prettify(converter.elementToKotlin(file));
}
return "";
}
@NotNull
private String methodToKotlin(Converter converter, String text) throws IOException {
String result = fileToKotlin(converter, "final class C {" + text + "}")
.replaceAll("class C\\(\\) \\{", "");
result = result.substring(0, result.lastIndexOf("}"));
return prettify(result);
}
@NotNull
private String statementToKotlin(Converter converter, String text) throws Exception {
String result = methodToKotlin(converter, "void main() {" + text + "}");
int pos = result.lastIndexOf("}");
result = result.substring(0, pos).replaceFirst("fun main\\(\\) : Unit \\{", "");
return prettify(result);
}
@NotNull
private String expressionToKotlin(Converter converter, String code) throws Exception {
String result = statementToKotlin(converter, "Object o =" + code + "}");
result = result.replaceFirst("var o : Any\\? =", "");
return prettify(result);
}
@NotNull
private static String prettify(@Nullable String code) {
if (code == null) {
return "";
}
return code
.trim()
.replaceAll("\r\n", "\n")
.replaceAll(" \n", "\n")
.replaceAll("\n ", "\n")
.replaceAll("\n+", "\n")
.replaceAll(" +", " ")
.trim()
;
}
}
@@ -0,0 +1,107 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.j2k;
import com.intellij.openapi.application.PathManager;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
abstract class TestCaseBuilder {
@NotNull
private static final FilenameFilter emptyFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
return true;
}
};
@NotNull
public static String getTestDataPathBase() {
return "testData";
}
public static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(TestCaseBuilder.class, "/org/jetbrains/jet/TestCaseBuilder.class")).getParentFile().getParentFile().getParent();
}
public interface NamedTestFactory {
@NotNull
Test createTest(@NotNull String dataPath, @NotNull String name);
}
@NotNull
public static TestSuite suiteForDirectory(String baseDataDir, @NotNull final String dataPath, @NotNull NamedTestFactory factory) {
return suiteForDirectory(baseDataDir, dataPath, true, emptyFilter, factory);
}
@NotNull
private static TestSuite suiteForDirectory(String baseDataDir, @NotNull final String dataPath, boolean recursive, @NotNull final FilenameFilter filter, @NotNull NamedTestFactory factory) {
TestSuite suite = new TestSuite(dataPath);
final String extensionJava = ".jav";
final FilenameFilter extensionFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, @NotNull String name) {
return name.endsWith(extensionJava);
}
};
FilenameFilter resultFilter;
if (filter != emptyFilter) {
resultFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return extensionFilter.accept(file, s) && filter.accept(file, s);
}
};
}
else {
resultFilter = extensionFilter;
}
File dir = new File(baseDataDir + dataPath);
FileFilter dirFilter = new FileFilter() {
@Override
public boolean accept(@NotNull File pathname) {
return pathname.isDirectory();
}
};
if (recursive) {
File[] files = dir.listFiles(dirFilter);
assert files != null : dir;
List<File> subdirs = Arrays.asList(files);
Collections.sort(subdirs);
for (File subdir : subdirs) {
suite.addTest(suiteForDirectory(baseDataDir, dataPath + "/" + subdir.getName(), recursive, filter, factory));
}
}
List<File> files = Arrays.asList(dir.listFiles(resultFilter));
Collections.sort(files);
for (File file : files) {
String fileName = file.getName();
assert fileName != null;
suite.addTest(factory.createTest(dataPath, fileName.substring(0, fileName.length() - extensionJava.length())));
}
return suite;
}
}
@@ -0,0 +1 @@
int[] a = new int[10]
@@ -0,0 +1 @@
var a : IntArray? = IntArray(10)
@@ -0,0 +1 @@
Object[] a = new Object[10]
@@ -0,0 +1 @@
var a : Array<Any?>? = arrayOfNulls<Any?>(10)
@@ -1 +1 @@
var d2 : Array<IntArray?>? = Array<IntArray?>(5)
var d2 : Array<IntArray?>? = arrayOfNulls<IntArray?>(5)
@@ -1 +1 @@
var d3 : Array<Array<IntArray?>?>? = Array<Array<IntArray?>?>(5, {Array<IntArray?>(5)})
var d3 : Array<Array<IntArray?>?>? = Array<Array<IntArray?>?>(5, {arrayOfNulls<IntArray?>(5)})
@@ -1 +1 @@
var ss : Array<Array<String?>?>? = Array<Array<String?>?>(5, {Array<String?>(5)})
var ss : Array<Array<String?>?>? = Array<Array<String?>?>(5, {arrayOfNulls<String?>(5)})
@@ -1 +1 @@
var sss : Array<Array<Array<String?>?>?>? = Array<Array<Array<String?>?>?>(5, {Array<Array<String?>?>(5, {Array<String?>(5)})})
var sss : Array<Array<Array<String?>?>?>? = Array<Array<Array<String?>?>?>(5, {Array<Array<String?>?>(5, {arrayOfNulls<String?>(5)})})
@@ -0,0 +1,9 @@
import java.util.BitSet;
class Foo {
void foo(BitSet o) {
BitSet o2 = o;
int foo = 0;
foo = o2.size();
}
}
@@ -0,0 +1,8 @@
import java.util.BitSet
open class Foo() {
open fun foo(o : BitSet?) : Unit {
var o2 : BitSet? = o
var foo : Int = 0
foo = o2?.size()!!
}
}
@@ -0,0 +1,14 @@
import java.util.ArrayList;
import java.util.List;
class Boxing {
void test() {
Integer i = 0;
Number n = 0.0f;
i = 1;
int j = i;
Integer k = i+2;
i = null;
j = i;
}
}
@@ -0,0 +1,12 @@
import java.util.ArrayList
open class Boxing() {
open fun test() : Unit {
var i : Int? = 0
var n : Number? = 0.0.toFloat()
i = 1
var j : Int = i!!
var k : Int? = i!! + 2
i = null
j = i!!
}
}
@@ -3,6 +3,7 @@ package demo;
class Test {
void test() {
Integer i = Integer.valueOf(100);
Short s = Short.valueOf(100);
short s = 3;
Short ss = Short.valueOf(s);
}
}
@@ -2,6 +2,7 @@ package demo
open class Test() {
open fun test() : Unit {
var i : Int? = Integer.valueOf(100)
var s : Short? = Short.valueOf(100)
var s : Short = 3
var ss : Short? = java.lang.Short.valueOf(s)
}
}
@@ -0,0 +1,13 @@
package test;
public class Short {
public static Short valueOf(String value) {return new Short();}
}
class Test {
public static void test() {
Short.valueOf("1");
test.Short.valueOf("1");
java.lang.Short.valueOf("1");
}
}
@@ -0,0 +1,17 @@
package test
public open class Short() {
class object {
public open fun valueOf(value : String?) : Short? {
return Short()
}
}
}
open class Test() {
class object {
public open fun test() : Unit {
test.Short.valueOf("1")
test.Short.valueOf("1")
java.lang.Short.valueOf("1")
}
}
}
@@ -1,4 +1,4 @@
public open class MyClass() {
private open fun init(arg1 : Int, arg2 : Int, arg3 : Int) : Unit {
private fun init(arg1 : Int, arg2 : Int, arg3 : Int) : Unit {
}
}
@@ -8,9 +8,9 @@ return _firstName
public open fun getLastName() : String? {
return _lastName
}
private open fun doSmthBefore() : Unit {
private fun doSmthBefore() : Unit {
}
private open fun doSmthAfter() : Unit {
private fun doSmthAfter() : Unit {
}
{
doSmthBefore()
@@ -1,5 +1,5 @@
public open class Identifier<T>(_myName : T?, _myHasDollar : Boolean) {
private val myName : T? = null
private val myName : T?
private var myHasDollar : Boolean = false
private var myNullable : Boolean = true
public open fun getName() : T? {
@@ -30,8 +30,8 @@ public open class User() {
class object {
public open fun main() : Unit {
var i1 : Identifier<*>? = Identifier.init<String?>("name", false, true)
var i2 : Identifier<Any?>? = Identifier.init<String?>("name", false)
var i3 : Identifier<Any?>? = Identifier.init<String?>("name")
var i2 : Identifier<*>? = Identifier.init<String?>("name", false)
var i3 : Identifier<*>? = Identifier.init<String?>("name")
}
}
}
@@ -1,5 +1,5 @@
public open class Identifier(_myName : String?, _myHasDollar : Boolean) {
private val myName : String? = null
private val myName : String?
private var myHasDollar : Boolean = false
private var myNullable : Boolean = true
public open fun getName() : String? {
@@ -1,3 +1,3 @@
open class C() {
val f : Foo? = Foo(1, 2)
val f : Foo = Foo(1, 2)
}
@@ -4,6 +4,6 @@ open class Test() {
open fun test() : Unit {
var i : Int? = 10
var j : Int? = 10
System.out?.println(i + j)
System.out?.println(i!! + j!!)
}
}
@@ -0,0 +1 @@
for (init(); ; update()) body();
@@ -0,0 +1,10 @@
{
init()
while (true)
{
body()
{
update()
}
}
}
@@ -0,0 +1 @@
for (; condition() ; update()) body();
@@ -0,0 +1,9 @@
{
while (condition())
{
body()
{
update()
}
}
}
@@ -0,0 +1 @@
for (init(); condition(); ) body();
@@ -0,0 +1,7 @@
{
init()
while (condition())
{
body()
}
}
@@ -1 +1 @@
(c.getType().getName() is String)
c.getType().getName() is String
@@ -1 +1 @@
(a is String)
a is String
@@ -0,0 +1,5 @@
class Test {
public static int foo(String[] args) {
return args.length;
}
}
@@ -0,0 +1,7 @@
open class Test() {
class object {
public open fun foo(args : Array<String?>?) : Int {
return args?.size!!
}
}
}
@@ -0,0 +1,22 @@
// This is an end-of-line comment
/*
This is a block comment
*/
class C {
// This is a class comment
/**
* This is a field doc comment.
*/
private int i;
/**
* This is a function doc comment.
*/
public void foo() {
/* This is a function comment */
}
}
@@ -0,0 +1,17 @@
// This is an end-of-line comment
/*
This is a block comment
*/
open class C() {
// This is a class comment
/**
* This is a field doc comment.
*/
private var i : Int = 0
/**
* This is a function doc comment.
*/
public open fun foo() : Unit {
/* This is a function comment */
}
}
@@ -4,8 +4,8 @@ open fun putInt(i : Int?) : Unit {
}
open fun test() : Unit {
var b : Byte = 10
putInt((b).toInt())
putInt(b.toInt())
var b2 : Byte? = 10
putInt((b2).toInt())
putInt(b2?.toInt())
}
}
+1 -1
View File
@@ -4,6 +4,6 @@ open fun putInt(i : Int) : Unit {
}
open fun test() : Unit {
var b : Byte = 10
putInt((b).toInt())
putInt(b.toInt())
}
}
+4 -4
View File
@@ -1,5 +1,5 @@
public open class Identifier<T>(_myName : T?, _myHasDollar : Boolean) {
private val myName : T? = null
private val myName : T?
private var myHasDollar : Boolean = false
private var myNullable : Boolean = true
public open fun getName() : T? {
@@ -30,9 +30,9 @@ public open class User() {
class object {
public open fun main(args : Array<String?>?) : Unit {
var i1 : Identifier<*>? = Identifier.init<String?>("name", false, true)
var i2 : Identifier<Any?>? = Identifier.init<String?>("name", false)
var i3 : Identifier<Any?>? = Identifier.init<String?>("name")
var i2 : Identifier<*>? = Identifier.init<String?>("name", false)
var i3 : Identifier<*>? = Identifier.init<String?>("name")
}
}
}
fun main(args : Array<String?>?) = User.main(args)
fun main(args : Array<String>) = User.main(args as Array<String?>?)

Some files were not shown because too many files have changed in this diff Show More