├── src ├── test │ └── scala │ │ └── com │ │ └── github │ │ └── scalatojava │ │ └── ScalaToJavaSpec.scala ├── main │ ├── scala │ │ └── com │ │ │ └── github │ │ │ └── scalatojava │ │ │ ├── Main.scala │ │ │ └── ScalaToJava.scala │ └── java │ │ └── com │ │ └── strobel │ │ └── assembler │ │ └── metadata │ │ └── CoreMetadataFactory.java └── assembly │ └── jar-with-dependencies-override.xml ├── LICENSE ├── readme.md └── pom.xml /src/test/scala/com/github/scalatojava/ScalaToJavaSpec.scala: -------------------------------------------------------------------------------- 1 | package com.github.scalatojava 2 | 3 | import org.scalatest._ 4 | 5 | class ScalaToJavaSpec extends FlatSpec with Matchers { 6 | it should "be able to convert scala to java" in { 7 | ScalaToJava("""println("hello world")""") should include("class _") 8 | } 9 | 10 | it should "be able to compile object" in { 11 | ScalaToJava( """object A""") should 12 | include("public class _$$anon$1$A$") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/scala/com/github/scalatojava/Main.scala: -------------------------------------------------------------------------------- 1 | package com.github.scalatojava 2 | 3 | /** 4 | * @author Ivan Zaytsev 5 | * 2015-07-12 6 | */ 7 | object Main extends App { 8 | val source = Iterator.continually(scala.io.StdIn.readLine()).takeWhile( 9 | _ != null).mkString("\n") 10 | 11 | println() 12 | private val java = ScalaToJava(source) 13 | 14 | println(if (args.contains("--slim")) java.replaceFirst("(?s)public final class _\\$\\s+.*", "") else java) 15 | } 16 | -------------------------------------------------------------------------------- /src/assembly/jar-with-dependencies-override.xml: -------------------------------------------------------------------------------- 1 | 6 | jar-with-dependencies-override 7 | 8 | jar 9 | 10 | false 11 | 12 | 13 | / 14 | true 15 | true 16 | runtime 17 | 18 | 19 | 20 | 21 | ${project.build.directory}/classes 22 | / 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ivan Zaitsev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Scala To Java 2 | --------- 3 | 4 | Simple tool written in Scala that reveals the mystery of scala compiler. 5 | Reads scala code from the StdIn and writes it's decompiled Java version 6 | to StdOut. 7 | 8 | 9 | Usage 10 | --- 11 | 12 | * Make sure you have Java 1.8 and Maven installed 13 | * Checkout the project 14 | * In project directory invoke `mvn clean package`. 15 | In target directory `scala-to-java.jar` will be created 16 | * Run application with `java -jar target/scala-to-java.jar --slim`. 17 | Optional `--slim` flag removes some boilerplate from the output 18 | * Type any scala code, for example `println("hello, world")` 19 | and finish with `END` character (`Ctrl-D`) 20 | 21 | Download 22 | --- 23 | 24 | Just in case you don't want to bother yourself with building 25 | the project, I already [have built it for you](https://github.com/Aivean/scala-to-java/releases/download/v1.0.2/scala-to-java.jar). 26 | Please note that *Java 8* is required to run this tool. 27 | 28 | 29 | Source highlighting and more 30 | --- 31 | 32 | To improve usage experience, you may want to use external source code 33 | highlighter (like `pygmentize`) and `pv` as the indicator of transpiling 34 | process. 35 | 36 | My setup: 37 | ```sh 38 | alias scala-to-java='java -jar ~/.scala-to-java.jar --slim | pv -W | pygmentize -f 256 -l java -O style=monokai' 39 | ``` 40 | 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 | 4 | 4.0.0 5 | com.github.scalatojava 6 | scala-to-java 7 | 1.0.2 8 | 9 | jar 10 | 11 | 2.11.4 12 | 13 | 14 | 15 | 16 | scala-tools.org 17 | Scala-Tools Maven2 Repository 18 | http://scala-tools.org/repo-releases 19 | 20 | 21 | 22 | 23 | 24 | scala-tools.org 25 | Scala-Tools Maven2 Repository 26 | http://scala-tools.org/repo-releases 27 | 28 | 29 | 30 | 31 | 32 | org.scala-lang 33 | scala-library 34 | ${scala.version} 35 | 36 | 37 | org.scala-lang 38 | scala-compiler 39 | ${scala.version} 40 | 41 | 42 | org.scala-lang 43 | scala-reflect 44 | ${scala.version} 45 | 46 | 47 | org.bitbucket.mstrobel 48 | procyon-compilertools 49 | 0.5.29 50 | 51 | 52 | org.scalatest 53 | scalatest_2.11 54 | 2.2.5 55 | test 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-compiler-plugin 64 | 3.3 65 | 66 | 1.8 67 | 1.8 68 | 69 | 70 | 71 | org.scala-tools 72 | maven-scala-plugin 73 | 2.15.2 74 | 75 | 76 | 77 | compile 78 | testCompile 79 | 80 | 81 | 82 | 83 | ${scala.version} 84 | 85 | -target:jvm-1.8 86 | 87 | 88 | 89 | 90 | 91 | org.apache.maven.plugins 92 | maven-surefire-plugin 93 | 2.7 94 | 95 | true 96 | 97 | 98 | 99 | 100 | org.scalatest 101 | scalatest-maven-plugin 102 | 1.0 103 | 104 | 105 | ${project.build.directory}/surefire-reports 106 | 107 | . 108 | WDF TestSuite.txt 109 | 110 | 111 | 112 | test 113 | 114 | test 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | make-assembly 123 | package 124 | 125 | single 126 | 127 | 128 | 129 | maven-assembly-plugin 130 | 2.5.5 131 | 132 | 133 | 134 | com.github.scalatojava.Main 135 | 136 | 137 | 138 | 139 | src/assembly/jar-with-dependencies-override.xml 140 | 141 | 142 | scala-to-java 143 | false 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | org.scala-tools 152 | maven-scala-plugin 153 | 154 | ${scala.version} 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /src/main/java/com/strobel/assembler/metadata/CoreMetadataFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * CoreMetadataFactory.java 3 | * 4 | * Copyright (c) 2013 Mike Strobel 5 | * 6 | * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb 7 | * Evain; 8 | * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. 9 | * 10 | * This source code is subject to terms and conditions of the Apache License, 11 | * Version 2.0. 12 | * A copy of the license can be found in the License.html file at the root of 13 | * this distribution. 14 | * By using this source code in any fashion, you are agreeing to be bound by 15 | * the terms of the 16 | * Apache License, Version 2.0. 17 | * 18 | * You must not remove this notice, or any other, from this software. 19 | */ 20 | 21 | package com.strobel.assembler.metadata; 22 | 23 | import com.strobel.assembler.ir.attributes.AttributeNames; 24 | import com.strobel.assembler.ir.attributes.InnerClassEntry; 25 | import com.strobel.assembler.ir.attributes.InnerClassesAttribute; 26 | import com.strobel.assembler.ir.attributes.SourceAttribute; 27 | import com.strobel.assembler.metadata.signatures.*; 28 | import com.strobel.core.ArrayUtilities; 29 | import com.strobel.core.StringUtilities; 30 | import com.strobel.core.VerifyArgument; 31 | 32 | import java.util.List; 33 | import java.util.Stack; 34 | 35 | /** 36 | * I had to patch this class in order to make it decompile class 37 | * name like '_$$anon$1$A$'. 38 | */ 39 | public class CoreMetadataFactory implements MetadataFactory { 40 | private final TypeDefinition _owner; 41 | private final IMetadataResolver _resolver; 42 | private final IGenericContext _scope; 43 | private final Stack _tempScope; 44 | 45 | private CoreMetadataFactory(final TypeDefinition owner, final 46 | IMetadataResolver resolver, final IGenericContext scope) { 47 | _owner = owner; 48 | _resolver = resolver; 49 | _scope = scope; 50 | _tempScope = new Stack<>(); 51 | } 52 | 53 | public static CoreMetadataFactory make(final TypeDefinition owner, final 54 | IGenericContext scope) { 55 | return new CoreMetadataFactory(VerifyArgument.notNull(owner, "owner") 56 | , owner.getResolver(), scope); 57 | } 58 | 59 | public static CoreMetadataFactory make(final IMetadataResolver resolver, 60 | final IGenericContext scope) { 61 | return new CoreMetadataFactory(null, resolver, scope); 62 | } 63 | 64 | private IGenericContext getScope() { 65 | return _scope; 66 | } 67 | 68 | public GenericParameter makeTypeVariable(final String name, final 69 | FieldTypeSignature[] bounds) { 70 | final GenericParameter genericParameter = new GenericParameter(name); 71 | 72 | if (ArrayUtilities.isNullOrEmpty(bounds)) { 73 | return genericParameter; 74 | } 75 | 76 | _tempScope.push(genericParameter); 77 | 78 | try { 79 | final TypeReference extendsBound = makeTypeBound(bounds); 80 | genericParameter.setExtendsBound(extendsBound); 81 | return genericParameter; 82 | } finally { 83 | _tempScope.pop(); 84 | } 85 | } 86 | 87 | public WildcardType makeWildcard( 88 | final FieldTypeSignature superBound, 89 | final FieldTypeSignature extendsBound) { 90 | 91 | if (superBound == null || superBound == BottomSignature.make()) { 92 | if (extendsBound == null || 93 | (extendsBound instanceof SimpleClassTypeSignature && 94 | StringUtilities.equals("java.lang.Object", ( 95 | (SimpleClassTypeSignature) extendsBound) 96 | .getName()))) { 97 | 98 | return WildcardType.unbounded(); 99 | } 100 | 101 | return WildcardType.makeExtends(makeTypeBound(extendsBound)); 102 | } else { 103 | return WildcardType.makeSuper(makeTypeBound(superBound)); 104 | } 105 | } 106 | 107 | protected TypeReference makeTypeBound(final FieldTypeSignature... bounds) { 108 | final TypeReference baseType; 109 | final List interfaceTypes; 110 | 111 | Reifier reifier = null; 112 | 113 | if (ArrayUtilities.isNullOrEmpty(bounds)) { 114 | return null; 115 | } 116 | 117 | if (bounds[0] != BottomSignature.make()) { 118 | reifier = Reifier.make(this); 119 | bounds[0].accept(reifier); 120 | baseType = reifier.getResult(); 121 | assert baseType != null; 122 | } else { 123 | baseType = null; 124 | } 125 | 126 | if (bounds.length == 1) { 127 | return baseType; 128 | } 129 | 130 | if (reifier == null) { 131 | reifier = Reifier.make(this); 132 | } 133 | 134 | if (bounds.length == 2 && baseType == null) { 135 | bounds[1].accept(reifier); 136 | final TypeReference singleInterface = reifier.getResult(); 137 | assert singleInterface != null; 138 | return singleInterface; 139 | } 140 | 141 | final TypeReference[] it = new TypeReference[bounds.length - 1]; 142 | 143 | for (int i = 0; i < it.length; i++) { 144 | bounds[i + 1].accept(reifier); 145 | it[i] = reifier.getResult(); 146 | assert it[i] != null; 147 | } 148 | 149 | interfaceTypes = ArrayUtilities.asUnmodifiableList(it); 150 | 151 | return new CompoundTypeReference(baseType, interfaceTypes); 152 | } 153 | 154 | public TypeReference makeParameterizedType( 155 | final TypeReference declaration, 156 | final TypeReference owner, 157 | final TypeReference... typeArguments) { 158 | 159 | if (typeArguments.length == 0) { 160 | return declaration; 161 | } 162 | return declaration.makeGenericType(typeArguments); 163 | } 164 | 165 | public GenericParameter findTypeVariable(final String name) { 166 | for (int i = _tempScope.size() - 1; i >= 0; i--) { 167 | final GenericParameter genericParameter = _tempScope.get(i); 168 | 169 | if (genericParameter != null && StringUtilities.equals 170 | (genericParameter.getName(), name)) { 171 | return genericParameter; 172 | } 173 | } 174 | 175 | final IGenericContext scope = getScope(); 176 | 177 | if (scope != null) { 178 | return scope.findTypeVariable(name); 179 | } 180 | 181 | return null; 182 | } 183 | 184 | private InnerClassEntry findInnerClassEntry(final String name) { 185 | if (_owner == null) { 186 | return null; 187 | } 188 | 189 | final String internalName = name.replace('.', '/'); 190 | final SourceAttribute attribute = SourceAttribute.find(AttributeNames 191 | .InnerClasses, _owner.getSourceAttributes()); 192 | 193 | if (attribute instanceof InnerClassesAttribute) { 194 | final List entries = ((InnerClassesAttribute) 195 | attribute).getEntries(); 196 | 197 | for (final InnerClassEntry entry : entries) { 198 | if (StringUtilities.equals(entry.getInnerClassName(), 199 | internalName)) { 200 | return entry; 201 | } 202 | } 203 | } 204 | 205 | return null; 206 | } 207 | 208 | public TypeReference makeNamedType(final String name) { 209 | final int length = name.length(); 210 | 211 | final InnerClassEntry entry = findInnerClassEntry(name); 212 | 213 | if (entry != null) { 214 | final String innerClassName = entry.getInnerClassName(); 215 | final int packageEnd = innerClassName.lastIndexOf('/'); 216 | final String shortName = StringUtilities.isNullOrEmpty(entry 217 | .getShortName()) ? null : entry.getShortName(); 218 | final TypeReference declaringType; 219 | 220 | if (!StringUtilities.isNullOrEmpty(entry.getOuterClassName())) { 221 | declaringType = makeNamedType(entry.getOuterClassName() 222 | .replace('/', '.')); 223 | } else { 224 | int lastDollarIndex = name.lastIndexOf('$'); 225 | 226 | while (lastDollarIndex >= 1 && 227 | lastDollarIndex < length && 228 | name.charAt(lastDollarIndex - 1) == '$') { 229 | 230 | if (lastDollarIndex > 1) { 231 | lastDollarIndex = name.lastIndexOf(lastDollarIndex, 232 | lastDollarIndex - 2); 233 | } else { 234 | lastDollarIndex = -1; 235 | } 236 | } 237 | 238 | if (lastDollarIndex == length - 1) { 239 | lastDollarIndex = -1; 240 | } 241 | 242 | if (lastDollarIndex != -1) { 243 | declaringType = makeNamedType(name.substring(0, 244 | lastDollarIndex).replace('/', '.')); 245 | } else { 246 | return new UnresolvedType( 247 | packageEnd < 0 ? innerClassName : innerClassName 248 | .substring(packageEnd + 1), 249 | name, null); 250 | } 251 | 252 | } 253 | 254 | return new UnresolvedType( 255 | declaringType, 256 | packageEnd < 0 ? innerClassName : innerClassName 257 | .substring(packageEnd + 1), 258 | shortName 259 | ); 260 | } 261 | 262 | final int packageEnd = name.lastIndexOf('.'); 263 | 264 | if (packageEnd < 0) { 265 | return new UnresolvedType(StringUtilities.EMPTY, name, null); 266 | } 267 | 268 | return new UnresolvedType( 269 | packageEnd < 0 ? StringUtilities.EMPTY : name.substring(0, 270 | packageEnd), 271 | packageEnd < 0 ? name : name.substring(packageEnd + 1), 272 | null 273 | ); 274 | } 275 | 276 | public TypeReference makeArrayType(final TypeReference componentType) { 277 | return componentType.makeArrayType(); 278 | } 279 | 280 | public TypeReference makeByte() { 281 | return BuiltinTypes.Byte; 282 | } 283 | 284 | public TypeReference makeBoolean() { 285 | return BuiltinTypes.Boolean; 286 | } 287 | 288 | public TypeReference makeShort() { 289 | return BuiltinTypes.Short; 290 | } 291 | 292 | public TypeReference makeChar() { 293 | return BuiltinTypes.Character; 294 | } 295 | 296 | public TypeReference makeInt() { 297 | return BuiltinTypes.Integer; 298 | } 299 | 300 | public TypeReference makeLong() { 301 | return BuiltinTypes.Long; 302 | } 303 | 304 | public TypeReference makeFloat() { 305 | return BuiltinTypes.Float; 306 | } 307 | 308 | public TypeReference makeDouble() { 309 | return BuiltinTypes.Double; 310 | } 311 | 312 | public TypeReference makeVoid() { 313 | return BuiltinTypes.Void; 314 | } 315 | 316 | @Override 317 | public IMethodSignature makeMethodSignature( 318 | final TypeReference returnType, 319 | final List parameterTypes, 320 | final List genericParameters, 321 | final List thrownTypes) { 322 | 323 | return new MethodSignature( 324 | parameterTypes, 325 | returnType, 326 | genericParameters, 327 | thrownTypes 328 | ); 329 | } 330 | 331 | @Override 332 | public IClassSignature makeClassSignature( 333 | final TypeReference baseType, 334 | final List interfaceTypes, 335 | final List genericParameters) { 336 | 337 | return new ClassSignature(baseType, interfaceTypes, genericParameters); 338 | } 339 | 340 | private final static class ClassSignature implements IClassSignature { 341 | private final TypeReference _baseType; 342 | private final List _interfaceTypes; 343 | private final List _genericParameters; 344 | 345 | private ClassSignature( 346 | final TypeReference baseType, 347 | final List interfaceTypes, 348 | final List genericParameters) { 349 | 350 | _baseType = VerifyArgument.notNull(baseType, "baseType"); 351 | _interfaceTypes = VerifyArgument.noNullElements(interfaceTypes, 352 | "interfaceTypes"); 353 | _genericParameters = VerifyArgument.noNullElements 354 | (genericParameters, "genericParameters"); 355 | } 356 | 357 | @Override 358 | public TypeReference getBaseType() { 359 | return _baseType; 360 | } 361 | 362 | @Override 363 | public List getExplicitInterfaces() { 364 | return _interfaceTypes; 365 | } 366 | 367 | @Override 368 | public boolean hasGenericParameters() { 369 | return !_genericParameters.isEmpty(); 370 | } 371 | 372 | @Override 373 | public boolean isGenericDefinition() { 374 | return false; 375 | } 376 | 377 | @Override 378 | public List getGenericParameters() { 379 | return _genericParameters; 380 | } 381 | } 382 | 383 | private final static class MethodSignature implements IMethodSignature { 384 | private final List _parameters; 385 | private final TypeReference _returnType; 386 | private final List _genericParameters; 387 | private final List _thrownTypes; 388 | 389 | MethodSignature( 390 | final List parameterTypes, 391 | final TypeReference returnType, 392 | final List genericParameters, 393 | final List thrownTypes) { 394 | 395 | VerifyArgument.notNull(parameterTypes, "parameterTypes"); 396 | VerifyArgument.notNull(returnType, "returnType"); 397 | VerifyArgument.notNull(genericParameters, "genericParameters"); 398 | VerifyArgument.notNull(thrownTypes, "thrownTypes"); 399 | 400 | final ParameterDefinition[] parameters = new 401 | ParameterDefinition[parameterTypes.size()]; 402 | 403 | for (int i = 0, slot = 0, n = parameters.length; i < n; i++, 404 | slot++) { 405 | final TypeReference parameterType = parameterTypes.get(i); 406 | 407 | parameters[i] = new ParameterDefinition(slot, parameterType); 408 | 409 | if (parameterType.getSimpleType().isDoubleWord()) { 410 | slot++; 411 | } 412 | } 413 | 414 | _parameters = ArrayUtilities.asUnmodifiableList(parameters); 415 | _returnType = returnType; 416 | _genericParameters = genericParameters; 417 | _thrownTypes = thrownTypes; 418 | } 419 | 420 | @Override 421 | public boolean hasParameters() { 422 | return !_parameters.isEmpty(); 423 | } 424 | 425 | @Override 426 | public List getParameters() { 427 | return _parameters; 428 | } 429 | 430 | @Override 431 | public TypeReference getReturnType() { 432 | return _returnType; 433 | } 434 | 435 | @Override 436 | public List getThrownTypes() { 437 | return _thrownTypes; 438 | } 439 | 440 | @Override 441 | public boolean hasGenericParameters() { 442 | return !_genericParameters.isEmpty(); 443 | } 444 | 445 | @Override 446 | public boolean isGenericDefinition() { 447 | return !_genericParameters.isEmpty(); 448 | } 449 | 450 | @Override 451 | public List getGenericParameters() { 452 | return _genericParameters; 453 | } 454 | 455 | @Override 456 | public GenericParameter findTypeVariable(final String name) { 457 | for (final GenericParameter genericParameter : 458 | getGenericParameters()) { 459 | if (StringUtilities.equals(genericParameter.getName(), name)) { 460 | return genericParameter; 461 | } 462 | } 463 | 464 | return null; 465 | } 466 | } 467 | 468 | private final class UnresolvedType extends TypeReference { 469 | private final String _name; 470 | private final String _shortName; 471 | private final String _packageName; 472 | private final GenericParameterCollection _genericParameters; 473 | 474 | private String _fullName; 475 | private String _internalName; 476 | private String _signature; 477 | private String _erasedSignature; 478 | 479 | UnresolvedType(final TypeReference declaringType, final String name, 480 | final String shortName) { 481 | _name = VerifyArgument.notNull(name, "name"); 482 | _shortName = shortName; 483 | setDeclaringType(VerifyArgument.notNull(declaringType, 484 | "declaringType")); 485 | _packageName = declaringType.getPackageName(); 486 | _genericParameters = new GenericParameterCollection(this); 487 | _genericParameters.freeze(); 488 | } 489 | 490 | UnresolvedType(final String packageName, final String name, final 491 | String shortName) { 492 | _packageName = VerifyArgument.notNull(packageName, "packageName"); 493 | _name = VerifyArgument.notNull(name, "name"); 494 | _shortName = shortName; 495 | _genericParameters = new GenericParameterCollection(this); 496 | _genericParameters.freeze(); 497 | } 498 | 499 | UnresolvedType(final TypeReference declaringType, final String name, 500 | final String shortName, final List 501 | genericParameters) { 502 | _name = VerifyArgument.notNull(name, "name"); 503 | _shortName = shortName; 504 | setDeclaringType(VerifyArgument.notNull(declaringType, 505 | "declaringType")); 506 | _packageName = declaringType.getPackageName(); 507 | 508 | _genericParameters = new GenericParameterCollection(this); 509 | 510 | for (final GenericParameter genericParameter : genericParameters) { 511 | _genericParameters.add(genericParameter); 512 | } 513 | 514 | _genericParameters.freeze(); 515 | } 516 | 517 | UnresolvedType(final String packageName, final String name, final 518 | String shortName, final List genericParameters) { 519 | _packageName = VerifyArgument.notNull(packageName, "packageName"); 520 | _name = VerifyArgument.notNull(name, "name"); 521 | _shortName = shortName; 522 | 523 | _genericParameters = new GenericParameterCollection(this); 524 | 525 | for (final GenericParameter genericParameter : genericParameters) { 526 | _genericParameters.add(genericParameter); 527 | } 528 | } 529 | 530 | @Override 531 | public String getName() { 532 | return _name; 533 | } 534 | 535 | @Override 536 | public String getPackageName() { 537 | return _packageName; 538 | } 539 | 540 | public String getFullName() { 541 | if (_fullName == null) { 542 | _fullName = super.getFullName(); 543 | } 544 | return _fullName; 545 | } 546 | 547 | @Override 548 | public String getErasedSignature() { 549 | if (_erasedSignature == null) { 550 | _erasedSignature = super.getErasedSignature(); 551 | } 552 | return _erasedSignature; 553 | } 554 | 555 | @Override 556 | public String getSignature() { 557 | if (_signature == null) { 558 | _signature = super.getSignature(); 559 | } 560 | return _signature; 561 | } 562 | 563 | public String getInternalName() { 564 | if (_internalName == null) { 565 | _internalName = super.getInternalName(); 566 | } 567 | return _internalName; 568 | } 569 | 570 | @Override 571 | public R accept(final TypeMetadataVisitor 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 getGenericParameters() { 588 | return _genericParameters; 589 | } 590 | 591 | @Override 592 | public TypeReference makeGenericType(final List typeArguments) { 594 | VerifyArgument.noNullElementsAndNotEmpty(typeArguments, 595 | "typeArguments"); 596 | 597 | return new UnresolvedGenericType( 598 | this, 599 | ArrayUtilities.asUnmodifiableList(typeArguments.toArray(new 600 | TypeReference[typeArguments.size()])) 601 | ); 602 | } 603 | 604 | @Override 605 | public TypeReference makeGenericType(final TypeReference... 606 | typeArguments) { 607 | VerifyArgument.noNullElementsAndNotEmpty(typeArguments, 608 | "typeArguments"); 609 | 610 | return new UnresolvedGenericType( 611 | this, 612 | ArrayUtilities.asUnmodifiableList(typeArguments.clone()) 613 | ); 614 | } 615 | 616 | @Override 617 | public TypeDefinition resolve() { 618 | return _resolver.resolve(this); 619 | } 620 | 621 | @Override 622 | public FieldDefinition resolve(final FieldReference field) { 623 | return _resolver.resolve(field); 624 | } 625 | 626 | @Override 627 | public MethodDefinition resolve(final MethodReference method) { 628 | return _resolver.resolve(method); 629 | } 630 | 631 | @Override 632 | public TypeDefinition resolve(final TypeReference type) { 633 | return _resolver.resolve(type); 634 | } 635 | } 636 | 637 | private final class UnresolvedGenericType extends TypeReference 638 | implements IGenericInstance { 639 | private final TypeReference _genericDefinition; 640 | private final List _typeParameters; 641 | 642 | private String _signature; 643 | 644 | UnresolvedGenericType(final TypeReference genericDefinition, final 645 | List typeParameters) { 646 | _genericDefinition = genericDefinition; 647 | _typeParameters = typeParameters; 648 | } 649 | 650 | @Override 651 | public TypeReference getElementType() { 652 | return null; 653 | } 654 | 655 | @Override 656 | public R accept(final TypeMetadataVisitor 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 getGenericParameters() { 716 | if (!_genericDefinition.isGenericDefinition()) { 717 | final TypeDefinition resolvedDefinition = _genericDefinition 718 | .resolve(); 719 | 720 | if (resolvedDefinition != null) { 721 | return resolvedDefinition.getGenericParameters(); 722 | } 723 | } 724 | 725 | return _genericDefinition.getGenericParameters(); 726 | } 727 | 728 | @Override 729 | public boolean hasTypeArguments() { 730 | return true; 731 | } 732 | 733 | @Override 734 | public List getTypeArguments() { 735 | return _typeParameters; 736 | } 737 | 738 | @Override 739 | public IGenericParameterProvider getGenericDefinition() { 740 | return _genericDefinition; 741 | } 742 | 743 | @Override 744 | public TypeReference getUnderlyingType() { 745 | return _genericDefinition; 746 | } 747 | 748 | @Override 749 | public TypeDefinition resolve() { 750 | return _resolver.resolve(this); 751 | } 752 | 753 | @Override 754 | public FieldDefinition resolve(final FieldReference field) { 755 | return _resolver.resolve(field); 756 | } 757 | 758 | @Override 759 | public MethodDefinition resolve(final MethodReference method) { 760 | return _resolver.resolve(method); 761 | } 762 | 763 | @Override 764 | public TypeDefinition resolve(final TypeReference type) { 765 | return _resolver.resolve(type); 766 | } 767 | } 768 | } 769 | 770 | --------------------------------------------------------------------------------