JavaToKotlinCli added
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<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>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -13,6 +13,17 @@
|
||||
<element id="module-output" name="j2k" />
|
||||
</root>
|
||||
</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 name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
@@ -616,6 +627,13 @@
|
||||
</component>
|
||||
<component name="WebServicesPlugin" addRequiredLibraries="true" />
|
||||
<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">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/commons-io-2.1.jar!/" />
|
||||
|
||||
Binary file not shown.
@@ -1,3 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: org.jetbrains.jet.j2k.JavaToKotlinTranslator
|
||||
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: org.jetbrains.jet.j2k.JavaToKotlinCli
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.j2k.ast.*;
|
||||
import org.jetbrains.jet.j2k.ast.Class;
|
||||
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.visitors.*;
|
||||
|
||||
@@ -35,9 +34,20 @@ public class Converter {
|
||||
@Nullable
|
||||
private static PsiType ourMethodReturnType = null;
|
||||
|
||||
@NotNull
|
||||
private static Set<String> settings = new HashSet<String>();
|
||||
|
||||
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) {
|
||||
ourClassIdentifiers = identifiers;
|
||||
}
|
||||
@@ -327,7 +337,7 @@ public class Converter {
|
||||
|
||||
final IdentifierImpl identifier = new IdentifierImpl(method.getName());
|
||||
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 List<Element> typeParameters = elementsToElementList(method.getTypeParameters());
|
||||
|
||||
@@ -608,10 +618,10 @@ public class Converter {
|
||||
for (PsiExpression e : arguments)
|
||||
actualTypes.add(e.getType());
|
||||
|
||||
assert actualTypes.size() == expectedTypes.size() : "The type list must have the same length";
|
||||
|
||||
for (int i = 0; i < actualTypes.size(); i++)
|
||||
conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i)));
|
||||
if (conversions.size() == actualTypes.size() && actualTypes.size() == expectedTypes.size()) {
|
||||
for (int i = 0; i < actualTypes.size(); i++)
|
||||
conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i)));
|
||||
}
|
||||
}
|
||||
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
|
||||
private static String prettify(@Nullable String code) {
|
||||
static String prettify(@Nullable String code) {
|
||||
if (code == null)
|
||||
return "";
|
||||
return code
|
||||
@@ -175,8 +175,8 @@ public class JavaToKotlinTranslator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static String generateKotlinCode(@NotNull String arg) {
|
||||
PsiFile file = createFile(arg);
|
||||
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());
|
||||
@@ -185,8 +185,8 @@ public class JavaToKotlinTranslator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static String generateKotlinCodeWithCompatibilityImport(@NotNull String arg) {
|
||||
PsiFile file = createFile(arg);
|
||||
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());
|
||||
|
||||
@@ -16,7 +16,7 @@ public class AnonymousClass extends Class {
|
||||
Collections.<Type>emptyList(),
|
||||
Collections.<Expression>emptyList(),
|
||||
Collections.<Type>emptyList(),
|
||||
members
|
||||
getMembers(members)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.j2k.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.j2k.Converter;
|
||||
import org.jetbrains.jet.j2k.util.AstUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -19,20 +20,34 @@ public class Class extends Member {
|
||||
String TYPE = "class";
|
||||
final Identifier myName;
|
||||
private final List<Expression> myBaseClassParams;
|
||||
private final List<? extends Member> myMembers;
|
||||
private final List<Member> myMembers;
|
||||
private final List<Element> myTypeParameters;
|
||||
private final List<Type> myExtendsTypes;
|
||||
private final List<Type> myImplementsTypes;
|
||||
|
||||
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;
|
||||
myBaseClassParams = baseClassParams;
|
||||
myModifiers = modifiers;
|
||||
myTypeParameters = typeParameters;
|
||||
myExtendsTypes = extendsTypes;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Set;
|
||||
public class Enum extends Class {
|
||||
public Enum(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes,
|
||||
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() {
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.Set;
|
||||
public class Trait extends Class {
|
||||
public Trait(Identifier name, Set<String> modifiers, List<Element> typeParameters, List<Type> extendsTypes,
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.j2k.visitors;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.j2k.Converter;
|
||||
import org.jetbrains.jet.j2k.ast.*;
|
||||
import org.jetbrains.jet.j2k.util.AstUtil;
|
||||
|
||||
@@ -74,6 +75,8 @@ public class TypeVisitor extends PsiTypeVisitor<Type> {
|
||||
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))
|
||||
|
||||
Reference in New Issue
Block a user