Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 com.kodebeagle.javaparser; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.core.dom.*; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Stack; public class MethodInvocationResolver extends TypeResolver { private static final String OBJECT_TYPE = "java.lang.Object"; private Map<String, List<MethodInvokRef>> methodInvoks = new HashMap<String, List<MethodInvokRef>>(); private Stack<MethodDeclaration> methodStack = new Stack<MethodDeclaration>(); private List<MethodDecl> declaredMethods = new ArrayList<MethodDecl>(); private List<TypeDecl> typeDeclarations = new ArrayList<>(); protected Map<String, String> types = new HashMap(); protected Queue<String> typesInFile = new ArrayDeque<>(); protected String superType; private List<Object> interfacesFullyQualifiedName = new ArrayList<Object>(); protected List<String> interfaces = new ArrayList<String>(); public String getSuperType() { return superType; } public List<TypeDecl> getTypeDeclarations() { return typeDeclarations; } public Map<String, List<MethodInvokRef>> getMethodInvoks() { return methodInvoks; } public List<MethodDecl> getDeclaredMethods() { return declaredMethods; } String type = ""; private String removeSpecialSymbols(final String pType) { String type = pType; if (type != null && type.contains("<")) { type = type.substring(0, type.indexOf("<")); } else if (type != null && type.contains("[")) { type = type.substring(0, type.indexOf("[")); } return type; } @Override public boolean visit(org.eclipse.jdt.core.dom.TypeDeclaration td) { if (typesInFile.isEmpty()) { type = ""; } if (td.getSuperclassType() != null) { superType = getFullyQualifiedNameFor(removeSpecialSymbols(td.getSuperclassType().toString())); } interfacesFullyQualifiedName.addAll(Arrays.<Object>asList(td.superInterfaceTypes().toArray())); typesInFile.add(td.getName().getFullyQualifiedName()); String type = removeSpecialSymbols(td.getName().getFullyQualifiedName()); TypeDecl obj = new TypeDecl(type, td.getName().getStartPosition()); typeDeclarations.add(obj); return true; } public Map<String, String> getTypes() { return types; } @Override public void endVisit(org.eclipse.jdt.core.dom.TypeDeclaration td) { if (!typesInFile.isEmpty()) { String xyz = typesInFile.remove(); type = type + xyz + "."; types.put(xyz, currentPackage + "." + type.substring(0, type.lastIndexOf("."))); } } @Override public boolean visit(MethodDeclaration node) { methodStack.push(node); addMethodDecl(node); return super.visit(node); } @Override public void endVisit(MethodDeclaration node) { if (!methodStack.isEmpty()) { methodStack.pop(); } super.endVisit(node); } public boolean visit(Assignment assignment) { return super.visit(assignment); } @SuppressWarnings("rawtypes") @Override public boolean visit(ClassInstanceCreation node) { List args = node.arguments(); Map<String, Integer> scopeBindings = getNodeScopes().get(node); List<String> argTypes = translateArgsToTypes(args, scopeBindings); String type = getNameOfType(node.getType()); if (!methodStack.empty()) { MethodDeclaration currentMethod = methodStack.peek(); String currMethodName = currentMethod.getName().toString(); List<MethodInvokRef> invoks = methodInvoks.get(currMethodName); if (invoks == null) { invoks = new ArrayList<MethodInvokRef>(); methodInvoks.put(currMethodName, invoks); } MethodInvokRef methodInvokRef = new MethodInvokRef(node.getType().toString(), type, "", args.size(), node.getStartPosition(), argTypes, node.getLength(), true, getReturnType(node)); invoks.add(methodInvokRef); } return super.visit(node); } @SuppressWarnings("rawtypes") @Override public boolean visit(MethodInvocation node) { SimpleName methodName = node.getName(); List args = node.arguments(); Expression expression = node.getExpression(); Map<String, Integer> scopeBindings = getNodeScopes().get(node); String target = getTarget(expression); String targetType = translateTargetToType(expression, scopeBindings); List<String> argTypes = translateArgsToTypes(args, scopeBindings); if (!methodStack.empty()) { MethodDeclaration currentMethod = methodStack.peek(); String currMethodName = currentMethod.getName().toString(); List<MethodInvokRef> invoks = methodInvoks.get(currMethodName); if (invoks == null) { invoks = new ArrayList<MethodInvokRef>(); methodInvoks.put(currMethodName, invoks); } MethodInvokRef methodInvokRef = new MethodInvokRef(methodName.toString(), targetType, target, args.size(), node.getName().getStartPosition(), argTypes, methodName.getLength(), false, getReturnType(node)); invoks.add(methodInvokRef); } return true; } /** * If the passed node is a method invocation or class creation then return the * return type of the method based on what is the returned value assigned to. * @param node * @return return type */ private String getReturnType(Expression node) { ASTNode parent = node.getParent(); if (parent instanceof VariableDeclarationFragment) { ASTNode grandParent = parent.getParent(); if (grandParent instanceof VariableDeclarationStatement) { Type typ = ((VariableDeclarationStatement) grandParent).getType(); return getFullyQualifiedNameFor(typ.toString()); } } return null; } @SuppressWarnings("rawtypes") private void addMethodDecl(MethodDeclaration node) { SimpleName nameNode = node.getName(); String methodName = nameNode.toString(); List params = node.parameters(); int num = params.size(); List<String> paramTypes = new ArrayList<String>(); for (Object p : params) { String typeName = OBJECT_TYPE; if (p instanceof SingleVariableDeclaration) { SingleVariableDeclaration svd = (SingleVariableDeclaration) p; Type type = svd.getType(); typeName = getNameOfType(type); } else { System.err.println("Unxepected AST node type for param - " + p); } paramTypes.add(typeName); } declaredMethods.add(new MethodDecl(methodName, num, nameNode.getStartPosition(), paramTypes)); } protected String translateTargetToType(Expression expression, Map<String, Integer> scopeBindings) { String targetType = ""; if (expression != null) { String target = getTarget(expression); final Integer variableId = scopeBindings.get(target); if (variableId == null || !getVariableBinding().containsKey(variableId)) { targetType = getFullyQualifiedNameFor(target); } else { targetType = getVariableTypes().get(variableId); } } return targetType; } private String getTarget(Expression expression) { String target = ""; if (expression != null) { target = expression.toString(); if (target.contains("this.")) { target = StringUtils.substringAfter(target, "this."); } } return target; } @SuppressWarnings("rawtypes") protected List<String> translateArgsToTypes(List args, Map<String, Integer> scopeBindings) { List<String> argTypes = new ArrayList<String>(); for (Object o : args) { String name = o.toString(); Integer varId = scopeBindings.get(name); if (varId == null) { String staticTypeRef = getImportedNames().get(name); if (staticTypeRef != null) { argTypes.add("<static>" + staticTypeRef); } else { argTypes.add(OBJECT_TYPE); } } else { argTypes.add(getVariableTypes().get(varId)); } } return argTypes; } public List<String> getInterfaces() { for (int i = 0; i < interfacesFullyQualifiedName.size(); i++) interfaces.add( getFullyQualifiedNameFor(removeSpecialSymbols(interfacesFullyQualifiedName.get(i).toString()))); return interfaces; } public static class TypeDecl { private String className; private Integer loc; public TypeDecl(String className, Integer loc) { super(); this.className = className; this.loc = loc; } public String getClassName() { return className; } public Integer getLoc() { return loc; } } public static class MethodDecl { private String methodName; private Integer argNum; private Integer location; private List<String> argTypes; public MethodDecl(String methodName, Integer argNum, Integer location, List<String> argTypes) { super(); this.methodName = methodName; this.argNum = argNum; this.location = location; this.argTypes = argTypes; } public String getMethodName() { return methodName; } public Integer getArgNum() { return argNum; } public Integer getLocation() { return location; } public List<String> getArgTypes() { return argTypes; } @Override public String toString() { return "MethodDecl [methodName=" + methodName + ", argNum=" + argNum + ", location=" + location + ", argTypes=" + argTypes + "]"; } } public static class MethodInvokRef { private String methodName; private String targetType; private String target; private Integer argNum; private Integer location; private Integer length; private String returnType; private Boolean isConstructor; private List<String> argTypes; private MethodInvokRef(String methodName, String targetType, String target, Integer argNum, Integer location, List<String> argTypes, Integer length, Boolean isConstructor, String returnType) { super(); this.methodName = methodName; this.targetType = targetType; this.argNum = argNum; this.location = location; this.argTypes = argTypes; this.target = target; this.length = length; this.returnType = returnType; this.isConstructor = isConstructor; } public Integer getLength() { return length; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public String getTargetType() { return targetType; } public void setTargetType(String targetType) { this.targetType = targetType; } public String getTarget() { return target; } public void setTarget(String target) { this.target = target; } public Integer getArgNum() { return argNum; } public void setArgNum(Integer argNum) { this.argNum = argNum; } public Integer getLocation() { return location; } public void setLocation(Integer location) { this.location = location; } public List<String> getArgTypes() { return argTypes; } public void setArgTypes(List<String> argTypes) { this.argTypes = argTypes; } public Boolean getConstructor() { return isConstructor; } public String getReturnType() { return returnType; } @Override public String toString() { return "MethodInvokRef{" + "methodName='" + methodName + '\'' + ", targetType='" + targetType + '\'' + ", target='" + target + '\'' + ", argNum=" + argNum + ", location=" + location + ", length=" + length + ", returnType='" + returnType + '\'' + ", isConstructor=" + isConstructor + ", argTypes=" + argTypes + '}'; } } }