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.createMainFunction;
|
||||
import static org.jetbrains.jet.j2k.visitors.TypeVisitor.*;
|
||||
import static com.intellij.psi.CommonClassNames.*;
|
||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.j2k.Converter.isConstructorPrimary;
|
||||
import static org.jetbrains.jet.j2k.visitors.TypeVisitor.*;
|
||||
import static com.intellij.psi.CommonClassNames.*;
|
||||
|
||||
/**
|
||||
* @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.IdentifierImpl;
|
||||
|
||||
import static org.jetbrains.jet.j2k.visitors.TypeVisitor.JAVA_LANG_OBJECT;
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT;
|
||||
|
||||
/**
|
||||
* @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