Reformat code to use 4 spaces indent

This commit is contained in:
Andrey Breslav
2012-01-27 17:33:00 +04:00
parent e678e072f1
commit 6c5bfc3b8e
93 changed files with 3856 additions and 3667 deletions
File diff suppressed because it is too large Load Diff
@@ -16,101 +16,103 @@ import static org.jetbrains.jet.j2k.Converter.NOT_NULL_ANNOTATIONS;
* @author ignatov * @author ignatov
*/ */
public class ConverterUtil { public class ConverterUtil {
private ConverterUtil() { private ConverterUtil() {
}
@NotNull
public static String createMainFunction(@NotNull PsiFile file) {
List<Pair<String, PsiMethod>> classNamesWithMains = new LinkedList<Pair<String, PsiMethod>>();
for (PsiClass c : ((PsiJavaFile) file).getClasses()) {
PsiMethod main = findMainMethod(c);
if (main != null) {
classNamesWithMains.add(new Pair<String, PsiMethod>(c.getName(), main));
}
}
if (classNamesWithMains.size() > 0) {
String className = classNamesWithMains.get(0).getFirst();
return MessageFormat.format("fun main(args : Array<String?>?) = {0}.main(args)", className);
}
return "";
}
@Nullable
private static PsiMethod findMainMethod(@NotNull PsiClass aClass) {
if (isMainClass(aClass)) {
final PsiMethod[] mainMethods = aClass.findMethodsByName("main", false);
return findMainMethod(mainMethods);
}
return null;
}
@Nullable
private static PsiMethod findMainMethod(@NotNull PsiMethod[] mainMethods) {
for (PsiMethod mainMethod : mainMethods) {
if (isMainMethod(mainMethod)) return mainMethod;
}
return null;
}
private static boolean isMainClass(@NotNull PsiClass psiClass) {
if (psiClass instanceof PsiAnonymousClass) return false;
if (psiClass.isInterface()) return false;
return psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC);
}
public static boolean isMainMethod(@Nullable PsiMethod method) {
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;
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 1) return false;
final PsiType type = parameters[0].getType();
if (!(type instanceof PsiArrayType)) return false;
final PsiType componentType = ((PsiArrayType) type).getComponentType();
return componentType.equalsToText("java.lang.String");
}
public static int countWritingAccesses(@Nullable PsiElement element, @Nullable PsiElement container) {
int counter = 0;
if (container != null) {
ReferenceCollector visitor = new ReferenceCollector();
container.accept(visitor);
for (PsiReferenceExpression e : visitor.getCollectedReferences())
if (e.isReferenceTo(element) && PsiUtil.isAccessedForWriting(e))
counter++;
}
return counter;
}
static boolean isReadOnly(PsiElement element, PsiElement container) {
return countWritingAccesses(element, container) == 0;
}
public static boolean isAnnotatedAsNotNull(@Nullable PsiModifierList modifierList) {
if (modifierList != null) {
PsiAnnotation[] annotations = modifierList.getAnnotations();
for (PsiAnnotation a : annotations) {
String qualifiedName = a.getQualifiedName();
if (qualifiedName != null && NOT_NULL_ANNOTATIONS.contains(qualifiedName))
return true;
}
}
return false;
}
static class ReferenceCollector extends JavaRecursiveElementVisitor {
public List<PsiReferenceExpression> getCollectedReferences() {
return myCollectedReferences;
} }
private List<PsiReferenceExpression> myCollectedReferences = new LinkedList<PsiReferenceExpression>(); @NotNull
public static String createMainFunction(@NotNull PsiFile file) {
List<Pair<String, PsiMethod>> classNamesWithMains = new LinkedList<Pair<String, PsiMethod>>();
@Override for (PsiClass c : ((PsiJavaFile) file).getClasses()) {
public void visitReferenceExpression(PsiReferenceExpression expression) { PsiMethod main = findMainMethod(c);
super.visitReferenceExpression(expression); if (main != null) {
myCollectedReferences.add(expression); classNamesWithMains.add(new Pair<String, PsiMethod>(c.getName(), main));
}
}
if (classNamesWithMains.size() > 0) {
String className = classNamesWithMains.get(0).getFirst();
return MessageFormat.format("fun main(args : Array<String?>?) = {0}.main(args)", className);
}
return "";
}
@Nullable
private static PsiMethod findMainMethod(@NotNull PsiClass aClass) {
if (isMainClass(aClass)) {
final PsiMethod[] mainMethods = aClass.findMethodsByName("main", false);
return findMainMethod(mainMethods);
}
return null;
}
@Nullable
private static PsiMethod findMainMethod(@NotNull PsiMethod[] mainMethods) {
for (PsiMethod mainMethod : mainMethods) {
if (isMainMethod(mainMethod)) return mainMethod;
}
return null;
}
private static boolean isMainClass(@NotNull PsiClass psiClass) {
if (psiClass instanceof PsiAnonymousClass) return false;
if (psiClass.isInterface()) return false;
return psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC);
}
public static boolean isMainMethod(@Nullable PsiMethod method) {
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;
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 1) return false;
final PsiType type = parameters[0].getType();
if (!(type instanceof PsiArrayType)) return false;
final PsiType componentType = ((PsiArrayType) type).getComponentType();
return componentType.equalsToText("java.lang.String");
}
public static int countWritingAccesses(@Nullable PsiElement element, @Nullable PsiElement container) {
int counter = 0;
if (container != null) {
ReferenceCollector visitor = new ReferenceCollector();
container.accept(visitor);
for (PsiReferenceExpression e : visitor.getCollectedReferences())
if (e.isReferenceTo(element) && PsiUtil.isAccessedForWriting(e)) {
counter++;
}
}
return counter;
}
static boolean isReadOnly(PsiElement element, PsiElement container) {
return countWritingAccesses(element, container) == 0;
}
public static boolean isAnnotatedAsNotNull(@Nullable PsiModifierList modifierList) {
if (modifierList != null) {
PsiAnnotation[] annotations = modifierList.getAnnotations();
for (PsiAnnotation a : annotations) {
String qualifiedName = a.getQualifiedName();
if (qualifiedName != null && NOT_NULL_ANNOTATIONS.contains(qualifiedName)) {
return true;
}
}
}
return false;
}
static class ReferenceCollector extends JavaRecursiveElementVisitor {
public List<PsiReferenceExpression> getCollectedReferences() {
return myCollectedReferences;
}
private List<PsiReferenceExpression> myCollectedReferences = new LinkedList<PsiReferenceExpression>();
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
myCollectedReferences.add(expression);
}
} }
}
} }
@@ -38,178 +38,185 @@ import java.net.URLClassLoader;
* @author ignatov * @author ignatov
*/ */
public class JavaToKotlinTranslator { public class JavaToKotlinTranslator {
private JavaToKotlinTranslator() { private JavaToKotlinTranslator() {
}
@Nullable
private static PsiFile createFile(@NotNull String text) {
JavaCoreEnvironment javaCoreEnvironment = setUpJavaCoreEnvironment();
return PsiFileFactory.getInstance(javaCoreEnvironment.getProject()).createFileFromText(
"test.java", JavaLanguage.INSTANCE, text
);
}
@Nullable
static PsiFile createFile(@NotNull JavaCoreEnvironment javaCoreEnvironment, @NotNull String text) {
return PsiFileFactory.getInstance(javaCoreEnvironment.getProject()).createFileFromText(
"test.java", JavaLanguage.INSTANCE, text
);
}
@NotNull
static JavaCoreEnvironment setUpJavaCoreEnvironment() {
JavaCoreEnvironment javaCoreEnvironment = new JavaCoreEnvironment(new Disposable() {
@Override
public void dispose() {
}
});
javaCoreEnvironment.addToClasspath(findRtJar());
File annotations = findAnnotations();
if (annotations != null && annotations.exists()) {
javaCoreEnvironment.addToClasspath(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 findRtJar() {
String javaHome = System.getenv("JAVA_HOME");
File rtJar;
if (javaHome == null) {
rtJar = findActiveRtJar(true);
if (rtJar == null) {
throw new SetupJavaCoreEnvironmentException("JAVA_HOME environment variable needs to be defined");
}
} else {
rtJar = findRtJar(javaHome);
} }
if (rtJar == null || !rtJar.exists()) { @Nullable
rtJar = findActiveRtJar(true); private static PsiFile createFile(@NotNull String text) {
JavaCoreEnvironment javaCoreEnvironment = setUpJavaCoreEnvironment();
if ((rtJar == null || !rtJar.exists())) { return PsiFileFactory.getInstance(javaCoreEnvironment.getProject()).createFileFromText(
throw new SetupJavaCoreEnvironmentException("No rt.jar found under JAVA_HOME=" + javaHome); "test.java", JavaLanguage.INSTANCE, text
} );
}
return rtJar;
}
@Nullable
private static File findRtJar(String javaHome) {
File rtJar = new File(javaHome, "jre/lib/rt.jar");
if (rtJar.exists()) {
return rtJar;
} }
File classesJar = new File(new File(javaHome).getParentFile().getAbsolutePath(), "Classes/classes.jar"); @Nullable
if (classesJar.exists()) { static PsiFile createFile(@NotNull JavaCoreEnvironment javaCoreEnvironment, @NotNull String text) {
return classesJar; return PsiFileFactory.getInstance(javaCoreEnvironment.getProject()).createFileFromText(
"test.java", JavaLanguage.INSTANCE, text
);
} }
return null;
}
@Nullable @NotNull
private static File findAnnotations() { static JavaCoreEnvironment setUpJavaCoreEnvironment() {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); JavaCoreEnvironment javaCoreEnvironment = new JavaCoreEnvironment(new Disposable() {
if (systemClassLoader instanceof URLClassLoader) { @Override
URLClassLoader loader = (URLClassLoader) systemClassLoader; public void dispose() {
for (URL url : loader.getURLs()) }
if ("file".equals(url.getProtocol()) && url.getFile().endsWith("/annotations.jar")) });
return new File(url.getFile());
}
return null;
}
@Nullable javaCoreEnvironment.addToClasspath(findRtJar());
private static File findActiveRtJar(boolean failOnError) { File annotations = findAnnotations();
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); if (annotations != null && annotations.exists()) {
if (systemClassLoader instanceof URLClassLoader) { javaCoreEnvironment.addToClasspath(annotations);
URLClassLoader loader = (URLClassLoader) systemClassLoader;
for (URL url : loader.getURLs()) {
if ("file".equals(url.getProtocol())) {
if (url.getFile().endsWith("/lib/rt.jar")) {
return new File(url.getFile());
}
if (url.getFile().endsWith("/Classes/classes.jar")) {
return new File(url.getFile()).getAbsoluteFile();
}
} }
} return javaCoreEnvironment;
if (failOnError) {
throw new SetupJavaCoreEnvironmentException("Could not find rt.jar in system class loader: " + StringUtil.join(loader.getURLs(), new Function<URL, String>() {
@NotNull
@Override
public String fun(@NotNull URL url) {
return url.toString() + "\n";
}
}, ", "));
}
} else if (failOnError) {
throw new SetupJavaCoreEnvironmentException("System class loader is not an URLClassLoader: " + systemClassLoader);
} }
return null;
}
static void setClassIdentifiers(@NotNull PsiElement psiFile) { @NotNull
ClassVisitor c = new ClassVisitor(); static String prettify(@Nullable String code) {
psiFile.accept(c); if (code == null) {
Converter.clearClassIdentifiers(); return "";
Converter.setClassIdentifiers(c.getClassIdentifiers()); }
} return code
.trim()
@NotNull .replaceAll("\r\n", "\n")
static String generateKotlinCode(@NotNull String javaCode) { .replaceAll(" \n", "\n")
PsiFile file = createFile(javaCode); .replaceAll("\n ", "\n")
if (file != null && file instanceof PsiJavaFile) { .replaceAll("\n+", "\n")
setClassIdentifiers(file); .replaceAll(" +", " ")
return prettify(Converter.fileToFile((PsiJavaFile) file).toKotlin()); .trim()
;
} }
return "";
}
@NotNull @Nullable
static String generateKotlinCodeWithCompatibilityImport(@NotNull String javaCode) { private static File findRtJar() {
PsiFile file = createFile(javaCode); String javaHome = System.getenv("JAVA_HOME");
if (file != null && file instanceof PsiJavaFile) { File rtJar;
setClassIdentifiers(file); if (javaHome == null) {
return prettify(Converter.fileToFileWithCompatibilityImport((PsiJavaFile) file).toKotlin()); rtJar = findActiveRtJar(true);
}
return "";
}
public static void main(@NotNull String[] args) throws IOException { if (rtJar == null) {
//noinspection UseOfSystemOutOrSystemErr throw new SetupJavaCoreEnvironmentException("JAVA_HOME environment variable needs to be defined");
final PrintStream out = System.out; }
if (args.length == 1) { }
String kotlinCode = ""; else {
try { rtJar = findRtJar(javaHome);
kotlinCode = generateKotlinCode(args[0]); }
} catch (Exception e) {
out.println("EXCEPTION: " + e.getMessage()); if (rtJar == null || !rtJar.exists()) {
} rtJar = findActiveRtJar(true);
if (kotlinCode.isEmpty())
out.println("EXCEPTION: generated code is empty."); if ((rtJar == null || !rtJar.exists())) {
else throw new SetupJavaCoreEnvironmentException("No rt.jar found under JAVA_HOME=" + javaHome);
out.println(kotlinCode); }
} else { }
out.println("EXCEPTION: wrong number of arguments (should be 1)."); return rtJar;
}
@Nullable
private static File findRtJar(String javaHome) {
File rtJar = new File(javaHome, "jre/lib/rt.jar");
if (rtJar.exists()) {
return rtJar;
}
File classesJar = new File(new File(javaHome).getParentFile().getAbsolutePath(), "Classes/classes.jar");
if (classesJar.exists()) {
return classesJar;
}
return null;
}
@Nullable
private static File findAnnotations() {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if (systemClassLoader instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) systemClassLoader;
for (URL url : loader.getURLs())
if ("file".equals(url.getProtocol()) && url.getFile().endsWith("/annotations.jar")) {
return new File(url.getFile());
}
}
return null;
}
@Nullable
private static File findActiveRtJar(boolean failOnError) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if (systemClassLoader instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) systemClassLoader;
for (URL url : loader.getURLs()) {
if ("file".equals(url.getProtocol())) {
if (url.getFile().endsWith("/lib/rt.jar")) {
return new File(url.getFile());
}
if (url.getFile().endsWith("/Classes/classes.jar")) {
return new File(url.getFile()).getAbsoluteFile();
}
}
}
if (failOnError) {
throw new SetupJavaCoreEnvironmentException("Could not find rt.jar in system class loader: " + StringUtil.join(loader.getURLs(), new Function<URL, String>() {
@NotNull
@Override
public String fun(@NotNull URL url) {
return url.toString() + "\n";
}
}, ", "));
}
}
else if (failOnError) {
throw new SetupJavaCoreEnvironmentException("System class loader is not an URLClassLoader: " + systemClassLoader);
}
return null;
}
static void setClassIdentifiers(@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(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(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).");
}
} }
}
} }
@@ -4,6 +4,6 @@ package org.jetbrains.jet.j2k;
* @author ignatov * @author ignatov
*/ */
public class SetupJavaCoreEnvironmentException extends RuntimeException { public class SetupJavaCoreEnvironmentException extends RuntimeException {
public SetupJavaCoreEnvironmentException(String s) { public SetupJavaCoreEnvironmentException(String s) {
} }
} }
@@ -9,20 +9,20 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class AnonymousClass extends Class { public class AnonymousClass extends Class {
public AnonymousClass(List<Member> members) { public AnonymousClass(List<Member> members) {
super(new IdentifierImpl("anonClass"), super(new IdentifierImpl("anonClass"),
Collections.<String>emptySet(), Collections.<String>emptySet(),
Collections.<Element>emptyList(), Collections.<Element>emptyList(),
Collections.<Type>emptyList(), Collections.<Type>emptyList(),
Collections.<Expression>emptyList(), Collections.<Expression>emptyList(),
Collections.<Type>emptyList(), Collections.<Type>emptyList(),
getMembers(members) getMembers(members)
); );
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return bodyToKotlin(); return bodyToKotlin();
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ArrayAccessExpression extends Expression { public class ArrayAccessExpression extends Expression {
private final Expression myExpression; private final Expression myExpression;
private final Expression myIndex; private final Expression myIndex;
public ArrayAccessExpression(Expression expression, Expression index) { public ArrayAccessExpression(Expression expression, Expression index) {
myExpression = expression; myExpression = expression;
myIndex = index; myIndex = index;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myExpression.toKotlin() + "[" + myIndex.toKotlin() + "]"; return myExpression.toKotlin() + "[" + myIndex.toKotlin() + "]";
} }
} }
@@ -9,62 +9,64 @@ import java.util.*;
* @author ignatov * @author ignatov
*/ */
public class ArrayInitializerExpression extends Expression { public class ArrayInitializerExpression extends Expression {
private final Type myType; private final Type myType;
private final List<Expression> myInitializers; private final List<Expression> myInitializers;
public ArrayInitializerExpression(final Type type, List<Expression> initializers) { public ArrayInitializerExpression(final Type type, List<Expression> initializers) {
myType = type; myType = type;
myInitializers = initializers; myInitializers = initializers;
}
@NotNull
private static String createArrayFunction(@NotNull final Type type) {
String sType = innerTypeStr(type);
if (PRIMITIVE_TYPES.contains(sType))
return sType + "Array"; // intArray
return AstUtil.lowerFirstCharacter(type.convertedToNotNull().toKotlin()); // array<Foo?>
}
@NotNull
private static String innerTypeStr(@NotNull final Type type) {
return type.convertedToNotNull().toKotlin().replace("Array", "").toLowerCase();
}
@NotNull
private static String createInitializers(@NotNull final Type type, @NotNull final List<Expression> initializers) {
List<String> arguments = new LinkedList<String>();
for (Expression i : initializers)
arguments.add(explicitConvertIfNeeded(type, i));
return AstUtil.join(arguments, COMMA_WITH_SPACE);
}
@NotNull
private static String explicitConvertIfNeeded(@NotNull final Type type, @NotNull final Expression i) {
Set<String> doubleOrFloatTypes = new HashSet<String>(
Arrays.asList("double", "float", "java.lang.double", "java.lang.float")
);
String afterReplace = innerTypeStr(type).replace(">", "").replace("<", "").replace("?", "");
if (doubleOrFloatTypes.contains(afterReplace)) {
if (i.getKind() == Kind.LITERAL) {
if (i.toKotlin().contains("."))
return i.toKotlin();
return i.toKotlin() + DOT + ZERO;
}
return "(" + i.toKotlin() + ")" + getConversion(afterReplace);
} }
return i.toKotlin();
}
@NotNull @NotNull
private static String getConversion(@NotNull final String afterReplace) { private static String createArrayFunction(@NotNull final Type type) {
if (afterReplace.contains("double")) return DOT + "dbl"; String sType = innerTypeStr(type);
if (afterReplace.contains("float")) return DOT + "flt"; if (PRIMITIVE_TYPES.contains(sType)) {
return ""; return sType + "Array"; // intArray
} }
return AstUtil.lowerFirstCharacter(type.convertedToNotNull().toKotlin()); // array<Foo?>
}
@NotNull @NotNull
@Override private static String innerTypeStr(@NotNull final Type type) {
public String toKotlin() { return type.convertedToNotNull().toKotlin().replace("Array", "").toLowerCase();
return createArrayFunction(myType) + "(" + createInitializers(myType, myInitializers) + ")"; }
}
@NotNull
private static String createInitializers(@NotNull final Type type, @NotNull final List<Expression> initializers) {
List<String> arguments = new LinkedList<String>();
for (Expression i : initializers)
arguments.add(explicitConvertIfNeeded(type, i));
return AstUtil.join(arguments, COMMA_WITH_SPACE);
}
@NotNull
private static String explicitConvertIfNeeded(@NotNull final Type type, @NotNull final Expression i) {
Set<String> doubleOrFloatTypes = new HashSet<String>(
Arrays.asList("double", "float", "java.lang.double", "java.lang.float")
);
String afterReplace = innerTypeStr(type).replace(">", "").replace("<", "").replace("?", "");
if (doubleOrFloatTypes.contains(afterReplace)) {
if (i.getKind() == Kind.LITERAL) {
if (i.toKotlin().contains(".")) {
return i.toKotlin();
}
return i.toKotlin() + DOT + ZERO;
}
return "(" + i.toKotlin() + ")" + getConversion(afterReplace);
}
return i.toKotlin();
}
@NotNull
private static String getConversion(@NotNull final String afterReplace) {
if (afterReplace.contains("double")) return DOT + "dbl";
if (afterReplace.contains("float")) return DOT + "flt";
return "";
}
@NotNull
@Override
public String toKotlin() {
return createArrayFunction(myType) + "(" + createInitializers(myType, myInitializers) + ")";
}
} }
@@ -6,27 +6,28 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ArrayType extends Type { public class ArrayType extends Type {
private final Type myType; private final Type myType;
public ArrayType(Type type) { public ArrayType(Type type) {
myType = type; myType = type;
} }
public Type getInnerType() { public Type getInnerType() {
return myType; return myType;
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.ARRAY_TYPE; return Kind.ARRAY_TYPE;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (PRIMITIVE_TYPES.contains(myType.toKotlin().toLowerCase())) if (PRIMITIVE_TYPES.contains(myType.toKotlin().toLowerCase())) {
return myType.toKotlin() + "Array" + isNullableStr(); // returns IntArray, BooleanArray, etc. return myType.toKotlin() + "Array" + isNullableStr(); // returns IntArray, BooleanArray, etc.
return "Array" + "<" + myType.toKotlin() + ">" + isNullableStr(); }
} return "Array" + "<" + myType.toKotlin() + ">" + isNullableStr();
}
} }
@@ -9,45 +9,48 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class ArrayWithoutInitializationExpression extends Expression { public class ArrayWithoutInitializationExpression extends Expression {
private final Type myType; private final Type myType;
private final List<Expression> myExpressions; private final List<Expression> myExpressions;
public ArrayWithoutInitializationExpression(Type type, List<Expression> expressions) { public ArrayWithoutInitializationExpression(Type type, List<Expression> expressions) {
myType = type; myType = type;
myExpressions = expressions; myExpressions = expressions;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myType.getKind() == Kind.ARRAY_TYPE) if (myType.getKind() == Kind.ARRAY_TYPE) {
return constructInnerType((ArrayType) myType, myExpressions); return constructInnerType((ArrayType) myType, myExpressions);
return getConstructorName(myType); }
} return getConstructorName(myType);
}
@NotNull @NotNull
private static String constructInnerType(@NotNull ArrayType hostType, @NotNull List<Expression> expressions) { private static String constructInnerType(@NotNull ArrayType hostType, @NotNull List<Expression> expressions) {
if (expressions.size() == 1) if (expressions.size() == 1) {
return oneDim(hostType, expressions.get(0)); return oneDim(hostType, expressions.get(0));
Type innerType = hostType.getInnerType(); }
if (expressions.size() > 1 && innerType.getKind() == Kind.ARRAY_TYPE) Type innerType = hostType.getInnerType();
return oneDim(hostType, expressions.get(0), "{" + constructInnerType((ArrayType) innerType, expressions.subList(1, expressions.size())) + "}"); if (expressions.size() > 1 && innerType.getKind() == Kind.ARRAY_TYPE) {
return getConstructorName(hostType); return oneDim(hostType, expressions.get(0), "{" + constructInnerType((ArrayType) innerType, expressions.subList(1, expressions.size())) + "}");
} }
return getConstructorName(hostType);
}
@NotNull @NotNull
private static String oneDim(@NotNull Type type, @NotNull Expression size) { private static String oneDim(@NotNull Type type, @NotNull Expression size) {
return oneDim(type, size, EMPTY); return oneDim(type, size, EMPTY);
} }
@NotNull @NotNull
private static String oneDim(@NotNull Type type, @NotNull Expression size, @NotNull String init) { private static String oneDim(@NotNull Type type, @NotNull Expression size, @NotNull String init) {
String commaWithInit = init.isEmpty() ? EMPTY : COMMA_WITH_SPACE + init; String commaWithInit = init.isEmpty() ? EMPTY : COMMA_WITH_SPACE + init;
return getConstructorName(type) + "(" + size.toKotlin() + commaWithInit + ")"; return getConstructorName(type) + "(" + size.toKotlin() + commaWithInit + ")";
} }
@NotNull @NotNull
private static String getConstructorName(@NotNull Type type) { private static String getConstructorName(@NotNull Type type) {
return AstUtil.replaceLastQuest(type.toKotlin()); return AstUtil.replaceLastQuest(type.toKotlin());
} }
} }
@@ -6,18 +6,18 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class AssertStatement extends Statement { public class AssertStatement extends Statement {
private final Expression myCondition; private final Expression myCondition;
private final Expression myDetail; private final Expression myDetail;
public AssertStatement(Expression condition, Expression detail) { public AssertStatement(Expression condition, Expression detail) {
myCondition = condition; myCondition = condition;
myDetail = detail; myDetail = detail;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
String detail = myDetail != Expression.EMPTY_EXPRESSION ? "(" + myDetail.toKotlin() + ")" : EMPTY; String detail = myDetail != Expression.EMPTY_EXPRESSION ? "(" + myDetail.toKotlin() + ")" : EMPTY;
return "assert" + detail + SPACE + "{" + myCondition.toKotlin() + "}"; return "assert" + detail + SPACE + "{" + myCondition.toKotlin() + "}";
} }
} }
@@ -6,33 +6,33 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class AssignmentExpression extends Expression { public class AssignmentExpression extends Expression {
private final Expression myLeft; private final Expression myLeft;
private final Expression myRight; private final Expression myRight;
private final String myOp; private final String myOp;
public Expression getLeft() { public Expression getLeft() {
return myLeft; return myLeft;
} }
public Expression getRight() { public Expression getRight() {
return myRight; return myRight;
} }
public AssignmentExpression(Expression left, Expression right, String op) { public AssignmentExpression(Expression left, Expression right, String op) {
myLeft = left; myLeft = left;
myRight = right; myRight = right;
myOp = op; myOp = op;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myLeft.toKotlin() + SPACE + myOp + SPACE + myRight.toKotlin(); return myLeft.toKotlin() + SPACE + myOp + SPACE + myRight.toKotlin();
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.ASSIGNMENT_EXPRESSION; return Kind.ASSIGNMENT_EXPRESSION;
} }
} }
@@ -10,26 +10,26 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class BinaryExpression extends Expression { public class BinaryExpression extends Expression {
private final Expression myLeft; private final Expression myLeft;
private final Expression myRight; private final Expression myRight;
private final String myOp; private final String myOp;
private final List<String> myConversions; private final List<String> myConversions;
public BinaryExpression(Expression left, Expression right, String op) { public BinaryExpression(Expression left, Expression right, String op) {
this(left, right, op, Arrays.asList("", "")); this(left, right, op, Arrays.asList("", ""));
} }
public BinaryExpression(Expression left, Expression right, String op, List<String> conversions) { public BinaryExpression(Expression left, Expression right, String op, List<String> conversions) {
myLeft = left; myLeft = left;
myRight = right; myRight = right;
myOp = op; myOp = op;
myConversions = conversions; myConversions = conversions;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
List<String> expressionsWithConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(Arrays.asList(myLeft, myRight)), myConversions); List<String> expressionsWithConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(Arrays.asList(myLeft, myRight)), myConversions);
return AstUtil.join(expressionsWithConversions, SPACE + myOp + SPACE); return AstUtil.join(expressionsWithConversions, SPACE + myOp + SPACE);
} }
} }
+32 -31
View File
@@ -10,42 +10,43 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class Block extends Statement { public class Block extends Statement {
@NotNull @NotNull
public final static Block EMPTY_BLOCK = new Block(); public final static Block EMPTY_BLOCK = new Block();
private List<Statement> myStatements; private List<Statement> myStatements;
private boolean myNotEmpty = false; private boolean myNotEmpty = false;
private Block() { private Block() {
myStatements = new LinkedList<Statement>(); myStatements = new LinkedList<Statement>();
} }
public Block(List<Statement> statements) { public Block(List<Statement> statements) {
myStatements = new LinkedList<Statement>(); myStatements = new LinkedList<Statement>();
myStatements = statements; myStatements = statements;
} }
public Block(List<Statement> statements, boolean notEmpty) { public Block(List<Statement> statements, boolean notEmpty) {
myStatements = new LinkedList<Statement>(); myStatements = new LinkedList<Statement>();
myStatements = statements; myStatements = statements;
myNotEmpty = notEmpty; myNotEmpty = notEmpty;
} }
public boolean isEmpty() { public boolean isEmpty() {
return !myNotEmpty && myStatements.size() == 0; return !myNotEmpty && myStatements.size() == 0;
} }
public List<Statement> getStatements() { public List<Statement> getStatements() {
return myStatements; return myStatements;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (!isEmpty()) if (!isEmpty()) {
return "{" + N + return "{" + N +
AstUtil.joinNodes(myStatements, N) + N + AstUtil.joinNodes(myStatements, N) + N +
"}"; "}";
return EMPTY; }
} return EMPTY;
}
} }
@@ -6,26 +6,27 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class BreakStatement extends Statement { public class BreakStatement extends Statement {
private Identifier myLabel = Identifier.EMPTY_IDENTIFIER; private Identifier myLabel = Identifier.EMPTY_IDENTIFIER;
public BreakStatement(Identifier label) { public BreakStatement(Identifier label) {
myLabel = label; myLabel = label;
} }
public BreakStatement() { public BreakStatement() {
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.BREAK; return Kind.BREAK;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myLabel.isEmpty()) if (myLabel.isEmpty()) {
return "break"; return "break";
return "break" + AT + myLabel.toKotlin(); }
} return "break" + AT + myLabel.toKotlin();
}
} }
@@ -6,37 +6,40 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class CallChainExpression extends Expression { public class CallChainExpression extends Expression {
private final Expression myExpression; private final Expression myExpression;
private final Expression myIdentifier; private final Expression myIdentifier;
public Expression getIdentifier() { public Expression getIdentifier() {
return myIdentifier; return myIdentifier;
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.CALL_CHAIN; return Kind.CALL_CHAIN;
} }
public CallChainExpression(Expression expression, Expression identifier) { public CallChainExpression(Expression expression, Expression identifier) {
myExpression = expression; myExpression = expression;
myIdentifier = identifier; myIdentifier = identifier;
} }
@Override @Override
public boolean isNullable() { public boolean isNullable() {
return myIdentifier.isNullable(); return myIdentifier.isNullable();
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (!myExpression.isEmpty()) if (!myExpression.isEmpty()) {
if (myExpression.isNullable()) if (myExpression.isNullable()) {
return myExpression.toKotlin() + QUESTDOT + myIdentifier.toKotlin(); return myExpression.toKotlin() + QUESTDOT + myIdentifier.toKotlin();
else }
return myExpression.toKotlin() + DOT + myIdentifier.toKotlin(); else {
return myIdentifier.toKotlin(); return myExpression.toKotlin() + DOT + myIdentifier.toKotlin();
} }
}
return myIdentifier.toKotlin();
}
} }
@@ -10,21 +10,22 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class CaseContainer extends Statement { public class CaseContainer extends Statement {
private final List<Statement> myCaseStatement; private final List<Statement> myCaseStatement;
private final Block myBlock; private final Block myBlock;
public CaseContainer(final List<Statement> caseStatement, @NotNull final List<Statement> statements) { public CaseContainer(final List<Statement> caseStatement, @NotNull final List<Statement> statements) {
myCaseStatement = caseStatement; myCaseStatement = caseStatement;
List<Statement> newStatements = new LinkedList<Statement>(); List<Statement> newStatements = new LinkedList<Statement>();
for (Statement s : statements) for (Statement s : statements)
if (s.getKind() != Kind.BREAK && s.getKind() != Kind.CONTINUE) if (s.getKind() != Kind.BREAK && s.getKind() != Kind.CONTINUE) {
newStatements.add(s); newStatements.add(s);
myBlock = new Block(newStatements); }
} myBlock = new Block(newStatements);
}
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return AstUtil.joinNodes(myCaseStatement, COMMA_WITH_SPACE) + SPACE + "->" + SPACE + myBlock.toKotlin(); return AstUtil.joinNodes(myCaseStatement, COMMA_WITH_SPACE) + SPACE + "->" + SPACE + myBlock.toKotlin();
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class CatchStatement extends Statement { public class CatchStatement extends Statement {
private final Parameter myVariable; private final Parameter myVariable;
private final Block myBlock; private final Block myBlock;
public CatchStatement(Parameter variable, Block block) { public CatchStatement(Parameter variable, Block block) {
myVariable = variable; myVariable = variable;
myBlock = block; myBlock = block;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "catch" + SPACE + "(" + myVariable.toKotlin() + ")" + SPACE + myBlock.toKotlin(); return "catch" + SPACE + "(" + myVariable.toKotlin() + ")" + SPACE + myBlock.toKotlin();
} }
} }
+222 -206
View File
@@ -16,221 +16,237 @@ import static org.jetbrains.jet.j2k.util.AstUtil.*;
* @author ignatov * @author ignatov
*/ */
public class Class extends Member { public class Class extends Member {
@NotNull @NotNull
String TYPE = "class"; String TYPE = "class";
final Identifier myName; final Identifier myName;
private final List<Expression> myBaseClassParams; private final List<Expression> myBaseClassParams;
private final List<Member> myMembers; private final List<Member> myMembers;
private final List<Element> myTypeParameters; private final List<Element> myTypeParameters;
private final List<Type> myExtendsTypes; private final List<Type> myExtendsTypes;
private final List<Type> myImplementsTypes; private final List<Type> myImplementsTypes;
public Class(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes, public Class(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes,
List<Expression> baseClassParams, List<Type> implementsTypes, List<Member> members) { List<Expression> baseClassParams, List<Type> implementsTypes, List<Member> members) {
myName = name; myName = name;
myBaseClassParams = baseClassParams; myBaseClassParams = baseClassParams;
myModifiers = modifiers; myModifiers = modifiers;
myTypeParameters = typeParameters; myTypeParameters = typeParameters;
myExtendsTypes = extendsTypes; myExtendsTypes = extendsTypes;
myImplementsTypes = implementsTypes; myImplementsTypes = implementsTypes;
myMembers= getMembers(members); myMembers = getMembers(members);
} }
static List<Member> getMembers(List<Member> members) { static List<Member> getMembers(List<Member> members) {
List<Member> withoutPrivate = new LinkedList<Member>(); List<Member> withoutPrivate = new LinkedList<Member>();
if (Converter.hasSetting("public-only")) { if (Converter.hasSetting("public-only")) {
for (Member m : members) { for (Member m : members) {
if (m.accessModifier().equals("public") || m.accessModifier().equals("protected")) { if (m.accessModifier().equals("public") || m.accessModifier().equals("protected")) {
withoutPrivate.add(m); withoutPrivate.add(m);
}
}
} }
}
} else {
withoutPrivate = members;
}
return withoutPrivate;
}
@Nullable
private Constructor getPrimaryConstructor() {
for (Member m : myMembers)
if (m.getKind() == Kind.CONSTRUCTOR)
if (((Constructor) m).isPrimary())
return (Constructor) m;
return null;
}
String primaryConstructorSignatureToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null)
return maybeConstructor.primarySignatureToKotlin();
return "(" + ")";
}
String primaryConstructorBodyToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null && !maybeConstructor.getBlock().isEmpty())
return maybeConstructor.primaryBodyToKotlin();
return EMPTY;
}
private boolean hasWhere() {
for (Element t : myTypeParameters)
if (t instanceof TypeParameter && ((TypeParameter) t).hasWhere())
return true;
return false;
}
@NotNull
String typeParameterWhereToKotlin() {
if (hasWhere()) {
List<String> wheres = new LinkedList<String>();
for (Element t : myTypeParameters)
if (t instanceof TypeParameter)
wheres.add(((TypeParameter) t).getWhereToKotlin());
return SPACE + "where" + SPACE + join(wheres, COMMA_WITH_SPACE) + SPACE;
}
return EMPTY;
}
@NotNull
LinkedList<Member> membersExceptConstructors() {
final LinkedList<Member> result = new LinkedList<Member>();
for (Member m : myMembers)
if (m.getKind() != Kind.CONSTRUCTOR)
result.add(m);
return result;
}
@NotNull
List<Function> secondaryConstructorsAsStaticInitFunction() {
final LinkedList<Function> result = new LinkedList<Function>();
for (Member m : myMembers)
if (m.getKind() == Kind.CONSTRUCTOR && !((Constructor) m).isPrimary()) {
Function f = (Function) m;
Set<String> modifiers = new HashSet<String>(m.myModifiers);
modifiers.add(Modifier.STATIC);
final List<Statement> statements = f.getBlock().getStatements();
statements.add(new ReturnStatement(new IdentifierImpl("__"))); // TODO: move to one place, find other __ usages
final Block block = new Block(statements);
final List<Element> typeParameters = new LinkedList<Element>();
if (f.getTypeParameters().size() == 0)
typeParameters.addAll(myTypeParameters);
else { else {
typeParameters.addAll(myTypeParameters); withoutPrivate = members;
typeParameters.addAll(f.getTypeParameters()); }
return withoutPrivate;
}
@Nullable
private Constructor getPrimaryConstructor() {
for (Member m : myMembers)
if (m.getKind() == Kind.CONSTRUCTOR) {
if (((Constructor) m).isPrimary()) {
return (Constructor) m;
}
}
return null;
}
String primaryConstructorSignatureToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null) {
return maybeConstructor.primarySignatureToKotlin();
}
return "(" + ")";
}
String primaryConstructorBodyToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null && !maybeConstructor.getBlock().isEmpty()) {
return maybeConstructor.primaryBodyToKotlin();
}
return EMPTY;
}
private boolean hasWhere() {
for (Element t : myTypeParameters)
if (t instanceof TypeParameter && ((TypeParameter) t).hasWhere()) {
return true;
}
return false;
}
@NotNull
String typeParameterWhereToKotlin() {
if (hasWhere()) {
List<String> wheres = new LinkedList<String>();
for (Element t : myTypeParameters)
if (t instanceof TypeParameter) {
wheres.add(((TypeParameter) t).getWhereToKotlin());
}
return SPACE + "where" + SPACE + join(wheres, COMMA_WITH_SPACE) + SPACE;
}
return EMPTY;
}
@NotNull
LinkedList<Member> membersExceptConstructors() {
final LinkedList<Member> result = new LinkedList<Member>();
for (Member m : myMembers)
if (m.getKind() != Kind.CONSTRUCTOR) {
result.add(m);
}
return result;
}
@NotNull
List<Function> secondaryConstructorsAsStaticInitFunction() {
final LinkedList<Function> result = new LinkedList<Function>();
for (Member m : myMembers)
if (m.getKind() == Kind.CONSTRUCTOR && !((Constructor) m).isPrimary()) {
Function f = (Function) m;
Set<String> modifiers = new HashSet<String>(m.myModifiers);
modifiers.add(Modifier.STATIC);
final List<Statement> statements = f.getBlock().getStatements();
statements.add(new ReturnStatement(new IdentifierImpl("__"))); // TODO: move to one place, find other __ usages
final Block block = new Block(statements);
final List<Element> typeParameters = new LinkedList<Element>();
if (f.getTypeParameters().size() == 0) {
typeParameters.addAll(myTypeParameters);
}
else {
typeParameters.addAll(myTypeParameters);
typeParameters.addAll(f.getTypeParameters());
}
result.add(new Function(
new IdentifierImpl("init"),
modifiers,
new ClassType(myName, typeParameters, false),
typeParameters,
f.getParams(),
block
));
}
return result;
}
@NotNull
String typeParametersToKotlin() {
return myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY;
}
List<String> baseClassSignatureWithParams() {
if (TYPE.equals("class") && myExtendsTypes.size() == 1) {
LinkedList<String> result = new LinkedList<String>();
result.add(myExtendsTypes.get(0).toKotlin() + "(" + joinNodes(myBaseClassParams, COMMA_WITH_SPACE) + ")");
return result;
}
else {
return nodesToKotlin(myExtendsTypes);
}
}
@NotNull
String implementTypesToKotlin() {
List<String> allTypes = new LinkedList<String>() {
{
addAll(baseClassSignatureWithParams());
addAll(nodesToKotlin(myImplementsTypes));
}
};
return allTypes.size() == 0 ? EMPTY : SPACE + COLON + SPACE + join(allTypes, COMMA_WITH_SPACE);
}
@NotNull
String modifiersToKotlin() {
List<String> modifierList = new LinkedList<String>();
if (needAbstractModifier()) {
modifierList.add(Modifier.ABSTRACT);
} }
result.add(new Function( modifierList.add(accessModifier());
new IdentifierImpl("init"),
modifiers,
new ClassType(myName, typeParameters, false),
typeParameters,
f.getParams(),
block
));
}
return result;
}
@NotNull if (needOpenModifier()) {
String typeParametersToKotlin() { modifierList.add(Modifier.OPEN);
return myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY; }
}
List<String> baseClassSignatureWithParams() { if (modifierList.size() > 0) {
if (TYPE.equals("class") && myExtendsTypes.size() == 1) { return join(modifierList, SPACE) + SPACE;
LinkedList<String> result = new LinkedList<String>(); }
result.add(myExtendsTypes.get(0).toKotlin() + "(" + joinNodes(myBaseClassParams, COMMA_WITH_SPACE) + ")");
return result;
} else
return nodesToKotlin(myExtendsTypes);
}
@NotNull return EMPTY;
String implementTypesToKotlin() {
List<String> allTypes = new LinkedList<String>() {
{
addAll(baseClassSignatureWithParams());
addAll(nodesToKotlin(myImplementsTypes));
}
};
return allTypes.size() == 0 ? EMPTY : SPACE + COLON + SPACE + join(allTypes, COMMA_WITH_SPACE);
}
@NotNull
String modifiersToKotlin() {
List<String> modifierList = new LinkedList<String>();
if (needAbstractModifier())
modifierList.add(Modifier.ABSTRACT);
modifierList.add(accessModifier());
if (needOpenModifier())
modifierList.add(Modifier.OPEN);
if (modifierList.size() > 0)
return join(modifierList, SPACE) + SPACE;
return EMPTY;
}
boolean needOpenModifier() {
return !myModifiers.contains(Modifier.FINAL);
}
boolean needAbstractModifier() {
return isAbstract();
}
@NotNull
String bodyToKotlin() {
return SPACE + "{" + N +
AstUtil.joinNodes(getNonStatic(membersExceptConstructors()), N) + N +
primaryConstructorBodyToKotlin() + N +
classObjectToKotlin() + N +
"}";
}
@NotNull
private static List<Member> getStatic(@NotNull List<? extends Member> members) {
List<Member> result = new LinkedList<Member>();
for (Member m : members)
if (m.isStatic())
result.add(m);
return result;
}
@NotNull
private static List<Member> getNonStatic(@NotNull List<? extends Member> members) {
List<Member> result = new LinkedList<Member>();
for (Member m : members)
if (!m.isStatic())
result.add(m);
return result;
}
@NotNull
private String classObjectToKotlin() {
final List<Member> staticMembers = new LinkedList<Member>(secondaryConstructorsAsStaticInitFunction());
staticMembers.addAll(getStatic(membersExceptConstructors()));
if (staticMembers.size() > 0) {
return "class" + SPACE + "object" + SPACE + "{" + N +
AstUtil.joinNodes(staticMembers, N) + N +
"}";
} }
return EMPTY;
}
@NotNull boolean needOpenModifier() {
@Override return !myModifiers.contains(Modifier.FINAL);
public String toKotlin() { }
return modifiersToKotlin() + TYPE + SPACE + myName.toKotlin() + typeParametersToKotlin() + primaryConstructorSignatureToKotlin() +
implementTypesToKotlin() + boolean needAbstractModifier() {
typeParameterWhereToKotlin() + return isAbstract();
bodyToKotlin(); }
}
@NotNull
String bodyToKotlin() {
return SPACE + "{" + N +
AstUtil.joinNodes(getNonStatic(membersExceptConstructors()), N) + N +
primaryConstructorBodyToKotlin() + N +
classObjectToKotlin() + N +
"}";
}
@NotNull
private static List<Member> getStatic(@NotNull List<? extends Member> members) {
List<Member> result = new LinkedList<Member>();
for (Member m : members)
if (m.isStatic()) {
result.add(m);
}
return result;
}
@NotNull
private static List<Member> getNonStatic(@NotNull List<? extends Member> members) {
List<Member> result = new LinkedList<Member>();
for (Member m : members)
if (!m.isStatic()) {
result.add(m);
}
return result;
}
@NotNull
private String classObjectToKotlin() {
final List<Member> staticMembers = new LinkedList<Member>(secondaryConstructorsAsStaticInitFunction());
staticMembers.addAll(getStatic(membersExceptConstructors()));
if (staticMembers.size() > 0) {
return "class" + SPACE + "object" + SPACE + "{" + N +
AstUtil.joinNodes(staticMembers, N) + N +
"}";
}
return EMPTY;
}
@NotNull
@Override
public String toKotlin() {
return modifiersToKotlin() + TYPE + SPACE + myName.toKotlin() + typeParametersToKotlin() + primaryConstructorSignatureToKotlin() +
implementTypesToKotlin() +
typeParameterWhereToKotlin() +
bodyToKotlin();
}
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ClassObjectAccessExpression extends Expression { public class ClassObjectAccessExpression extends Expression {
private final Element myTypeElement; private final Element myTypeElement;
public ClassObjectAccessExpression(Element typeElement) { public ClassObjectAccessExpression(Element typeElement) {
myTypeElement = typeElement; myTypeElement = typeElement;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "getJavaClass" + "<" + myTypeElement.toKotlin() + ">"; return "getJavaClass" + "<" + myTypeElement.toKotlin() + ">";
} }
} }
@@ -10,30 +10,32 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class ClassType extends Type { public class ClassType extends Type {
private final Identifier myType; private final Identifier myType;
private final List<? extends Element> myParameters; private final List<? extends Element> myParameters;
public ClassType(Identifier type, List<? extends Element> parameters, boolean nullable) { public ClassType(Identifier type, List<? extends Element> parameters, boolean nullable) {
myType = type; myType = type;
myParameters = parameters; myParameters = parameters;
myNullable = nullable; myNullable = nullable;
} }
public ClassType(Identifier type, List<? extends Element> parameters) { public ClassType(Identifier type, List<? extends Element> parameters) {
myType = type; myType = type;
myParameters = parameters; myParameters = parameters;
} }
public ClassType(Identifier type) { public ClassType(Identifier type) {
myType = type; myType = type;
myNullable = false; myNullable = false;
myParameters = Collections.emptyList(); myParameters = Collections.emptyList();
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
String params = myParameters.size() == 0 ? EMPTY : "<" + AstUtil.joinNodes(myParameters, COMMA_WITH_SPACE) + ">"; String params = myParameters.size() == 0
return myType.toKotlin() + params + isNullableStr(); ? EMPTY
} : "<" + AstUtil.joinNodes(myParameters, COMMA_WITH_SPACE) + ">";
return myType.toKotlin() + params + isNullableStr();
}
} }
@@ -9,30 +9,30 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class Constructor extends Function { public class Constructor extends Function {
private final boolean myIsPrimary; private final boolean myIsPrimary;
public Constructor(Identifier identifier, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block, boolean isPrimary) { public Constructor(Identifier identifier, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block, boolean isPrimary) {
super(identifier, modifiers, type, typeParameters, params, block); super(identifier, modifiers, type, typeParameters, params, block);
myIsPrimary = isPrimary; myIsPrimary = isPrimary;
} }
@NotNull @NotNull
public String primarySignatureToKotlin() { public String primarySignatureToKotlin() {
return "(" + myParams.toKotlin() + ")"; return "(" + myParams.toKotlin() + ")";
} }
@NotNull @NotNull
public String primaryBodyToKotlin() { public String primaryBodyToKotlin() {
return myBlock.toKotlin(); return myBlock.toKotlin();
} }
public boolean isPrimary() { public boolean isPrimary() {
return myIsPrimary; return myIsPrimary;
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.CONSTRUCTOR; return Kind.CONSTRUCTOR;
} }
} }
@@ -6,26 +6,27 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ContinueStatement extends Statement { public class ContinueStatement extends Statement {
private Identifier myLabel = Identifier.EMPTY_IDENTIFIER; private Identifier myLabel = Identifier.EMPTY_IDENTIFIER;
public ContinueStatement(Identifier label) { public ContinueStatement(Identifier label) {
myLabel = label; myLabel = label;
} }
public ContinueStatement() { public ContinueStatement() {
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.CONTINUE; return Kind.CONTINUE;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myLabel.isEmpty()) if (myLabel.isEmpty()) {
return "continue"; return "continue";
return "continue" + AT + myLabel.toKotlin(); }
} return "continue" + AT + myLabel.toKotlin();
}
} }
@@ -10,31 +10,31 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class DeclarationStatement extends Statement { public class DeclarationStatement extends Statement {
private final List<Element> myElements; private final List<Element> myElements;
public DeclarationStatement(List<Element> elements) { public DeclarationStatement(List<Element> elements) {
myElements = elements; myElements = elements;
}
@NotNull
private static List<String> toStringList(@NotNull List<Element> elements) {
List<String> result = new LinkedList<String>();
for (Element e : elements) {
if (e instanceof LocalVariable) {
LocalVariable v = (LocalVariable) e;
final String varKeyword = v.hasModifier(Modifier.FINAL) ? "val" : "var";
result.add(
varKeyword + SPACE + e.toKotlin()
);
}
} }
return result;
}
@NotNull @NotNull
@Override private static List<String> toStringList(@NotNull List<Element> elements) {
public String toKotlin() { List<String> result = new LinkedList<String>();
return AstUtil.join(toStringList(myElements), N); for (Element e : elements) {
} if (e instanceof LocalVariable) {
LocalVariable v = (LocalVariable) e;
final String varKeyword = v.hasModifier(Modifier.FINAL) ? "val" : "var";
result.add(
varKeyword + SPACE + e.toKotlin()
);
}
}
return result;
}
@NotNull
@Override
public String toKotlin() {
return AstUtil.join(toStringList(myElements), N);
}
} }
@@ -6,9 +6,9 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class DefaultSwitchLabelStatement extends Statement { public class DefaultSwitchLabelStatement extends Statement {
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "else"; return "else";
} }
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class DoWhileStatement extends WhileStatement { public class DoWhileStatement extends WhileStatement {
public DoWhileStatement(Expression condition, Statement statement) { public DoWhileStatement(Expression condition, Statement statement) {
super(condition, statement); super(condition, statement);
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "do" + N + return "do" + N +
myStatement.toKotlin() + N + myStatement.toKotlin() + N +
"while" + SPACE + "(" + myCondition.toKotlin() + ")"; "while" + SPACE + "(" + myCondition.toKotlin() + ")";
} }
} }
@@ -6,19 +6,19 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class DummyMethodCallExpression extends Expression { public class DummyMethodCallExpression extends Expression {
private final Element myWho; private final Element myWho;
private final String myMethodName; private final String myMethodName;
private final Element myWhat; private final Element myWhat;
public DummyMethodCallExpression(Element who, String methodName, Element what) { public DummyMethodCallExpression(Element who, String methodName, Element what) {
myWho = who; myWho = who;
myMethodName = methodName; myMethodName = methodName;
myWhat = what; myWhat = what;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myWho.toKotlin() + DOT + myMethodName + "(" + myWhat.toKotlin() + ")"; return myWho.toKotlin() + DOT + myMethodName + "(" + myWhat.toKotlin() + ")";
} }
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class DummyStringExpression extends Expression { public class DummyStringExpression extends Expression {
private final String myString; private final String myString;
public DummyStringExpression(String string) { public DummyStringExpression(String string) {
myString = string; myString = string;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myString; return myString;
} }
} }
+18 -18
View File
@@ -6,26 +6,26 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public abstract class Element extends Node { public abstract class Element extends Node {
@NotNull
public static final Element EMPTY_ELEMENT = new EmptyElement();
public boolean isEmpty() {
return false;
}
/**
* @author ignatov
*/
private static class EmptyElement extends Element {
@NotNull @NotNull
@Override public static final Element EMPTY_ELEMENT = new EmptyElement();
public String toKotlin() {
return EMPTY; public boolean isEmpty() {
return false;
} }
@Override /**
public boolean isEmpty() { * @author ignatov
return true; */
private static class EmptyElement extends Element {
@NotNull
@Override
public String toKotlin() {
return EMPTY;
}
@Override
public boolean isEmpty() {
return true;
}
} }
}
} }
+23 -23
View File
@@ -10,30 +10,30 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class Enum extends Class { public class Enum extends Class {
public Enum(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes, public Enum(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes,
List<Expression> baseClassParams, List<Type> implementsTypes, List<Member> members) { List<Expression> baseClassParams, List<Type> implementsTypes, List<Member> members) {
super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, getMembers(members)); super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, getMembers(members));
} }
String primaryConstructorSignatureToKotlin() { String primaryConstructorSignatureToKotlin() {
String s = super.primaryConstructorSignatureToKotlin(); String s = super.primaryConstructorSignatureToKotlin();
return s.equals("()") ? EMPTY : s; return s.equals("()") ? EMPTY : s;
} }
@Override @Override
boolean needOpenModifier() { boolean needOpenModifier() {
return false; return false;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return modifiersToKotlin() + "enum class" + SPACE + myName.toKotlin() + primaryConstructorSignatureToKotlin() + return modifiersToKotlin() + "enum class" + SPACE + myName.toKotlin() + primaryConstructorSignatureToKotlin() +
typeParametersToKotlin() + implementTypesToKotlin() + SPACE + "{" + N + typeParametersToKotlin() + implementTypesToKotlin() + SPACE + "{" + N +
AstUtil.joinNodes(membersExceptConstructors(), N) + N + AstUtil.joinNodes(membersExceptConstructors(), N) + N +
primaryConstructorBodyToKotlin() + N + primaryConstructorBodyToKotlin() + N +
"public fun name() : String { return \"\" }" + N + // TODO : remove hack "public fun name() : String { return \"\" }" + N + // TODO : remove hack
"public fun order() : Int { return 0 }" + N + "public fun order() : Int { return 0 }" + N +
"}"; "}";
} }
} }
@@ -8,15 +8,16 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class EnumConstant extends Field { public class EnumConstant extends Field {
public EnumConstant(Identifier identifier, Set<String> modifiers, @NotNull Type type, Element params) { public EnumConstant(Identifier identifier, Set<String> modifiers, @NotNull Type type, Element params) {
super(identifier, modifiers, type.convertedToNotNull(), params, 0); super(identifier, modifiers, type.convertedToNotNull(), params, 0);
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myInitializer.toKotlin().isEmpty()) if (myInitializer.toKotlin().isEmpty()) {
return myIdentifier.toKotlin(); return myIdentifier.toKotlin();
return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + "(" + myInitializer.toKotlin() + ")"; }
} return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + "(" + myInitializer.toKotlin() + ")";
}
} }
@@ -6,26 +6,26 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public abstract class Expression extends Statement { public abstract class Expression extends Statement {
@NotNull
public static final Expression EMPTY_EXPRESSION = new EmptyExpression();
/**
* @author ignatov
*/
private static class EmptyExpression extends Expression {
@NotNull @NotNull
@Override public static final Expression EMPTY_EXPRESSION = new EmptyExpression();
public String toKotlin() {
return EMPTY; /**
* @author ignatov
*/
private static class EmptyExpression extends Expression {
@NotNull
@Override
public String toKotlin() {
return EMPTY;
}
@Override
public boolean isEmpty() {
return true;
}
} }
@Override boolean isNullable() {
public boolean isEmpty() { return false;
return true;
} }
}
boolean isNullable() {
return false;
}
} }
@@ -9,19 +9,19 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class ExpressionList extends Expression { public class ExpressionList extends Expression {
private final List<Expression> myExpressions; private final List<Expression> myExpressions;
public ExpressionList(List<Expression> expressions, List<Type> types) { public ExpressionList(List<Expression> expressions, List<Type> types) {
myExpressions = expressions; myExpressions = expressions;
} }
public ExpressionList(List<Expression> expressions) { public ExpressionList(List<Expression> expressions) {
myExpressions = expressions; myExpressions = expressions;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return AstUtil.joinNodes(myExpressions, COMMA_WITH_SPACE); return AstUtil.joinNodes(myExpressions, COMMA_WITH_SPACE);
} }
} }
@@ -9,15 +9,15 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class ExpressionListStatement extends Expression { public class ExpressionListStatement extends Expression {
private final List<Expression> myExpressions; private final List<Expression> myExpressions;
public ExpressionListStatement(List<Expression> expressions) { public ExpressionListStatement(List<Expression> expressions) {
myExpressions = expressions; myExpressions = expressions;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return AstUtil.joinNodes(myExpressions, N); return AstUtil.joinNodes(myExpressions, N);
} }
} }
+51 -46
View File
@@ -13,65 +13,70 @@ import static org.jetbrains.jet.j2k.Converter.getDefaultInitializer;
* @author ignatov * @author ignatov
*/ */
public class Field extends Member { public class Field extends Member {
final Identifier myIdentifier; final Identifier myIdentifier;
private final int myWritingAccesses; private final int myWritingAccesses;
final Type myType; final Type myType;
final Element myInitializer; final Element myInitializer;
public Field(Identifier identifier, Set<String> modifiers, Type type, Element initializer, int writingAccesses) { public Field(Identifier identifier, Set<String> modifiers, Type type, Element initializer, int writingAccesses) {
myIdentifier = identifier; myIdentifier = identifier;
myWritingAccesses = writingAccesses; myWritingAccesses = writingAccesses;
myModifiers = modifiers; myModifiers = modifiers;
myType = type; myType = type;
myInitializer = initializer; myInitializer = initializer;
} }
public Element getInitializer() { public Element getInitializer() {
return myInitializer; return myInitializer;
} }
public Identifier getIdentifier() { public Identifier getIdentifier() {
return myIdentifier; return myIdentifier;
} }
public Type getType() { public Type getType() {
return myType; return myType;
} }
@NotNull @NotNull
String modifiersToKotlin() { String modifiersToKotlin() {
List<String> modifierList = new LinkedList<String>(); List<String> modifierList = new LinkedList<String>();
if (isAbstract()) if (isAbstract()) {
modifierList.add(Modifier.ABSTRACT); modifierList.add(Modifier.ABSTRACT);
}
modifierList.add(accessModifier()); modifierList.add(accessModifier());
modifierList.add(isVal() ? "val" : "var"); modifierList.add(isVal() ? "val" : "var");
if (modifierList.size() > 0) if (modifierList.size() > 0) {
return AstUtil.join(modifierList, SPACE) + SPACE; return AstUtil.join(modifierList, SPACE) + SPACE;
}
return EMPTY; return EMPTY;
} }
public boolean isVal() { public boolean isVal() {
return myModifiers.contains(Modifier.FINAL); return myModifiers.contains(Modifier.FINAL);
} }
@Override @Override
public boolean isStatic() { public boolean isStatic() {
return myModifiers.contains(Modifier.STATIC); return myModifiers.contains(Modifier.STATIC);
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
final String declaration = modifiersToKotlin() + myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin(); final String declaration = modifiersToKotlin() + myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin();
if (myInitializer.isEmpty()) if (myInitializer.isEmpty()) {
return declaration + (isVal() && !isStatic() && myWritingAccesses == 1 ? EMPTY : SPACE + EQUAL + SPACE + getDefaultInitializer(this)); return declaration + (isVal() && !isStatic() && myWritingAccesses == 1
? EMPTY
: SPACE + EQUAL + SPACE + getDefaultInitializer(this));
}
return declaration + SPACE + EQUAL + SPACE + myInitializer.toKotlin(); return declaration + SPACE + EQUAL + SPACE + myInitializer.toKotlin();
} }
} }
+20 -19
View File
@@ -9,25 +9,26 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class File extends Node { public class File extends Node {
private final String myPackageName; private final String myPackageName;
private final List<Import> myImports; private final List<Import> myImports;
private final List<Class> myClasses; private final List<Class> myClasses;
private final String myMainFunction; private final String myMainFunction;
public File(String packageName, List<Import> imports, List<Class> classes, String mainFunction) { public File(String packageName, List<Import> imports, List<Class> classes, String mainFunction) {
myPackageName = packageName; myPackageName = packageName;
myImports = imports; myImports = imports;
myClasses = classes; myClasses = classes;
myMainFunction = mainFunction; myMainFunction = mainFunction;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
final String common = AstUtil.joinNodes(myImports, N) + N2 + AstUtil.joinNodes(myClasses, N) + N + myMainFunction; final String common = AstUtil.joinNodes(myImports, N) + N2 + AstUtil.joinNodes(myClasses, N) + N + myMainFunction;
if (myPackageName.isEmpty()) if (myPackageName.isEmpty()) {
return common; return common;
return "package" + SPACE + myPackageName + N + }
common; return "package" + SPACE + myPackageName + N +
} common;
}
} }
@@ -6,20 +6,20 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ForeachStatement extends Statement { public class ForeachStatement extends Statement {
private final Parameter myVariable; private final Parameter myVariable;
private final Expression myExpression; private final Expression myExpression;
private final Statement myStatement; private final Statement myStatement;
public ForeachStatement(Parameter variable, Expression expression, Statement statement) { public ForeachStatement(Parameter variable, Expression expression, Statement statement) {
myVariable = variable; myVariable = variable;
myExpression = expression; myExpression = expression;
myStatement = statement; myStatement = statement;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "for" + SPACE + "(" + myVariable.toKotlin() + SPACE + IN + SPACE + myExpression.toKotlin() + ")" + N + return "for" + SPACE + "(" + myVariable.toKotlin() + SPACE + IN + SPACE + myExpression.toKotlin() + ")" + N +
myStatement.toKotlin(); myStatement.toKotlin();
} }
} }
@@ -6,24 +6,24 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ForeachWithRangeStatement extends Statement { public class ForeachWithRangeStatement extends Statement {
private final Expression myStart; private final Expression myStart;
private final IdentifierImpl myIdentifier; private final IdentifierImpl myIdentifier;
private final Expression myEnd; private final Expression myEnd;
private final Statement myBody; private final Statement myBody;
public ForeachWithRangeStatement(IdentifierImpl identifier, Expression start, Expression end, Statement body) { public ForeachWithRangeStatement(IdentifierImpl identifier, Expression start, Expression end, Statement body) {
myStart = start; myStart = start;
myIdentifier = identifier; myIdentifier = identifier;
myEnd = end; myEnd = end;
myBody = body; myBody = body;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "for" + SPACE + "(" + return "for" + SPACE + "(" +
myIdentifier.toKotlin() + SPACE + "in" + SPACE + myStart.toKotlin() + ".." + myEnd.toKotlin() + myIdentifier.toKotlin() + SPACE + "in" + SPACE + myStart.toKotlin() + ".." + myEnd.toKotlin() +
")" + SPACE + ")" + SPACE +
myBody.toKotlin(); myBody.toKotlin();
} }
} }
+86 -78
View File
@@ -11,93 +11,101 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class Function extends Member { public class Function extends Member {
private final Identifier myName; private final Identifier myName;
private final Type myType; private final Type myType;
private final List<Element> myTypeParameters; private final List<Element> myTypeParameters;
final Element myParams; final Element myParams;
// TODO: maybe remove it? // TODO: maybe remove it?
public void setBlock(Block block) { public void setBlock(Block block) {
myBlock = block; myBlock = block;
}
Block myBlock;
public Function(Identifier name, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block) {
myName = name;
myModifiers = modifiers;
myType = type;
myTypeParameters = typeParameters;
myParams = params;
myBlock = block;
}
public List<Element> getTypeParameters() {
return myTypeParameters;
}
public Element getParams() {
return myParams;
}
public Block getBlock() {
return myBlock;
}
@NotNull
private String typeParametersToKotlin() {
return myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY;
}
private boolean hasWhere() {
for (Element t : myTypeParameters)
if (t instanceof TypeParameter && ((TypeParameter) t).hasWhere())
return true;
return false;
}
private String typeParameterWhereToKotlin() {
if (hasWhere()) {
List<String> wheres = new LinkedList<String>();
for (Element t : myTypeParameters)
if (t instanceof TypeParameter)
wheres.add(((TypeParameter) t).getWhereToKotlin());
return SPACE + "where" + SPACE + AstUtil.join(wheres, COMMA_WITH_SPACE) + SPACE;
} }
return EMPTY;
}
String modifiersToKotlin() { Block myBlock;
List<String> modifierList = new LinkedList<String>();
if (isAbstract()) public Function(Identifier name, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block) {
modifierList.add(Modifier.ABSTRACT); myName = name;
myModifiers = modifiers;
myType = type;
myTypeParameters = typeParameters;
myParams = params;
myBlock = block;
}
if (myModifiers.contains(Modifier.OVERRIDE)) public List<Element> getTypeParameters() {
modifierList.add(Modifier.OVERRIDE); return myTypeParameters;
}
if (!myModifiers.contains(Modifier.OVERRIDE) && !myModifiers.contains(Modifier.FINAL)) public Element getParams() {
modifierList.add(Modifier.OPEN); return myParams;
}
if (myModifiers.contains(Modifier.NOT_OPEN)) public Block getBlock() {
modifierList.remove(Modifier.OPEN); return myBlock;
}
String accessModifier = accessModifier(); @NotNull
if (!accessModifier.isEmpty()) private String typeParametersToKotlin() {
modifierList.add(accessModifier); return myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY;
}
if (modifierList.size() > 0) private boolean hasWhere() {
return AstUtil.join(modifierList, SPACE) + SPACE; for (Element t : myTypeParameters)
if (t instanceof TypeParameter && ((TypeParameter) t).hasWhere()) {
return true;
}
return false;
}
return EMPTY; private String typeParameterWhereToKotlin() {
} if (hasWhere()) {
List<String> wheres = new LinkedList<String>();
for (Element t : myTypeParameters)
if (t instanceof TypeParameter) {
wheres.add(((TypeParameter) t).getWhereToKotlin());
}
return SPACE + "where" + SPACE + AstUtil.join(wheres, COMMA_WITH_SPACE) + SPACE;
}
return EMPTY;
}
@NotNull String modifiersToKotlin() {
@Override List<String> modifierList = new LinkedList<String>();
public String toKotlin() {
return modifiersToKotlin() + "fun" + SPACE + myName.toKotlin() + typeParametersToKotlin() + "(" + myParams.toKotlin() + ")" + SPACE + COLON + if (isAbstract()) {
SPACE + myType.toKotlin() + SPACE + modifierList.add(Modifier.ABSTRACT);
typeParameterWhereToKotlin() + }
myBlock.toKotlin();
} if (myModifiers.contains(Modifier.OVERRIDE)) {
modifierList.add(Modifier.OVERRIDE);
}
if (!myModifiers.contains(Modifier.OVERRIDE) && !myModifiers.contains(Modifier.FINAL)) {
modifierList.add(Modifier.OPEN);
}
if (myModifiers.contains(Modifier.NOT_OPEN)) {
modifierList.remove(Modifier.OPEN);
}
String accessModifier = accessModifier();
if (!accessModifier.isEmpty()) {
modifierList.add(accessModifier);
}
if (modifierList.size() > 0) {
return AstUtil.join(modifierList, SPACE) + SPACE;
}
return EMPTY;
}
@NotNull
@Override
public String toKotlin() {
return modifiersToKotlin() + "fun" + SPACE + myName.toKotlin() + typeParametersToKotlin() + "(" + myParams.toKotlin() + ")" + SPACE + COLON +
SPACE + myType.toKotlin() + SPACE +
typeParameterWhereToKotlin() +
myBlock.toKotlin();
}
} }
@@ -4,7 +4,7 @@ package org.jetbrains.jet.j2k.ast;
* @author ignatov * @author ignatov
*/ */
public interface IMember extends INode { public interface IMember extends INode {
boolean isStatic(); boolean isStatic();
boolean isAbstract(); boolean isAbstract();
} }
+7 -7
View File
@@ -6,13 +6,13 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public interface INode { public interface INode {
@NotNull @NotNull
String toKotlin(); String toKotlin();
@NotNull @NotNull
Kind getKind(); Kind getKind();
enum Kind { enum Kind {
UNDEFINED, TYPE, CONSTRUCTOR, BREAK, CONTINUE, VARARG, TRAIT, ASSIGNMENT_EXPRESSION, CALL_CHAIN, LITERAL, ARRAY_TYPE, UNDEFINED, TYPE, CONSTRUCTOR, BREAK, CONTINUE, VARARG, TRAIT, ASSIGNMENT_EXPRESSION, CALL_CHAIN, LITERAL, ARRAY_TYPE,
} }
} }
@@ -6,10 +6,10 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public interface Identifier extends INode { public interface Identifier extends INode {
@NotNull @NotNull
Identifier EMPTY_IDENTIFIER = new IdentifierImpl(""); Identifier EMPTY_IDENTIFIER = new IdentifierImpl("");
boolean isEmpty(); boolean isEmpty();
String getName(); String getName();
} }
@@ -6,54 +6,55 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class IdentifierImpl extends Expression implements Identifier { public class IdentifierImpl extends Expression implements Identifier {
private final String myName; private final String myName;
private boolean myIsNullable = true; private boolean myIsNullable = true;
private boolean myQuotingNeeded = true; private boolean myQuotingNeeded = true;
public IdentifierImpl(String name) { public IdentifierImpl(String name) {
myName = name; myName = name;
} }
public IdentifierImpl(String name, boolean isNullable) { public IdentifierImpl(String name, boolean isNullable) {
myName = name; myName = name;
myIsNullable = isNullable; myIsNullable = isNullable;
} }
public IdentifierImpl(String name, boolean isNullable, boolean quotingNeeded) { public IdentifierImpl(String name, boolean isNullable, boolean quotingNeeded) {
myName = name; myName = name;
myIsNullable = isNullable; myIsNullable = isNullable;
myQuotingNeeded = quotingNeeded; myQuotingNeeded = quotingNeeded;
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return myName.length() == 0; return myName.length() == 0;
} }
@Override @Override
public String getName() { public String getName() {
return myName; return myName;
} }
@NotNull @NotNull
private static String quote(String str) { private static String quote(String str) {
return BACKTICK + str + BACKTICK; return BACKTICK + str + BACKTICK;
} }
@Override @Override
public boolean isNullable() { public boolean isNullable() {
return myIsNullable; return myIsNullable;
} }
private String ifNeedQuote() { private String ifNeedQuote() {
if (myQuotingNeeded && (ONLY_KOTLIN_KEYWORDS.contains(myName) || myName.contains("$"))) if (myQuotingNeeded && (ONLY_KOTLIN_KEYWORDS.contains(myName) || myName.contains("$"))) {
return quote(myName); return quote(myName);
return myName; }
} return myName;
}
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return ifNeedQuote(); return ifNeedQuote();
} }
} }
@@ -6,26 +6,27 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class IfStatement extends Expression { public class IfStatement extends Expression {
private final Expression myCondition; private final Expression myCondition;
private final Statement myThenStatement; private final Statement myThenStatement;
private final Statement myElseStatement; private final Statement myElseStatement;
public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement) { public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement) {
myCondition = condition; myCondition = condition;
myThenStatement = thenStatement; myThenStatement = thenStatement;
myElseStatement = elseStatement; myElseStatement = elseStatement;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
String result = "if" + SPACE + "(" + myCondition.toKotlin() + ")" + N + myThenStatement.toKotlin() + N; String result = "if" + SPACE + "(" + myCondition.toKotlin() + ")" + N + myThenStatement.toKotlin() + N;
if (myElseStatement != Statement.EMPTY_STATEMENT) if (myElseStatement != Statement.EMPTY_STATEMENT) {
return result + return result +
"else" + N + "else" + N +
myElseStatement.toKotlin(); myElseStatement.toKotlin();
}
return result; return result;
} }
} }
+12 -12
View File
@@ -6,19 +6,19 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class Import extends Node { public class Import extends Node {
private final String myName; private final String myName;
public String getName() { public String getName() {
return myName; return myName;
} }
public Import(String name) { public Import(String name) {
myName = name; myName = name;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "import" + SPACE + myName; return "import" + SPACE + myName;
} }
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class InProjectionType extends Type { public class InProjectionType extends Type {
private final Type myBound; private final Type myBound;
public InProjectionType(Type bound) { public InProjectionType(Type bound) {
myBound = bound; myBound = bound;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "in" + SPACE + myBound.toKotlin(); return "in" + SPACE + myBound.toKotlin();
} }
} }
@@ -8,16 +8,16 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class Initializer extends Member { public class Initializer extends Member {
private final Block myBlock; private final Block myBlock;
public Initializer(Block block, Set<String> modifiers) { public Initializer(Block block, Set<String> modifiers) {
myBlock = block; myBlock = block;
myModifiers = modifiers; myModifiers = modifiers;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myBlock.toKotlin(); return myBlock.toKotlin();
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class IsOperator extends Expression { public class IsOperator extends Expression {
private final Expression myExpression; private final Expression myExpression;
private final Element myTypeElement; private final Element myTypeElement;
public IsOperator(Expression expression, Element typeElement) { public IsOperator(Expression expression, Element typeElement) {
myExpression = expression; myExpression = expression;
myTypeElement = typeElement; myTypeElement = typeElement;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "(" + myExpression.toKotlin() + SPACE + "is" + SPACE + myTypeElement.toKotlin() + ")"; return "(" + myExpression.toKotlin() + SPACE + "is" + SPACE + myTypeElement.toKotlin() + ")";
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class LabelStatement extends Statement { public class LabelStatement extends Statement {
private final Identifier myName; private final Identifier myName;
private final Statement myStatement; private final Statement myStatement;
public LabelStatement(Identifier name, Statement statement) { public LabelStatement(Identifier name, Statement statement) {
myName = name; myName = name;
myStatement = statement; myStatement = statement;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return AT + myName.toKotlin() + SPACE + myStatement.toKotlin(); return AT + myName.toKotlin() + SPACE + myStatement.toKotlin();
} }
} }
@@ -6,21 +6,21 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class LiteralExpression extends Expression { public class LiteralExpression extends Expression {
private final Identifier myIdentifier; private final Identifier myIdentifier;
public LiteralExpression(Identifier identifier) { public LiteralExpression(Identifier identifier) {
myIdentifier = identifier; myIdentifier = identifier;
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.LITERAL; return Kind.LITERAL;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myIdentifier.toKotlin(); return myIdentifier.toKotlin();
} }
} }
@@ -8,29 +8,30 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class LocalVariable extends Expression { public class LocalVariable extends Expression {
private final Identifier myIdentifier; private final Identifier myIdentifier;
private final Set<String> myModifiersSet; private final Set<String> myModifiersSet;
private final Type myType; private final Type myType;
private final Expression myInitializer; private final Expression myInitializer;
public LocalVariable(Identifier identifier, Set<String> modifiersSet, Type type, Expression initializer) { public LocalVariable(Identifier identifier, Set<String> modifiersSet, Type type, Expression initializer) {
myIdentifier = identifier; myIdentifier = identifier;
myModifiersSet = modifiersSet; myModifiersSet = modifiersSet;
myType = type; myType = type;
myInitializer = initializer; myInitializer = initializer;
} }
public boolean hasModifier(String modifier) { public boolean hasModifier(String modifier) {
return myModifiersSet.contains(modifier); return myModifiersSet.contains(modifier);
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myInitializer.isEmpty()) if (myInitializer.isEmpty()) {
return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin(); return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin();
}
return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + SPACE + return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + SPACE +
EQUAL + SPACE + myInitializer.toKotlin(); EQUAL + SPACE + myInitializer.toKotlin();
} }
} }
+17 -16
View File
@@ -8,23 +8,24 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public abstract class Member extends Node implements IMember { public abstract class Member extends Node implements IMember {
Set<String> myModifiers; Set<String> myModifiers;
@NotNull @NotNull
String accessModifier() { String accessModifier() {
for (String m : myModifiers) for (String m : myModifiers)
if (m.equals(Modifier.PUBLIC) || m.equals(Modifier.PROTECTED) || m.equals(Modifier.PRIVATE)) if (m.equals(Modifier.PUBLIC) || m.equals(Modifier.PROTECTED) || m.equals(Modifier.PRIVATE)) {
return m; return m;
return EMPTY; // package local converted to internal, but we use internal by default }
} return EMPTY; // package local converted to internal, but we use internal by default
}
@Override @Override
public boolean isAbstract() { public boolean isAbstract() {
return myModifiers.contains(Modifier.ABSTRACT); return myModifiers.contains(Modifier.ABSTRACT);
} }
@Override @Override
public boolean isStatic() { public boolean isStatic() {
return myModifiers.contains(Modifier.STATIC); return myModifiers.contains(Modifier.STATIC);
} }
} }
@@ -9,34 +9,36 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class MethodCallExpression extends Expression { public class MethodCallExpression extends Expression {
private final Expression myMethodCall; private final Expression myMethodCall;
private final List<Expression> myArguments; private final List<Expression> myArguments;
private final List<String> myConversions; private final List<String> myConversions;
private final boolean myIsResultNullable; private final boolean myIsResultNullable;
private final List<Type> myTypeParameters; private final List<Type> myTypeParameters;
public MethodCallExpression(Expression methodCall, List<Expression> arguments, List<Type> typeParameters) { public MethodCallExpression(Expression methodCall, List<Expression> arguments, List<Type> typeParameters) {
this(methodCall, arguments, AstUtil.createListWithEmptyString(arguments), false, typeParameters); this(methodCall, arguments, AstUtil.createListWithEmptyString(arguments), false, typeParameters);
} }
public MethodCallExpression(Expression methodCall, List<Expression> arguments, List<String> conversions, boolean nullable, List<Type> typeParameters) { public MethodCallExpression(Expression methodCall, List<Expression> arguments, List<String> conversions, boolean nullable, List<Type> typeParameters) {
myMethodCall = methodCall; myMethodCall = methodCall;
myArguments = arguments; myArguments = arguments;
myConversions = conversions; myConversions = conversions;
myIsResultNullable = nullable; myIsResultNullable = nullable;
myTypeParameters = typeParameters; myTypeParameters = typeParameters;
} }
@Override @Override
public boolean isNullable() { public boolean isNullable() {
return myIsResultNullable; return myIsResultNullable;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
String typeParamsToKotlin = myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY; String typeParamsToKotlin = myTypeParameters.size() > 0
List<String> applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions); ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">"
return myMethodCall.toKotlin() + typeParamsToKotlin + "(" + AstUtil.join(applyConversions, COMMA_WITH_SPACE) + ")"; : EMPTY;
} List<String> applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions);
return myMethodCall.toKotlin() + typeParamsToKotlin + "(" + AstUtil.join(applyConversions, COMMA_WITH_SPACE) + ")";
}
} }
+20 -20
View File
@@ -6,24 +6,24 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public abstract class Modifier { public abstract class Modifier {
@NotNull @NotNull
public static final String PUBLIC = "public"; public static final String PUBLIC = "public";
@NotNull @NotNull
public static final String PROTECTED = "protected"; public static final String PROTECTED = "protected";
@NotNull @NotNull
public static final String PRIVATE = "private"; public static final String PRIVATE = "private";
@NotNull @NotNull
public static final String INTERNAL = "internal"; public static final String INTERNAL = "internal";
@NotNull @NotNull
public static final String STATIC = "static"; public static final String STATIC = "static";
@NotNull @NotNull
public static final String ABSTRACT = "abstract"; public static final String ABSTRACT = "abstract";
@NotNull @NotNull
public static final String FINAL = "final"; public static final String FINAL = "final";
@NotNull @NotNull
public static final String OPEN = "open"; public static final String OPEN = "open";
@NotNull @NotNull
public static final String NOT_OPEN = "not open"; public static final String NOT_OPEN = "not open";
@NotNull @NotNull
public static final String OVERRIDE = "override"; public static final String OVERRIDE = "override";
} }
@@ -10,37 +10,38 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class NewClassExpression extends Expression { public class NewClassExpression extends Expression {
private final Element myName; private final Element myName;
private final List<Expression> myArguments; private final List<Expression> myArguments;
private Expression myQualifier; private Expression myQualifier;
private List<String> myConversions; private List<String> myConversions;
@Nullable @Nullable
private AnonymousClass myAnonymousClass = null; private AnonymousClass myAnonymousClass = null;
private NewClassExpression(Element name, List<Expression> arguments) { private NewClassExpression(Element name, List<Expression> arguments) {
myName = name; myName = name;
myQualifier = EMPTY_EXPRESSION; myQualifier = EMPTY_EXPRESSION;
myArguments = arguments; myArguments = arguments;
myConversions = AstUtil.createListWithEmptyString(arguments); myConversions = AstUtil.createListWithEmptyString(arguments);
} }
public NewClassExpression(@NotNull Expression qualifier, @NotNull Element name, @NotNull List<Expression> arguments, public NewClassExpression(@NotNull Expression qualifier, @NotNull Element name, @NotNull List<Expression> arguments,
@NotNull List<String> conversions, @Nullable AnonymousClass anonymousClass) { @NotNull List<String> conversions, @Nullable AnonymousClass anonymousClass) {
this(name, arguments); this(name, arguments);
myQualifier = qualifier; myQualifier = qualifier;
myConversions = conversions; myConversions = conversions;
myAnonymousClass = anonymousClass; myAnonymousClass = anonymousClass;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
final String callOperator = myQualifier.isNullable() ? QUESTDOT : DOT; final String callOperator = myQualifier.isNullable() ? QUESTDOT : DOT;
final String qualifier = myQualifier.isEmpty() ? EMPTY : myQualifier.toKotlin() + callOperator; final String qualifier = myQualifier.isEmpty() ? EMPTY : myQualifier.toKotlin() + callOperator;
List<String> applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions); List<String> applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions);
String appliedArguments = AstUtil.join(applyConversions, COMMA_WITH_SPACE); String appliedArguments = AstUtil.join(applyConversions, COMMA_WITH_SPACE);
return myAnonymousClass != null ? return myAnonymousClass != null ?
"object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + appliedArguments + ")" + myAnonymousClass.toKotlin() : "object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + appliedArguments + ")" + myAnonymousClass.toKotlin()
qualifier + myName.toKotlin() + "(" + appliedArguments + ")"; :
} qualifier + myName.toKotlin() + "(" + appliedArguments + ")";
}
} }
+42 -42
View File
@@ -10,49 +10,49 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public abstract class Node implements INode { public abstract class Node implements INode {
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.UNDEFINED; return Kind.UNDEFINED;
} }
@NotNull @NotNull
final static Set<String> ONLY_KOTLIN_KEYWORDS = new HashSet<String>(Arrays.asList( final static Set<String> ONLY_KOTLIN_KEYWORDS = new HashSet<String>(Arrays.asList(
"package", "as", "type", "val", "var", "fun", "is", "in", "object", "when", "trait", "This" "package", "as", "type", "val", "var", "fun", "is", "in", "object", "when", "trait", "This"
)); ));
@NotNull @NotNull
public final static Set<String> PRIMITIVE_TYPES = new HashSet<String>(Arrays.asList( public final static Set<String> PRIMITIVE_TYPES = new HashSet<String>(Arrays.asList(
"double", "float", "long", "int", "short", "byte", "boolean", "char" "double", "float", "long", "int", "short", "byte", "boolean", "char"
)); ));
static final String N = "\n"; static final String N = "\n";
@NotNull @NotNull
static final String N2 = N + N; static final String N2 = N + N;
@NotNull @NotNull
static final String SPACE = " "; static final String SPACE = " ";
@NotNull @NotNull
static final String EQUAL = "="; static final String EQUAL = "=";
@NotNull @NotNull
static final String EMPTY = ""; static final String EMPTY = "";
@NotNull @NotNull
static final String DOT = "."; static final String DOT = ".";
@NotNull @NotNull
static final String QUESTDOT = "?."; static final String QUESTDOT = "?.";
@NotNull @NotNull
static final String COLON = ":"; static final String COLON = ":";
@NotNull @NotNull
static final String IN = "in"; static final String IN = "in";
@NotNull @NotNull
static final String AT = "@"; static final String AT = "@";
@NotNull @NotNull
static final String BACKTICK = "`"; static final String BACKTICK = "`";
@NotNull @NotNull
static final String QUEST = "?"; static final String QUEST = "?";
@NotNull @NotNull
static final String COMMA_WITH_SPACE = "," + SPACE; static final String COMMA_WITH_SPACE = "," + SPACE;
@NotNull @NotNull
static final String STAR = "*"; static final String STAR = "*";
@NotNull @NotNull
protected static final String ZERO = "0"; protected static final String ZERO = "0";
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class OutProjectionType extends Type { public class OutProjectionType extends Type {
private final Type myBound; private final Type myBound;
public OutProjectionType(Type bound) { public OutProjectionType(Type bound) {
myBound = bound; myBound = bound;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "out" + SPACE + myBound.toKotlin(); return "out" + SPACE + myBound.toKotlin();
} }
} }
@@ -6,26 +6,26 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class Parameter extends Expression { public class Parameter extends Expression {
private final Identifier myIdentifier; private final Identifier myIdentifier;
private final Type myType; private final Type myType;
private boolean myReadOnly; private boolean myReadOnly;
public Parameter(Identifier identifier, Type type) { public Parameter(Identifier identifier, Type type) {
myIdentifier = identifier; myIdentifier = identifier;
myType = type; myType = type;
myReadOnly = true; myReadOnly = true;
} }
public Parameter(IdentifierImpl identifier, Type type, boolean readOnly) { public Parameter(IdentifierImpl identifier, Type type, boolean readOnly) {
this(identifier, type); this(identifier, type);
myReadOnly = readOnly; myReadOnly = readOnly;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
String vararg = myType.getKind() == Kind.VARARG ? "vararg" + SPACE : EMPTY; String vararg = myType.getKind() == Kind.VARARG ? "vararg" + SPACE : EMPTY;
String var = myReadOnly ? EMPTY : "var" + SPACE; String var = myReadOnly ? EMPTY : "var" + SPACE;
return vararg + var + myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin(); return vararg + var + myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin();
} }
} }
@@ -9,15 +9,15 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class ParameterList extends Expression { public class ParameterList extends Expression {
private final List<Parameter> myParameters; private final List<Parameter> myParameters;
public ParameterList(List<Parameter> parameters) { public ParameterList(List<Parameter> parameters) {
myParameters = parameters; myParameters = parameters;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return AstUtil.joinNodes(myParameters, COMMA_WITH_SPACE); return AstUtil.joinNodes(myParameters, COMMA_WITH_SPACE);
} }
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ParenthesizedExpression extends Expression { public class ParenthesizedExpression extends Expression {
private final Expression myExpression; private final Expression myExpression;
public ParenthesizedExpression(Expression expression) { public ParenthesizedExpression(Expression expression) {
myExpression = expression; myExpression = expression;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "(" + myExpression.toKotlin() + ")"; return "(" + myExpression.toKotlin() + ")";
} }
} }
@@ -9,21 +9,21 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class PolyadicExpression extends Expression { public class PolyadicExpression extends Expression {
private final List<Expression> myExpressions; private final List<Expression> myExpressions;
private final String myToken; private final String myToken;
private final List<String> myConversions; private final List<String> myConversions;
public PolyadicExpression(List<Expression> expressions, String token, List<String> conversions) { public PolyadicExpression(List<Expression> expressions, String token, List<String> conversions) {
super(); super();
myExpressions = expressions; myExpressions = expressions;
myToken = token; myToken = token;
myConversions = conversions; myConversions = conversions;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
List<String> expressionsWithConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myExpressions), myConversions); List<String> expressionsWithConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myExpressions), myConversions);
return AstUtil.join(expressionsWithConversions, SPACE + myToken + SPACE); return AstUtil.join(expressionsWithConversions, SPACE + myToken + SPACE);
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class PostfixOperator extends Expression { public class PostfixOperator extends Expression {
private final String myOp; private final String myOp;
private final Expression myExpression; private final Expression myExpression;
public PostfixOperator(String op, Expression expression) { public PostfixOperator(String op, Expression expression) {
myOp = op; myOp = op;
myExpression = expression; myExpression = expression;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myExpression.toKotlin() + myOp; return myExpression.toKotlin() + myOp;
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class PrefixOperator extends Expression { public class PrefixOperator extends Expression {
private final String myOp; private final String myOp;
private final Expression myExpression; private final Expression myExpression;
public PrefixOperator(String op, Expression expression) { public PrefixOperator(String op, Expression expression) {
myOp = op; myOp = op;
myExpression = expression; myExpression = expression;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myOp + myExpression.toKotlin(); return myOp + myExpression.toKotlin();
} }
} }
@@ -6,20 +6,20 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class PrimitiveType extends Type { public class PrimitiveType extends Type {
private final Identifier myType; private final Identifier myType;
public PrimitiveType(Identifier type) { public PrimitiveType(Identifier type) {
myType = type; myType = type;
} }
@Override @Override
public boolean isNullable() { public boolean isNullable() {
return false; return false;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myType.toKotlin(); return myType.toKotlin();
} }
} }
@@ -9,20 +9,20 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class ReferenceElement extends Element { public class ReferenceElement extends Element {
@NotNull @NotNull
private final Identifier myReference; private final Identifier myReference;
@NotNull @NotNull
private final List<Type> myTypes; private final List<Type> myTypes;
public ReferenceElement(@NotNull Identifier reference, @NotNull List<Type> types) { public ReferenceElement(@NotNull Identifier reference, @NotNull List<Type> types) {
myReference = reference; myReference = reference;
myTypes = types; myTypes = types;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
String typesIfNeeded = myTypes.size() > 0 ? "<" + AstUtil.joinNodes(myTypes, COMMA_WITH_SPACE) + ">" : EMPTY; String typesIfNeeded = myTypes.size() > 0 ? "<" + AstUtil.joinNodes(myTypes, COMMA_WITH_SPACE) + ">" : EMPTY;
return myReference.toKotlin() + typesIfNeeded; return myReference.toKotlin() + typesIfNeeded;
} }
} }
@@ -7,21 +7,21 @@ import org.jetbrains.jet.j2k.util.AstUtil;
* @author ignatov * @author ignatov
*/ */
public class ReturnStatement extends Statement { public class ReturnStatement extends Statement {
private final Expression myExpression; private final Expression myExpression;
private String myConversion = EMPTY; private String myConversion = EMPTY;
public ReturnStatement(Expression expression) { public ReturnStatement(Expression expression) {
myExpression = expression; myExpression = expression;
} }
public ReturnStatement(final Expression expression, final String conversion) { public ReturnStatement(final Expression expression, final String conversion) {
this(expression); this(expression);
myConversion = conversion; myConversion = conversion;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "return" + SPACE + AstUtil.applyConversionForOneItem(myExpression.toKotlin(), myConversion); return "return" + SPACE + AstUtil.applyConversionForOneItem(myExpression.toKotlin(), myConversion);
} }
} }
@@ -6,16 +6,16 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class StarProjectionType extends Type { public class StarProjectionType extends Type {
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
G g = new G(""); G g = new G("");
G<String> g2 = new G<String>(""); G<String> g2 = new G<String>("");
return STAR; return STAR;
} }
} }
class G <T extends String> { class G<T extends String> {
public <T> G(T t) { public <T> G(T t) {
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public abstract class Statement extends Element { public abstract class Statement extends Element {
@NotNull
public static final Statement EMPTY_STATEMENT = new EmptyStatement();
/**
* @author ignatov
*/
private static class EmptyStatement extends Statement {
@NotNull @NotNull
@Override public static final Statement EMPTY_STATEMENT = new EmptyStatement();
public String toKotlin() {
return EMPTY; /**
* @author ignatov
*/
private static class EmptyStatement extends Statement {
@NotNull
@Override
public String toKotlin() {
return EMPTY;
}
} }
}
} }
@@ -6,17 +6,18 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class SuperExpression extends Expression { public class SuperExpression extends Expression {
private final Identifier myIdentifier; private final Identifier myIdentifier;
public SuperExpression(Identifier identifier) { public SuperExpression(Identifier identifier) {
myIdentifier = identifier; myIdentifier = identifier;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myIdentifier.isEmpty()) if (myIdentifier.isEmpty()) {
return "super"; return "super";
return "super" + AT + myIdentifier.toKotlin(); }
} return "super" + AT + myIdentifier.toKotlin();
}
} }
@@ -6,22 +6,22 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class SureCallChainExpression extends Expression { public class SureCallChainExpression extends Expression {
private final Expression myExpression; private final Expression myExpression;
private final String myConversion; private final String myConversion;
public SureCallChainExpression(Expression expression, String conversion) { public SureCallChainExpression(Expression expression, String conversion) {
myExpression = expression; myExpression = expression;
myConversion = conversion; myConversion = conversion;
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return myExpression.isEmpty(); return myExpression.isEmpty();
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myExpression.toKotlin() + myConversion; return myExpression.toKotlin() + myConversion;
} }
} }
@@ -9,19 +9,19 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class SwitchContainer extends Statement { public class SwitchContainer extends Statement {
private final Expression myExpression; private final Expression myExpression;
private final List<CaseContainer> myCaseContainers; private final List<CaseContainer> myCaseContainers;
public SwitchContainer(final Expression expression, final List<CaseContainer> caseContainers) { public SwitchContainer(final Expression expression, final List<CaseContainer> caseContainers) {
myExpression = expression; myExpression = expression;
myCaseContainers = caseContainers; myCaseContainers = caseContainers;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "when" + SPACE + "(" + myExpression.toKotlin() + ")" + SPACE + "{" + N + return "when" + SPACE + "(" + myExpression.toKotlin() + ")" + SPACE + "{" + N +
AstUtil.joinNodes(myCaseContainers, N) + N + AstUtil.joinNodes(myCaseContainers, N) + N +
"}"; "}";
} }
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class SwitchLabelStatement extends Statement { public class SwitchLabelStatement extends Statement {
private final Expression myExpression; private final Expression myExpression;
public SwitchLabelStatement(final Expression expression) { public SwitchLabelStatement(final Expression expression) {
myExpression = expression; myExpression = expression;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myExpression.toKotlin(); return myExpression.toKotlin();
} }
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class SynchronizedStatement extends Statement { public class SynchronizedStatement extends Statement {
private final Expression myExpression; private final Expression myExpression;
private final Block myBlock; private final Block myBlock;
public SynchronizedStatement(Expression expression, Block block) { public SynchronizedStatement(Expression expression, Block block) {
myExpression = expression; myExpression = expression;
myBlock = block; myBlock = block;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "synchronized" + SPACE + "(" + myExpression.toKotlin() + ")" + SPACE + myBlock.toKotlin(); return "synchronized" + SPACE + "(" + myExpression.toKotlin() + ")" + SPACE + myBlock.toKotlin();
} }
} }
@@ -6,17 +6,18 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ThisExpression extends Expression { public class ThisExpression extends Expression {
private final Identifier myIdentifier; private final Identifier myIdentifier;
public ThisExpression(Identifier identifier) { public ThisExpression(Identifier identifier) {
myIdentifier = identifier; myIdentifier = identifier;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myIdentifier.isEmpty()) if (myIdentifier.isEmpty()) {
return "this"; return "this";
return "this" + AT + myIdentifier.toKotlin(); }
} return "this" + AT + myIdentifier.toKotlin();
}
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class ThrowStatement extends Expression { public class ThrowStatement extends Expression {
private final Expression myExpression; private final Expression myExpression;
public ThrowStatement(Expression expression) { public ThrowStatement(Expression expression) {
myExpression = expression; myExpression = expression;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "throw" + SPACE + myExpression.toKotlin(); return "throw" + SPACE + myExpression.toKotlin();
} }
} }
+12 -12
View File
@@ -7,18 +7,18 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class Trait extends Class { public class Trait extends Class {
public Trait(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes, public Trait(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes,
List<Expression> baseClassParams, List<Type> implementsTypes, List<Member> members) { List<Expression> baseClassParams, List<Type> implementsTypes, List<Member> members) {
super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, getMembers(members)); super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, getMembers(members));
TYPE = "trait"; TYPE = "trait";
} }
@Override @Override
String primaryConstructorSignatureToKotlin() { String primaryConstructorSignatureToKotlin() {
return EMPTY; return EMPTY;
} }
boolean needOpenModifier() { boolean needOpenModifier() {
return false; return false;
} }
} }
@@ -9,22 +9,22 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class TryStatement extends Statement { public class TryStatement extends Statement {
private final Block myBlock; private final Block myBlock;
private final List<CatchStatement> myCatches; private final List<CatchStatement> myCatches;
private final Block myFinallyBlock; private final Block myFinallyBlock;
public TryStatement(Block block, List<CatchStatement> catches, Block finallyBlock) { public TryStatement(Block block, List<CatchStatement> catches, Block finallyBlock) {
myBlock = block; myBlock = block;
myCatches = catches; myCatches = catches;
myFinallyBlock = finallyBlock; myFinallyBlock = finallyBlock;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "try" + N + return "try" + N +
myBlock.toKotlin() + N + myBlock.toKotlin() + N +
AstUtil.joinNodes(myCatches, N) + N + AstUtil.joinNodes(myCatches, N) + N +
(myFinallyBlock.isEmpty() ? EMPTY : "finally" + N + myFinallyBlock.toKotlin()); (myFinallyBlock.isEmpty() ? EMPTY : "finally" + N + myFinallyBlock.toKotlin());
} }
} }
+33 -33
View File
@@ -6,43 +6,43 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public abstract class Type extends Element { public abstract class Type extends Element {
@NotNull @NotNull
public static final Type EMPTY_TYPE = new EmptyType(); public static final Type EMPTY_TYPE = new EmptyType();
boolean myNullable = true; boolean myNullable = true;
@NotNull
@Override
public Kind getKind() {
return Kind.TYPE;
}
@NotNull
public Type convertedToNotNull() {
myNullable = false;
return this;
}
public boolean isNullable() {
return myNullable;
}
String isNullableStr() {
return isNullable() ? QUEST : EMPTY;
}
/**
* @author ignatov
*/
private static class EmptyType extends Type {
@NotNull @NotNull
@Override @Override
public String toKotlin() { public Kind getKind() {
return "UNRESOLVED_TYPE"; return Kind.TYPE;
} }
@Override @NotNull
public boolean isNullable() { public Type convertedToNotNull() {
return false; myNullable = false;
return this;
}
public boolean isNullable() {
return myNullable;
}
String isNullableStr() {
return isNullable() ? QUEST : EMPTY;
}
/**
* @author ignatov
*/
private static class EmptyType extends Type {
@NotNull
@Override
public String toKotlin() {
return "UNRESOLVED_TYPE";
}
@Override
public boolean isNullable() {
return false;
}
} }
}
} }
@@ -6,17 +6,17 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class TypeCastExpression extends Expression { public class TypeCastExpression extends Expression {
private final Type myType; private final Type myType;
private final Expression myExpression; private final Expression myExpression;
public TypeCastExpression(Type type, Expression expression) { public TypeCastExpression(Type type, Expression expression) {
myType = type; myType = type;
myExpression = expression; myExpression = expression;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "(" + myExpression.toKotlin() + SPACE + "as" + SPACE + myType.toKotlin() + ")"; return "(" + myExpression.toKotlin() + SPACE + "as" + SPACE + myType.toKotlin() + ")";
} }
} }
@@ -6,15 +6,15 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class TypeElement extends Element { public class TypeElement extends Element {
private final Type myType; private final Type myType;
public TypeElement(Type type) { public TypeElement(Type type) {
myType = type; myType = type;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myType.toKotlin(); return myType.toKotlin();
} }
} }
@@ -8,30 +8,32 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
public class TypeParameter extends Element { public class TypeParameter extends Element {
private final Identifier myName; private final Identifier myName;
private final List<Type> myExtendsTypes; private final List<Type> myExtendsTypes;
public TypeParameter(Identifier name, List<Type> extendsTypes) { public TypeParameter(Identifier name, List<Type> extendsTypes) {
myName = name; myName = name;
myExtendsTypes = extendsTypes; myExtendsTypes = extendsTypes;
} }
public boolean hasWhere() { public boolean hasWhere() {
return myExtendsTypes.size() > 1; return myExtendsTypes.size() > 1;
} }
@NotNull @NotNull
public String getWhereToKotlin() { public String getWhereToKotlin() {
if (hasWhere()) if (hasWhere()) {
return myName.toKotlin() + SPACE + COLON + SPACE + myExtendsTypes.get(1).toKotlin(); return myName.toKotlin() + SPACE + COLON + SPACE + myExtendsTypes.get(1).toKotlin();
return EMPTY; }
} return EMPTY;
}
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
if (myExtendsTypes.size() > 0) if (myExtendsTypes.size() > 0) {
return myName.toKotlin() + SPACE + COLON + SPACE + myExtendsTypes.get(0).toKotlin(); return myName.toKotlin() + SPACE + COLON + SPACE + myExtendsTypes.get(0).toKotlin();
return myName.toKotlin(); }
} return myName.toKotlin();
}
} }
+14 -14
View File
@@ -6,21 +6,21 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class VarArg extends Type { public class VarArg extends Type {
private final Type myType; private final Type myType;
public VarArg(Type type) { public VarArg(Type type) {
myType = type; myType = type;
} }
@NotNull @NotNull
@Override @Override
public Kind getKind() { public Kind getKind() {
return Kind.VARARG; return Kind.VARARG;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return myType.toKotlin(); return myType.toKotlin();
} }
} }
@@ -6,18 +6,18 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov * @author ignatov
*/ */
public class WhileStatement extends Statement { public class WhileStatement extends Statement {
final Expression myCondition; final Expression myCondition;
final Statement myStatement; final Statement myStatement;
public WhileStatement(Expression condition, Statement statement) { public WhileStatement(Expression condition, Statement statement) {
myCondition = condition; myCondition = condition;
myStatement = statement; myStatement = statement;
} }
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return "while" + SPACE + "(" + myCondition.toKotlin() + ")" + N + return "while" + SPACE + "(" + myCondition.toKotlin() + ")" + N +
myStatement.toKotlin(); myStatement.toKotlin();
} }
} }
+78 -73
View File
@@ -12,86 +12,91 @@ import java.util.Map;
* @author ignatov * @author ignatov
*/ */
public class AstUtil { public class AstUtil {
private AstUtil() { private AstUtil() {
}
private static String join(@NotNull final String[] array, @Nullable final String delimiter) {
StringBuilder buffer = new StringBuilder();
boolean haveDelimiter = (delimiter != null);
for (int i = 0; i < array.length; i++) {
buffer.append(array[i]);
if (haveDelimiter && (i + 1) < array.length)
buffer.append(delimiter);
} }
return buffer.toString(); private static String join(@NotNull final String[] array, @Nullable final String delimiter) {
} StringBuilder buffer = new StringBuilder();
boolean haveDelimiter = (delimiter != null);
public static String joinNodes(@NotNull final List<? extends INode> nodes, final String delimiter) { for (int i = 0; i < array.length; i++) {
return join(nodesToKotlin(nodes), delimiter); buffer.append(array[i]);
}
public static String join(@NotNull final List<String> array, final String delimiter) { if (haveDelimiter && (i + 1) < array.length) {
return join(array.toArray(new String[array.size()]), delimiter); buffer.append(delimiter);
} }
}
@NotNull return buffer.toString();
public static List<String> nodesToKotlin(@NotNull List<? extends INode> nodes) {
List<String> result = new LinkedList<String>();
for (INode n : nodes)
result.add(n.toKotlin());
return result;
}
@NotNull
public static String upperFirstCharacter(@NotNull String string) {
return string.substring(0, 1).toUpperCase() + string.substring(1);
}
@NotNull
public static String lowerFirstCharacter(@NotNull String string) {
return string.substring(0, 1).toLowerCase() + string.substring(1);
}
@NotNull
public static <T> List<String> createListWithEmptyString(@NotNull final List<T> arguments) {
final List<String> conversions = new LinkedList<String>();
//noinspection UnusedDeclaration
for (T argument : arguments) conversions.add("");
return conversions;
}
@NotNull
public static List<String> applyConversions(@NotNull List<String> first, @NotNull List<String> second) {
List<String> result = new LinkedList<String>();
assert first.size() == second.size() : "Lists must have the same size.";
for (int i = 0; i < first.size(); i++) {
result.add(applyConversionForOneItem(first.get(i), second.get(i)));
} }
return result;
}
@NotNull public static String joinNodes(@NotNull final List<? extends INode> nodes, final String delimiter) {
public static String applyConversionForOneItem(@NotNull String f, @NotNull String s) { return join(nodesToKotlin(nodes), delimiter);
if (s.isEmpty()) }
return f;
else
return "(" + f + ")" + s;
}
@NotNull public static String join(@NotNull final List<String> array, final String delimiter) {
public static <T> T getOrElse(@NotNull Map<T, T> map, @NotNull T e, @NotNull T orElse) { return join(array.toArray(new String[array.size()]), delimiter);
if (map.containsKey(e)) }
return map.get(e);
return orElse;
}
@NotNull @NotNull
public static String replaceLastQuest(@NotNull String str) { public static List<String> nodesToKotlin(@NotNull List<? extends INode> nodes) {
if (str.endsWith("?")) List<String> result = new LinkedList<String>();
return str.substring(0, str.length() - 1); for (INode n : nodes)
return str; result.add(n.toKotlin());
} return result;
}
@NotNull
public static String upperFirstCharacter(@NotNull String string) {
return string.substring(0, 1).toUpperCase() + string.substring(1);
}
@NotNull
public static String lowerFirstCharacter(@NotNull String string) {
return string.substring(0, 1).toLowerCase() + string.substring(1);
}
@NotNull
public static <T> List<String> createListWithEmptyString(@NotNull final List<T> arguments) {
final List<String> conversions = new LinkedList<String>();
//noinspection UnusedDeclaration
for (T argument : arguments) conversions.add("");
return conversions;
}
@NotNull
public static List<String> applyConversions(@NotNull List<String> first, @NotNull List<String> second) {
List<String> result = new LinkedList<String>();
assert first.size() == second.size() : "Lists must have the same size.";
for (int i = 0; i < first.size(); i++) {
result.add(applyConversionForOneItem(first.get(i), second.get(i)));
}
return result;
}
@NotNull
public static String applyConversionForOneItem(@NotNull String f, @NotNull String s) {
if (s.isEmpty()) {
return f;
}
else {
return "(" + f + ")" + s;
}
}
@NotNull
public static <T> T getOrElse(@NotNull Map<T, T> map, @NotNull T e, @NotNull T orElse) {
if (map.containsKey(e)) {
return map.get(e);
}
return orElse;
}
@NotNull
public static String replaceLastQuest(@NotNull String str) {
if (str.endsWith("?")) {
return str.substring(0, str.length() - 1);
}
return str;
}
} }
@@ -11,20 +11,20 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class ClassVisitor extends JavaRecursiveElementVisitor { public class ClassVisitor extends JavaRecursiveElementVisitor {
private final Set<String> myClassIdentifiers; private final Set<String> myClassIdentifiers;
public ClassVisitor() { public ClassVisitor() {
myClassIdentifiers = new HashSet<String>(); myClassIdentifiers = new HashSet<String>();
} }
@NotNull @NotNull
public Set<String> getClassIdentifiers() { public Set<String> getClassIdentifiers() {
return new HashSet<String>(myClassIdentifiers); return new HashSet<String>(myClassIdentifiers);
} }
@Override @Override
public void visitClass(@NotNull PsiClass aClass) { public void visitClass(@NotNull PsiClass aClass) {
myClassIdentifiers.add(aClass.getQualifiedName()); myClassIdentifiers.add(aClass.getQualifiedName());
super.visitClass(aClass); super.visitClass(aClass);
} }
} }
@@ -4,17 +4,17 @@ package org.jetbrains.jet.j2k.visitors;
* @author ignatov * @author ignatov
*/ */
public class Dispatcher { public class Dispatcher {
private ExpressionVisitor myExpressionVisitor; private ExpressionVisitor myExpressionVisitor;
public void setExpressionVisitor(final ExpressionVisitor expressionVisitor) { public void setExpressionVisitor(final ExpressionVisitor expressionVisitor) {
this.myExpressionVisitor = expressionVisitor; this.myExpressionVisitor = expressionVisitor;
} }
public Dispatcher() { public Dispatcher() {
myExpressionVisitor = new ExpressionVisitor(); myExpressionVisitor = new ExpressionVisitor();
} }
public ExpressionVisitor getExpressionVisitor() { public ExpressionVisitor getExpressionVisitor() {
return myExpressionVisitor; return myExpressionVisitor;
} }
} }
@@ -7,86 +7,87 @@ import org.jetbrains.jet.j2k.ast.*;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.j2k.Converter.*; import static org.jetbrains.jet.j2k.Converter.*;
import static org.jetbrains.jet.j2k.ConverterUtil.*; import static org.jetbrains.jet.j2k.ConverterUtil.isAnnotatedAsNotNull;
/** /**
* @author ignatov * @author ignatov
*/ */
public class ElementVisitor extends JavaElementVisitor { public class ElementVisitor extends JavaElementVisitor {
@NotNull @NotNull
private Element myResult = Element.EMPTY_ELEMENT; private Element myResult = Element.EMPTY_ELEMENT;
@NotNull @NotNull
public Element getResult() { public Element getResult() {
return myResult; return myResult;
}
@Override
public void visitLocalVariable(@NotNull PsiLocalVariable variable) {
super.visitLocalVariable(variable);
myResult = new LocalVariable(
new IdentifierImpl(variable.getName()), // TODO
modifiersListToModifiersSet(variable.getModifierList()),
typeToType(variable.getType(), isAnnotatedAsNotNull(variable.getModifierList())),
createSureCallOnlyForChain(variable.getInitializer(), variable.getType())
);
}
@Override
public void visitExpressionList(@NotNull PsiExpressionList list) {
super.visitExpressionList(list);
myResult = new ExpressionList(
expressionsToExpressionList(list.getExpressions()),
typesToTypeList(list.getExpressionTypes())
);
}
@Override
public void visitReferenceElement(@NotNull PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
final List<Type> types = typesToTypeList(reference.getTypeParameters());
if (!reference.isQualified()) {
myResult = new ReferenceElement(
new IdentifierImpl(reference.getReferenceName()),
types
);
} else {
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();
}
myResult = new ReferenceElement(
new IdentifierImpl(result),
types
);
} }
}
@Override @Override
public void visitTypeElement(@NotNull PsiTypeElement type) { public void visitLocalVariable(@NotNull PsiLocalVariable variable) {
super.visitTypeElement(type); super.visitLocalVariable(variable);
myResult = new TypeElement(typeToType(type.getType()));
}
@Override myResult = new LocalVariable(
public void visitTypeParameter(@NotNull PsiTypeParameter classParameter) { new IdentifierImpl(variable.getName()), // TODO
super.visitTypeParameter(classParameter); modifiersListToModifiersSet(variable.getModifierList()),
myResult = new TypeParameter( typeToType(variable.getType(), isAnnotatedAsNotNull(variable.getModifierList())),
new IdentifierImpl(classParameter.getName()), // TODO createSureCallOnlyForChain(variable.getInitializer(), variable.getType())
typesToTypeList(classParameter.getExtendsListTypes()) );
); }
}
@Override @Override
public void visitParameterList(@NotNull PsiParameterList list) { public void visitExpressionList(@NotNull PsiExpressionList list) {
super.visitParameterList(list); super.visitExpressionList(list);
myResult = new ParameterList( myResult = new ExpressionList(
parametersToParameterList(list.getParameters()) expressionsToExpressionList(list.getExpressions()),
); typesToTypeList(list.getExpressionTypes())
} );
}
@Override
public void visitReferenceElement(@NotNull PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
final List<Type> types = typesToTypeList(reference.getTypeParameters());
if (!reference.isQualified()) {
myResult = new ReferenceElement(
new IdentifierImpl(reference.getReferenceName()),
types
);
}
else {
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();
}
myResult = new ReferenceElement(
new IdentifierImpl(result),
types
);
}
}
@Override
public void visitTypeElement(@NotNull PsiTypeElement type) {
super.visitTypeElement(type);
myResult = new TypeElement(typeToType(type.getType()));
}
@Override
public void visitTypeParameter(@NotNull PsiTypeParameter classParameter) {
super.visitTypeParameter(classParameter);
myResult = new TypeParameter(
new IdentifierImpl(classParameter.getName()), // TODO
typesToTypeList(classParameter.getExtendsListTypes())
);
}
@Override
public void visitParameterList(@NotNull PsiParameterList list) {
super.visitParameterList(list);
myResult = new ParameterList(
parametersToParameterList(list.getParameters())
);
}
} }
@@ -16,442 +16,469 @@ import static org.jetbrains.jet.j2k.visitors.TypeVisitor.*;
* @author ignatov * @author ignatov
*/ */
public class ExpressionVisitor extends StatementVisitor { public class ExpressionVisitor extends StatementVisitor {
@NotNull @NotNull
Expression myResult = Expression.EMPTY_EXPRESSION; Expression myResult = Expression.EMPTY_EXPRESSION;
@Override @Override
public void visitExpression(final PsiExpression expression) { public void visitExpression(final PsiExpression expression) {
myResult = Expression.EMPTY_EXPRESSION; myResult = Expression.EMPTY_EXPRESSION;
}
@NotNull
@Override
public Expression getResult() {
return myResult;
}
@Override
public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expression) {
super.visitArrayAccessExpression(expression);
myResult = new ArrayAccessExpression(
expressionToExpression(expression.getArrayExpression()),
expressionToExpression(expression.getIndexExpression())
);
}
@Override
public void visitArrayInitializerExpression(@NotNull PsiArrayInitializerExpression expression) {
super.visitArrayInitializerExpression(expression);
myResult = new ArrayInitializerExpression(
typeToType(expression.getType()),
expressionsToExpressionList(expression.getInitializers())
);
}
@Override
public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
// TODO: simplify
final IElementType tokenType = expression.getOperationSign().getTokenType();
String secondOp = "";
if (tokenType == JavaTokenType.GTGTEQ) secondOp = "shr";
if (tokenType == JavaTokenType.LTLTEQ) secondOp = "shl";
if (tokenType == JavaTokenType.XOREQ) secondOp = "xor";
if (tokenType == JavaTokenType.ANDEQ) secondOp = "and";
if (tokenType == JavaTokenType.OREQ) secondOp = "or";
if (tokenType == JavaTokenType.GTGTGTEQ) secondOp = "ushr";
if (!secondOp.isEmpty()) // if not Kotlin operators
myResult = new AssignmentExpression(
expressionToExpression(expression.getLExpression()),
new BinaryExpression(
expressionToExpression(expression.getLExpression()),
expressionToExpression(expression.getRExpression()),
secondOp
),
"="
);
else
myResult = new AssignmentExpression(
expressionToExpression(expression.getLExpression()),
expressionToExpression(expression.getRExpression()),
expression.getOperationSign().getText() // TODO
);
}
@NotNull
private static String getOperatorString(@NotNull IElementType tokenType) {
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 "";
}
@Override
public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) {
super.visitBinaryExpression(expression);
if (expression.getOperationSign().getTokenType() == JavaTokenType.GTGTGT)
myResult = new DummyMethodCallExpression(
expressionToExpression(expression.getLOperand()),
"ushr",
expressionToExpression(expression.getROperand()));
else
myResult =
new BinaryExpression(
expressionToExpression(expression.getLOperand()),
expressionToExpression(expression.getROperand()),
getOperatorString(expression.getOperationSign().getTokenType()),
createConversions(expression, PsiType.BOOLEAN)
);
}
@Override
public void visitClassObjectAccessExpression(@NotNull PsiClassObjectAccessExpression expression) {
super.visitClassObjectAccessExpression(expression);
myResult = new ClassObjectAccessExpression(elementToElement(expression.getOperand()));
}
@Override
public void visitConditionalExpression(@NotNull PsiConditionalExpression expression) {
super.visitConditionalExpression(expression);
PsiExpression condition = expression.getCondition();
PsiType type = condition.getType();
Expression e = type != null ?
createSureCallOnlyForChain(condition, type) :
expressionToExpression(condition);
myResult = new ParenthesizedExpression(
new IfStatement(
e,
expressionToExpression(expression.getThenExpression()),
expressionToExpression(expression.getElseExpression())
)
);
}
@Override
public void visitExpressionList(@NotNull PsiExpressionList list) {
super.visitExpressionList(list);
myResult = new ExpressionList(expressionsToExpressionList(list.getExpressions()));
}
@Override
public void visitInstanceOfExpression(@NotNull PsiInstanceOfExpression expression) {
super.visitInstanceOfExpression(expression);
myResult = new IsOperator(
expressionToExpression(expression.getOperand()),
elementToElement(expression.getCheckType()));
}
@Override
public void visitLiteralExpression(@NotNull PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
final Object value = expression.getValue();
String text = expression.getText();
boolean isQuotingNeeded = true;
final PsiType type = expression.getType();
if (type != null) {
String canonicalTypeStr = type.getCanonicalText();
if (canonicalTypeStr.equals("double") || canonicalTypeStr.equals(JAVA_LANG_DOUBLE))
text = text.replace("D", "").replace("d", "");
if (canonicalTypeStr.equals("float") || canonicalTypeStr.equals(JAVA_LANG_FLOAT))
text = text.replace("F", "").replace("f", "") + "." + "flt";
if (canonicalTypeStr.equals("long") || canonicalTypeStr.equals(JAVA_LANG_LONG))
text = text.replace("L", "").replace("l", "");
if (canonicalTypeStr.equals("int") || canonicalTypeStr.equals(JAVA_LANG_INTEGER)) // need for hex support
text = value != null ? value.toString() : text;
if (canonicalTypeStr.equals(JAVA_LANG_STRING))
isQuotingNeeded = false;
if (canonicalTypeStr.equals("char") || canonicalTypeStr.equals(JAVA_LANG_CHARACTER))
isQuotingNeeded = false;
} }
myResult = new LiteralExpression(new IdentifierImpl(text, false, isQuotingNeeded));
}
@Override @NotNull
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { @Override
super.visitMethodCallExpression(expression); public Expression getResult() {
if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) { return myResult;
myResult = // TODO: not resolved }
new MethodCallExpression(
expressionToExpression(expression.getMethodExpression()), @Override
expressionsToExpressionList(expression.getArgumentList().getExpressions()), public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expression) {
createConversions(expression), super.visitArrayAccessExpression(expression);
typeToType(expression.getType()).isNullable(), myResult = new ArrayAccessExpression(
typesToTypeList(expression.getTypeArguments()) expressionToExpression(expression.getArrayExpression()),
expressionToExpression(expression.getIndexExpression())
); );
} }
}
@Override @Override
public void visitCallExpression(PsiCallExpression callExpression) { public void visitArrayInitializerExpression(@NotNull PsiArrayInitializerExpression expression) {
super.visitCallExpression(callExpression); super.visitArrayInitializerExpression(expression);
} myResult = new ArrayInitializerExpression(
typeToType(expression.getType()),
@Override expressionsToExpressionList(expression.getInitializers())
public void visitNewExpression(@NotNull PsiNewExpression expression) { );
super.visitNewExpression(expression);
if (expression.getArrayInitializer() != null) // new Foo[] {Foo(1), Foo(2)}
myResult = createNewEmptyArray(expression);
else if (expression.getArrayDimensions().length > 0) { // new Foo[5]
myResult = createNewEmptyArrayWithoutInitialization(expression);
} else { // new Class(): common case
myResult = createNewClassExpression(expression);
} }
}
@NotNull @Override
private static Expression createNewClassExpression(@NotNull PsiNewExpression expression) { public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
final PsiAnonymousClass anonymousClass = expression.getAnonymousClass(); super.visitAssignmentExpression(expression);
final PsiMethod constructor = expression.resolveMethod();
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
final boolean isNotConvertedClass = classReference != null && !getClassIdentifiers().contains(classReference.getQualifiedName());
PsiExpressionList argumentList = expression.getArgumentList();
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
return new NewClassExpression(
expressionToExpression(expression.getQualifier()),
elementToElement(classReference),
expressionsToExpressionList(arguments),
createConversions(expression),
anonymousClass != null ? anonymousClassToAnonymousClass(anonymousClass) : null
);
}
// is constructor secondary
final PsiJavaCodeReferenceElement reference = expression.getClassReference();
final List<Type> typeParameters = reference != null ? typesToTypeList(reference.getTypeParameters()) : Collections.<Type>emptyList();
return new CallChainExpression(
new IdentifierImpl(constructor.getName(), false),
new MethodCallExpression(
new IdentifierImpl("init"),
expressionsToExpressionList(arguments),
typeParameters));
}
@NotNull // TODO: simplify
private static Expression createNewEmptyArrayWithoutInitialization(@NotNull PsiNewExpression expression) {
return new ArrayWithoutInitializationExpression(
typeToType(expression.getType(), true),
expressionsToExpressionList(expression.getArrayDimensions())
);
}
@NotNull final IElementType tokenType = expression.getOperationSign().getTokenType();
private static Expression createNewEmptyArray(@NotNull PsiNewExpression expression) {
return expressionToExpression(expression.getArrayInitializer());
}
@Override String secondOp = "";
public void visitParenthesizedExpression(@NotNull PsiParenthesizedExpression expression) { if (tokenType == JavaTokenType.GTGTEQ) secondOp = "shr";
super.visitParenthesizedExpression(expression); if (tokenType == JavaTokenType.LTLTEQ) secondOp = "shl";
myResult = new ParenthesizedExpression( if (tokenType == JavaTokenType.XOREQ) secondOp = "xor";
expressionToExpression(expression.getExpression()) if (tokenType == JavaTokenType.ANDEQ) secondOp = "and";
); if (tokenType == JavaTokenType.OREQ) secondOp = "or";
} if (tokenType == JavaTokenType.GTGTGTEQ) secondOp = "ushr";
@Override if (!secondOp.isEmpty()) // if not Kotlin operators
public void visitPostfixExpression(@NotNull PsiPostfixExpression expression) { {
super.visitPostfixExpression(expression); myResult = new AssignmentExpression(
myResult = new PostfixOperator( expressionToExpression(expression.getLExpression()),
getOperatorString(expression.getOperationSign().getTokenType()), new BinaryExpression(
expressionToExpression(expression.getOperand()) expressionToExpression(expression.getLExpression()),
); expressionToExpression(expression.getRExpression()),
} secondOp
),
@Override "="
public void visitPrefixExpression(@NotNull PsiPrefixExpression expression) { );
super.visitPrefixExpression(expression);
if (expression.getOperationTokenType() == JavaTokenType.TILDE)
myResult = new DummyMethodCallExpression(
new ParenthesizedExpression(expressionToExpression(expression.getOperand())), "inv", Expression.EMPTY_EXPRESSION
);
else
myResult = new PrefixOperator(
getOperatorString(expression.getOperationSign().getTokenType()),
expressionToExpression(expression.getOperand())
);
}
@Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final boolean isFieldReference = isFieldReference(expression, getContainingClass(expression));
final boolean insideSecondaryConstructor = isInsideSecondaryConstructor(expression);
final boolean hasReceiver = isFieldReference && insideSecondaryConstructor;
final boolean isThis = isThisExpression(expression);
final boolean isNullable = typeToType(expression.getType()).isNullable();
final String className = getClassNameWithConstructor(expression);
Expression identifier = new IdentifierImpl(expression.getReferenceName(), isNullable);
final String __ = "__";
if (hasReceiver)
identifier = new CallChainExpression(new IdentifierImpl(__, false), new IdentifierImpl(expression.getReferenceName(), isNullable));
else if (insideSecondaryConstructor && isThis)
identifier = new IdentifierImpl("val __ = " + className); // TODO: hack
myResult = new CallChainExpression(
expressionToExpression(expression.getQualifierExpression()),
identifier // TODO: if type exists so identifier is nullable
);
}
@NotNull
private static String getClassNameWithConstructor(@NotNull PsiReferenceExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
final PsiClass containingClass = ((PsiMethod) context).getContainingClass();
if (containingClass != null) {
final PsiIdentifier identifier = containingClass.getNameIdentifier();
if (identifier != null)
return identifier.getText();
} }
} else {
context = context.getContext(); myResult = new AssignmentExpression(
} expressionToExpression(expression.getLExpression()),
return ""; expressionToExpression(expression.getRExpression()),
} expression.getOperationSign().getText() // TODO
);
@NotNull
static String getClassName(@NotNull PsiExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiClass) {
final PsiClass containingClass = (PsiClass) context;
final PsiIdentifier identifier = containingClass.getNameIdentifier();
if (identifier != null)
return identifier.getText();
}
context = context.getContext();
}
return "";
}
private static boolean isFieldReference(@NotNull PsiReferenceExpression expression, PsiClass currentClass) {
final PsiReference reference = expression.getReference();
if (reference != null) {
final PsiElement resolvedReference = reference.resolve();
if (resolvedReference != null) {
if (resolvedReference instanceof PsiField) {
return ((PsiField) resolvedReference).getContainingClass() == currentClass;
} }
}
} }
return false;
}
private static boolean isInsideSecondaryConstructor(@NotNull PsiReferenceExpression expression) { @NotNull
PsiElement context = expression.getContext(); private static String getOperatorString(@NotNull IElementType tokenType) {
while (context != null) { if (tokenType == JavaTokenType.PLUS) return "+";
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) if (tokenType == JavaTokenType.MINUS) return "-";
return !isConstructorPrimary((PsiMethod) context); if (tokenType == JavaTokenType.ASTERISK) return "*";
context = context.getContext(); 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 "";
} }
return false;
}
private static boolean isInsidePrimaryConstructor(@NotNull PsiExpression expression) { @Override
PsiElement context = expression.getContext(); public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) {
while (context != null) { super.visitBinaryExpression(expression);
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor())
return isConstructorPrimary((PsiMethod) context); if (expression.getOperationSign().getTokenType() == JavaTokenType.GTGTGT) {
context = context.getContext(); myResult = new DummyMethodCallExpression(
expressionToExpression(expression.getLOperand()),
"ushr",
expressionToExpression(expression.getROperand()));
}
else {
myResult =
new BinaryExpression(
expressionToExpression(expression.getLOperand()),
expressionToExpression(expression.getROperand()),
getOperatorString(expression.getOperationSign().getTokenType()),
createConversions(expression, PsiType.BOOLEAN)
);
}
} }
return false;
}
@Nullable @Override
private static PsiClass getContainingClass(@NotNull PsiExpression expression) { public void visitClassObjectAccessExpression(@NotNull PsiClassObjectAccessExpression expression) {
PsiElement context = expression.getContext(); super.visitClassObjectAccessExpression(expression);
while (context != null) { myResult = new ClassObjectAccessExpression(elementToElement(expression.getOperand()));
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor())
return ((PsiMethod) context).getContainingClass();
context = context.getContext();
} }
return null;
}
private static boolean isThisExpression(@NotNull PsiReferenceExpression expression) { @Override
for (PsiReference r : expression.getReferences()) public void visitConditionalExpression(@NotNull PsiConditionalExpression expression) {
if (r.getCanonicalText().equals("this")) { super.visitConditionalExpression(expression);
final PsiElement res = r.resolve(); PsiExpression condition = expression.getCondition();
if (res != null && res instanceof PsiMethod && ((PsiMethod) res).isConstructor()) PsiType type = condition.getType();
return true; Expression e = type != null ?
} createSureCallOnlyForChain(condition, type) :
return false; expressionToExpression(condition);
} myResult = new ParenthesizedExpression(
new IfStatement(
@Override e,
public void visitSuperExpression(@NotNull PsiSuperExpression expression) { expressionToExpression(expression.getThenExpression()),
super.visitSuperExpression(expression); expressionToExpression(expression.getElseExpression())
final PsiJavaCodeReferenceElement qualifier = expression.getQualifier(); )
myResult = new SuperExpression( );
qualifier != null ?
new IdentifierImpl(qualifier.getQualifiedName()) :
Identifier.EMPTY_IDENTIFIER
);
}
@Override
public void visitThisExpression(@NotNull PsiThisExpression expression) {
super.visitThisExpression(expression);
final PsiJavaCodeReferenceElement qualifier = expression.getQualifier();
myResult = new ThisExpression(
qualifier != null ?
new IdentifierImpl(qualifier.getQualifiedName()) :
Identifier.EMPTY_IDENTIFIER
);
}
@Override
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
final PsiTypeElement castType = expression.getCastType();
if (castType != null) {
myResult = new TypeCastExpression(
typeToType(castType.getType()),
expressionToExpression(expression.getOperand())
);
} }
}
@Override @Override
public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) { public void visitExpressionList(@NotNull PsiExpressionList list) {
super.visitPolyadicExpression(expression); super.visitExpressionList(list);
myResult = new PolyadicExpression( myResult = new ExpressionList(expressionsToExpressionList(list.getExpressions()));
expressionsToExpressionList(expression.getOperands()), }
getOperatorString(expression.getOperationTokenType()),
createConversions(expression, PsiType.BOOLEAN) @Override
); public void visitInstanceOfExpression(@NotNull PsiInstanceOfExpression expression) {
} super.visitInstanceOfExpression(expression);
myResult = new IsOperator(
expressionToExpression(expression.getOperand()),
elementToElement(expression.getCheckType()));
}
@Override
public void visitLiteralExpression(@NotNull PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
final Object value = expression.getValue();
String text = expression.getText();
boolean isQuotingNeeded = true;
final PsiType type = expression.getType();
if (type != null) {
String canonicalTypeStr = type.getCanonicalText();
if (canonicalTypeStr.equals("double") || canonicalTypeStr.equals(JAVA_LANG_DOUBLE)) {
text = text.replace("D", "").replace("d", "");
}
if (canonicalTypeStr.equals("float") || canonicalTypeStr.equals(JAVA_LANG_FLOAT)) {
text = text.replace("F", "").replace("f", "") + "." + "flt";
}
if (canonicalTypeStr.equals("long") || canonicalTypeStr.equals(JAVA_LANG_LONG)) {
text = text.replace("L", "").replace("l", "");
}
if (canonicalTypeStr.equals("int") || canonicalTypeStr.equals(JAVA_LANG_INTEGER)) // need for hex support
{
text = value != null ? value.toString() : text;
}
if (canonicalTypeStr.equals(JAVA_LANG_STRING)) {
isQuotingNeeded = false;
}
if (canonicalTypeStr.equals("char") || canonicalTypeStr.equals(JAVA_LANG_CHARACTER)) {
isQuotingNeeded = false;
}
}
myResult = new LiteralExpression(new IdentifierImpl(text, false, isQuotingNeeded));
}
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
myResult = // TODO: not resolved
new MethodCallExpression(
expressionToExpression(expression.getMethodExpression()),
expressionsToExpressionList(expression.getArgumentList().getExpressions()),
createConversions(expression),
typeToType(expression.getType()).isNullable(),
typesToTypeList(expression.getTypeArguments())
);
}
}
@Override
public void visitCallExpression(PsiCallExpression callExpression) {
super.visitCallExpression(callExpression);
}
@Override
public void visitNewExpression(@NotNull PsiNewExpression expression) {
super.visitNewExpression(expression);
if (expression.getArrayInitializer() != null) // new Foo[] {Foo(1), Foo(2)}
{
myResult = createNewEmptyArray(expression);
}
else if (expression.getArrayDimensions().length > 0) { // new Foo[5]
myResult = createNewEmptyArrayWithoutInitialization(expression);
}
else { // new Class(): common case
myResult = createNewClassExpression(expression);
}
}
@NotNull
private static Expression createNewClassExpression(@NotNull PsiNewExpression expression) {
final PsiAnonymousClass anonymousClass = expression.getAnonymousClass();
final PsiMethod constructor = expression.resolveMethod();
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
final boolean isNotConvertedClass = classReference != null && !getClassIdentifiers().contains(classReference.getQualifiedName());
PsiExpressionList argumentList = expression.getArgumentList();
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
return new NewClassExpression(
expressionToExpression(expression.getQualifier()),
elementToElement(classReference),
expressionsToExpressionList(arguments),
createConversions(expression),
anonymousClass != null ? anonymousClassToAnonymousClass(anonymousClass) : null
);
}
// is constructor secondary
final PsiJavaCodeReferenceElement reference = expression.getClassReference();
final List<Type> typeParameters = reference != null
? typesToTypeList(reference.getTypeParameters())
: Collections.<Type>emptyList();
return new CallChainExpression(
new IdentifierImpl(constructor.getName(), false),
new MethodCallExpression(
new IdentifierImpl("init"),
expressionsToExpressionList(arguments),
typeParameters));
}
@NotNull
private static Expression createNewEmptyArrayWithoutInitialization(@NotNull PsiNewExpression expression) {
return new ArrayWithoutInitializationExpression(
typeToType(expression.getType(), true),
expressionsToExpressionList(expression.getArrayDimensions())
);
}
@NotNull
private static Expression createNewEmptyArray(@NotNull PsiNewExpression expression) {
return expressionToExpression(expression.getArrayInitializer());
}
@Override
public void visitParenthesizedExpression(@NotNull PsiParenthesizedExpression expression) {
super.visitParenthesizedExpression(expression);
myResult = new ParenthesizedExpression(
expressionToExpression(expression.getExpression())
);
}
@Override
public void visitPostfixExpression(@NotNull PsiPostfixExpression expression) {
super.visitPostfixExpression(expression);
myResult = new PostfixOperator(
getOperatorString(expression.getOperationSign().getTokenType()),
expressionToExpression(expression.getOperand())
);
}
@Override
public void visitPrefixExpression(@NotNull PsiPrefixExpression expression) {
super.visitPrefixExpression(expression);
if (expression.getOperationTokenType() == JavaTokenType.TILDE) {
myResult = new DummyMethodCallExpression(
new ParenthesizedExpression(expressionToExpression(expression.getOperand())), "inv", Expression.EMPTY_EXPRESSION
);
}
else {
myResult = new PrefixOperator(
getOperatorString(expression.getOperationSign().getTokenType()),
expressionToExpression(expression.getOperand())
);
}
}
@Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final boolean isFieldReference = isFieldReference(expression, getContainingClass(expression));
final boolean insideSecondaryConstructor = isInsideSecondaryConstructor(expression);
final boolean hasReceiver = isFieldReference && insideSecondaryConstructor;
final boolean isThis = isThisExpression(expression);
final boolean isNullable = typeToType(expression.getType()).isNullable();
final String className = getClassNameWithConstructor(expression);
Expression identifier = new IdentifierImpl(expression.getReferenceName(), isNullable);
final String __ = "__";
if (hasReceiver) {
identifier = new CallChainExpression(new IdentifierImpl(__, false), new IdentifierImpl(expression.getReferenceName(), isNullable));
}
else if (insideSecondaryConstructor && isThis) {
identifier = new IdentifierImpl("val __ = " + className); // TODO: hack
}
myResult = new CallChainExpression(
expressionToExpression(expression.getQualifierExpression()),
identifier // TODO: if type exists so identifier is nullable
);
}
@NotNull
private static String getClassNameWithConstructor(@NotNull PsiReferenceExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
final PsiClass containingClass = ((PsiMethod) context).getContainingClass();
if (containingClass != null) {
final PsiIdentifier identifier = containingClass.getNameIdentifier();
if (identifier != null) {
return identifier.getText();
}
}
}
context = context.getContext();
}
return "";
}
@NotNull
static String getClassName(@NotNull PsiExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiClass) {
final PsiClass containingClass = (PsiClass) context;
final PsiIdentifier identifier = containingClass.getNameIdentifier();
if (identifier != null) {
return identifier.getText();
}
}
context = context.getContext();
}
return "";
}
private static boolean isFieldReference(@NotNull PsiReferenceExpression expression, PsiClass currentClass) {
final PsiReference reference = expression.getReference();
if (reference != null) {
final PsiElement resolvedReference = reference.resolve();
if (resolvedReference != null) {
if (resolvedReference instanceof PsiField) {
return ((PsiField) resolvedReference).getContainingClass() == currentClass;
}
}
}
return false;
}
private static boolean isInsideSecondaryConstructor(@NotNull PsiReferenceExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
return !isConstructorPrimary((PsiMethod) context);
}
context = context.getContext();
}
return false;
}
private static boolean isInsidePrimaryConstructor(@NotNull PsiExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
return isConstructorPrimary((PsiMethod) context);
}
context = context.getContext();
}
return false;
}
@Nullable
private static PsiClass getContainingClass(@NotNull PsiExpression expression) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
return ((PsiMethod) context).getContainingClass();
}
context = context.getContext();
}
return null;
}
private static boolean isThisExpression(@NotNull PsiReferenceExpression expression) {
for (PsiReference r : expression.getReferences())
if (r.getCanonicalText().equals("this")) {
final PsiElement res = r.resolve();
if (res != null && res instanceof PsiMethod && ((PsiMethod) res).isConstructor()) {
return true;
}
}
return false;
}
@Override
public void visitSuperExpression(@NotNull PsiSuperExpression expression) {
super.visitSuperExpression(expression);
final PsiJavaCodeReferenceElement qualifier = expression.getQualifier();
myResult = new SuperExpression(
qualifier != null ?
new IdentifierImpl(qualifier.getQualifiedName()) :
Identifier.EMPTY_IDENTIFIER
);
}
@Override
public void visitThisExpression(@NotNull PsiThisExpression expression) {
super.visitThisExpression(expression);
final PsiJavaCodeReferenceElement qualifier = expression.getQualifier();
myResult = new ThisExpression(
qualifier != null ?
new IdentifierImpl(qualifier.getQualifiedName()) :
Identifier.EMPTY_IDENTIFIER
);
}
@Override
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
final PsiTypeElement castType = expression.getCastType();
if (castType != null) {
myResult = new TypeCastExpression(
typeToType(castType.getType()),
expressionToExpression(expression.getOperand())
);
}
}
@Override
public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) {
super.visitPolyadicExpression(expression);
myResult = new PolyadicExpression(
expressionsToExpressionList(expression.getOperands()),
getOperatorString(expression.getOperationTokenType()),
createConversions(expression, PsiType.BOOLEAN)
);
}
} }
@@ -13,33 +13,38 @@ import static org.jetbrains.jet.j2k.visitors.TypeVisitor.JAVA_LANG_OBJECT;
* @author ignatov * @author ignatov
*/ */
public class ExpressionVisitorForDirectObjectInheritors extends ExpressionVisitor { public class ExpressionVisitorForDirectObjectInheritors extends ExpressionVisitor {
@Override @Override
public void visitMethodCallExpression(@NotNull final PsiMethodCallExpression expression) { public void visitMethodCallExpression(@NotNull final PsiMethodCallExpression expression) {
if (superMethodInvocation(expression.getMethodExpression(), "hashCode")) if (superMethodInvocation(expression.getMethodExpression(), "hashCode")) {
myResult = new DummyMethodCallExpression(new IdentifierImpl("System"), "identityHashCode", new IdentifierImpl("this")); myResult = new DummyMethodCallExpression(new IdentifierImpl("System"), "identityHashCode", new IdentifierImpl("this"));
else if (superMethodInvocation(expression.getMethodExpression(), "equals")) }
myResult = new DummyMethodCallExpression(new IdentifierImpl("this"), "identityEquals", Converter.elementToElement(expression.getArgumentList())); else if (superMethodInvocation(expression.getMethodExpression(), "equals")) {
else if (superMethodInvocation(expression.getMethodExpression(), "toString")) myResult = new DummyMethodCallExpression(new IdentifierImpl("this"), "identityEquals", Converter.elementToElement(expression.getArgumentList()));
myResult = new DummyStringExpression(String.format("getJavaClass<%s>.getName() + '@' + Integer.toHexString(hashCode())", getClassName(expression.getMethodExpression()))); }
else else if (superMethodInvocation(expression.getMethodExpression(), "toString")) {
super.visitMethodCallExpression(expression); myResult = new DummyStringExpression(String.format("getJavaClass<%s>.getName() + '@' + Integer.toHexString(hashCode())", getClassName(expression.getMethodExpression())));
} }
else {
@Override super.visitMethodCallExpression(expression);
public void visitReferenceExpression(@NotNull final PsiReferenceExpression expression) { }
super.visitReferenceExpression(expression); }
}
@Override
private static boolean superMethodInvocation(@NotNull final PsiReferenceExpression expression, final String methodName) { public void visitReferenceExpression(@NotNull final PsiReferenceExpression expression) {
String referenceName = expression.getReferenceName(); super.visitReferenceExpression(expression);
PsiExpression qualifierExpression = expression.getQualifierExpression(); }
if (referenceName != null && referenceName.equals(methodName)) {
if (qualifierExpression instanceof PsiSuperExpression) { private static boolean superMethodInvocation(@NotNull final PsiReferenceExpression expression, final String methodName) {
PsiType type = qualifierExpression.getType(); String referenceName = expression.getReferenceName();
if (type != null && type.getCanonicalText().equals(JAVA_LANG_OBJECT)) PsiExpression qualifierExpression = expression.getQualifierExpression();
return true; if (referenceName != null && referenceName.equals(methodName)) {
} if (qualifierExpression instanceof PsiSuperExpression) {
PsiType type = qualifierExpression.getType();
if (type != null && type.getCanonicalText().equals(JAVA_LANG_OBJECT)) {
return true;
}
}
}
return false;
} }
return false;
}
} }
@@ -19,341 +19,358 @@ import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
* @author ignatov * @author ignatov
*/ */
public class StatementVisitor extends ElementVisitor { public class StatementVisitor extends ElementVisitor {
private Statement myResult = Statement.EMPTY_STATEMENT; private Statement myResult = Statement.EMPTY_STATEMENT;
@NotNull @NotNull
@Override @Override
public Statement getResult() { public Statement getResult() {
return myResult; return myResult;
}
@Override
public void visitAssertStatement(@NotNull PsiAssertStatement statement) {
super.visitAssertStatement(statement);
myResult = new AssertStatement(
expressionToExpression(statement.getAssertCondition()),
expressionToExpression(statement.getAssertDescription())
);
}
@Override
public void visitBlockStatement(@NotNull PsiBlockStatement statement) {
super.visitBlockStatement(statement);
myResult = new Block(
statementsToStatementList(statement.getCodeBlock().getStatements()),
true
);
}
@Override
public void visitBreakStatement(@NotNull PsiBreakStatement statement) {
super.visitBreakStatement(statement);
if (statement.getLabelIdentifier() == null)
myResult = new BreakStatement();
else
myResult = new BreakStatement(
identifierToIdentifier(statement.getLabelIdentifier())
);
}
@Override
public void visitContinueStatement(@NotNull PsiContinueStatement statement) {
super.visitContinueStatement(statement);
if (statement.getLabelIdentifier() == null)
myResult = new ContinueStatement();
else
myResult = new ContinueStatement(
identifierToIdentifier(statement.getLabelIdentifier())
);
}
@Override
public void visitDeclarationStatement(@NotNull PsiDeclarationStatement statement) {
super.visitDeclarationStatement(statement);
myResult = new DeclarationStatement(
elementsToElementList(statement.getDeclaredElements())
);
}
@Override
public void visitDoWhileStatement(@NotNull PsiDoWhileStatement statement) {
super.visitDoWhileStatement(statement);
PsiExpression condition = statement.getCondition();
@SuppressWarnings("ConstantConditions")
Expression expression = condition != null && condition.getType() != null ?
createSureCallOnlyForChain(condition, condition.getType()) :
expressionToExpression(condition);
myResult = new DoWhileStatement(
expression,
statementToStatement(statement.getBody())
);
}
@Override
public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) {
super.visitExpressionStatement(statement);
myResult = expressionToExpression(statement.getExpression());
}
@Override
public void visitExpressionListStatement(@NotNull PsiExpressionListStatement statement) {
super.visitExpressionListStatement(statement);
myResult =
new ExpressionListStatement(expressionsToExpressionList(statement.getExpressionList().getExpressions()));
}
@Override
public void visitForStatement(@NotNull PsiForStatement statement) {
super.visitForStatement(statement);
final PsiStatement initialization = statement.getInitialization();
final PsiStatement update = statement.getUpdate();
final PsiExpression condition = statement.getCondition();
final PsiStatement body = statement.getBody();
final PsiLocalVariable firstChild = initialization != null && initialization.getFirstChild() instanceof PsiLocalVariable ?
(PsiLocalVariable) initialization.getFirstChild() : null;
int bodyWriteCount = countWritingAccesses(firstChild, body);
int conditionWriteCount = countWritingAccesses(firstChild, condition);
int updateWriteCount = countWritingAccesses(firstChild, update);
boolean onceWritableIterator = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0;
final IElementType operationTokenType = condition != null && condition instanceof PsiBinaryExpression ?
((PsiBinaryExpression) condition).getOperationTokenType() : null;
if (
initialization != null &&
initialization instanceof PsiDeclarationStatement
&& initialization.getFirstChild() == initialization.getLastChild()
&& condition != null
&& update != null
&& update.getChildren().length == 1
&& isPlusPlusExpression(update.getChildren()[0])
&& operationTokenType != null
&& (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE)
&& initialization.getFirstChild() != null
&& initialization.getFirstChild() instanceof PsiLocalVariable
&& firstChild != null
&& firstChild.getNameIdentifier() != null
&& onceWritableIterator
) {
final Expression end = expressionToExpression(((PsiBinaryExpression) condition).getROperand());
final Expression endExpression = operationTokenType == JavaTokenType.LT ?
new BinaryExpression(end, new IdentifierImpl("1"), "-") :
end;
myResult = new ForeachWithRangeStatement(
new IdentifierImpl(firstChild.getName()),
expressionToExpression(firstChild.getInitializer()),
endExpression,
statementToStatement(body)
);
} else { // common case: while loop instead of for loop
List<Statement> forStatements = new LinkedList<Statement>();
forStatements.add(statementToStatement(initialization));
forStatements.add(new WhileStatement(
expressionToExpression(condition),
new Block(
Arrays.asList(statementToStatement(body),
new Block(Arrays.asList(statementToStatement(update)))))));
myResult = new Block(forStatements);
} }
}
private static boolean isPlusPlusExpression(@NotNull PsiElement psiElement) { @Override
return (psiElement instanceof PsiPostfixExpression && ((PsiPostfixExpression) psiElement).getOperationTokenType() == JavaTokenType.PLUSPLUS) public void visitAssertStatement(@NotNull PsiAssertStatement statement) {
|| (psiElement instanceof PsiPrefixExpression && ((PsiPrefixExpression) psiElement).getOperationTokenType() == JavaTokenType.PLUSPLUS); super.visitAssertStatement(statement);
} myResult = new AssertStatement(
expressionToExpression(statement.getAssertCondition()),
expressionToExpression(statement.getAssertDescription())
);
}
@Override @Override
public void visitForeachStatement(@NotNull PsiForeachStatement statement) { public void visitBlockStatement(@NotNull PsiBlockStatement statement) {
super.visitForeachStatement(statement); super.visitBlockStatement(statement);
myResult = new ForeachStatement( myResult = new Block(
parameterToParameter(statement.getIterationParameter()), statementsToStatementList(statement.getCodeBlock().getStatements()),
expressionToExpression(statement.getIteratedValue()), true
statementToStatement(statement.getBody()) );
); }
}
@Override @Override
public void visitIfStatement(@NotNull PsiIfStatement statement) { public void visitBreakStatement(@NotNull PsiBreakStatement statement) {
super.visitIfStatement(statement); super.visitBreakStatement(statement);
PsiExpression condition = statement.getCondition(); if (statement.getLabelIdentifier() == null) {
@SuppressWarnings("ConstantConditions") myResult = new BreakStatement();
Expression expression = condition != null && condition.getType() != null ? }
createSureCallOnlyForChain(condition, condition.getType()) : else {
expressionToExpression(condition); myResult = new BreakStatement(
myResult = new IfStatement( identifierToIdentifier(statement.getLabelIdentifier())
expression, );
statementToStatement(statement.getThenBranch()),
statementToStatement(statement.getElseBranch())
);
}
@Override
public void visitLabeledStatement(@NotNull PsiLabeledStatement statement) {
super.visitLabeledStatement(statement);
myResult = new LabelStatement(
identifierToIdentifier(statement.getLabelIdentifier()),
statementToStatement(statement.getStatement())
);
}
@Override
public void visitSwitchLabelStatement(@NotNull PsiSwitchLabelStatement statement) {
super.visitSwitchLabelStatement(statement);
myResult = statement.isDefaultCase() ?
new DefaultSwitchLabelStatement() :
new SwitchLabelStatement(expressionToExpression(statement.getCaseValue()));
}
@Override
public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
super.visitSwitchStatement(statement);
myResult = new SwitchContainer(
expressionToExpression(statement.getExpression()),
switchBodyToCases(statement.getBody())
);
}
@NotNull
private static List<CaseContainer> switchBodyToCases(@Nullable final PsiCodeBlock body) {
final List<List<PsiStatement>> cases = splitToCases(body);
final List<PsiStatement> allSwitchStatements = body != null ? Arrays.asList(body.getStatements()) : Collections.<PsiStatement>emptyList();
List<CaseContainer> result = new LinkedList<CaseContainer>();
List<Statement> pendingLabels = new LinkedList<Statement>();
int i = 0;
for (List<PsiStatement> ls : cases) {
assert ls.size() > 0;
PsiStatement label = ls.get(0);
assert label instanceof PsiSwitchLabelStatement;
assert allSwitchStatements.get(i) == label : "not a right index";
if (ls.size() > 1) {
pendingLabels.add(statementToStatement(label));
List<PsiStatement> slice = ls.subList(1, ls.size());
if (!containsBreak(slice)) {
List<Statement> statements = statementsToStatementList(slice);
statements.addAll(
statementsToStatementList(getAllToNextBreak(allSwitchStatements, i + ls.size()))
);
result.add(new CaseContainer(pendingLabels, statements));
pendingLabels = new LinkedList<Statement>();
} else {
result.add(new CaseContainer(pendingLabels, statementsToStatementList(slice)));
pendingLabels = new LinkedList<Statement>();
} }
} else // ls.size() == 1
pendingLabels.add(statementToStatement(label));
i += ls.size();
} }
return result;
}
private static boolean containsBreak(@NotNull final List<PsiStatement> slice) { @Override
for (PsiStatement s : slice) public void visitContinueStatement(@NotNull PsiContinueStatement statement) {
if (s instanceof PsiBreakStatement) super.visitContinueStatement(statement);
return true; if (statement.getLabelIdentifier() == null) {
return false; myResult = new ContinueStatement();
} }
else {
myResult = new ContinueStatement(
identifierToIdentifier(statement.getLabelIdentifier())
);
}
}
@NotNull @Override
private static List<PsiStatement> getAllToNextBreak(@NotNull final List<PsiStatement> allStatements, final int start) { public void visitDeclarationStatement(@NotNull PsiDeclarationStatement statement) {
List<PsiStatement> result = new LinkedList<PsiStatement>(); super.visitDeclarationStatement(statement);
for (int i = start; i < allStatements.size(); i++) { myResult = new DeclarationStatement(
PsiStatement s = allStatements.get(i); elementsToElementList(statement.getDeclaredElements())
if (s instanceof PsiBreakStatement || s instanceof PsiReturnStatement) );
}
@Override
public void visitDoWhileStatement(@NotNull PsiDoWhileStatement statement) {
super.visitDoWhileStatement(statement);
PsiExpression condition = statement.getCondition();
@SuppressWarnings("ConstantConditions")
Expression expression = condition != null && condition.getType() != null ?
createSureCallOnlyForChain(condition, condition.getType()) :
expressionToExpression(condition);
myResult = new DoWhileStatement(
expression,
statementToStatement(statement.getBody())
);
}
@Override
public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) {
super.visitExpressionStatement(statement);
myResult = expressionToExpression(statement.getExpression());
}
@Override
public void visitExpressionListStatement(@NotNull PsiExpressionListStatement statement) {
super.visitExpressionListStatement(statement);
myResult =
new ExpressionListStatement(expressionsToExpressionList(statement.getExpressionList().getExpressions()));
}
@Override
public void visitForStatement(@NotNull PsiForStatement statement) {
super.visitForStatement(statement);
final PsiStatement initialization = statement.getInitialization();
final PsiStatement update = statement.getUpdate();
final PsiExpression condition = statement.getCondition();
final PsiStatement body = statement.getBody();
final PsiLocalVariable firstChild = initialization != null && initialization.getFirstChild() instanceof PsiLocalVariable
?
(PsiLocalVariable) initialization.getFirstChild()
: null;
int bodyWriteCount = countWritingAccesses(firstChild, body);
int conditionWriteCount = countWritingAccesses(firstChild, condition);
int updateWriteCount = countWritingAccesses(firstChild, update);
boolean onceWritableIterator = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0;
final IElementType operationTokenType = condition != null && condition instanceof PsiBinaryExpression ?
((PsiBinaryExpression) condition).getOperationTokenType() : null;
if (
initialization != null &&
initialization instanceof PsiDeclarationStatement
&& initialization.getFirstChild() == initialization.getLastChild()
&& condition != null
&& update != null
&& update.getChildren().length == 1
&& isPlusPlusExpression(update.getChildren()[0])
&& operationTokenType != null
&& (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE)
&& initialization.getFirstChild() != null
&& initialization.getFirstChild() instanceof PsiLocalVariable
&& firstChild != null
&& firstChild.getNameIdentifier() != null
&& onceWritableIterator
) {
final Expression end = expressionToExpression(((PsiBinaryExpression) condition).getROperand());
final Expression endExpression = operationTokenType == JavaTokenType.LT ?
new BinaryExpression(end, new IdentifierImpl("1"), "-") :
end;
myResult = new ForeachWithRangeStatement(
new IdentifierImpl(firstChild.getName()),
expressionToExpression(firstChild.getInitializer()),
endExpression,
statementToStatement(body)
);
}
else { // common case: while loop instead of for loop
List<Statement> forStatements = new LinkedList<Statement>();
forStatements.add(statementToStatement(initialization));
forStatements.add(new WhileStatement(
expressionToExpression(condition),
new Block(
Arrays.asList(statementToStatement(body),
new Block(Arrays.asList(statementToStatement(update)))))));
myResult = new Block(forStatements);
}
}
private static boolean isPlusPlusExpression(@NotNull PsiElement psiElement) {
return (psiElement instanceof PsiPostfixExpression && ((PsiPostfixExpression) psiElement).getOperationTokenType() == JavaTokenType.PLUSPLUS)
|| (psiElement instanceof PsiPrefixExpression && ((PsiPrefixExpression) psiElement).getOperationTokenType() == JavaTokenType.PLUSPLUS);
}
@Override
public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
super.visitForeachStatement(statement);
myResult = new ForeachStatement(
parameterToParameter(statement.getIterationParameter()),
expressionToExpression(statement.getIteratedValue()),
statementToStatement(statement.getBody())
);
}
@Override
public void visitIfStatement(@NotNull PsiIfStatement statement) {
super.visitIfStatement(statement);
PsiExpression condition = statement.getCondition();
@SuppressWarnings("ConstantConditions")
Expression expression = condition != null && condition.getType() != null ?
createSureCallOnlyForChain(condition, condition.getType()) :
expressionToExpression(condition);
myResult = new IfStatement(
expression,
statementToStatement(statement.getThenBranch()),
statementToStatement(statement.getElseBranch())
);
}
@Override
public void visitLabeledStatement(@NotNull PsiLabeledStatement statement) {
super.visitLabeledStatement(statement);
myResult = new LabelStatement(
identifierToIdentifier(statement.getLabelIdentifier()),
statementToStatement(statement.getStatement())
);
}
@Override
public void visitSwitchLabelStatement(@NotNull PsiSwitchLabelStatement statement) {
super.visitSwitchLabelStatement(statement);
myResult = statement.isDefaultCase() ?
new DefaultSwitchLabelStatement() :
new SwitchLabelStatement(expressionToExpression(statement.getCaseValue()));
}
@Override
public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
super.visitSwitchStatement(statement);
myResult = new SwitchContainer(
expressionToExpression(statement.getExpression()),
switchBodyToCases(statement.getBody())
);
}
@NotNull
private static List<CaseContainer> switchBodyToCases(@Nullable final PsiCodeBlock body) {
final List<List<PsiStatement>> cases = splitToCases(body);
final List<PsiStatement> allSwitchStatements = body != null
? Arrays.asList(body.getStatements())
: Collections.<PsiStatement>emptyList();
List<CaseContainer> result = new LinkedList<CaseContainer>();
List<Statement> pendingLabels = new LinkedList<Statement>();
int i = 0;
for (List<PsiStatement> ls : cases) {
assert ls.size() > 0;
PsiStatement label = ls.get(0);
assert label instanceof PsiSwitchLabelStatement;
assert allSwitchStatements.get(i) == label : "not a right index";
if (ls.size() > 1) {
pendingLabels.add(statementToStatement(label));
List<PsiStatement> slice = ls.subList(1, ls.size());
if (!containsBreak(slice)) {
List<Statement> statements = statementsToStatementList(slice);
statements.addAll(
statementsToStatementList(getAllToNextBreak(allSwitchStatements, i + ls.size()))
);
result.add(new CaseContainer(pendingLabels, statements));
pendingLabels = new LinkedList<Statement>();
}
else {
result.add(new CaseContainer(pendingLabels, statementsToStatementList(slice)));
pendingLabels = new LinkedList<Statement>();
}
}
else // ls.size() == 1
{
pendingLabels.add(statementToStatement(label));
}
i += ls.size();
}
return result; return result;
if (!(s instanceof PsiSwitchLabelStatement))
result.add(s);
} }
return result;
}
@NotNull private static boolean containsBreak(@NotNull final List<PsiStatement> slice) {
private static List<List<PsiStatement>> splitToCases(@Nullable final PsiCodeBlock body) { for (PsiStatement s : slice)
List<List<PsiStatement>> cases = new LinkedList<List<PsiStatement>>(); if (s instanceof PsiBreakStatement) {
List<PsiStatement> currentCaseStatements = new LinkedList<PsiStatement>(); return true;
boolean isFirst = true; }
if (body != null) { return false;
for (PsiStatement s : body.getStatements()) { }
if (s instanceof PsiSwitchLabelStatement) {
if (isFirst) @NotNull
isFirst = false; private static List<PsiStatement> getAllToNextBreak(@NotNull final List<PsiStatement> allStatements, final int start) {
else { List<PsiStatement> result = new LinkedList<PsiStatement>();
cases.add(currentCaseStatements); for (int i = start; i < allStatements.size(); i++) {
currentCaseStatements = new LinkedList<PsiStatement>(); PsiStatement s = allStatements.get(i);
} if (s instanceof PsiBreakStatement || s instanceof PsiReturnStatement) {
return result;
}
if (!(s instanceof PsiSwitchLabelStatement)) {
result.add(s);
}
} }
currentCaseStatements.add(s); return result;
}
cases.add(currentCaseStatements);
}
return cases;
}
@Override
public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) {
super.visitSynchronizedStatement(statement);
myResult = new SynchronizedStatement(
expressionToExpression(statement.getLockExpression()),
blockToBlock(statement.getBody())
);
}
@Override
public void visitThrowStatement(@NotNull PsiThrowStatement statement) {
super.visitThrowStatement(statement);
myResult = new ThrowStatement(
expressionToExpression(statement.getException())
);
}
@Override
public void visitTryStatement(@NotNull PsiTryStatement statement) {
super.visitTryStatement(statement);
List<CatchStatement> catches = new LinkedList<CatchStatement>();
for (int i = 0; i < statement.getCatchBlocks().length; i++) {
catches.add(new CatchStatement(
parameterToParameter(statement.getCatchBlockParameters()[i]),
blockToBlock(statement.getCatchBlocks()[i], true)
));
} }
myResult = new TryStatement( @NotNull
blockToBlock(statement.getTryBlock(), true), private static List<List<PsiStatement>> splitToCases(@Nullable final PsiCodeBlock body) {
catches, List<List<PsiStatement>> cases = new LinkedList<List<PsiStatement>>();
blockToBlock(statement.getFinallyBlock(), true) List<PsiStatement> currentCaseStatements = new LinkedList<PsiStatement>();
); boolean isFirst = true;
} if (body != null) {
for (PsiStatement s : body.getStatements()) {
if (s instanceof PsiSwitchLabelStatement) {
if (isFirst) {
isFirst = false;
}
else {
cases.add(currentCaseStatements);
currentCaseStatements = new LinkedList<PsiStatement>();
}
}
currentCaseStatements.add(s);
}
cases.add(currentCaseStatements);
}
return cases;
}
@Override @Override
public void visitWhileStatement(@NotNull PsiWhileStatement statement) { public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) {
super.visitWhileStatement(statement); super.visitSynchronizedStatement(statement);
PsiExpression condition = statement.getCondition(); myResult = new SynchronizedStatement(
@SuppressWarnings("ConstantConditions") expressionToExpression(statement.getLockExpression()),
Expression expression = condition != null && condition.getType() != null ? blockToBlock(statement.getBody())
createSureCallOnlyForChain(condition, condition.getType()) : );
expressionToExpression(condition); }
myResult = new WhileStatement(
expression,
statementToStatement(statement.getBody())
);
}
@Override @Override
public void visitReturnStatement(@NotNull PsiReturnStatement statement) { public void visitThrowStatement(@NotNull PsiThrowStatement statement) {
super.visitReturnStatement(statement); super.visitThrowStatement(statement);
PsiExpression returnValue = statement.getReturnValue(); myResult = new ThrowStatement(
PsiType methodReturnType = Converter.getMethodReturnType(); expressionToExpression(statement.getException())
Expression expression = returnValue != null && methodReturnType != null ? );
createSureCallOnlyForChain(returnValue, methodReturnType) : }
expressionToExpression(returnValue);
myResult = new ReturnStatement( @Override
expression public void visitTryStatement(@NotNull PsiTryStatement statement) {
); super.visitTryStatement(statement);
}
List<CatchStatement> catches = new LinkedList<CatchStatement>();
for (int i = 0; i < statement.getCatchBlocks().length; i++) {
catches.add(new CatchStatement(
parameterToParameter(statement.getCatchBlockParameters()[i]),
blockToBlock(statement.getCatchBlocks()[i], true)
));
}
myResult = new TryStatement(
blockToBlock(statement.getTryBlock(), true),
catches,
blockToBlock(statement.getFinallyBlock(), true)
);
}
@Override
public void visitWhileStatement(@NotNull PsiWhileStatement statement) {
super.visitWhileStatement(statement);
PsiExpression condition = statement.getCondition();
@SuppressWarnings("ConstantConditions")
Expression expression = condition != null && condition.getType() != null ?
createSureCallOnlyForChain(condition, condition.getType()) :
expressionToExpression(condition);
myResult = new WhileStatement(
expression,
statementToStatement(statement.getBody())
);
}
@Override
public void visitReturnStatement(@NotNull PsiReturnStatement statement) {
super.visitReturnStatement(statement);
PsiExpression returnValue = statement.getReturnValue();
PsiType methodReturnType = Converter.getMethodReturnType();
Expression expression = returnValue != null && methodReturnType != null ?
createSureCallOnlyForChain(returnValue, methodReturnType) :
expressionToExpression(returnValue);
myResult = new ReturnStatement(
expression
);
}
} }
@@ -10,32 +10,33 @@ import java.util.HashSet;
* @author ignatov * @author ignatov
*/ */
public class SuperVisitor extends JavaRecursiveElementVisitor { public class SuperVisitor extends JavaRecursiveElementVisitor {
@NotNull @NotNull
private final HashSet<PsiExpressionList> myResolvedSuperCallParameters; private final HashSet<PsiExpressionList> myResolvedSuperCallParameters;
public SuperVisitor() { public SuperVisitor() {
myResolvedSuperCallParameters = new HashSet<PsiExpressionList>(); myResolvedSuperCallParameters = new HashSet<PsiExpressionList>();
} }
@NotNull @NotNull
public HashSet<PsiExpressionList> getResolvedSuperCallParameters() { public HashSet<PsiExpressionList> getResolvedSuperCallParameters() {
return myResolvedSuperCallParameters; return myResolvedSuperCallParameters;
} }
@Override @Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression); super.visitMethodCallExpression(expression);
if (isSuper(expression.getMethodExpression())) if (isSuper(expression.getMethodExpression())) {
myResolvedSuperCallParameters.add(expression.getArgumentList()); myResolvedSuperCallParameters.add(expression.getArgumentList());
} }
}
static boolean isSuper(@NotNull PsiReference r) {
if (r.getCanonicalText().equals("super")) { static boolean isSuper(@NotNull PsiReference r) {
final PsiElement baseConstructor = r.resolve(); if (r.getCanonicalText().equals("super")) {
if (baseConstructor != null && baseConstructor instanceof PsiMethod && ((PsiMethod) baseConstructor).isConstructor()) { final PsiElement baseConstructor = r.resolve();
return true; if (baseConstructor != null && baseConstructor instanceof PsiMethod && ((PsiMethod) baseConstructor).isConstructor()) {
} return true;
}
}
return false;
} }
return false;
}
} }
@@ -10,28 +10,30 @@ import java.util.HashSet;
* @author ignatov * @author ignatov
*/ */
public class ThisVisitor extends JavaRecursiveElementVisitor { public class ThisVisitor extends JavaRecursiveElementVisitor {
@NotNull @NotNull
private final HashSet<PsiMethod> myResolvedConstructors = new HashSet<PsiMethod>(); private final HashSet<PsiMethod> myResolvedConstructors = new HashSet<PsiMethod>();
@Override @Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
for (PsiReference r : expression.getReferences()) for (PsiReference r : expression.getReferences())
if (r.getCanonicalText().equals("this")) { if (r.getCanonicalText().equals("this")) {
final PsiElement res = r.resolve(); final PsiElement res = r.resolve();
if (res != null && res instanceof PsiMethod && ((PsiMethod) res).isConstructor()) if (res != null && res instanceof PsiMethod && ((PsiMethod) res).isConstructor()) {
myResolvedConstructors.add((PsiMethod) res); myResolvedConstructors.add((PsiMethod) res);
} }
} }
}
@Nullable
public PsiMethod getPrimaryConstructor() { @Nullable
if (myResolvedConstructors.size() > 0) { public PsiMethod getPrimaryConstructor() {
PsiMethod first = myResolvedConstructors.toArray(new PsiMethod[myResolvedConstructors.size()])[0]; if (myResolvedConstructors.size() > 0) {
for (PsiMethod m : myResolvedConstructors) PsiMethod first = myResolvedConstructors.toArray(new PsiMethod[myResolvedConstructors.size()])[0];
if (m.hashCode() != first.hashCode()) for (PsiMethod m : myResolvedConstructors)
return null; if (m.hashCode() != first.hashCode()) {
return first; return null;
}
return first;
}
return null;
} }
return null;
}
} }
@@ -17,160 +17,176 @@ import static org.jetbrains.jet.j2k.Converter.typesToTypeList;
* @author ignatov * @author ignatov
*/ */
public class TypeVisitor extends PsiTypeVisitor<Type> { public class TypeVisitor extends PsiTypeVisitor<Type> {
public static final String JAVA_LANG_BYTE = "java.lang.Byte"; 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_CHARACTER = "java.lang.Character";
public static final String JAVA_LANG_DOUBLE = "java.lang.Double"; 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_FLOAT = "java.lang.Float";
public static final String JAVA_LANG_INTEGER = "java.lang.Integer"; 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_LONG = "java.lang.Long";
public static final String JAVA_LANG_SHORT = "java.lang.Short"; public static final String JAVA_LANG_SHORT = "java.lang.Short";
private static final String JAVA_LANG_BOOLEAN = "java.lang.Boolean"; 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_OBJECT = "java.lang.Object";
public static final String JAVA_LANG_STRING = "java.lang.String"; 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_LANG_ITERABLE = "java.lang.Iterable";
private static final String JAVA_UTIL_ITERATOR = "java.util.Iterator"; private static final String JAVA_UTIL_ITERATOR = "java.util.Iterator";
private Type myResult = Type.EMPTY_TYPE; private Type myResult = Type.EMPTY_TYPE;
@NotNull @NotNull
public Type getResult() { public Type getResult() {
return myResult; 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 == Type.EMPTY_TYPE)
myResult = new ArrayType(typeToType(arrayType.getComponentType()));
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);
else
myResult = new ClassType(identifier, typesToTypeList(classType.getParameters()));
return super.visitClassType(classType);
}
@NotNull
private static 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") && Converter.hasSetting("fqn"))
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()) @Override
return new IdentifierImpl(getClassTypeName(classType)); public Type visitPrimitiveType(@NotNull PsiPrimitiveType primitiveType) {
final String name = primitiveType.getCanonicalText();
final IdentifierImpl identifier = new IdentifierImpl(name);
return new IdentifierImpl(classTypeName); if (name.equals("void")) {
} myResult = new PrimitiveType(new IdentifierImpl("Unit"));
@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; else if (Node.PRIMITIVE_TYPES.contains(name)) {
} myResult = new PrimitiveType(new IdentifierImpl(AstUtil.upperFirstCharacter(name)));
}
else {
myResult = new PrimitiveType(identifier);
}
return super.visitPrimitiveType(primitiveType);
} }
return classTypeName;
}
@NotNull @Override
private static List<Type> createRawTypesForResolvedReference(@NotNull PsiClassType classType) { public Type visitArrayType(@NotNull PsiArrayType arrayType) {
final List<Type> typeParams = new LinkedList<Type>(); if (myResult == Type.EMPTY_TYPE) {
if (classType instanceof PsiClassReferenceType) { myResult = new ArrayType(typeToType(arrayType.getComponentType()));
final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType) classType).getReference(); }
final PsiElement resolve = reference.resolve(); return super.visitArrayType(arrayType);
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])), typesToTypeList(p.getSuperTypes()[0].getParameters()), true) :
new StarProjectionType();
typeParams.add(boundType);
}
}
} }
return typeParams;
}
@NotNull @Override
private static String getClassTypeName(@NotNull PsiClassType classType) { public Type visitClassType(@NotNull PsiClassType classType) {
String canonicalTypeStr = classType.getCanonicalText(); final IdentifierImpl identifier = constructClassTypeIdentifier(classType);
if (canonicalTypeStr.equals(JAVA_LANG_OBJECT)) return "Any"; final List<Type> resolvedClassTypeParams = createRawTypesForResolvedReference(classType);
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 if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
public Type visitWildcardType(@NotNull PsiWildcardType wildcardType) { myResult = new ClassType(identifier, resolvedClassTypeParams);
if (wildcardType.isExtends()) }
myResult = new OutProjectionType(typeToType(wildcardType.getExtendsBound())); else {
else if (wildcardType.isSuper()) myResult = new ClassType(identifier, typesToTypeList(classType.getParameters()));
myResult = new InProjectionType(typeToType(wildcardType.getSuperBound())); }
else return super.visitClassType(classType);
myResult = new StarProjectionType(); }
return super.visitWildcardType(wildcardType);
}
@Override @NotNull
public Type visitEllipsisType(@NotNull PsiEllipsisType ellipsisType) { private static IdentifierImpl constructClassTypeIdentifier(@NotNull PsiClassType classType) {
myResult = new VarArg(typeToType(ellipsisType.getComponentType())); final PsiClass psiClass = classType.resolve();
return super.visitEllipsisType(ellipsisType); if (psiClass != null) {
} String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName != null) {
if (!qualifiedName.equals("java.lang.Object") && Converter.hasSetting("fqn")) {
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);
@Override if (classTypeName.isEmpty()) {
public Type visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) { return new IdentifierImpl(getClassTypeName(classType));
return super.visitCapturedWildcardType(capturedWildcardType); }
}
@Override return new IdentifierImpl(classTypeName);
public Type visitDisjunctionType(PsiDisjunctionType disjunctionType) { }
return super.visitDisjunctionType(disjunctionType);
} @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 static 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])), 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(typeToType(wildcardType.getExtendsBound()));
}
else if (wildcardType.isSuper()) {
myResult = new InProjectionType(typeToType(wildcardType.getSuperBound()));
}
else {
myResult = new StarProjectionType();
}
return super.visitWildcardType(wildcardType);
}
@Override
public Type visitEllipsisType(@NotNull PsiEllipsisType ellipsisType) {
myResult = new VarArg(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);
}
} }
@@ -16,78 +16,79 @@ import java.util.List;
* @author ignatov * @author ignatov
*/ */
abstract class TestCaseBuilder { 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 @NotNull
Test createTest(@NotNull String dataPath, @NotNull String name); private static final FilenameFilter emptyFilter = new FilenameFilter() {
}
@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 @Override
public boolean accept(File file, String s) { public boolean accept(File file, String name) {
return extensionFilter.accept(file, s) && filter.accept(file, s); return true;
} }
};
} 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); @NotNull
assert files != null : dir; public static String getTestDataPathBase() {
List<File> subdirs = Arrays.asList(files); return "testData";
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); public static String getHomeDirectory() {
for (File file : files) { return new File(PathManager.getResourceRoot(TestCaseBuilder.class, "/org/jetbrains/jet/TestCaseBuilder.class")).getParentFile().getParentFile().getParent();
String fileName = file.getName(); }
assert fileName != null;
suite.addTest(factory.createTest(dataPath, fileName.substring(0, fileName.length() - extensionJava.length()))); 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;
} }
return suite;
}
} }