diff --git a/src/main/java/depends/deptypes/DependencyType.java b/src/main/java/depends/deptypes/DependencyType.java index b3a94e9..65ce37d 100644 --- a/src/main/java/depends/deptypes/DependencyType.java +++ b/src/main/java/depends/deptypes/DependencyType.java @@ -46,7 +46,8 @@ public class DependencyType { public static final String PomParent = "Parent"; public static final String PomPlugin = "Plugin"; public static final String PomDependency = "Dependency"; - + + public static final String DuckTypingLabel = "(duck)"; public static ArrayList allDependencies() { ArrayList depedencyTypes = new ArrayList(); diff --git a/src/main/java/depends/generator/DependencyGenerator.java b/src/main/java/depends/generator/DependencyGenerator.java index c23d112..6f943f5 100644 --- a/src/main/java/depends/generator/DependencyGenerator.java +++ b/src/main/java/depends/generator/DependencyGenerator.java @@ -24,6 +24,7 @@ SOFTWARE. package depends.generator; +import depends.entity.CandidateTypes; import depends.entity.Entity; import depends.entity.EntityNameBuilder; import depends.entity.FileEntity; @@ -32,6 +33,7 @@ import depends.matrix.core.DependencyDetail; import depends.matrix.core.DependencyMatrix; import depends.matrix.core.LocationInfo; import depends.matrix.transform.OrderedMatrixGenerator; +import depends.relations.Relation; import multilang.depends.util.file.path.EmptyFilenameWritter; import multilang.depends.util.file.path.FilenameWritter; import multilang.depends.util.file.strip.EmptyLeadingNameStripper; @@ -39,8 +41,13 @@ import multilang.depends.util.file.strip.ILeadingNameStrippper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; import java.util.List; +import static depends.deptypes.DependencyType.DuckTypingLabel; + public abstract class DependencyGenerator { private static Logger logger = LoggerFactory.getLogger(DependencyGenerator.class); @@ -56,7 +63,74 @@ public abstract class DependencyGenerator { return dependencyMatrix; } - public abstract DependencyMatrix build(EntityRepo entityRepo,List typeFilter); + /** + * Build the dependency matrix (without re-mapping file id) + * @param entityRepo which contains entities and relations + * @return the generated dependency matrix + */ + public DependencyMatrix build(EntityRepo entityRepo,List typeFilter) { + DependencyMatrix dependencyMatrix = new DependencyMatrix(typeFilter); + Iterator iterator = entityRepo.entityIterator(); + System.out.println("Start create dependencies matrix...."); + while(iterator.hasNext()) { + Entity entity = iterator.next(); + if (!entity.inScope()) continue; + if (outputLevelMatch(entity)){ + dependencyMatrix.addNode(nameOf(entity),entity.getId()); + } + int entityFrom = upToOutputLevelEntityId(entityRepo, entity); + if (entityFrom==-1) continue; + for (Relation relation:entity.getRelations()) { + Entity relatedEntity = relation.getEntity(); + if (relatedEntity==null) continue; + List relatedEntities = expandEntity(relatedEntity); + String duckTypingFlag = relatedEntity instanceof CandidateTypes? DuckTypingLabel:""; + relatedEntities.forEach(theEntity->{ + if (theEntity.getId()>=0) { + int entityTo = upToOutputLevelEntityId(entityRepo,theEntity); + if (entityTo!=-1) { + DependencyDetail detail = buildDescription(entity, theEntity, relation.getFromLine()); + detail = rewriteDetail(detail); + dependencyMatrix.addDependency(relation.getType()+duckTypingFlag, entityFrom,entityTo,1,detail); + } + } + }); + } + } + System.out.println("Finish create dependencies matrix...."); + return dependencyMatrix; + } + + private List expandEntity(Entity relatedEntity) { + List entities = new ArrayList<>(); + if (relatedEntity instanceof CandidateTypes) { + entities = Collections.unmodifiableList((List) ((CandidateTypes) relatedEntity).getCandidateTypes()); + }else { + entities.add(relatedEntity); + } + return entities; + } + + private DependencyDetail rewriteDetail(DependencyDetail detail) { + if (detail==null) return null; + String srcFile = filenameWritter.reWrite( + stripper.stripFilename(detail.getSrc().getFile()) + ); + String dstFile = filenameWritter.reWrite( + stripper.stripFilename(detail.getDest().getFile())); + return new DependencyDetail( + new LocationInfo(detail.getSrc().getObject(), + srcFile, detail.getSrc().getLineNumber()) + , + new LocationInfo(detail.getDest().getObject(), + dstFile, detail.getDest().getLineNumber())); + } + + protected abstract int upToOutputLevelEntityId(EntityRepo entityRepo, Entity entity); + + protected abstract String nameOf(Entity entity); + + protected abstract boolean outputLevelMatch(Entity entity); protected ILeadingNameStrippper stripper = new EmptyLeadingNameStripper(); protected FilenameWritter filenameWritter = new EmptyFilenameWritter(); diff --git a/src/main/java/depends/generator/FileDependencyGenerator.java b/src/main/java/depends/generator/FileDependencyGenerator.java index 1758b77..23ee29f 100644 --- a/src/main/java/depends/generator/FileDependencyGenerator.java +++ b/src/main/java/depends/generator/FileDependencyGenerator.java @@ -24,88 +24,24 @@ SOFTWARE. package depends.generator; -import depends.entity.CandidateTypes; import depends.entity.Entity; import depends.entity.FileEntity; -import depends.entity.TypeEntity; import depends.entity.repo.EntityRepo; -import depends.matrix.core.DependencyDetail; -import depends.matrix.core.DependencyMatrix; -import depends.matrix.core.LocationInfo; -import depends.relations.Relation; - -import java.util.Iterator; -import java.util.List; public class FileDependencyGenerator extends DependencyGenerator{ - /** - * Build the dependency matrix (without re-mapping file id) - * @param entityRepo which contains entities and relations - * @return the generated dependency matrix - */ @Override - public DependencyMatrix build(EntityRepo entityRepo,List typeFilter) { - DependencyMatrix dependencyMatrix = new DependencyMatrix(typeFilter); - Iterator iterator = entityRepo.entityIterator(); - System.out.println("Start create dependencies matrix...."); - while(iterator.hasNext()) { - Entity entity = iterator.next(); - if (!entity.inScope()) continue; - if (entity instanceof FileEntity){ - String name = stripper.stripFilename(entity.getDisplayName()); - name = filenameWritter.reWrite(name); - dependencyMatrix.addNode(name,entity.getId()); - } - int fileEntityFrom = getFileEntityIdNoException(entityRepo, entity); - if (fileEntityFrom==-1) continue; - for (Relation relation:entity.getRelations()) { - Entity relatedEntity = relation.getEntity(); - if (relatedEntity==null) continue; - if (relatedEntity instanceof CandidateTypes) { - List candidateTypes = ((CandidateTypes)relatedEntity).getCandidateTypes(); - for (TypeEntity candidateType:candidateTypes) { - if (candidateType.getId()>=0) { - int fileEntityTo = getFileEntityIdNoException(entityRepo,candidateType); - if (fileEntityTo!=-1) { - DependencyDetail detail = buildDescription(entity,candidateType,relation.getFromLine()); - detail = rewriteDetail(detail); - dependencyMatrix.addDependency(relation.getType(), fileEntityFrom,fileEntityTo,1,detail); - } - } - } - }else { - if (relatedEntity.getId()>=0) { - int fileEntityTo = getFileEntityIdNoException(entityRepo,relatedEntity); - if (fileEntityTo!=-1) { - DependencyDetail detail = buildDescription(entity, relatedEntity, relation.getFromLine()); - detail = rewriteDetail(detail); - dependencyMatrix.addDependency(relation.getType(), fileEntityFrom,fileEntityTo,1,detail); - } - } - } - } - } - System.out.println("Finish create dependencies matrix...."); - - return dependencyMatrix; + protected String nameOf(Entity entity) { + String name = stripper.stripFilename(entity.getDisplayName()); + return filenameWritter.reWrite(name); } - private DependencyDetail rewriteDetail(DependencyDetail detail) { - if (detail==null) return null; - String srcFile = filenameWritter.reWrite( - stripper.stripFilename(detail.getSrc().getFile()) - ); - String dstFile = filenameWritter.reWrite( - stripper.stripFilename(detail.getDest().getFile())); - return new DependencyDetail( - new LocationInfo(detail.getSrc().getObject(), - srcFile, detail.getSrc().getLineNumber()) - , - new LocationInfo(detail.getDest().getObject(), - dstFile, detail.getDest().getLineNumber())); + @Override + protected boolean outputLevelMatch(Entity entity) { + return (entity instanceof FileEntity); } - private int getFileEntityIdNoException(EntityRepo entityRepo, Entity entity) { + @Override + protected int upToOutputLevelEntityId(EntityRepo entityRepo, Entity entity) { Entity ancestor = entity.getAncestorOfType(FileEntity.class); if (ancestor==null) { return -1; diff --git a/src/main/java/depends/generator/FunctionDependencyGenerator.java b/src/main/java/depends/generator/FunctionDependencyGenerator.java index c90fd4c..f434e63 100644 --- a/src/main/java/depends/generator/FunctionDependencyGenerator.java +++ b/src/main/java/depends/generator/FunctionDependencyGenerator.java @@ -25,47 +25,19 @@ SOFTWARE. package depends.generator; import depends.entity.Entity; +import depends.entity.EntityNameBuilder; import depends.entity.FileEntity; import depends.entity.FunctionEntity; -import depends.entity.EntityNameBuilder; import depends.entity.repo.EntityRepo; -import depends.matrix.core.DependencyMatrix; -import depends.relations.Relation; - -import java.util.Iterator; -import java.util.List; public class FunctionDependencyGenerator extends DependencyGenerator { - public DependencyMatrix build(EntityRepo entityRepo,List typeFilter) { - DependencyMatrix dependencyMatrix = new DependencyMatrix(typeFilter); - Iterator iterator = entityRepo.entityIterator(); - while(iterator.hasNext()) { - Entity entity = iterator.next(); - if (!entity.inScope()) continue; - if (entity instanceof FunctionEntity) { - String name = getFunctionEntityDisplayName((FunctionEntity)entity); - dependencyMatrix.addNode(name,entity.getId()); - } - int entityFrom = getFunctionEntityIdNoException(entity); - if (entityFrom == -1) - continue; - for (Relation relation : entity.getRelations()) { - Entity relatedEntity = relation.getEntity(); - if (relatedEntity==null) continue; - if (relatedEntity.getId() >= 0) { - int entityTo = getFunctionEntityIdNoException(relation.getEntity()); - if (entityTo == -1) - continue; - dependencyMatrix.addDependency(relation.getType(), entityFrom, entityTo, 1,buildDescription(entity, - relation.getEntity(),relation.getFromLine())); - } - } - } - return dependencyMatrix; + @Override + protected boolean outputLevelMatch(Entity entity) { + return (entity instanceof FunctionEntity); } - - private String getFunctionEntityDisplayName(FunctionEntity entity) { + @Override + protected String nameOf(Entity entity) { FileEntity file = (FileEntity) entity.getAncestorOfType(FileEntity.class); String name = stripper.stripFilename(file.getRawName().uniqName()); name = filenameWritter.reWrite(name); @@ -75,8 +47,8 @@ public class FunctionDependencyGenerator extends DependencyGenerator { return name; } - - private int getFunctionEntityIdNoException(Entity entity) { + @Override + protected int upToOutputLevelEntityId(EntityRepo entityRepo, Entity entity) { Entity ancestor = entity.getAncestorOfType(FunctionEntity.class); if (ancestor == null) return -1; diff --git a/src/main/java/depends/generator/StructureDependencyGenerator.java b/src/main/java/depends/generator/StructureDependencyGenerator.java index b063d23..c211209 100644 --- a/src/main/java/depends/generator/StructureDependencyGenerator.java +++ b/src/main/java/depends/generator/StructureDependencyGenerator.java @@ -26,68 +26,16 @@ package depends.generator; import depends.entity.*; import depends.entity.repo.EntityRepo; -import depends.matrix.core.DependencyDetail; -import depends.matrix.core.DependencyMatrix; -import depends.matrix.core.LocationInfo; -import depends.relations.Relation; - -import java.util.Iterator; -import java.util.List; public class StructureDependencyGenerator extends DependencyGenerator{ - /** - * Build the dependency matrix (without re-mapping file id) - * @param entityRepo which contains entities and relations - * @return the generated dependency matrix - */ @Override - public DependencyMatrix build(EntityRepo entityRepo,List typeFilter) { - DependencyMatrix dependencyMatrix = new DependencyMatrix(typeFilter); - Iterator iterator = entityRepo.entityIterator(); - System.out.println("Start create dependencies matrix...."); - while(iterator.hasNext()) { - Entity entity = iterator.next(); - if (!entity.inScope()) continue; - if (isStructureEntityType(entity)){ - String name = entity.getQualifiedName() + "|" + entity.getClass().getSimpleName().replace("Entity",""); - dependencyMatrix.addNode(name,entity.getId()); - } - - int fileEntityFrom = getStructureEntityIdNoException(entity); - if (fileEntityFrom==-1) continue; - for (Relation relation:entity.getRelations()) { - Entity relatedEntity = relation.getEntity(); - if (relatedEntity==null) continue; - if (relatedEntity instanceof CandidateTypes) { - List candidateTypes = ((CandidateTypes)relatedEntity).getCandidateTypes(); - for (TypeEntity candidateType:candidateTypes) { - if (candidateType.getId()>=0) { - int fileEntityTo = getStructureEntityIdNoException(candidateType); - if (fileEntityTo!=-1) { - DependencyDetail detail = buildDescription(entity,candidateType,relation.getFromLine()); - dependencyMatrix.addDependency(relation.getType(), fileEntityFrom,fileEntityTo,1,detail); - } - } - } - }else { - if (relatedEntity.getId()>=0) { - int fileEntityTo = getStructureEntityIdNoException(relatedEntity); - if (fileEntityTo!=-1) { - DependencyDetail detail = buildDescription(entity, relatedEntity, relation.getFromLine()); - dependencyMatrix.addDependency(relation.getType(), fileEntityFrom,fileEntityTo,1,detail); - } - } - } - } - } - System.out.println("Finish create dependencies matrix...."); - - return dependencyMatrix; + protected String nameOf(Entity entity) { + return entity.getQualifiedName() + "|" + entity.getClass().getSimpleName().replace("Entity",""); } - - private boolean isStructureEntityType(Entity entity) { + @Override + protected boolean outputLevelMatch(Entity entity) { if (entity instanceof FileEntity) return false; if (entity instanceof TypeEntity) return true; //package included if (entity instanceof VarEntity && entity.getParent() instanceof TypeEntity) return true; @@ -95,7 +43,8 @@ public class StructureDependencyGenerator extends DependencyGenerator{ return false; } - private int getStructureEntityIdNoException(Entity entity) { + @Override + protected int upToOutputLevelEntityId(EntityRepo entityRepo, Entity entity) { Entity ancestor = getAncestorOfType(entity); if (ancestor==null) { return -1; @@ -106,7 +55,7 @@ public class StructureDependencyGenerator extends DependencyGenerator{ public Entity getAncestorOfType(Entity fromEntity) { while(fromEntity!=null) { - if (isStructureEntityType(fromEntity)) + if (outputLevelMatch(fromEntity)) return fromEntity; if (fromEntity.getParent()==null) return null; fromEntity = fromEntity.getParent(); diff --git a/src/main/java/depends/matrix/core/DependencyMatrix.java b/src/main/java/depends/matrix/core/DependencyMatrix.java index 94d58fe..f74cc84 100644 --- a/src/main/java/depends/matrix/core/DependencyMatrix.java +++ b/src/main/java/depends/matrix/core/DependencyMatrix.java @@ -31,6 +31,8 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; +import static depends.deptypes.DependencyType.DuckTypingLabel; + public class DependencyMatrix { private HashMap dependencyPairs = new HashMap<>(); private ArrayList nodes = new ArrayList<>(); @@ -67,7 +69,7 @@ public class DependencyMatrix { } public void addDependency(String depType, Integer from, Integer to, int weight,DependencyDetail detail) { - if (typeFilter!=null && (!typeFilter.contains(depType))) + if (typeFilter!=null && (!typeFilter.contains(depType.replace(DuckTypingLabel,"")))) return; if(from.equals(to) || from == -1 || to == -1) { return;