Example usage for java.util.stream Node getClass

List of usage examples for java.util.stream Node getClass

Introduction

In this page you can find the example usage for java.util.stream Node getClass.

Prototype

@HotSpotIntrinsicCandidate
public final native Class<?> getClass();

Source Link

Document

Returns the runtime class of this Object .

Usage

From source file:com.heliosdecompiler.helios.tasks.DecompileTask.java

private String recursivelyHandleNameExpr(MethodCallExpr methodCallExpr, NameExpr nameExpr, int depth) { //fixme generics
    if (methodCallExpr.getNameExpr() != nameExpr)
        return null;
    print(depth, "RHNE " + methodCallExpr + " " + nameExpr);
    print(depth,//from w  w w.j  a v  a2s  . c  o  m
            "Scope is " + ((methodCallExpr.getScope() == null) ? null : methodCallExpr.getScope().getClass())
                    + " " + methodCallExpr.getScope());
    Pair<Integer, Integer> offsets = getOffsets(lineSizes, nameExpr);
    ClickableSyntaxTextArea.Link link = new ClickableSyntaxTextArea.Link(nameExpr.getBeginLine(),
            nameExpr.getBeginColumn(), offsets.getValue0(), offsets.getValue1());

    Set<String> possibleClassNames = new HashSet<>();

    if (methodCallExpr.getScope() instanceof NameExpr || methodCallExpr.getScope() instanceof ArrayAccessExpr) {
        Node tmp = methodCallExpr.getScope();

        if (tmp instanceof ArrayAccessExpr) {
            ArrayAccessExpr expr = (ArrayAccessExpr) tmp;
            tmp = expr.getName(); //todo could be other than nameexpr
        }

        /*
         * Cases:
         * Static method
         *   SomeClass.someStaticMethod()
         * Variable
         *   myVar.someVirtualMethod()
         * Field
         *   field.someVirtualMethod()
         */
        Node fnode = tmp;
        NameExpr scopeExpr = (NameExpr) tmp;
        String scope = scopeExpr.toString();
        if (scope.contains(".")) {
            throw new IllegalArgumentException("Was not expecting '.' in " + scope);
        }

        /*
         * In Java, variables have priority
         * Therefore, something like this
         *
         * Object Integer = null;
         * Integer.parseInt("4");
         *
         * would fail
         */

        Node node = methodCallExpr.getParentNode();
        List<com.github.javaparser.ast.type.Type> ref = new ArrayList<>();
        List<Node> parentChain = new ArrayList<>();
        Node tmpNode = node;
        while (tmpNode != null) {
            parentChain.add(tmpNode);
            tmpNode = tmpNode.getParentNode();
        }
        while (ref.size() == 0 && node != null) {
            print(depth, "Trying to find localvar in " + node.getClass());
            node.accept(new VoidVisitorAdapter<Node>() {
                @Override
                public void visit(VariableDeclarationExpr n, Node arg) {
                    boolean equals = false;
                    for (VariableDeclarator var : n.getVars()) {
                        if (var.getId().getName().equals(scopeExpr.getName())) {
                            equals = true;
                        }
                    }
                    if (equals) {
                        print(depth, "Found VariableDeclarationExpr " + n);
                        print(depth, "This is it! Type is " + n.getType());
                        ref.add(n.getType());
                    }
                    super.visit(n, n);
                }

                @Override
                public void visit(MultiTypeParameter n, Node arg) {
                    if (n.getId().getName().equals(((NameExpr) fnode).getName())) {
                        print(depth, "Found VariableDeclarationExpr " + n);
                        print(depth, "This is it! Type is " + n.getType());
                        ref.addAll(n.getType().getElements());
                    }
                }

                @Override
                public void visit(Parameter n, Node arg) {
                    if (n.getId().getName().equals(((NameExpr) fnode).getName())) {
                        print(depth, "Found Parameter " + n);
                        print(depth, "This is it! Type is " + n.getType());
                        ref.add(n.getType());
                    }
                }

                @Override
                public void visit(BlockStmt n, Node arg) {
                    if (parentChain.contains(n)) {
                        super.visit(n, n);
                    }
                }
            }, null);
            if (node instanceof BodyDeclaration) {
                // We don't want to check for variables outside of this method. That would be a field
                break;
            }
            node = node.getParentNode();
        }
        if (ref.size() > 0) {
            if (ref.size() > 1) {
                throw new IllegalArgumentException("Was not expecting more than one localvar " + ref);
            }
            com.github.javaparser.ast.type.Type type = ref.get(0); //fixme check all
            while (type instanceof ReferenceType) {
                type = ((ReferenceType) type).getType();
            }
            print(depth, "Final type is " + type.getClass() + " " + type);
            if (type instanceof ClassOrInterfaceType) {
                ClassOrInterfaceType coit = (ClassOrInterfaceType) type;
                possibleClassNames.addAll(generatePossibilities(coit));
                possibleClassNames.add("java/lang/" + coit.getName() + ".class");
                if (packageName != null) {
                    possibleClassNames.add(packageName + "/" + coit.getName() + ".class");
                }
            } else {
                throw new IllegalArgumentException("Got unexpected type " + type.getClass());
            }
        }

        /*
         * Check for static method invocation
         * If this class was called "Test" we want to check for
         *
         * Test.staticMethod();
         */

        print(depth, "Simple name is " + simpleName);
        if (scopeExpr.getName().equals(simpleName)) {
            possibleClassNames.add(this.className);
        }

        /*
         * Finally, check imports
         */
        for (ImportDeclaration importDeclaration : compilationUnit.getImports()) {
            if (importDeclaration.isAsterisk()) {
                String fullImport = importDeclaration.getName().toString();
                String internalName = fullImport.replace('.', '/');
                possibleClassNames.add(internalName + "/" + scope + ".class");
            } else if (importDeclaration.isStatic()) {

            } else {
                NameExpr importName = importDeclaration.getName();
                if (importName.getName().equals(scope)) {
                    String javaName = importDeclaration.getName().toString();
                    String internalName = javaName.replace('.', '/');
                    possibleClassNames.add(internalName + ".class");
                }
            }
        }

        /*
         * java.lang.* classes don't need to be imported
         * Add it just in case
         */
        possibleClassNames.add("java/lang/" + scope + ".class");

        FieldAccessExpr expr = new FieldAccessExpr(null, scope);
        Set<String> owners = handleFieldExpr(expr, className, depth);
        possibleClassNames.addAll(owners);

        /*
         * Classes in the current package don't need to be imported
         * Add it just in case
         */
        if (packageName != null) {
            possibleClassNames.add(packageName + "/" + scope + ".class");
        }
    } else if (methodCallExpr.getScope() instanceof MethodCallExpr) {
        /*
         * Recursively handle the chained method. The return should be the class name we want
         */
        possibleClassNames.add(recursivelyHandleNameExpr((MethodCallExpr) methodCallExpr.getScope(),
                ((MethodCallExpr) methodCallExpr.getScope()).getNameExpr(), depth + 1));
    } else if (methodCallExpr.getScope() == null) {
        /*
         * Another way of calling a static/virtual method within the same class.
         *
         * someStaticMethod();
         */
        possibleClassNames.add(this.className);
    } else if (methodCallExpr.getScope() instanceof ThisExpr) {
        /*
         * Another way of calling a static/virtual method within the same class
         *
         * this.someVirtualMethod();
         *
         * fixme what about Outer.this.method();
         */
        possibleClassNames.add(this.className);
    } else if (methodCallExpr.getScope() instanceof SuperExpr) {
        /*
         * Calling a super method
         *
         * super.someVirtualMethod();
         */
        LoadedFile loadedFile = Helios.getLoadedFile(fileName);
        ClassNode node = loadedFile.getClassNode(this.className);
        possibleClassNames.add(node.superName);
    } else if (methodCallExpr.getScope() instanceof EnclosedExpr) {
        /*
         * fixme We could be missing CastExprs elsewhere but it's unlikely
         *
         * EnclosedExpr represents an expression surrounded by brackets
         * It's assumed that there may be a cast within
         *
         * ((String) obj).toCharArray();
         */
        EnclosedExpr enclosedExpr = (EnclosedExpr) methodCallExpr.getScope();
        if (enclosedExpr.getInner() instanceof CastExpr) {
            CastExpr castExpr = (CastExpr) enclosedExpr.getInner();
            com.github.javaparser.ast.type.Type type = castExpr.getType();
            while (type instanceof ReferenceType) {
                type = ((ReferenceType) type).getType();
            }
            if (type instanceof ClassOrInterfaceType) {
                ClassOrInterfaceType coit = (ClassOrInterfaceType) type;
                possibleClassNames.addAll(handleClassOrInterfaceType(coit));
            } else {
                throw new IllegalArgumentException("Got unexpected type " + type.getClass());
            }
        }
    } else if (methodCallExpr.getScope() instanceof FieldAccessExpr) { // Handle fields
        /*
         * Could either be a field OR a FQN
         *
         * System.out.println(); -> System.out is the FieldAccessExpr
         *
         * java.lang.System.out.println(); -> java.lang.System.out is the FieldAccessExpr
         */

        FieldAccessExpr expr = (FieldAccessExpr) methodCallExpr.getScope();

        String left = expr.getScope().toString();
        Set<String> possible;
        if (left.equals("this")) {
            possible = new HashSet<>();
            possible.add(className);
        } else {
            ClassOrInterfaceType type = new ClassOrInterfaceType(left);
            type.setBeginLine(expr.getScope().getBeginLine());
            type.setEndLine(expr.getScope().getEndLine());
            type.setBeginColumn(expr.getScope().getBeginColumn());
            type.setEndColumn(expr.getScope().getEndColumn());
            possible = handleClassOrInterfaceType(type);
        }

        if (possible.size() > 0) { // Maybe field
            print(depth, "FieldAccessExpr field: " + expr.getScope() + " " + expr.getField() + " "
                    + expr.getScope().getClass() + " " + possible);
            for (String p : possible) {
                Set<String> types = handleFieldExpr(expr, p, depth);
                possibleClassNames.addAll(types);
            }
        } else {
            ClassOrInterfaceType type = new ClassOrInterfaceType(expr.toString());
            type.setBeginLine(expr.getBeginLine());
            type.setEndLine(expr.getEndLine());
            type.setBeginColumn(expr.getBeginColumn());
            type.setEndColumn(expr.getEndColumn());
            possible = handleClassOrInterfaceType(type);
            if (possible.size() == 0) {
                print(depth, "Error: Could not parse FieldAccessExpr");
            } else {
                print(depth, "FieldAccessExpr fqn: " + expr.getScope() + " " + expr.getField() + " "
                        + expr.getScope().getClass() + " " + possible);
                possibleClassNames.addAll(possible);
            }
        }
    } else if (methodCallExpr.getScope() instanceof ArrayAccessExpr) {
        /*
         * somearray[index].method()
         */
    } else if (methodCallExpr.getScope() instanceof ObjectCreationExpr) {
        /*
         * new Object().method()
         */
        ObjectCreationExpr objectCreationExpr = (ObjectCreationExpr) methodCallExpr.getScope();
        possibleClassNames.addAll(handleClassOrInterfaceType(objectCreationExpr.getType()));
    }

    print(depth, possibleClassNames.toString());
    Map<String, LoadedFile> mapping = possibleClassNames.stream()
            .map(name -> new AbstractMap.SimpleEntry<>(name, getFileFor(name)))
            .filter(ent -> ent.getValue() != null)
            .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));

    if (mapping.size() == 0) {
        print(depth, "Error: Could not find classname");
    } else if (mapping.size() > 1) {
        print(depth, "Error: More than one classname found: " + mapping.keySet()); //fixme filter by which one contains the method
    } else {
        print(depth, "ClassName is " + mapping.keySet());
        String className = mapping.keySet().iterator().next();
        String internalName = className.substring(0, className.length() - 6);

        try {
            while (true) {
                LoadedFile readFrom = null;

                String fileName = internalName + ".class";
                LoadedFile file = Helios.getLoadedFile(this.fileName);
                if (file.getAllData().get(fileName) != null) {
                    readFrom = file;
                } else {
                    Set<LoadedFile> check = new HashSet<>();
                    check.addAll(Helios.getAllFiles());
                    check.addAll(Helios.getPathFiles().values());
                    for (LoadedFile loadedFile : check) {
                        if (loadedFile.getAllData().get(fileName) != null) {
                            readFrom = loadedFile;
                            break;
                        }
                    }
                }
                if (readFrom != null) {
                    print(depth, "Found in " + readFrom.getName());
                    link.fileName = readFrom.getName();
                    link.className = fileName;
                    link.jumpTo = " " + nameExpr.getName() + "(";
                    textArea.links.add(link);

                    ClassNode classNode = readFrom.getEmptyClasses().get(internalName);
                    print(depth, "Looking for method with name " + methodCallExpr.getName() + " in "
                            + internalName + " " + classNode);
                    MethodNode node = classNode.methods.stream()
                            .filter(mn -> mn.name.equals(methodCallExpr.getName())).findFirst().orElse(null);
                    if (node != null) {
                        link.className = internalName + ".class";
                        Type returnType = Type.getType(node.desc);
                        if (returnType.getReturnType().getSort() == Type.OBJECT) {
                            print(depth, "Found method with return type " + returnType);
                            return returnType.getReturnType().getInternalName() + ".class";
                        } else if (returnType.getReturnType().getSort() == Type.ARRAY) {
                            return "java/lang/Object.class";
                        } else {
                            return null;
                        }
                    } else {
                        print(depth, "Could not find methodnode " + methodCallExpr.getName());
                    }
                    if (internalName.equals("java/lang/Object")) {
                        break;
                    }
                    internalName = classNode.superName;
                } else {
                    print(depth, "Could not find readfrom ");
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
    return null;
}