List of usage examples for java.util.stream Node getClass
@HotSpotIntrinsicCandidate public final native Class<?> getClass();
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; }