add call-as-impl for cpp variables, and also avoid call/cast count relation duplicately

This commit is contained in:
Gang ZHANG 2020-01-08 23:00:37 +08:00
parent 2c61f9a3e2
commit 24ab7cccd7
13 changed files with 135 additions and 22 deletions

View File

@ -188,7 +188,7 @@ public abstract class ContainerEntity extends DecoratedEntity {
expression.setType(entity.getType(), entity, inferer);
continue;
}
if (expression.isCall) {
if (expression.isCall()) {
FunctionEntity func = this.lookupFunctionInVisibleScope(expression.getIdentifier());
if (func != null) {
expression.setType(func.getType(), func, inferer);

View File

@ -40,7 +40,15 @@ public class Expression implements Serializable{
private GenericName identifier; // the varName, or method name, etc.
public boolean isSet = false; // is a set relation from right to leftHand
public boolean isDot = false; // is a dot expression, will decuce variable tfype left to right
public boolean isCall = false;
public boolean isCall() {
return isCall;
}
public void setCall(boolean isCall) {
this.isCall = isCall;
}
private boolean isCall = false;
public boolean isLogic = false;
public boolean isCreate = false;
public boolean isCast = false;
@ -147,7 +155,7 @@ public class Expression implements Serializable{
}
/* if it is a.b, and we already get a's type, b's type could be identified easily */
else if (parent.isDot) {
if (parent.isCall) {
if (parent.isCall()) {
FunctionEntity func = this.getType().lookupFunctionInVisibleScope(parent.identifier);
if (func!=null) {
parent.setType(func.getType(), func,inferer);

View File

@ -150,7 +150,7 @@ abstract public class AbstractLangProcessor {
* @param callAsImpl
* @return unsolved bindings
*/
private void resolveBindings(boolean callAsImpl) {
public void resolveBindings(boolean callAsImpl) {
System.out.println("Resolve types and bindings of variables, methods and expressions....");
this.potentialExternalDependencies = inferer.resolveAllBindings(callAsImpl,this);
if (getExternalDependencies().size() > 0) {

View File

@ -117,7 +117,7 @@ public class CppVisitor extends ASTVisitor {
child.accept(this);
}
return ASTVisitor.PROCESS_SKIP;
// return super.visit(tu);
// return super.visit(tu);
}

View File

@ -52,12 +52,16 @@ public class ExpressionUsage {
/* create expression and link it with parent*/
Expression expression = new Expression(idGenerator.generateId());
context.lastContainer().addExpression(declarator,expression);
expression.isCall = true;
expression.setCall(true);
expression.setIdentifier(functionName);
}
public void foundExpression(IASTExpression ctx) {
Expression parent = findParentInStack(ctx);
//If parent already a call
if (ctx instanceof IASTIdExpression && (parent.isCall() || parent.isCast)) {
return;
}
/* create expression and link it with parent*/
Expression expression = new Expression(idGenerator.generateId());
expression.text = ctx.getRawSignature(); //for debug purpose. no actual effect
@ -71,7 +75,7 @@ public class ExpressionUsage {
}
expression.isSet = isSet(ctx);
expression.isCall = (ctx instanceof IASTFunctionCallExpression)?true:false;
expression.setCall((ctx instanceof IASTFunctionCallExpression)?true:false);
expression.isLogic = isLogic(ctx);
if (ctx instanceof ICPPASTNewExpression){
expression.isCreate = true;
@ -88,11 +92,11 @@ public class ExpressionUsage {
//method call
if (ctx instanceof IASTFunctionCallExpression) {
expression.setIdentifier(getMethodCallIdentifier((IASTFunctionCallExpression)ctx));
expression.isCall = true;
expression.setCall(true);
}
if (ctx instanceof ICPPASTNewExpression) {
expression.setRawType(GenericName.build(ASTStringUtilExt.getTypeIdString(((ICPPASTNewExpression)ctx).getTypeId())));
expression.isCall = true;
expression.setCall(true);
expression.deriveTypeFromChild = false;
}

View File

@ -57,7 +57,7 @@ public class ExpressionUsage {
}
expression.isSet = isSet(ctx);
expression.isCall = ctx.methodCall()==null?false:true;
expression.setCall(ctx.methodCall()==null?false:true);
expression.isLogic = isLogic(ctx);
expression.isDot = isDot(ctx);
if (ctx.creator()!=null ||ctx.innerCreator()!=null){
@ -76,12 +76,12 @@ public class ExpressionUsage {
//method call
if (ctx.methodCall()!=null) {
expression.setIdentifier(getMethodCallIdentifier(ctx.methodCall()));
expression.isCall = true;
expression.setCall(true);
}
//new
if (ctx.NEW()!=null && ctx.creator()!=null) {
expression.setRawType(CreatorContextHelper.getCreatorType(ctx.creator()));
expression.isCall = true;
expression.setCall(true);
expression.deriveTypeFromChild = false;
}

View File

@ -86,15 +86,15 @@ public class ExpressionUsage {
Entity prefixEntity = context.foundEntityWithName(preFix);
if (prefixEntity instanceof VarEntity) {
((VarEntity) prefixEntity).addFunctionCall(functionName);
expression.isCall = true;
expression.setCall(true);
}
}
if (!expression.isCall) {
if (!expression.isCall()) {
Entity typeEntity = context.foundEntityWithName(expression.getIdentifier());
if (typeEntity instanceof TypeEntity && typeEntity.getId() > 0) {
expression.isCreate = true;
} else {
expression.isCall = true;
expression.setCall(true);
}
}
} else if (expr.member_access() != null) {

View File

@ -108,7 +108,7 @@ public class ExpressionUsage {
expression.isSet = true;
} else if (helper.isFunctionCall(ctx)) {
String name = helper.getName(ctx);
expression.isCall = true;
expression.setCall(true);
if (name.equals("new")) {
expression.isCreate = true;
List<Node> childNodes = ctx.childNodes();

View File

@ -130,7 +130,8 @@ public class RelationCounter {
return;
}
boolean matched = false;
if (expression.isCall) {
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) {
@ -143,10 +144,8 @@ public class RelationCounter {
}
}
}
if (!matched) {
entity.addRelation(buildRelation(DependencyType.CALL,referredEntity));
matched = true;
}
entity.addRelation(buildRelation(DependencyType.CALL,referredEntity));
matched = true;
}
if (expression.isCreate) {
@ -162,7 +161,16 @@ public class RelationCounter {
matched = true;
}
if (!matched) {
entity.addRelation(buildRelation(DependencyType.USE,referredEntity));
if (callAsImpl && repo.getEntity(referredEntity.getQualifiedName()) instanceof MultiDeclareEntities) {
MultiDeclareEntities m = (MultiDeclareEntities)(repo.getEntity(referredEntity.getQualifiedName()));
for (Entity e:m.getEntities()) {
entity.addRelation(buildRelation(DependencyType.USE,e));
matched = true;
}
}
else {
entity.addRelation(buildRelation(DependencyType.USE,referredEntity));
}
}
}

View File

@ -0,0 +1,73 @@
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;
public class RelationToImplementationTest extends CppParserTest{
@Before
public void setUp() {
super.init();
}
@Test
public void should_convert_call_relation_to_impl() throws IOException {
String[] srcs = new String[] {
"./src/test/resources/cpp-code-examples/relation_to_impl/A.h",
"./src/test/resources/cpp-code-examples/relation_to_impl/B.c",
"./src/test/resources/cpp-code-examples/relation_to_impl/A.c",
};
for (String src:srcs) {
CppFileParser parser = createParser(src);
parser.parse();
}
inferer.resolveAllBindings(true,null);
Entity bar = repo.getEntity("bar");
int matchCount = 0;
for (Relation relation:bar.getRelations()) {
if (relation.getEntity() instanceof FunctionEntityProto) {
matchCount++;
}
if (relation.getEntity() instanceof FunctionEntityImpl) {
matchCount++;
}
}
assertEquals(2, matchCount);
}
@Test
public void should_convert_var_relation_to_impl() throws IOException {
String[] srcs = new String[] {
"./src/test/resources/cpp-code-examples/relation_to_impl/A.h",
"./src/test/resources/cpp-code-examples/relation_to_impl/B.c",
"./src/test/resources/cpp-code-examples/relation_to_impl/A.c",
};
for (String src:srcs) {
CppFileParser parser = createParser(src);
parser.parse();
}
inferer.resolveAllBindings(true,null);
Entity bar = repo.getEntity("baz");
int matchCount = 0;
for (Relation relation:bar.getRelations()) {
if (relation.getEntity() instanceof VarEntity) {
matchCount++;
}
}
assertEquals(2, matchCount);
}
}

View File

@ -0,0 +1,5 @@
#include "A.h"
int x;
void foo()
{
}

View File

@ -0,0 +1,7 @@
#ifndef A_H
#define A_H
void foo();
extern int x;
#endif

View File

@ -0,0 +1,8 @@
#include "A.h"
void bar(){
foo();
}
void baz(){
x++;
}