package org.lrg.outcode.builder.ast; import java.util.List; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.Assignment; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SuperFieldAccess; import org.eclipse.jdt.core.dom.ThisExpression; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.lrg.outcode.builder.RelTypes; import org.lrg.outcode.builder.db.GraphDatasource; import org.neo4j.graphdb.Node; public class OutCodeVisitor extends ASTVisitor { private GraphDatasource db = GraphDatasource.INSTANCE; private String commit; private ITypeBinding currentTypeResolvedBinding; private String commitID; private int added; private int removed; public OutCodeVisitor(String commit, String commitID, int added, int removed) { this.commit = commit; this.commitID = commitID; this.removed = removed; this.added = added; } /* * public boolean visit(SingleVariableDeclaration singleVariableDeclaration) { if (singleVariableDeclaration.getParent() instanceof MethodDeclaration) { * addParameterToMethod(singleVariableDeclaration); } return true; } * * private void addParameterToMethod(SingleVariableDeclaration singleVariableDeclaration) { MethodDeclaration methodDeclaration = (MethodDeclaration) * singleVariableDeclaration.getParent(); IJavaElement methodJavaElement = getIJavaElement(methodDeclaration); if (methodJavaElement != null) { Node methodIJavaElementNode = * db.createIJavaElementNode(methodJavaElement, dbService, commit); SimpleName simpleName = singleVariableDeclaration.getName(); String identifier = simpleName.getIdentifier(); * // hacky create node call, createNode should be private Node createParameterNode = db.createNode(dbService, methodJavaElement.getHandleIdentifier() + "_" + identifier, * identifier, "Parameter", methodJavaElement, commit); methodIJavaElementNode.createRelationshipTo(createParameterNode, RelTypes.HAS_PARAM); * * if (singleVariableDeclaration.getType().isPrimitiveType()) { createParameterNode.setProperty("primitive type", singleVariableDeclaration.getType().toString()); } else { * ITypeBinding typeBinding = singleVariableDeclaration.getType().resolveBinding(); IJavaElement parameterTypeIJavaElement = typeBinding.getJavaElement(); if * (parameterTypeIJavaElement != null) { Node parameterIJavaElementNode = db.createIJavaElementNode(parameterTypeIJavaElement, dbService, commit); * createParameterNode.createRelationshipTo(parameterIJavaElementNode, RelTypes.IS_OF_TYPE); } } } } */ private IJavaElement getIJavaElement(MethodDeclaration methodDeclaration) { IMethodBinding resolveBinding = methodDeclaration.resolveBinding(); if (resolveBinding != null) { IMethod methodJavaElement = (IMethod) resolveBinding.getJavaElement(); return methodJavaElement; } return null; } @Override public boolean visit(FieldDeclaration fieldDeclaration) { List fragments = fieldDeclaration.fragments(); for (Object object : fragments) { if (object instanceof VariableDeclarationFragment) { VariableDeclarationFragment variableDeclarationFragment = (VariableDeclarationFragment) object; IVariableBinding resolveBinding = variableDeclarationFragment.resolveBinding(); if (resolveBinding != null) { IJavaElement iJavaElement = resolveBinding.getJavaElement(); if (iJavaElement != null) { int modifiers = fieldDeclaration.getModifiers(); Node field = db.createIJavaElementNode(iJavaElement, commit, commitID, added, removed); if (Modifier.isProtected(modifiers)) field.setProperty("protected", true); if (Modifier.isPublic(modifiers)) field.setProperty("public", true); if (Modifier.isPrivate(modifiers)) field.setProperty("private", true); } } } } return true; } // check if getter or setter @Override public boolean visit(MethodDeclaration methodDeclaration) { methodMetrics(methodDeclaration); if (methodDeclaration.isConstructor()) return true; if (methodDeclaration.getBody() == null || methodDeclaration.getBody().statements().size() != 1) return true; if (methodDeclaration.getName().getIdentifier().startsWith("get")) { Object object = methodDeclaration.getBody().statements().get(0); if (!(object instanceof ReturnStatement)) return true; else { ReturnStatement returnStatement = (ReturnStatement) object; Expression expression = returnStatement.getExpression(); if (expression == null) return true; // method name starts with get but returns // null if (isObjectFieldAccess(expression)) { if (methodDeclaration != null) { IMethodBinding methodBinding = methodDeclaration.resolveBinding(); if (methodBinding != null) { Node method = db.createIJavaElementNode(methodBinding.getJavaElement(), commit, commitID, added, removed); method.setProperty("get", true); } } } } } else if (methodDeclaration.getName().getIdentifier().startsWith("set")) { Object object = methodDeclaration.getBody().statements().get(0); if (!(object instanceof Assignment) && !(object instanceof ExpressionStatement)) return true; if (object instanceof ExpressionStatement) object = ((ExpressionStatement) object).getExpression(); if (!(object instanceof Assignment)) return true; Assignment assignment = (Assignment) object; Expression leftExpression = assignment.getLeftHandSide(); if (isObjectFieldAccess(leftExpression) && isParameterAccess(assignment.getRightHandSide())) { IMethodBinding methodBinding = methodDeclaration.resolveBinding(); if (methodBinding != null) { IJavaElement methodJavaElement = methodBinding.getJavaElement(); if (methodJavaElement != null) { Node method = db.createIJavaElementNode(methodJavaElement, commit, commitID, added, removed); method.setProperty("get", true); } } } } return true; } private void methodMetrics(MethodDeclaration methodDeclaration) { IJavaElement iJavaElement = getIJavaElement(methodDeclaration); if (iJavaElement != null) { MetricVisitor metricVisitor = new MetricVisitor(); metricVisitor.process(methodDeclaration); int cyclomaticComplexity = metricVisitor.getCyclomaticComplexity(); int numberOfStatements = metricVisitor.getNumberOfStatements(); Node method = db.createIJavaElementNode(iJavaElement, commit, commitID, added, removed); method.setProperty("cyclomaticComplexity", cyclomaticComplexity); method.setProperty("numberOfStatements", numberOfStatements); int modifiers = methodDeclaration.getModifiers(); if (Modifier.isProtected(modifiers)) method.setProperty("protected", true); if (Modifier.isPublic(modifiers)) method.setProperty("public", true); if (Modifier.isPrivate(modifiers)) method.setProperty("private", true); if (currentTypeResolvedBinding != null) { IMethodBinding resolveBinding2 = methodDeclaration.resolveBinding(); ITypeBinding superclass = currentTypeResolvedBinding.getSuperclass(); if (superclass != null) { IMethodBinding[] superDeclaredMethods = superclass.getDeclaredMethods(); for (IMethodBinding iMethodBinding : superDeclaredMethods) { if (resolveBinding2.overrides(iMethodBinding)) { method.setProperty("overiding", true); } } } } } } private boolean isParameterAccess(Expression rightHandSide) { return rightHandSide.getNodeType() == Expression.SIMPLE_NAME; } private boolean isObjectFieldAccess(Expression leftExpression) { if (leftExpression.getNodeType() == Expression.FIELD_ACCESS) { FieldAccess fieldAccess = (FieldAccess) leftExpression; if (fieldAccess.getExpression() instanceof ThisExpression) { return true; } } else if (leftExpression.getNodeType() == Expression.SIMPLE_NAME) { return true; } return false; } @Override public boolean visit(TypeDeclaration td) { currentTypeResolvedBinding = td.resolveBinding(); ITypeBinding superClassBinding = currentTypeResolvedBinding.getSuperclass(); if (superClassBinding != null && superClassBinding.isFromSource()) { if (currentTypeResolvedBinding.getJavaElement() != null & superClassBinding.getJavaElement() != null) { Node subclass = db.createIJavaElementNode(currentTypeResolvedBinding.getJavaElement(), commit, commitID, added, removed); Node superClass = db.createIJavaElementNode(superClassBinding.getJavaElement(), commit, commitID, added, removed); subclass.createRelationshipTo(superClass, RelTypes.EXTENDS); } } return true; } @Override public boolean visit(FieldAccess node) { IVariableBinding resolveFieldBinding = node.resolveFieldBinding(); if (resolveFieldBinding != null && resolveFieldBinding.getDeclaringClass() != null && resolveFieldBinding.getDeclaringClass().isFromSource()) { addFieldAccess(node, resolveFieldBinding); return false; } return true; } private void addFieldAccess(Expression node, IVariableBinding resolveFieldBinding) { if (resolveFieldBinding.getDeclaringClass().isFromSource()) { MethodDeclaration containingMethodDeclaration = findContaingMethod(node); if (containingMethodDeclaration != null) { IJavaElement containingIMethod = getIJavaElement(containingMethodDeclaration); if (containingIMethod != null) { IJavaElement accessedIField = resolveFieldBinding.getJavaElement(); if (accessedIField != null) { Node methodIJavaElementNode = db.createIJavaElementNode(containingIMethod, commit, commitID, added, removed); Node accessedIFieldElementNode = db.createIJavaElementNode(accessedIField, commit, commitID, added, removed); methodIJavaElementNode.createRelationshipTo(accessedIFieldElementNode, RelTypes.ACCESSES); } } } } } @Override public boolean visit(SuperFieldAccess node) { IVariableBinding resolveFieldBinding = node.resolveFieldBinding(); addFieldAccess(node, resolveFieldBinding); return true; } @Override public boolean visit(SimpleName simpleName) { IBinding resolveBinding = simpleName.resolveBinding(); if (resolveBinding != null) { IJavaElement javaElement = resolveBinding.getJavaElement(); if (javaElement != null) { int elementType = javaElement.getElementType(); if (resolveBinding != null && javaElement != null && elementType == IJavaElement.FIELD) { addFieldAccess(simpleName, (IVariableBinding) resolveBinding); } if (resolveBinding != null && javaElement != null && elementType == IJavaElement.METHOD && !(simpleName.getParent() instanceof MethodDeclaration)) { addMethodCall(simpleName, (IMethodBinding) resolveBinding); } } } return true; } private void addMethodCall(Expression simpleName, IMethodBinding resolveBinding) { if (resolveBinding.getDeclaringClass() != null && resolveBinding.getDeclaringClass().isFromSource()) { MethodDeclaration containingMethodDeclaration = findContaingMethod(simpleName); if (containingMethodDeclaration != null) { IJavaElement containingIMethod = getIJavaElement(containingMethodDeclaration); if (containingIMethod != null) { IJavaElement calledImethod = resolveBinding.getJavaElement(); if (calledImethod != null) { Node methodIJavaElementNode = db.createIJavaElementNode(containingIMethod, commit, commitID, added, removed); Node accessedIFieldElementNode = db.createIJavaElementNode(calledImethod, commit, commitID, added, removed); methodIJavaElementNode.createRelationshipTo(accessedIFieldElementNode, RelTypes.CALLS); } } } } } private MethodDeclaration findContaingMethod(ASTNode node) { if (node == null) return null; if (node.getNodeType() == ASTNode.METHOD_DECLARATION) { return (MethodDeclaration) node; } else return findContaingMethod(node.getParent()); } }