elimiate impl link of cpp which could locate symbol in same file

This commit is contained in:
Gang ZHANG 2020-08-13 08:09:15 +08:00
parent e8f45fc3c5
commit af9d8bc51c
13 changed files with 124 additions and 113 deletions

View File

@ -24,23 +24,16 @@ SOFTWARE.
package depends.entity;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import depends.entity.repo.EntityRepo;
import depends.relations.Inferer;
import depends.relations.Relation;
import multilang.depends.util.file.TemporaryFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import depends.entity.repo.EntityRepo;
import depends.relations.Inferer;
import multilang.depends.util.file.TemporaryFile;
import java.io.*;
import java.lang.ref.WeakReference;
import java.util.*;
/**
* ContainerEntity for example file, class, method, etc. they could contain
@ -271,6 +264,7 @@ public abstract class ContainerEntity extends DecoratedEntity {
this.expressionList.clear();
this.expressionList=null;
this.expressionList = new ArrayList<>();
this.expressionUseList = null;
}
private void cacheExpressionListToFile() {
@ -447,5 +441,35 @@ public abstract class ContainerEntity extends DecoratedEntity {
return resolvedMixins;
}
HashMap<String,Set<Expression>> expressionUseList = null;
public void addRelation(Expression expression, Relation relation) {
String key = relation.getEntity().qualifiedName+relation.getType();
if (this.expressionUseList==null)
expressionUseList = new HashMap<>();
if (expressionUseList.containsKey(key)){
Set<Expression> expressions = expressionUseList.get(key);
for (Expression expr:expressions){
if (linkedExpr(expr,expression)) return;
}
}else{
expressionUseList.put(key,new HashSet<>());
}
expressionUseList.get(key).add(expression);
super.addRelation(relation);
}
private boolean linkedExpr(Expression a, Expression b) {
Expression parent = a.getParent();
while(parent!=null){
if (parent==b) return true;
parent = parent.getParent();
}
parent = b.getParent();
while(parent!=null){
if (parent==a) return true;
parent = parent.getParent();
}
return false;
}
}

View File

@ -271,4 +271,5 @@ public abstract class Entity {
public Location getLocation() {
return this.location;
}
}

View File

@ -51,6 +51,7 @@ public class Expression implements Serializable{
private boolean isStatement = false; //statement is only used for return type calcuation in some langs such as ruby
//they will not be treat as real expressions in case of relation calculation
private boolean deriveTypeFromChild = true;
private Integer deduceTypeBasedId; //by default, parent expression type determined by most left child
private Integer parentId = -1;

View File

@ -24,11 +24,6 @@ SOFTWARE.
package depends.extractor.pom;
import java.util.List;
import java.util.Stack;
import org.antlr.v4.runtime.ParserRuleContext;
import depends.entity.Expression;
import depends.entity.GenericName;
import depends.entity.VarEntity;
@ -37,6 +32,10 @@ import depends.extractor.FileParser;
import depends.extractor.xml.XMLParser.ElementContext;
import depends.extractor.xml.XMLParserBaseListener;
import depends.relations.Inferer;
import org.antlr.v4.runtime.ParserRuleContext;
import java.util.List;
import java.util.Stack;
public class PomListener extends XMLParserBaseListener {
private PomHandlerContext context;

View File

@ -1,35 +1,19 @@
package depends.extractor.python.union;
import depends.entity.*;
import depends.entity.repo.IdGenerator;
import depends.extractor.HandlerContext;
import depends.extractor.python.PythonHandlerContext;
import depends.extractor.python.PythonParser.Assert_stmtContext;
import depends.extractor.python.PythonParser.AtomContext;
import depends.extractor.python.PythonParser.Del_stmtContext;
import depends.extractor.python.PythonParser.ExprContext;
import depends.extractor.python.PythonParser.Expr_stmtContext;
import depends.extractor.python.PythonParser.Raise_stmtContext;
import depends.extractor.python.PythonParser.Return_stmtContext;
import depends.extractor.python.PythonParser.Testlist_star_exprContext;
import depends.extractor.python.PythonParser.TrailerContext;
import depends.extractor.python.PythonParser.Yield_stmtContext;
import depends.extractor.python.PythonParser.*;
import depends.extractor.python.PythonParserBaseVisitor;
import depends.relations.Inferer;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RuleContext;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RuleContext;
import depends.entity.Entity;
import depends.entity.Expression;
import depends.entity.FunctionEntity;
import depends.entity.GenericName;
import depends.entity.TypeEntity;
import depends.entity.VarEntity;
import depends.entity.repo.IdGenerator;
import depends.extractor.HandlerContext;
public class ExpressionUsage {
HandlerContext context;
IdGenerator idGenerator;
@ -82,6 +66,7 @@ public class ExpressionUsage {
}else {
/* create expression and link it with parent*/
expression = new Expression(idGenerator.generateId());
expression.setText(ctx.getText());
context.lastContainer().addExpression(ctx,expression);
expression.setParent(parent);

