42 |
43 |
44 | Credits
45 | ---
46 |
47 | Thanks to [Stanley Shyiko](https://github.com/shyiko), who
48 | actually implemented all the magic.
49 |
--------------------------------------------------------------------------------
/src/main/scala/com/github/scalatojava/ScalaToJava.scala:
--------------------------------------------------------------------------------
1 | package com.github.scalatojava
2 |
3 | import java.io.{File, StringWriter}
4 | import java.nio.file.{Paths, Files}
5 |
6 | import com.strobel.assembler.InputTypeLoader
7 | import com.strobel.assembler.metadata._
8 | import com.strobel.decompiler.languages.Languages
9 | import com.strobel.decompiler.languages.java.JavaFormattingOptions
10 | import com.strobel.decompiler.{PlainTextOutput, DecompilerSettings, DecompilationOptions}
11 | import scala.collection.mutable
12 | import scala.tools.nsc._
13 | import java.io._
14 | import java.util.Arrays
15 |
16 | /**
17 | * Scala-to-Java translator
18 | * @author Stanley Shyiko
19 | */
20 | object ScalaToJava {
21 |
22 | def decompile(file: File): String = {
23 | val settings = new DecompilerSettings
24 | settings.setLanguage(Languages.java)
25 | settings.setTypeLoader(new InputTypeLoader)
26 | settings.setFormattingOptions(JavaFormattingOptions.createDefault)
27 |
28 | val options = new DecompilationOptions
29 | options.setSettings(settings)
30 | options.setFullDecompilation(true)
31 |
32 | settings.getTypeLoader.tryLoadType(file.getPath,
33 | new Buffer(Files.readAllBytes(Paths.get(file.getPath))))
34 |
35 | val metadataSystem = new NoRetryMetadataSystem(settings.getTypeLoader)
36 | val resolvedType = metadataSystem.resolveType(file.getName.substring(0,
37 | file.getName.length - ".class".length), mightBePrimitive = false)
38 | val writer = new StringWriter
39 | val output = new PlainTextOutput(writer)
40 | settings.getLanguage.decompileType(resolvedType, output, options)
41 | writer.flush()
42 | writer.toString
43 | }
44 |
45 | def compile(input: File, output: File): Array[File] = {
46 | val settings = new Settings
47 | settings processArgumentString "-target:jvm-1.8 -Xscript _ -usejavacp -d " +
48 | output.getPath
49 | val compiler = new Global(settings)
50 | val runner = new compiler.Run
51 | runner.compile(List(input.getPath))
52 | output.listFiles(new FilenameFilter {
53 | override def accept(dir: File, name: String): Boolean = name.endsWith(".class")
54 | })
55 | }
56 |
57 | def apply(value: String): String = {
58 | val output = Files.createTempDirectory("s2j").toFile
59 | val input = new File(output, "_.scala")
60 | Files.write(input.toPath, Arrays.asList(value))
61 | compile(input, output).map(decompile).mkString("\n\n")
62 | }
63 |
64 | class NoRetryMetadataSystem(typeLoader: ITypeLoader) extends MetadataSystem(typeLoader) {
65 |
66 | val failedTypes = mutable.Set[String]()
67 |
68 | override def resolveType(descriptor: String, mightBePrimitive: Boolean): TypeDefinition = {
69 | if (failedTypes.contains(descriptor)) {
70 | return null
71 | }
72 | val r = super.resolveType(descriptor, mightBePrimitive)
73 | if (r == null) {
74 | failedTypes.add(descriptor)
75 | }
76 | r
77 | }
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 | visitor, final
572 | P parameter) {
573 | return visitor.visitClassType(this, parameter);
574 | }
575 |
576 | @Override
577 | public String getSimpleName() {
578 | return _shortName != null ? _shortName : _name;
579 | }
580 |
581 | @Override
582 | public boolean isGenericDefinition() {
583 | return hasGenericParameters();
584 | }
585 |
586 | @Override
587 | public List visitor, final
657 | P parameter) {
658 | return visitor.visitParameterizedType(this, parameter);
659 | }
660 |
661 | @Override
662 | public String getName() {
663 | return _genericDefinition.getName();
664 | }
665 |
666 | @Override
667 | public String getPackageName() {
668 | return _genericDefinition.getPackageName();
669 | }
670 |
671 | @Override
672 | public TypeReference getDeclaringType() {
673 | return _genericDefinition.getDeclaringType();
674 | }
675 |
676 | @Override
677 | public String getSimpleName() {
678 | return _genericDefinition.getSimpleName();
679 | }
680 |
681 | @Override
682 | public String getFullName() {
683 | return _genericDefinition.getFullName();
684 | }
685 |
686 | @Override
687 | public String getInternalName() {
688 | return _genericDefinition.getInternalName();
689 | }
690 |
691 | @Override
692 | public String getSignature() {
693 | if (_signature == null) {
694 | _signature = super.getSignature();
695 | }
696 | return _signature;
697 | }
698 |
699 | @Override
700 | public String getErasedSignature() {
701 | return _genericDefinition.getErasedSignature();
702 | }
703 |
704 | @Override
705 | public boolean isGenericDefinition() {
706 | return false;
707 | }
708 |
709 | @Override
710 | public boolean isGenericType() {
711 | return true;
712 | }
713 |
714 | @Override
715 | public List