JavaToKotlinCli added

This commit is contained in:
Sergey Ignatov
2012-01-17 16:42:32 +04:00
parent 0ed16b5c9c
commit b93b25d002
12 changed files with 215 additions and 20 deletions
+2
View File
@@ -9,6 +9,8 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="TEST" name="commons-io-2.1" level="project" /> <orderEntry type="library" scope="TEST" name="commons-io-2.1" level="project" />
<orderEntry type="library" name="commons-cli-1.2" level="project" />
<orderEntry type="library" name="commons-io-2.1" level="project" />
</component> </component>
</module> </module>
+18
View File
@@ -13,6 +13,17 @@
<element id="module-output" name="j2k" /> <element id="module-output" name="j2k" />
</root> </root>
</artifact> </artifact>
<artifact type="jar" build-on-make="true" name="java2kotlin:jar">
<output-path>$PROJECT_DIR$/out/artifacts/java2kotlin_jar</output-path>
<root id="archive" name="java2kotlin.jar">
<element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/src/META-INF/MANIFEST.MF" />
</element>
<element id="module-output" name="j2k" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/commons-io-2.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/commons-cli-1.2.jar" path-in-jar="/" />
</root>
</artifact>
</component> </component>
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" /> <option name="DEFAULT_COMPILER" value="Javac" />
@@ -616,6 +627,13 @@
</component> </component>
<component name="WebServicesPlugin" addRequiredLibraries="true" /> <component name="WebServicesPlugin" addRequiredLibraries="true" />
<component name="libraryTable"> <component name="libraryTable">
<library name="commons-cli-1.2">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/commons-cli-1.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
<library name="commons-io-2.1"> <library name="commons-io-2.1">
<CLASSES> <CLASSES>
<root url="jar://$PROJECT_DIR$/lib/commons-io-2.1.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/commons-io-2.1.jar!/" />
Binary file not shown.
+1 -1
View File
@@ -1,3 +1,3 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
Main-Class: org.jetbrains.jet.j2k.JavaToKotlinTranslator Main-Class: org.jetbrains.jet.j2k.JavaToKotlinCli
+14 -4
View File
@@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.j2k.ast.*; import org.jetbrains.jet.j2k.ast.*;
import org.jetbrains.jet.j2k.ast.Class; import org.jetbrains.jet.j2k.ast.Class;
import org.jetbrains.jet.j2k.ast.Enum; import org.jetbrains.jet.j2k.ast.Enum;
import org.jetbrains.jet.j2k.ast.Modifier;
import org.jetbrains.jet.j2k.util.AstUtil; import org.jetbrains.jet.j2k.util.AstUtil;
import org.jetbrains.jet.j2k.visitors.*; import org.jetbrains.jet.j2k.visitors.*;
@@ -35,9 +34,20 @@ public class Converter {
@Nullable @Nullable
private static PsiType ourMethodReturnType = null; private static PsiType ourMethodReturnType = null;
@NotNull
private static Set<String> settings = new HashSet<String>();
private Converter() { private Converter() {
} }
public static boolean addSetting(@NotNull String value) {
return settings.add(value);
}
public static boolean hasSetting(@NotNull String value) {
return settings.contains(value);
}
public static void setClassIdentifiers(@NotNull Set<String> identifiers) { public static void setClassIdentifiers(@NotNull Set<String> identifiers) {
ourClassIdentifiers = identifiers; ourClassIdentifiers = identifiers;
} }
@@ -327,7 +337,7 @@ public class Converter {
final IdentifierImpl identifier = new IdentifierImpl(method.getName()); final IdentifierImpl identifier = new IdentifierImpl(method.getName());
final Type returnType = typeToType(method.getReturnType(), ConverterUtil.isAnnotatedAsNotNull(method.getModifierList())); final Type returnType = typeToType(method.getReturnType(), ConverterUtil.isAnnotatedAsNotNull(method.getModifierList()));
final Block body = blockToBlock(method.getBody(), notEmpty); final Block body = hasSetting("declarations-only") ? Block.EMPTY_BLOCK : blockToBlock(method.getBody(), notEmpty); // #TODO
final Element params = createFunctionParameters(method); final Element params = createFunctionParameters(method);
final List<Element> typeParameters = elementsToElementList(method.getTypeParameters()); final List<Element> typeParameters = elementsToElementList(method.getTypeParameters());
@@ -608,11 +618,11 @@ public class Converter {
for (PsiExpression e : arguments) for (PsiExpression e : arguments)
actualTypes.add(e.getType()); actualTypes.add(e.getType());
assert actualTypes.size() == expectedTypes.size() : "The type list must have the same length"; if (conversions.size() == actualTypes.size() && actualTypes.size() == expectedTypes.size()) {
for (int i = 0; i < actualTypes.size(); i++) for (int i = 0; i < actualTypes.size(); i++)
conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i))); conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i)));
} }
}
return conversions; return conversions;
} }
@@ -0,0 +1,147 @@
package org.jetbrains.jet.j2k;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import org.apache.commons.cli.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeStringToFile;
/**
* @author ignatov
*/
@SuppressWarnings({"CallToPrintStackTrace", "UseOfSystemOutOrSystemErr"})
public class JavaToKotlinCli {
private static final Logger myLogger = Logger.getAnonymousLogger();
private JavaToKotlinCli() {
}
public static void main(String[] args) {
CommandLineParser parser = new BasicParser();
Options options = new Options()
.addOption("h", "help", false, "Print usage information")
.addOption("f", "from", true, "Directory with Java sources")
.addOption("t", "to", true, "Directory with Kotlin sources")
.addOption("p", "public-only", false, "Only public and protected members")
.addOption("fqn", "fqn", false, "Full qualified names")
.addOption("d", "declarations-only", false, "Declarations only")
;
try {
CommandLine commandLine = parser.parse(options, args);
if (commandLine.hasOption("help"))
showHelpAndExit();
if (commandLine.hasOption("from") && commandLine.hasOption("to")) {
String from = commandLine.getOptionValue("from");
String to = commandLine.getOptionValue("to");
for (Option o : commandLine.getOptions()) {
Converter.addSetting(o.getLongOpt());
}
if (!from.isEmpty() && !to.isEmpty())
convertSourceTree(from, to);
else
showHelpAndExit();
} else
showHelpAndExit();
} catch (ParseException e) {
e.printStackTrace();
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static void convertSourceTree(String javaPath, String kotlinPath) {
try {
File javaDir = new File(javaPath);
File kotlinDir = new File(kotlinPath);
if (kotlinDir.exists())
kotlinDir.delete();
if (!kotlinDir.exists() && !kotlinDir.mkdir())
myLogger.warning("Creation failed: " + kotlinDir.getAbsolutePath());
for (File f : getJavaFiles(javaDir.getAbsolutePath())) {
String relative = javaDir.toURI().relativize(f.toURI()).getPath().replace(".java", ".kt");
File file = new File(kotlinPath, relative);
if (file.exists())
file.delete();
if (f.isDirectory())
if (!file.exists() && !file.mkdir())
myLogger.warning("Creation failed: " + file.getAbsolutePath());
if (f.isFile()) {
writeStringToFile(file, fileToKotlin(f));
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@NotNull
private static String fileToKotlin(File f) throws IOException {
final String javaCode = readJavaFileToString(f);
return generateKotlinCode(JavaToKotlinTranslator.createFile(JavaToKotlinTranslator.setUpJavaCoreEnvironment(), javaCode));
}
@NotNull
private static String generateKotlinCode(@Nullable PsiFile file) {
if (file != null && file instanceof PsiJavaFile) {
JavaToKotlinTranslator.setClassIdentifiers(file);
return JavaToKotlinTranslator.prettify(Converter.fileToFile((PsiJavaFile) file).toKotlin());
}
return "";
}
@NotNull
private static String readJavaFileToString(@NotNull File javaFile) throws IOException {
return Pattern.compile("\\s*/\\*.*\\*/", Pattern.DOTALL).matcher(readFileToString(javaFile)).replaceAll("");
}
private static void showHelpAndExit() {
System.err.println("Usage: java -jar java2kotlin.jar -f <from> -t <to>");
System.exit(1);
}
static public List<File> getJavaFiles(String startDirName) throws FileNotFoundException {
return getJavaFiles(new File(startDirName));
}
private static List<File> getJavaFiles(File start) throws FileNotFoundException {
List<File> result = new ArrayList<File>();
if (start.isFile())
return Arrays.asList(start);
for (File file : Arrays.asList(start.listFiles())) {
if ((file.isFile() && file.getName().endsWith(".java")) || file.isDirectory())
result.add(file);
if (file.isDirectory()) {
List<File> deeperList = getJavaFiles(file);
result.addAll(deeperList);
}
}
return result;
}
}
@@ -73,7 +73,7 @@ public class JavaToKotlinTranslator {
} }
@NotNull @NotNull
private static String prettify(@Nullable String code) { static String prettify(@Nullable String code) {
if (code == null) if (code == null)
return ""; return "";
return code return code
@@ -175,8 +175,8 @@ public class JavaToKotlinTranslator {
} }
@NotNull @NotNull
static String generateKotlinCode(@NotNull String arg) { static String generateKotlinCode(@NotNull String javaCode) {
PsiFile file = createFile(arg); PsiFile file = createFile(javaCode);
if (file != null && file instanceof PsiJavaFile) { if (file != null && file instanceof PsiJavaFile) {
setClassIdentifiers(file); setClassIdentifiers(file);
return prettify(Converter.fileToFile((PsiJavaFile) file).toKotlin()); return prettify(Converter.fileToFile((PsiJavaFile) file).toKotlin());
@@ -185,8 +185,8 @@ public class JavaToKotlinTranslator {
} }
@NotNull @NotNull
static String generateKotlinCodeWithCompatibilityImport(@NotNull String arg) { static String generateKotlinCodeWithCompatibilityImport(@NotNull String javaCode) {
PsiFile file = createFile(arg); PsiFile file = createFile(javaCode);
if (file != null && file instanceof PsiJavaFile) { if (file != null && file instanceof PsiJavaFile) {
setClassIdentifiers(file); setClassIdentifiers(file);
return prettify(Converter.fileToFileWithCompatibilityImport((PsiJavaFile) file).toKotlin()); return prettify(Converter.fileToFileWithCompatibilityImport((PsiJavaFile) file).toKotlin());
@@ -16,7 +16,7 @@ public class AnonymousClass extends Class {
Collections.<Type>emptyList(), Collections.<Type>emptyList(),
Collections.<Expression>emptyList(), Collections.<Expression>emptyList(),
Collections.<Type>emptyList(), Collections.<Type>emptyList(),
members getMembers(members)
); );
} }
+18 -3
View File
@@ -2,6 +2,7 @@ package org.jetbrains.jet.j2k.ast;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.j2k.Converter;
import org.jetbrains.jet.j2k.util.AstUtil; import org.jetbrains.jet.j2k.util.AstUtil;
import java.util.HashSet; import java.util.HashSet;
@@ -19,20 +20,34 @@ public class Class extends Member {
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<? extends 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<? extends 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 = members; myMembers= getMembers(members);
}
static List<Member> getMembers(List<Member> members) {
List<Member> withoutPrivate = new LinkedList<Member>();
if (Converter.hasSetting("public-only")) {
for (Member m : members) {
if (m.accessModifier().equals("public") || m.accessModifier().equals("protected") || m.accessModifier().isEmpty()) {
withoutPrivate.add(m);
}
}
} else {
withoutPrivate = members;
}
return withoutPrivate;
} }
+1 -1
View File
@@ -12,7 +12,7 @@ import java.util.Set;
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, members); super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, getMembers(members));
} }
String primaryConstructorSignatureToKotlin() { String primaryConstructorSignatureToKotlin() {
+1 -1
View File
@@ -9,7 +9,7 @@ import java.util.Set;
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, members); super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, getMembers(members));
TYPE = "trait"; TYPE = "trait";
} }
@@ -3,6 +3,7 @@ package org.jetbrains.jet.j2k.visitors;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.impl.source.PsiClassReferenceType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.j2k.Converter;
import org.jetbrains.jet.j2k.ast.*; import org.jetbrains.jet.j2k.ast.*;
import org.jetbrains.jet.j2k.util.AstUtil; import org.jetbrains.jet.j2k.util.AstUtil;
@@ -74,6 +75,8 @@ public class TypeVisitor extends PsiTypeVisitor<Type> {
if (psiClass != null) { if (psiClass != null) {
String qualifiedName = psiClass.getQualifiedName(); String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName != null) { if (qualifiedName != null) {
if (!qualifiedName.equals("java.lang.Object") && Converter.hasSetting("fqn"))
return new IdentifierImpl(qualifiedName);
if (qualifiedName.equals(JAVA_LANG_ITERABLE)) if (qualifiedName.equals(JAVA_LANG_ITERABLE))
return new IdentifierImpl(JAVA_LANG_ITERABLE); return new IdentifierImpl(JAVA_LANG_ITERABLE);
if (qualifiedName.equals(JAVA_UTIL_ITERATOR)) if (qualifiedName.equals(JAVA_UTIL_ITERATOR))