TypeVisitor to Kotlin
This commit is contained in:
committed by
Pavel V. Talanov
parent
3130b750d3
commit
85755df615
@@ -35,7 +35,7 @@ import java.util.*;
|
|||||||
|
|
||||||
import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
|
import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
|
||||||
import static org.jetbrains.jet.j2k.ConverterUtil.createMainFunction;
|
import static org.jetbrains.jet.j2k.ConverterUtil.createMainFunction;
|
||||||
import static org.jetbrains.jet.j2k.visitors.TypeVisitor.*;
|
import static com.intellij.psi.CommonClassNames.*;
|
||||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.j2k.Converter.isConstructorPrimary;
|
import static org.jetbrains.jet.j2k.Converter.isConstructorPrimary;
|
||||||
import static org.jetbrains.jet.j2k.visitors.TypeVisitor.*;
|
import static com.intellij.psi.CommonClassNames.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ignatov
|
* @author ignatov
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.jet.j2k.ast.DummyMethodCallExpression;
|
|||||||
import org.jetbrains.jet.j2k.ast.DummyStringExpression;
|
import org.jetbrains.jet.j2k.ast.DummyStringExpression;
|
||||||
import org.jetbrains.jet.j2k.ast.IdentifierImpl;
|
import org.jetbrains.jet.j2k.ast.IdentifierImpl;
|
||||||
|
|
||||||
import static org.jetbrains.jet.j2k.visitors.TypeVisitor.JAVA_LANG_OBJECT;
|
import static com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ignatov
|
* @author ignatov
|
||||||
|
|||||||
@@ -1,218 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.visitors;
|
|
||||||
|
|
||||||
import com.intellij.psi.*;
|
|
||||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
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 org.jetbrains.jet.j2k.util.AstUtil;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class TypeVisitor extends PsiTypeVisitor<Type> implements J2KVisitor {
|
|
||||||
public static final String JAVA_LANG_BYTE = "java.lang.Byte";
|
|
||||||
public static final String JAVA_LANG_CHARACTER = "java.lang.Character";
|
|
||||||
public static final String JAVA_LANG_DOUBLE = "java.lang.Double";
|
|
||||||
public static final String JAVA_LANG_FLOAT = "java.lang.Float";
|
|
||||||
public static final String JAVA_LANG_INTEGER = "java.lang.Integer";
|
|
||||||
public static final String JAVA_LANG_LONG = "java.lang.Long";
|
|
||||||
public static final String JAVA_LANG_SHORT = "java.lang.Short";
|
|
||||||
private static final String JAVA_LANG_BOOLEAN = "java.lang.Boolean";
|
|
||||||
public static final String JAVA_LANG_OBJECT = "java.lang.Object";
|
|
||||||
public static final String JAVA_LANG_STRING = "java.lang.String";
|
|
||||||
private static final String JAVA_LANG_ITERABLE = "java.lang.Iterable";
|
|
||||||
private static final String JAVA_UTIL_ITERATOR = "java.util.Iterator";
|
|
||||||
private final Converter myConverter;
|
|
||||||
private Type myResult = new EmptyType();
|
|
||||||
|
|
||||||
public TypeVisitor(@NotNull Converter myConverter) {
|
|
||||||
this.myConverter = myConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Type getResult() {
|
|
||||||
return myResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitPrimitiveType(@NotNull PsiPrimitiveType primitiveType) {
|
|
||||||
final String name = primitiveType.getCanonicalText();
|
|
||||||
final IdentifierImpl identifier = new IdentifierImpl(name);
|
|
||||||
|
|
||||||
if (name.equals("void")) {
|
|
||||||
myResult = new PrimitiveType(new IdentifierImpl("Unit"));
|
|
||||||
}
|
|
||||||
else if (Node.PRIMITIVE_TYPES.contains(name)) {
|
|
||||||
myResult = new PrimitiveType(new IdentifierImpl(AstUtil.upperFirstCharacter(name)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myResult = new PrimitiveType(identifier);
|
|
||||||
}
|
|
||||||
return super.visitPrimitiveType(primitiveType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitArrayType(@NotNull PsiArrayType arrayType) {
|
|
||||||
if (myResult instanceof EmptyType) {
|
|
||||||
myResult = new ArrayType(getConverter().typeToType(arrayType.getComponentType()), true);
|
|
||||||
}
|
|
||||||
return super.visitArrayType(arrayType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitClassType(@NotNull PsiClassType classType) {
|
|
||||||
final IdentifierImpl identifier = constructClassTypeIdentifier(classType);
|
|
||||||
final List<Type> resolvedClassTypeParams = createRawTypesForResolvedReference(classType);
|
|
||||||
|
|
||||||
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
|
||||||
myResult = new ClassType(identifier, resolvedClassTypeParams, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myResult = new ClassType(identifier, getConverter().typesToTypeList(classType.getParameters()), true);
|
|
||||||
}
|
|
||||||
return super.visitClassType(classType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private IdentifierImpl constructClassTypeIdentifier(@NotNull PsiClassType classType) {
|
|
||||||
final PsiClass psiClass = classType.resolve();
|
|
||||||
if (psiClass != null) {
|
|
||||||
String qualifiedName = psiClass.getQualifiedName();
|
|
||||||
if (qualifiedName != null) {
|
|
||||||
if (!qualifiedName.equals("java.lang.Object") && getConverter().hasFlag(J2KConverterFlags.FULLY_QUALIFIED_TYPE_NAMES)) {
|
|
||||||
return new IdentifierImpl(qualifiedName);
|
|
||||||
}
|
|
||||||
if (qualifiedName.equals(JAVA_LANG_ITERABLE)) {
|
|
||||||
return new IdentifierImpl(JAVA_LANG_ITERABLE);
|
|
||||||
}
|
|
||||||
if (qualifiedName.equals(JAVA_UTIL_ITERATOR)) {
|
|
||||||
return new IdentifierImpl(JAVA_UTIL_ITERATOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String classTypeName = createQualifiedName(classType);
|
|
||||||
|
|
||||||
if (classTypeName.isEmpty()) {
|
|
||||||
return new IdentifierImpl(getClassTypeName(classType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IdentifierImpl(classTypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String createQualifiedName(@NotNull PsiClassType classType) {
|
|
||||||
String classTypeName = "";
|
|
||||||
if (classType instanceof PsiClassReferenceType) {
|
|
||||||
final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType) classType).getReference();
|
|
||||||
if (reference.isQualified()) {
|
|
||||||
String result = new IdentifierImpl(reference.getReferenceName()).toKotlin();
|
|
||||||
PsiElement qualifier = reference.getQualifier();
|
|
||||||
while (qualifier != null) {
|
|
||||||
final PsiJavaCodeReferenceElement p = (PsiJavaCodeReferenceElement) qualifier;
|
|
||||||
result = new IdentifierImpl(p.getReferenceName()).toKotlin() + "." + result; // TODO: maybe need to replace by safe call?
|
|
||||||
qualifier = p.getQualifier();
|
|
||||||
}
|
|
||||||
classTypeName = result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return classTypeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private List<Type> createRawTypesForResolvedReference(@NotNull PsiClassType classType) {
|
|
||||||
final List<Type> typeParams = new LinkedList<Type>();
|
|
||||||
if (classType instanceof PsiClassReferenceType) {
|
|
||||||
final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType) classType).getReference();
|
|
||||||
final PsiElement resolve = reference.resolve();
|
|
||||||
if (resolve != null) {
|
|
||||||
if (resolve instanceof PsiClass)
|
|
||||||
//noinspection UnusedDeclaration
|
|
||||||
{
|
|
||||||
for (PsiTypeParameter p : ((PsiClass) resolve).getTypeParameters()) {
|
|
||||||
Type boundType = p.getSuperTypes().length > 0 ?
|
|
||||||
new ClassType(new IdentifierImpl(getClassTypeName(p.getSuperTypes()[0])), getConverter().typesToTypeList(p.getSuperTypes()[0].getParameters()), true)
|
|
||||||
:
|
|
||||||
new StarProjectionType();
|
|
||||||
|
|
||||||
typeParams.add(boundType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return typeParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String getClassTypeName(@NotNull PsiClassType classType) {
|
|
||||||
String canonicalTypeStr = classType.getCanonicalText();
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_OBJECT)) return "Any";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_BYTE)) return "Byte";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_CHARACTER)) return "Char";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_DOUBLE)) return "Double";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_FLOAT)) return "Float";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_INTEGER)) return "Int";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_LONG)) return "Long";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_SHORT)) return "Short";
|
|
||||||
if (canonicalTypeStr.equals(JAVA_LANG_BOOLEAN)) return "Boolean";
|
|
||||||
return classType.getClassName() != null ? classType.getClassName() : classType.getCanonicalText();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitWildcardType(@NotNull PsiWildcardType wildcardType) {
|
|
||||||
if (wildcardType.isExtends()) {
|
|
||||||
myResult = new OutProjectionType(getConverter().typeToType(wildcardType.getExtendsBound()));
|
|
||||||
}
|
|
||||||
else if (wildcardType.isSuper()) {
|
|
||||||
myResult = new InProjectionType(getConverter().typeToType(wildcardType.getSuperBound()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myResult = new StarProjectionType();
|
|
||||||
}
|
|
||||||
return super.visitWildcardType(wildcardType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitEllipsisType(@NotNull PsiEllipsisType ellipsisType) {
|
|
||||||
myResult = new VarArg(getConverter().typeToType(ellipsisType.getComponentType()));
|
|
||||||
return super.visitEllipsisType(ellipsisType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) {
|
|
||||||
return super.visitCapturedWildcardType(capturedWildcardType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitDisjunctionType(PsiDisjunctionType disjunctionType) {
|
|
||||||
return super.visitDisjunctionType(disjunctionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Converter getConverter() {
|
|
||||||
return myConverter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
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 org.jetbrains.jet.j2k.util.AstUtil
|
||||||
|
import java.util.LinkedList
|
||||||
|
import java.util.List
|
||||||
|
|
||||||
|
public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisitor<Type?>(), J2KVisitor {
|
||||||
|
private var myResult : Type = EmptyType()
|
||||||
|
public open fun getResult() : Type {
|
||||||
|
return myResult
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun visitPrimitiveType(primitiveType: PsiPrimitiveType?) : Type? {
|
||||||
|
val name : String = primitiveType?.getCanonicalText()!!
|
||||||
|
val identifier : IdentifierImpl = IdentifierImpl(name)
|
||||||
|
if (name == "void") {
|
||||||
|
myResult = PrimitiveType(IdentifierImpl("Unit"))
|
||||||
|
}
|
||||||
|
else if (Node.PRIMITIVE_TYPES.contains(name)) {
|
||||||
|
myResult = PrimitiveType(IdentifierImpl(AstUtil.upperFirstCharacter(name)))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
myResult = PrimitiveType(identifier)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun visitArrayType(arrayType: PsiArrayType?) : Type? {
|
||||||
|
if (myResult is EmptyType) {
|
||||||
|
myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun visitClassType(classType : PsiClassType?) : Type? {
|
||||||
|
if (classType == null) return null
|
||||||
|
val identifier : IdentifierImpl = constructClassTypeIdentifier(classType)
|
||||||
|
val resolvedClassTypeParams : List<Type> = createRawTypesForResolvedReference(classType)
|
||||||
|
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
||||||
|
myResult = ClassType(identifier, resolvedClassTypeParams, true)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()).requireNoNulls(), true)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun constructClassTypeIdentifier(classType : PsiClassType) : IdentifierImpl {
|
||||||
|
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 IdentifierImpl(qualifiedName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualifiedName.equals(CommonClassNames.JAVA_LANG_ITERABLE)) {
|
||||||
|
return IdentifierImpl(CommonClassNames.JAVA_LANG_ITERABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualifiedName.equals(CommonClassNames.JAVA_UTIL_ITERATOR)) {
|
||||||
|
return IdentifierImpl(CommonClassNames.JAVA_UTIL_ITERATOR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val classTypeName : String? = createQualifiedName(classType)
|
||||||
|
if (classTypeName?.isEmpty().sure())
|
||||||
|
{
|
||||||
|
return IdentifierImpl(getClassTypeName(classType))
|
||||||
|
}
|
||||||
|
|
||||||
|
return IdentifierImpl(classTypeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createRawTypesForResolvedReference(classType : PsiClassType) : List<Type> {
|
||||||
|
val typeParams : List<Type> = 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(IdentifierImpl(getClassTypeName(superTypes[0]!!)),
|
||||||
|
myConverter.typesToTypeList(superTypes[0]!!.getParameters()).requireNoNulls(),
|
||||||
|
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 null
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun visitEllipsisType(ellipsisType : PsiEllipsisType?) : Type? {
|
||||||
|
myResult = VarArg(myConverter.typeToType(ellipsisType?.getComponentType()))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun getConverter() : Converter = myConverter
|
||||||
|
|
||||||
|
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 = IdentifierImpl(reference.getReferenceName()).toKotlin()
|
||||||
|
var qualifier : PsiElement? = reference.getQualifier()
|
||||||
|
while (qualifier != null)
|
||||||
|
{
|
||||||
|
val p : PsiJavaCodeReferenceElement = (qualifier as PsiJavaCodeReferenceElement)
|
||||||
|
result = IdentifierImpl(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())!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user