package de.ovgu.cide.mining.database; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import org.eclipse.jdt.core.ICompilationUnit; 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.CastExpression; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ConstructorInvocation; import org.eclipse.jdt.core.dom.EnumConstantDeclaration; import org.eclipse.jdt.core.dom.EnumDeclaration; 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.ImportDeclaration; import org.eclipse.jdt.core.dom.InstanceofExpression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.SuperConstructorInvocation; import org.eclipse.jdt.core.dom.SuperMethodInvocation; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationExpression; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import cide.gparser.ParseException; import de.ovgu.cide.features.IFeature; import de.ovgu.cide.features.source.SourceFileColorManager; import de.ovgu.cide.language.jdt.ASTBridge; import de.ovgu.cide.language.jdt.JDTParserWrapper; import de.ovgu.cide.mining.database.model.AElement; import de.ovgu.cide.mining.database.model.AFlyweightElementFactory; import de.ovgu.cide.mining.database.model.AICategories; import de.ovgu.cide.mining.database.model.ARelationKind; import de.ovgu.cide.mining.database.recommendationengine.AElementColorManager; import de.ovgu.cide.util.MethodPathItem; import de.ovgu.cide.util.OverridingRelationUtils; import de.ovgu.cide.util.TypePathItem; /** * @author A.Dreiling * */ public class AAccessRelationBuilder implements Serializable { private static final long serialVersionUID = 3L; private int cuHash; private AbstractProgramDatabase aDB; private AFlyweightElementFactory elementFactory; private AElement curCUElement; private AElement curImport; private AElement curType; private AElement curMethod; private AElement curField; private AElement curLocalVariable; private AElement curExtendsAccess; private Stack<AElement> curTypeReminder; private Set<AElement> curParameter; private LocalContextElement curContext; private Stack<LocalContextElement> curContextReminder; private Map<String, AElement> importMap; private AElementColorManager elementColorManager; private SourceFileColorManager sourceColorManager; private class LocalContextElement { private ASTNode node; private AElement element; private ASTNode accessNode; public LocalContextElement(ASTNode node, ASTNode accessNode, AElement element) { this.node = node; this.element = element; this.accessNode = accessNode; } public ASTNode getNode() { return node; } public AElement getElement() { return element; } public ASTNode getAccessNode() { return accessNode; } } /** * Clear class fields and be ready to work on a different compilation unit. */ private void reset() { curCUElement = null; curImport = null; curTypeReminder = new Stack<AElement>(); curContextReminder = new Stack<LocalContextElement>(); importMap = new HashMap<String, AElement>(); curType = null; curMethod = null; curField = null; curLocalVariable = null; curContext = null; curExtendsAccess = null; curParameter = null; } public AAccessRelationBuilder(AbstractProgramDatabase aDB, AFlyweightElementFactory elementFactory) { this.aDB = aDB; this.elementFactory = elementFactory; } void update(ASTNode node) { node.accept(new ASTVisitor() { private void addElement(AElement element, Set<IFeature> colors) { aDB.addElement(element); for (IFeature color : colors) elementColorManager.addElementToColor(color, element); } private Set<IFeature> getColor(ASTNode node) { return sourceColorManager.getColors(ASTBridge.bridge(node)); } // COMPILATION UNIT CONTEXT// @Override public boolean visit(CompilationUnit node) { // create the CU element and store it curCUElement = (AElement) elementFactory.getElement(node); return super.visit(node); } // IMPORT CONTEXT// @Override public boolean visit(ImportDeclaration node) { curImport = (AElement) elementFactory.getElement(node); IBinding binding = node.resolveBinding(); if (binding instanceof ITypeBinding) { importMap.put(((ITypeBinding) binding).getKey(), curImport); } return super.visit(node); } public void endVisit(ImportDeclaration node) { curImport = null; } // TYPE CONTEXT// @Override public boolean visit(EnumDeclaration node) { ITypeBinding binding = node.resolveBinding(); visitType(node, binding); return super.visit(node); } @Override public boolean visit(TypeDeclaration node) { ITypeBinding binding = node.resolveBinding(); visitType(node, binding); return super.visit(node); } public void visitType(ASTNode node, ITypeBinding binding) { if (binding == null) return; if (!binding.isTopLevel()) { curTypeReminder.push(curType); } curType = (AElement) elementFactory.getElement(binding); if (curType == null) return; createExtendsAndImplementsTypeRelations(binding); // define extends access node if (node.getNodeType() != ASTNode.TYPE_DECLARATION) return; Object curExtendsType = node .getStructuralProperty(TypeDeclaration.SUPERCLASS_TYPE_PROPERTY); if (curExtendsType == null) return; curExtendsAccess = (AElement) elementFactory.createElement( AICategories.TYPE_ACCESS, null, cuHash, (ASTNode) curExtendsType); // StructuralPropertyDescriptor descriptor = // parent.getLocationInParent(); // // if (descriptor == TypeDeclaration.SUPERCLASS_TYPE_PROPERTY ) // { // aDB.addRelationAndTranspose(curType, ARelation.EXTENDS_TYPE, // typeAccessElement); // // } // else if (descriptor == // TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY || // descriptor == EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY) // { // aDB.addRelationAndTranspose(curType, // ARelation.IMPLEMENTS_TYPE, typeAccessElement); // } // else { // aDB.addRelationAndTranspose(curType, ARelation.ACCESS_TYPE, // typeAccessElement); // } // } private void createExtendsAndImplementsTypeRelations( ITypeBinding binding) { List<TypePathItem> directTypes = new ArrayList<TypePathItem>(); List<TypePathItem> transitiveTypes = new ArrayList<TypePathItem>(); if (collectExtendsAndImplementsTypeRelations(binding, directTypes, transitiveTypes)) { AElement typeElement; for (TypePathItem pathItem : directTypes) { typeElement = (AElement) elementFactory .getElement(pathItem.getBinding()); if (typeElement != null) { if (pathItem.isInterface()) { aDB.addRelationAndTranspose(curType, ARelationKind.IMPLEMENTS_TYPE, typeElement); } else { aDB .addRelationAndTranspose(curType, ARelationKind.EXTENDS_TYPE, typeElement); } } } for (TypePathItem pathItem : transitiveTypes) { typeElement = (AElement) elementFactory .getElement(pathItem.getBinding()); if (typeElement != null) { if (pathItem.isInterface()) { aDB .addRelationAndTranspose( curType, ARelationKind.IMPLEMENTS_TYPE_TRANSITIVE, typeElement); } else { aDB.addRelationAndTranspose(curType, ARelationKind.EXTENDS_TYPE_TRANSITIVE, typeElement); } } } } } private boolean collectExtendsAndImplementsTypeRelations( ITypeBinding declTypeBinding, List<TypePathItem> directTypes, List<TypePathItem> transitiveTypes) { if (declTypeBinding == null || transitiveTypes == null || directTypes == null) return false; Set<String> checkedInterfaces = new HashSet<String>(); ITypeBinding[] interfaces = declTypeBinding.getInterfaces(); for (ITypeBinding tmpInterface : interfaces) { directTypes.add(new TypePathItem(tmpInterface, true)); checkedInterfaces.add(tmpInterface.getKey()); OverridingRelationUtils .collectExtendedAndImplementedTypesInInterfaces( tmpInterface, transitiveTypes, checkedInterfaces); } ITypeBinding superClass = declTypeBinding.getSuperclass(); if (superClass != null) { directTypes.add(new TypePathItem(superClass, false)); OverridingRelationUtils .collectExtendedAndImplementedTypesInSuperClasses( superClass, transitiveTypes, checkedInterfaces); } if (directTypes.size() == 0 && transitiveTypes.size() == 0) return false; return true; } @Override public void endVisit(EnumDeclaration node) { ITypeBinding binding = node.resolveBinding(); endVisitType(binding); } @Override public void endVisit(TypeDeclaration node) { ITypeBinding binding = node.resolveBinding(); endVisitType(binding); } public void endVisitType(ITypeBinding binding) { if (binding == null) return; // restore current type and temp method if (!curTypeReminder.isEmpty()) { curType = (AElement) curTypeReminder.pop(); } else { curType = null; } } // METHOD CONTEXT// public boolean visit(MethodDeclaration node) { IMethodBinding binding = node.resolveBinding(); if (binding != null) { curMethod = elementFactory.getElement(binding); createInherritedAndOverriddenMethodRelations(binding); } return super.visit(node); } private void createInherritedAndOverriddenMethodRelations( IMethodBinding binding) { List<MethodPathItem> inhMethods = new ArrayList<MethodPathItem>(); if (collectInherritedOrOverridenMethods(binding, inhMethods)) { boolean first = true; AElement superMethod; ARelationKind overridesRelation = ARelationKind.OVERRIDES_METHOD; ARelationKind implementsRelation = ARelationKind.IMPLEMENTS_METHOD; for (MethodPathItem methodPathItem : inhMethods) { superMethod = (AElement) elementFactory .getElement(methodPathItem.getBinding()); if (superMethod != null) { if (!methodPathItem.isAbstract()) { aDB.addRelationAndTranspose(curMethod, overridesRelation, superMethod); } else { aDB.addRelationAndTranspose(curMethod, implementsRelation, superMethod); } } if (first) { first = false; overridesRelation = ARelationKind.OVERRIDES_METHOD_TRANSITIVE; implementsRelation = ARelationKind.IMPLEMENTS_METHOD_TRANSITIVE; } } } } private boolean collectInherritedOrOverridenMethods( IMethodBinding binding, List<MethodPathItem> inhMethods) { ITypeBinding declTypeBinding = binding.getDeclaringClass(); if (declTypeBinding == null) return false; Set<String> checkedInterfaces = new HashSet<String>(); // (recursively) collects all keys of methods in abstract // classes which // belongs to this declaration OverridingRelationUtils.collectSimilarMethodKeysInSuperClasses( binding, declTypeBinding.getSuperclass(), inhMethods, checkedInterfaces); // (recursively) collects all keys of methods in interfaces // which // belongs to this declaration OverridingRelationUtils.collectSimilarMethodKeysInInterfaces( binding, declTypeBinding.getInterfaces(), inhMethods, checkedInterfaces); // the set should contain at least one inherited method if (inhMethods.size() == 0) return false; return true; } @Override public void endVisit(MethodDeclaration node) { curMethod = null; } @Override public boolean visit(ConstructorInvocation node) { IMethodBinding binding = node.resolveConstructorBinding(); List args = node.arguments(); handleMethodCall(node, binding, args); return super.visit(node); } @Override public void endVisit(ConstructorInvocation node) { handleEndMethodCall(node); } @Override public boolean visit(ClassInstanceCreation node) { IMethodBinding binding = node.resolveConstructorBinding(); List args = node.arguments(); handleMethodCall(node, binding, args); return super.visit(node); } @Override public void endVisit(ClassInstanceCreation node) { handleEndMethodCall(node); } @Override public boolean visit(SuperConstructorInvocation node) { IMethodBinding binding = node.resolveConstructorBinding(); List args = node.arguments(); handleMethodCall(node, binding, args); return super.visit(node); } @Override public void endVisit(SuperConstructorInvocation node) { handleEndMethodCall(node); } @Override public boolean visit(SuperMethodInvocation node) { IMethodBinding binding = node.resolveMethodBinding(); List args = node.arguments(); handleMethodCall(node, binding, args); return super.visit(node); } @Override public void endVisit(SuperMethodInvocation node) { handleEndMethodCall(node); } @Override public boolean visit(MethodInvocation node) { IMethodBinding binding = node.resolveMethodBinding(); List args = node.arguments(); handleMethodCall(node, binding, args); return super.visit(node); } @Override public void endVisit(MethodInvocation node) { handleEndMethodCall(node); } private void handleMethodCall(ASTNode node, IMethodBinding binding, List arguments) { if (binding != null) { // DEFINING CONTEXT FOR METHOD AElement curElement = elementFactory.getElement(binding); if (curContext != null) { curContextReminder.push(curContext); } // cur element could also be null! curContext = new LocalContextElement(node, null, curElement); Set<AElement> localVars = null; if (curElement != null) { localVars = aDB.getRange(curElement, ARelationKind.DECLARES_LOCAL_VARIABLE); } curParameter = new HashSet<AElement>(); // create param access elements for (int i = 0; i < arguments.size(); i++) { ASTNode tmpArg = (ASTNode) arguments.get(i); AElement paramAccessElement = (AElement) elementFactory .createElement(AICategories.PARAMETER_ACCESS, null, cuHash, tmpArg); addElement(paramAccessElement, getColor(tmpArg)); curParameter.add(paramAccessElement); if (localVars == null) continue; // aDB.addRelationAndTranspose(curElement, // ARelation.ACCESS_PARAMETER, paramAccessElement); for (AElement localVar : localVars) { if (((AElement) localVar).getParamIndex() == i) { aDB.addRelationAndTranspose(localVar, ARelationKind.REQUIRES, paramAccessElement); } } } if (curParameter.size() == 0) curParameter = null; handleMethodAccess(node, curElement); } } private void handleEndMethodCall(ASTNode node) { handleEndVisitContext(node); curParameter = null; } // LOCAL VARIABLE AND FIELD CONTEXT// public boolean visit(VariableDeclarationFragment node) { IVariableBinding binding = node.resolveBinding(); visitFieldOrVariable(node, binding); return super.visit(node); } public boolean visit(SingleVariableDeclaration node) { IVariableBinding binding = node.resolveBinding(); visitFieldOrVariable(node, binding); return super.visit(node); } public boolean visit(EnumConstantDeclaration node) { IVariableBinding binding = node.resolveVariable(); visitFieldOrVariable(node, binding); return super.visit(node); } public void visitFieldOrVariable(ASTNode node, IVariableBinding binding) { if (binding == null) return; if (binding.isField() || binding.isEnumConstant()) { curField = (AElement) elementFactory.getElement(binding); } else { curLocalVariable = (AElement) elementFactory .getElement(binding); } // VariableDeclarationFragment extra handling is needed! if (node.getNodeType() == ASTNode.VARIABLE_DECLARATION_FRAGMENT) { handleTypeAccessForVarDeclFragment(node); } } public void endVisit(EnumConstantDeclaration node) { IVariableBinding binding = node.resolveVariable(); endVisitFieldOrVariable(node, binding); } public void endVisit(VariableDeclarationFragment node) { IVariableBinding binding = node.resolveBinding(); endVisitFieldOrVariable(node, binding); } public void endVisit(SingleVariableDeclaration node) { IVariableBinding binding = node.resolveBinding(); endVisitFieldOrVariable(node, binding); } public void endVisitFieldOrVariable(ASTNode node, IVariableBinding binding) { if (binding == null) return; if (binding.isField() || binding.isEnumConstant()) { curField = null; } else { curLocalVariable = null; } } public boolean visit(CastExpression node) { final ASTNode curNode = node; node.getExpression().accept(new ASTVisitor() { public boolean visit(SimpleName nameNode) { addContextForFieldorVariable(curNode, nameNode); return super.visit(nameNode); } }); return super.visit(node); } public void endVisit(CastExpression node) { handleEndVisitContext(node); } public boolean visit(InstanceofExpression node) { final ASTNode curNode = node; node.getLeftOperand().accept(new ASTVisitor() { public boolean visit(SimpleName nameNode) { addContextForFieldorVariable(curNode, nameNode); return super.visit(nameNode); } }); return super.visit(node); } public void endVisit(InstanceofExpression node) { handleEndVisitContext(node); } @Override public boolean visit(Assignment node) { final ASTNode curNode = node; node.getLeftHandSide().accept(new ASTVisitor() { public boolean visit(SimpleName nameNode) { addContextForFieldorVariable(curNode, nameNode); return super.visit(nameNode); } }); return super.visit(node); } private void addContextForFieldorVariable(ASTNode contextNode, SimpleName nameNode) { IBinding binding = nameNode.resolveBinding(); if (binding != null && binding instanceof IVariableBinding) { // DEFINING CONTEXT FOR FIELD OR LOCAL VARIABLE! AElement curElement = elementFactory.getElement(binding); if (curContext != null) { curContextReminder.push(curContext); } curContext = new LocalContextElement(contextNode, nameNode, curElement); } } public void endVisit(Assignment node) { handleEndVisitContext(node); } private void handleEndVisitContext(ASTNode node) { if (curContext == null) return; while (curContext != null && curContext.getNode().equals(node)) { if (!curContextReminder.isEmpty()) { curContext = curContextReminder.pop(); } else { curContext = null; } } } // ACCESS HANDLING// @Override public boolean visit(SimpleName node) { visitName(node); return super.visit(node); } // HANDLE ACCESS public void visitName(Name node) { IBinding binding = node.resolveBinding(); if (binding == null) return; if (binding instanceof ITypeBinding) { handleTypeAccess(node, (ITypeBinding) binding); } else if (binding instanceof IVariableBinding) { handleFieldOrVariableAccess(node, (IVariableBinding) binding); } // else if (binding instanceof IMethodBinding) { // handleMethodAccess(node,(IMethodBinding) binding); // } } // HANDLE TYPE ACCESS private void handleTypeAccess(Name node, ITypeBinding binding) { ASTNode parent = node.getParent(); // don't check type or enum declarations if (parent instanceof TypeDeclaration) return; if (parent instanceof EnumDeclaration) return; ASTNode elementNode = node; if (parent instanceof Type) { elementNode = parent; } AElement typeAccessElement = (AElement) elementFactory .createElement(AICategories.TYPE_ACCESS, null, cuHash, elementNode); addElement(typeAccessElement, getColor(elementNode)); AElement typeElement = (AElement) elementFactory .getElement(binding); // ADD ACCESS TO ACTUAL TYPE if (typeElement != null) aDB.addRelationAndTranspose(typeAccessElement, ARelationKind.BELONGS_TO, typeElement); AElement importElement = importMap.get(binding.getKey()); if (importElement != null && !importElement.equals(curImport)) aDB.addRelationAndTranspose(typeAccessElement, ARelationKind.BELONGS_TO, importElement); // ADD ALL ELEMENTS WHO ACCESS THIS ELEMENT // ADD ALWAYS ACCESS RELATION FOR COMP. UNIT aDB .addRelationAndTranspose(curCUElement, ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); // ADD ACCESS ELEMENT TO OTHER ELEMENTS DEPENDING ON CURRENT // CONTEXT if (curImport != null) aDB.addRelationAndTranspose(curImport, ARelationKind.ACCESS_TYPE, typeAccessElement); if (curType != null) aDB.addRelationAndTranspose(curType, ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); for (AElement tmpType : curTypeReminder) { aDB.addRelationAndTranspose(tmpType, ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); } // if (curParameter != null) { // for (AIElement paramAccess : curParameter) { // aDB.addRelationAndTranspose(typeAccessElement, // ARelation.DECLARES_PARAMETER, paramAccess); // } // curParameter = null; // } boolean directRelationAdded = false; // if is one of them, will be handled separately later on switch (elementNode.getParent().getNodeType()) { case ASTNode.VARIABLE_DECLARATION_STATEMENT: directRelationAdded = true; break; case ASTNode.VARIABLE_DECLARATION_EXPRESSION: directRelationAdded = true; break; case ASTNode.FIELD_DECLARATION: directRelationAdded = true; break; } if (!directRelationAdded && curContext != null) { directRelationAdded = true; if (curContext.getElement() != null) aDB.addRelationAndTranspose(curContext.getElement(), ARelationKind.ACCESS_TYPE, typeAccessElement); } for (LocalContextElement tmpContext : curContextReminder) { if (tmpContext.getElement() != null) aDB.addRelationAndTranspose(tmpContext.getElement(), ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); } if (curLocalVariable != null) { if (directRelationAdded) { aDB.addRelationAndTranspose(curLocalVariable, ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); } else { aDB.addRelationAndTranspose(curLocalVariable, ARelationKind.ACCESS_TYPE, typeAccessElement); directRelationAdded = true; } } if (curField != null) { if (directRelationAdded) { aDB.addRelationAndTranspose(curField, ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); } else { aDB.addRelationAndTranspose(curField, ARelationKind.ACCESS_TYPE, typeAccessElement); directRelationAdded = true; } } if (curMethod != null) { aDB.addRelationAndTranspose(curMethod, ARelationKind.DECLARES_TYPE_ACCESS, typeAccessElement); if (directRelationAdded) { aDB.addRelationAndTranspose(curMethod, ARelationKind.ACCESS_TYPE_TRANSITIVE, typeAccessElement); } else { aDB.addRelationAndTranspose(curMethod, ARelationKind.ACCESS_TYPE, typeAccessElement); } } } // in VariableDeclarationFragment the type is stored // in parent node, which was already handled private void handleTypeAccessForVarDeclFragment(ASTNode node) { ASTNode parentNode = node.getParent(); if (parentNode == null) return; Type type = null; switch (parentNode.getNodeType()) { case ASTNode.VARIABLE_DECLARATION_STATEMENT: type = ((VariableDeclarationStatement) parentNode) .getType(); break; case ASTNode.VARIABLE_DECLARATION_EXPRESSION: type = ((VariableDeclarationExpression) parentNode) .getType(); break; case ASTNode.FIELD_DECLARATION: type = ((FieldDeclaration) parentNode).getType(); break; } if (type == null) return; AElement typeAccessElement = (AElement) elementFactory .getElement(type); if (typeAccessElement == null) return; if (curField != null) aDB.addRelationAndTranspose(curField, ARelationKind.ACCESS_TYPE, typeAccessElement); if (curLocalVariable != null) aDB.addRelationAndTranspose(curLocalVariable, ARelationKind.ACCESS_TYPE, typeAccessElement); } // HANDLE FieldOrVariableAccess private void handleFieldOrVariableAccess(Name node, IVariableBinding binding) { ASTNode parent = node.getParent(); // don't check field / variable access in declaration if (parent instanceof VariableDeclarationFragment) return; if (parent instanceof EnumConstantDeclaration) return; if (parent instanceof SingleVariableDeclaration) return; AElement element = elementFactory.getElement(binding); ARelationKind accessRelation = ARelationKind.ACCESS_FIELD; ARelationKind accessTransitiveRelation = ARelationKind.ACCESS_FIELD_TRANSITIVE; ARelationKind declaresRelation = ARelationKind.DECLARES_FIELD_ACCESS; AICategories cat = AICategories.FIELD_ACCESS; boolean isField = true; if (element != null && element.getCategory() != AICategories.FIELD) { accessRelation = ARelationKind.ACCESS_LOCAL_VARIABLE; accessTransitiveRelation = ARelationKind.ACCESS_LOCAL_VARIABLE_TRANSITIVE; declaresRelation = ARelationKind.DECLARES_LOCAL_VARIABLE_ACCESS; cat = AICategories.LOCAL_VARIABLE_ACCESS; } AElement accessElement = elementFactory.createElement(cat, null, cuHash, node); addElement(accessElement, getColor(node)); // ADD ACCESS TO ACTUAL Element if (element != null) aDB.addRelationAndTranspose(accessElement, ARelationKind.BELONGS_TO, element); // ADD ALL ELEMENTS WHO ACCESS THIS ELEMENT // ADD ALWAYS TRANS. ACCESS RELATION FOR COMP. UNIT aDB.addRelationAndTranspose(curCUElement, accessTransitiveRelation, accessElement); // ADD ALWAYS TRANS. ACCESS RELATION FOR TYPE if (curType != null) { aDB.addRelationAndTranspose(curType, accessTransitiveRelation, accessElement); // TODO: CHECK SUPER ACCESS FOR OUT OF CONTEXT ELEMENTS! // check if field access is a super field access if (curExtendsAccess != null && element != null && isField) { if (isSuperAccess(element, ARelationKind.T_DECLARES_FIELD)) { aDB.addRelationAndTranspose(accessElement, ARelationKind.BELONGS_TO, curExtendsAccess); } } } for (AElement tmpType : curTypeReminder) { aDB.addRelationAndTranspose(tmpType, accessTransitiveRelation, accessElement); } boolean directRelationAdded = false; // do not add variable access for it self if (curContext != null) { if (curContext.getElement() == null) { if (!node.equals(curContext.getAccessNode())) { directRelationAdded = true; } } else if (!curContext.getElement().equals(element)) { aDB.addRelationAndTranspose(curContext.getElement(), accessRelation, accessElement); directRelationAdded = true; } } LocalContextElement tmpContext; int size = curContextReminder.size(); for (int i = 0; i < size; i++) { tmpContext = curContextReminder.get(i); // letzte eintrag! if (!directRelationAdded && size - i == 1) { directRelationAdded = true; if (tmpContext.getElement() == null) continue; aDB.addRelationAndTranspose(tmpContext.getElement(), accessRelation, accessElement); continue; } if (tmpContext.getElement() != null) aDB.addRelationAndTranspose(tmpContext.getElement(), accessTransitiveRelation, accessElement); } if (curLocalVariable != null) { if (directRelationAdded) { aDB.addRelationAndTranspose(curLocalVariable, accessTransitiveRelation, accessElement); } else { aDB.addRelationAndTranspose(curLocalVariable, accessRelation, accessElement); directRelationAdded = true; } } if (curField != null) { if (directRelationAdded) { aDB.addRelationAndTranspose(curField, accessTransitiveRelation, accessElement); } else { aDB.addRelationAndTranspose(curField, accessRelation, accessElement); directRelationAdded = true; } } if (curMethod != null) { aDB.addRelationAndTranspose(curMethod, declaresRelation, accessElement); if (directRelationAdded) { aDB.addRelationAndTranspose(curMethod, accessTransitiveRelation, accessElement); } else { aDB.addRelationAndTranspose(curMethod, accessRelation, accessElement); } } } // HANDLE METHOD ACCESS private void handleMethodAccess(ASTNode node, AElement element) { AElement accessElement = elementFactory.createElement( AICategories.METHOD_ACCESS, null, cuHash, node); addElement(accessElement, getColor(node)); // ADD BELONGS TO RELATION if (element != null) aDB.addRelationAndTranspose(accessElement, ARelationKind.BELONGS_TO, element); // ADD ALL ELEMENTS WHO ACCESS THIS ELEMENT // HANDLE CURRENT PARAMS if (curParameter != null) { for (AElement paramAccess : curParameter) { aDB.addRelationAndTranspose(accessElement, ARelationKind.DECLARES_PARAMETER, paramAccess); } curParameter = null; } // ADD ALWAYS TRANS. ACCESS RELATION FOR COMP. UNIT aDB.addRelationAndTranspose(curCUElement, ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); // ADD ALWAYS TRANS. ACCESS RELATION FOR TYPE if (curType != null) { aDB.addRelationAndTranspose(curType, ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); // TODO: CHECK IF IS SUPER ACCESS FOR OUT OF CONTEXT // ELEMENTS (element == null) // check if access is a super access if (curExtendsAccess != null && element != null) { if (isSuperAccess(element, ARelationKind.T_DECLARES_METHOD)) { aDB.addRelationAndTranspose(accessElement, ARelationKind.BELONGS_TO, curExtendsAccess); } } } for (AElement tmpType : curTypeReminder) { aDB.addRelationAndTranspose(tmpType, ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); } boolean directRelationAdded = false; LocalContextElement tmpContext; int size = curContextReminder.size(); for (int i = 0; i < size; i++) { tmpContext = curContextReminder.get(i); // set in last entry the direct relation if (size - i == 1) { directRelationAdded = true; // OUT OF CONTEXT ELEMENT! if (tmpContext.getElement() == null) continue; aDB.addRelationAndTranspose(tmpContext.getElement(), ARelationKind.ACCESS_METHOD, accessElement); continue; } // OUT OF CONTEXT ELEMENT! if (tmpContext.getElement() == null) continue; aDB.addRelationAndTranspose(tmpContext.getElement(), ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); } if (curLocalVariable != null) { if (directRelationAdded) { aDB.addRelationAndTranspose(curLocalVariable, ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); } else { aDB.addRelationAndTranspose(curLocalVariable, ARelationKind.ACCESS_METHOD, accessElement); directRelationAdded = true; } } if (curField != null) { if (directRelationAdded) { aDB.addRelationAndTranspose(curField, ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); } else { aDB.addRelationAndTranspose(curField, ARelationKind.ACCESS_METHOD, accessElement); directRelationAdded = true; } } if (curMethod != null) { aDB .addRelationAndTranspose(curMethod, ARelationKind.DECLARES_METHOD_ACCESS, accessElement); if (directRelationAdded) { aDB.addRelationAndTranspose(curMethod, ARelationKind.ACCESS_METHOD_TRANSITIVE, accessElement); } else { aDB.addRelationAndTranspose(curMethod, ARelationKind.ACCESS_METHOD, accessElement); } } } private boolean isSuperAccess(AElement declElement, ARelationKind declRelation) { Set<AElement> declareRange = aDB.getRange(declElement, declRelation); if (!declareRange.contains(curType)) { Set<AElement> superTypes = new HashSet<AElement>(); superTypes.addAll(aDB.getRange(curType, ARelationKind.EXTENDS_TYPE)); superTypes.addAll(aDB.getRange(curType, ARelationKind.EXTENDS_TYPE_TRANSITIVE)); for (AElement tmpSuperType : superTypes) { if (declareRange.contains(tmpSuperType)) { return true; } } } return false; } }); } public void buildRelations(ICompilationUnit cu, int cuHash, AElementColorManager elementColorManager, SourceFileColorManager sourceColorManager) { this.cuHash = cuHash; this.elementColorManager = elementColorManager; this.sourceColorManager = sourceColorManager; try { CompilationUnit ast = JDTParserWrapper.parseCompilationUnit(cu); reset(); update(ast); } catch (ParseException e) { e.printStackTrace(); } } }