View File

@ -24,37 +24,16 @@ SOFTWARE.
package depends.extractor.ruby.jruby;
import java.util.List;
import org.jrubyparser.ast.AndNode;
import org.jrubyparser.ast.AssignableNode;
import org.jrubyparser.ast.BlockNode;
import org.jrubyparser.ast.ClassVarNode;
import org.jrubyparser.ast.Colon3Node;
import org.jrubyparser.ast.ConstNode;
import org.jrubyparser.ast.FCallNode;
import org.jrubyparser.ast.FalseNode;
import org.jrubyparser.ast.GlobalVarNode;
import org.jrubyparser.ast.ILiteralNode;
import org.jrubyparser.ast.InstVarNode;
import org.jrubyparser.ast.ListNode;
import org.jrubyparser.ast.LocalVarNode;
import org.jrubyparser.ast.NewlineNode;
import org.jrubyparser.ast.Node;
import org.jrubyparser.ast.OrNode;
import org.jrubyparser.ast.ReturnNode;
import org.jrubyparser.ast.RootNode;
import org.jrubyparser.ast.TrueNode;
import org.jrubyparser.ast.VCallNode;
import depends.entity.ContainerEntity;
import depends.entity.Expression;
import depends.entity.FunctionEntity;
import depends.entity.GenericName;
import depends.entity.VarEntity;
import depends.entity.repo.IdGenerator;
import depends.extractor.ruby.RubyHandlerContext;
import depends.relations.Inferer;
import org.jrubyparser.ast.*;
import java.util.List;
public class ExpressionUsage {
RubyHandlerContext context;

View File

@ -112,7 +112,9 @@ public class RelationCounter {
if (referredEntity==null) {
return;
}
if (referredEntity.getId()<0){
return;
}
if (referredEntity instanceof MultiDeclareEntities) {
for (Entity e:((MultiDeclareEntities)referredEntity).getEntities()) {
addRelationFromExpression(entity,expression,e);
@ -124,14 +126,18 @@ public class RelationCounter {
if (expression.isCall()) {
/* if it is a FunctionEntityProto, add Relation to all Impl Entities*/
if (callAsImpl && referredEntity instanceof FunctionEntityProto) {
Entity multiDeclare = repo.getEntity(referredEntity.getQualifiedName());
if (multiDeclare instanceof MultiDeclareEntities) {
MultiDeclareEntities m = (MultiDeclareEntities)multiDeclare;
List<Entity> entities = m.getEntities().stream().filter(item->(item instanceof FunctionEntityImpl))
.collect(Collectors.toList());
for (Entity e:entities) {
entity.addRelation(buildRelation(entity,DependencyType.IMPLLINK,e,expression.getLocation()));
matched = true;
if (entity.getAncestorOfType(FileEntity.class).getId().equals(referredEntity.getAncestorOfType(FileEntity.class).getId())){
entity.addRelation(buildRelation(entity,DependencyType.CALL,referredEntity,expression.getLocation()));
}else {
Entity multiDeclare = repo.getEntity(referredEntity.getQualifiedName());
if (multiDeclare instanceof MultiDeclareEntities) {
MultiDeclareEntities m = (MultiDeclareEntities) multiDeclare;
List<Entity> entities = m.getEntities().stream().filter(item -> (item instanceof FunctionEntityImpl))
.collect(Collectors.toList());
for (Entity e : entities) {
entity.addRelation(expression, buildRelation(entity, DependencyType.IMPLLINK, e, expression.getLocation()));
matched = true;
}
}
}
}
@ -154,18 +160,22 @@ public class RelationCounter {
if (!matched) {
if (callAsImpl && repo.getEntity(referredEntity.getQualifiedName()) instanceof MultiDeclareEntities &&
(referredEntity instanceof VarEntity ||referredEntity instanceof FunctionEntity)) {
MultiDeclareEntities m = (MultiDeclareEntities)(repo.getEntity(referredEntity.getQualifiedName()));
for (Entity e:m.getEntities()) {
if (e==referredEntity) {
entity.addRelation(buildRelation(entity,DependencyType.USE,e,expression.getLocation()));
}else {
entity.addRelation(buildRelation(entity,DependencyType.IMPLLINK,e,expression.getLocation()));
if (entity.getAncestorOfType(FileEntity.class).getId().equals(referredEntity.getAncestorOfType(FileEntity.class).getId())){
entity.addRelation(buildRelation(entity,DependencyType.USE,referredEntity,expression.getLocation()));
}else {
MultiDeclareEntities m = (MultiDeclareEntities) (repo.getEntity(referredEntity.getQualifiedName()));
for (Entity e : m.getEntities()) {
if (e == referredEntity) {
entity.addRelation(expression, buildRelation(entity, DependencyType.USE, e, expression.getLocation()));
} else {
entity.addRelation(expression, buildRelation(entity, DependencyType.IMPLLINK, e, expression.getLocation()));
}
matched = true;
}
matched = true;
}
}
else {
entity.addRelation(buildRelation(entity,DependencyType.USE,referredEntity,expression.getLocation()));
entity.addRelation(expression,buildRelation(entity,DependencyType.USE,referredEntity,expression.getLocation()));
}
}
}

View File

@ -1,11 +1,12 @@
package depends.extractor.cpp;
import java.io.IOException;
import depends.deptypes.DependencyType;
import depends.entity.Entity;
import org.junit.Before;
import org.junit.Test;
import depends.deptypes.DependencyType;
import depends.entity.Entity;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
public class CppExpressionTest extends CppParserTest{
@Before
@ -31,4 +32,13 @@ public class CppExpressionTest extends CppParserTest{
this.assertContainsRelation(e, DependencyType.CONTAIN,"ClassA");
}
@Test
public void test_should_not_count_expr_duplicated() throws IOException {
String src = "./src/test/resources/cpp-code-examples/DupExpressions.cpp";
CppFileParser parser = createParser(src);
parser.parse();
inferer.resolveAllBindings();
Entity e = repo.getEntity("foo");
assertEquals(4,e.getRelations().size());
}
}

View File

@ -1,14 +1,11 @@
package depends.extractor.cpp;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import depends.deptypes.DependencyType;
import depends.entity.Entity;
import depends.relations.Inferer;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
public class MacroRelationTest extends CppParserTest{
@Before
@ -31,7 +28,6 @@ public class MacroRelationTest extends CppParserTest{
Entity e = repo.getEntity("foo");
this.assertContainsRelation(e, DependencyType.RETURN, Inferer.buildInType.getQualifiedName());
this.assertContainsRelation(e, DependencyType.CONTAIN, Inferer.buildInType.getQualifiedName());
this.assertContainsRelation(e, DependencyType.USE, Inferer.buildInType.getQualifiedName());
}

View File

@ -40,7 +40,7 @@ public class RelationInSameFileTest extends CppParserTest{
matchCount++;
}
}
assertEquals(2, matchCount);
assertEquals(1, matchCount);
}

View File

@ -1,19 +1,15 @@
package depends.extractor.cpp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.IOException;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import depends.deptypes.DependencyType;
import depends.entity.Entity;
import depends.entity.FunctionEntityImpl;
import depends.entity.FunctionEntityProto;
import depends.entity.VarEntity;
import depends.relations.Relation;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
public class RelationToImplementationTest extends CppParserTest{
@Before

View File

@ -1,17 +1,16 @@
package depends.extractor.java;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import depends.deptypes.DependencyType;
import depends.entity.ContainerEntity;
import depends.entity.Entity;
import depends.entity.FunctionEntity;
import depends.entity.TypeEntity;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
public class JavaVarResolveTest extends JavaParserTest{
@Before
@ -86,7 +85,7 @@ public class JavaVarResolveTest extends JavaParserTest{
JavaFileParser parser = createParser(src);
parser.parse();
inferer.resolveAllBindings();
assertEquals(13,entityRepo.getEntity("ValidateAll.validate").getRelations().size());
assertEquals(10,entityRepo.getEntity("ValidateAll.validate").getRelations().size());
}
@Test

View File

@ -0,0 +1,11 @@
typedef struct request_rec request_rec;
struct request_rec {
};
void foo(request_rec* r){
if (r->uri[0] != '/') {
return DECLINED;
}
}