add call-as-impl for cpp variables, and also avoid call/cast count relation duplicately
This commit is contained in:
parent
2c61f9a3e2
commit
24ab7cccd7
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
if (expression.isCreate) {
|
||||
|
@ -162,9 +161,18 @@ public class RelationCounter {
|
|||
matched = true;
|
||||
}
|
||||
if (!matched) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Relation buildRelation(String type, Entity referredEntity) {
|
||||
if (this.langProcessor==null)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#include "A.h"
|
||||
int x;
|
||||
void foo()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef A_H
|
||||
#define A_H
|
||||
|
||||
void foo();
|
||||
extern int x;
|
||||
#endif
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#include "A.h"
|
||||
void bar(){
|
||||
foo();
|
||||
}
|
||||
|
||||
void baz(){
|
||||
x++;
|
||||
}
|
Loading…
Reference in New Issue