summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
diff options
context:
space:
mode:
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>2014-08-28 21:34:14 +0400
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>2014-08-28 21:34:19 +0400
commit076e4393f25bf1ad1ff1bd2853153e2b595dd90b (patch)
treef1a17a12ea762525b5efbc0778b0945d906c68c9 /src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
parent663631f0456fcc245dd835889f86541d75161c53 (diff)
downloadfernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.gz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.lz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.xz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.zip
java-decompiler: post-import cleanup (formatting and copyright)
Diffstat (limited to 'src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java')
-rw-r--r--src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java247
1 files changed, 130 insertions, 117 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java b/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
index bf5f72f..3d42bda 100644
--- a/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
+++ b/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
@@ -1,12 +1,20 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.jetbrains.java.decompiler.main.rels;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.code.InstructionSequence;
@@ -23,116 +31,121 @@ import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.io.IOException;
+import java.util.*;
+
public class LambdaProcessor {
- private static final String JAVAC_LAMBDA_CLASS = "java/lang/invoke/LambdaMetafactory";
- private static final String JAVAC_LAMBDA_METHOD = "metafactory";
- private static final String JAVAC_LAMBDA_METHOD_DESCRIPTOR = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;";
-
- public void processClass(ClassNode node) throws IOException {
-
- for(ClassNode child : node.nested) {
- processClass(child);
- }
-
- if(node.nested.isEmpty()) {
- hasLambda(node);
- }
- }
-
- public boolean hasLambda(ClassNode node) throws IOException {
-
- ClassesProcessor clprocessor = DecompilerContext.getClassprocessor();
- StructClass cl = node.classStruct;
-
- if(cl.getBytecodeVersion() < CodeConstants.BYTECODE_JAVA_8) { // lamda beginning with Java 8
- return false;
- }
-
- StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
- if(bootstrap == null || bootstrap.getMethodsNumber() == 0) {
- return false; // no bootstrap constants in pool
- }
-
- Set<Integer> lambda_methods = new HashSet<Integer>();
-
- // find lambda bootstrap constants
- for(int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
- LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle
-
- if(JAVAC_LAMBDA_CLASS.equals(method_ref.classname) &&
- JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) &&
- JAVAC_LAMBDA_METHOD_DESCRIPTOR.equals(method_ref.descriptor)) { // check for javac lambda structure. FIXME: extend for Eclipse etc. at some point
- lambda_methods.add(i);
- }
- }
-
- if(lambda_methods.isEmpty()) {
- return false; // no lambda bootstrap constant found
- }
-
- Map<String, String> mapMethodsLambda = new HashMap<String, String>();
-
- // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
- for(StructMethod mt: cl.getMethods()) {
- mt.expandData();
-
- InstructionSequence seq = mt.getInstructionSequence();
- if(seq != null && seq.length() > 0) {
- int len = seq.length();
-
- for(int i = 0; i < len; ++i) {
- Instruction instr = seq.getInstr(i);
-
- if(instr.opcode == CodeConstants.opc_invokedynamic) {
- LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.getOperand(0));
-
- if(lambda_methods.contains(invoke_dynamic.index1)) { // lambda invocation found
-
- List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
- MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);
-
- String lambda_class_name = md.ret.value;
- String lambda_method_name = invoke_dynamic.elementname;
- String lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments.get(2)).getString(); // method type
-
- LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
-
- ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.classname, content_method_handle.elementname,
- content_method_handle.descriptor, content_method_handle.index1,
- lambda_class_name, lambda_method_name, lambda_method_descriptor, cl);
- node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
- node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
-
- node.nested.add(node_lambda);
- node_lambda.parent = node;
-
- clprocessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
- mapMethodsLambda.put(node_lambda.lambda_information.content_method_key, node_lambda.simpleName);
- }
- }
- }
- }
-
- mt.releaseResources();
- }
-
- // build class hierarchy on lambda
- for(ClassNode nd : node.nested) {
- if(nd.type == ClassNode.CLASS_LAMBDA) {
- String parent_class_name = mapMethodsLambda.get(nd.enclosingMethod);
- if(parent_class_name != null) {
- ClassNode parent_class = clprocessor.getMapRootClasses().get(parent_class_name);
-
- parent_class.nested.add(nd);
- nd.parent = parent_class;
- }
- }
- }
-
- // FIXME: mixed hierarchy?
-
- return false;
- }
-
+ private static final String JAVAC_LAMBDA_CLASS = "java/lang/invoke/LambdaMetafactory";
+ private static final String JAVAC_LAMBDA_METHOD = "metafactory";
+ private static final String JAVAC_LAMBDA_METHOD_DESCRIPTOR =
+ "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;";
+
+ public void processClass(ClassNode node) throws IOException {
+
+ for (ClassNode child : node.nested) {
+ processClass(child);
+ }
+
+ if (node.nested.isEmpty()) {
+ hasLambda(node);
+ }
+ }
+
+ public boolean hasLambda(ClassNode node) throws IOException {
+
+ ClassesProcessor clprocessor = DecompilerContext.getClassprocessor();
+ StructClass cl = node.classStruct;
+
+ if (cl.getBytecodeVersion() < CodeConstants.BYTECODE_JAVA_8) { // lamda beginning with Java 8
+ return false;
+ }
+
+ StructBootstrapMethodsAttribute bootstrap =
+ (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
+ if (bootstrap == null || bootstrap.getMethodsNumber() == 0) {
+ return false; // no bootstrap constants in pool
+ }
+
+ Set<Integer> lambda_methods = new HashSet<Integer>();
+
+ // find lambda bootstrap constants
+ for (int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
+ LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle
+
+ if (JAVAC_LAMBDA_CLASS.equals(method_ref.classname) &&
+ JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) &&
+ JAVAC_LAMBDA_METHOD_DESCRIPTOR
+ .equals(method_ref.descriptor)) { // check for javac lambda structure. FIXME: extend for Eclipse etc. at some point
+ lambda_methods.add(i);
+ }
+ }
+
+ if (lambda_methods.isEmpty()) {
+ return false; // no lambda bootstrap constant found
+ }
+
+ Map<String, String> mapMethodsLambda = new HashMap<String, String>();
+
+ // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
+ for (StructMethod mt : cl.getMethods()) {
+ mt.expandData();
+
+ InstructionSequence seq = mt.getInstructionSequence();
+ if (seq != null && seq.length() > 0) {
+ int len = seq.length();
+
+ for (int i = 0; i < len; ++i) {
+ Instruction instr = seq.getInstr(i);
+
+ if (instr.opcode == CodeConstants.opc_invokedynamic) {
+ LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.getOperand(0));
+
+ if (lambda_methods.contains(invoke_dynamic.index1)) { // lambda invocation found
+
+ List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
+ MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);
+
+ String lambda_class_name = md.ret.value;
+ String lambda_method_name = invoke_dynamic.elementname;
+ String lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments.get(2)).getString(); // method type
+
+ LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
+
+ ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.classname, content_method_handle.elementname,
+ content_method_handle.descriptor, content_method_handle.index1,
+ lambda_class_name, lambda_method_name, lambda_method_descriptor, cl);
+ node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
+ node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
+
+ node.nested.add(node_lambda);
+ node_lambda.parent = node;
+
+ clprocessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
+ mapMethodsLambda.put(node_lambda.lambda_information.content_method_key, node_lambda.simpleName);
+ }
+ }
+ }
+ }
+
+ mt.releaseResources();
+ }
+
+ // build class hierarchy on lambda
+ for (ClassNode nd : node.nested) {
+ if (nd.type == ClassNode.CLASS_LAMBDA) {
+ String parent_class_name = mapMethodsLambda.get(nd.enclosingMethod);
+ if (parent_class_name != null) {
+ ClassNode parent_class = clprocessor.getMapRootClasses().get(parent_class_name);
+
+ parent_class.nested.add(nd);
+ nd.parent = parent_class;
+ }
+ }
+ }
+
+ // FIXME: mixed hierarchy?
+
+ return false;
+ }
}