refactory: adjust expression resolve strategy

This commit is contained in:
Gang ZHANG 2020-04-27 08:15:08 +08:00
parent 2cf795860d
commit a778caf06c
29 changed files with 305 additions and 210 deletions

View File

@ -167,11 +167,6 @@ public class CandidateTypes extends TypeEntity {
super.resolveExpressions(inferer);
}
@Override
public TypeEntity getLastExpressionType() {
System.err.println("error: getLastExpressionType should not been invoked");
return super.getLastExpressionType();
}
@Override
public void addMixin(GenericName moduleName) {

View File

@ -116,6 +116,7 @@ public abstract class ContainerEntity extends DecoratedEntity {
public void addExpression(Object key, Expression expression) {
expressions().put(key, expression);
expressionList().add(expression);
expressionCount = expressionList.size();
}
public boolean containsExpression(Object key) {
@ -133,10 +134,12 @@ public abstract class ContainerEntity extends DecoratedEntity {
for (FunctionEntity func : this.getFunctions()) {
func.inferLocalLevelEntities(inferer);
}
resolvedMixins = identiferToContainerEntity(inferer, getMixins());
if (inferer.isEagerExpressionResolve()) {
this.resolveExpressions(inferer);
reloadExpression(inferer.getRepo());
resolveExpressions(inferer);
cacheExpressions();
}
resolvedMixins = identiferToContainerEntity(inferer, getMixins());
}
private Collection<GenericName> getMixins() {
@ -165,13 +168,18 @@ public abstract class ContainerEntity extends DecoratedEntity {
* @param inferer
*/
public void resolveExpressions(Inferer inferer) {
if (this instanceof FunctionEntity) {
((FunctionEntity)this).linkReturnToLastExpression();
}
if (expressionList==null) return;
if(expressionList.size()>10000) return;
for (Expression expression : expressionList) {
// 1. if expression's type existed, break;
if (expression.getType() != null)
continue;
if (expression.isDot) { // wait for previous
if (expression.isDot()) { // wait for previous
continue;
}
if (expression.getRawType() == null && expression.getIdentifier() == null)
@ -190,7 +198,7 @@ public abstract class ContainerEntity extends DecoratedEntity {
String composedName = expression.getIdentifier().toString();
Expression theExpr = expression;
if (entity==null) {
while(theExpr.getParent()!=null && theExpr.getParent().isDot) {
while(theExpr.getParent()!=null && theExpr.getParent().isDot()) {
theExpr = theExpr.getParent();
if (theExpr.getIdentifier()==null) break;
composedName = composedName + "." + theExpr.getIdentifier().toString();
@ -251,7 +259,6 @@ public abstract class ContainerEntity extends DecoratedEntity {
}
private void cacheExpressionListToFile() {
expressionCount = this.expressionList.size();
if (expressionCount ==0) return;
try {
FileOutputStream fileOut = new FileOutputStream(TemporaryFile.getInstance().exprPath(this.id));
@ -284,15 +291,6 @@ public abstract class ContainerEntity extends DecoratedEntity {
}
}
public TypeEntity getLastExpressionType() {
if (expressionList==null) return null;
for (int i = this.expressionList.size() - 1; i >= 0; i--) {
Expression expr = this.expressionList.get(i);
if (expr.isStatement)
return expr.getType();
}
return null;
}
public List<Expression> expressionList() {
if (expressionList==null)
@ -303,17 +301,6 @@ public abstract class ContainerEntity extends DecoratedEntity {
public boolean containsExpression() {
return expressions().size() > 0;
}
public String dumpExpressions() {
if (expressionList==null) return "";
StringBuilder sb = new StringBuilder();
for (Expression exp : expressionList) {
sb.append(exp.toString()).append("\n");
}
return sb.toString();
}
/**
* The entry point of lookup functions. It will treat multi-declare entities and

View File

@ -110,6 +110,7 @@ public abstract class Entity {
public void addRelation(Relation relation) {
if (relations==null)
relations = new ArrayList<>();
if (relation.getEntity()==null) return;
relations.add(relation);
}

View File

@ -28,59 +28,104 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import depends.entity.repo.EntityRepo;
import depends.relations.Inferer;
/**
* Expression
*/
public class Expression implements Serializable{
private static final long serialVersionUID = 1L;
public Integer id;
public String text; // for debug purpose
private GenericName rawType; //the raw type name
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() {
return isCall;
}
public void setCall(boolean isCall) {
this.isCall = isCall;
}
private String text; // for debug purpose
private GenericName rawType; // the raw type name
private GenericName identifier; // the varName, or method name, etc.
private boolean isSet = false; // is a set relation from right to leftHand
private boolean isDot = false; // is a dot expression, will decuce variable tfype left to right
private boolean isCall = false;
public boolean isLogic = false;
public boolean isCreate = false;
public boolean isCast = false;
public boolean isThrow = false;
public 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
public boolean deriveTypeFromChild = true;
public Integer deduceTypeBasedId; //by default, parent expression type determined by most left child
private boolean isLogic = false;
private boolean isCreate = false;
private boolean isCast = false;
private boolean isThrow = false;
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;
private List<Integer> deducedTypeVarsId = new ArrayList<>();
private List<Integer> deducedTypeFunctionsId = new ArrayList<>();
private transient Expression parent;
private transient TypeEntity type; // the type we care - for relation calculation.
//for leaf, it equals to referredEntity.getType. otherwise, depends on child's type strategy
private transient Entity referredEntity;
private transient List<VarEntity> deducedTypeVars = new ArrayList<>();
private List<Integer> deducedTypeVarsId = new ArrayList<>();
private transient List<FunctionEntity> deducedTypeFunctions= new ArrayList<>();
public TypeEntity getType() {
return type;
private List<Integer> deducedTypeFunctionsId = new ArrayList<>();
private Integer referredEntityId;
private transient Entity referredEntity;
private transient TypeEntity type; // the type we care - for relation calculation.
//for leaf, it equals to referredEntity.getType. otherwise, depends on child's type strategy
/*
* */
public Expression() {
deducedTypeVars = new ArrayList<>();
deducedTypeFunctions = new ArrayList<>();
}
public Expression(Integer id) {
this.id = id;
deducedTypeVars = new ArrayList<>();
deducedTypeFunctions = new ArrayList<>();
}
public void setType(TypeEntity type, Entity referredEntity, Inferer inferer) {
if (this.referredEntity==null && referredEntity!=null) {
this.referredEntity = referredEntity;
public void reload(EntityRepo repo, ArrayList<Expression> expressionList) {
this.deducedTypeFunctions = new ArrayList<>();
this.deducedTypeVars = new ArrayList<>();
//recover parent relation
if (parentId!=-1) {
for (Expression expr:expressionList) {
if (expr.id==parentId) {
parent = expr;
break;
}
}
}
if (type instanceof CandidateTypes) {
return ;
//recover deducedTypeFunctionsId
if (deducedTypeFunctionsId!=null) {
for (Integer funcId:this.deducedTypeFunctionsId) {
this.deducedTypeFunctions.add((FunctionEntity) repo.getEntity(funcId));
}
}
//recover deducedTypeVars
if (deducedTypeVarsId!=null) {
for (Integer varId:this.deducedTypeVarsId) {
this.deducedTypeVars.add((VarEntity) repo.getEntity(varId));
}
}
//referer referredEntity -- TODO:maybe not require
if (this.referredEntityId!=null && this.referredEntity==null)
this.referredEntity = repo.getEntity(this.referredEntityId);
}
/**
* Set type of the expression
* @param type
* @param referredEntity
* @param inferer
*/
public void setType(TypeEntity type, Entity referredEntity, Inferer inferer) {
if (this.getReferredEntity()==null && referredEntity!=null) {
this.setReferredEntity(referredEntity);
}
boolean changedType = false;
if (this.type==null && type!=null) {
this.type = type;
@ -97,38 +142,12 @@ public class Expression implements Serializable{
changedType = true;
}
if (this.referredEntity==null)
this.referredEntity = this.type;
this.setReferredEntity(this.type);
if (changedType)
deduceTheParentType(inferer);
}
public Expression() {
deducedTypeVars = new ArrayList<>();
deducedTypeFunctions = new ArrayList<>();
}
public Expression(Integer id) {
this.id = id;
deducedTypeVars = new ArrayList<>();
deducedTypeFunctions = new ArrayList<>();
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append("[").append(text).append("]").append("|")
.append("rawType:").append(rawType).append("|")
.append("identifier:").append(identifier).append("|")
.append("prop:").append(isDot?"[dot]":"")
.append(isSet?"[set]":"")
.append(isLogic?"[bool]":"")
.append(isCall?"[call]":"").append("|")
.append(isCreate?"[new]":"").append("|")
.append(isThrow?"[throw]":"").append("|")
.append("parent:").append(parent==null?"nil":parent.text).append("|")
.append("type:").append(type).append("|");
return s.toString();
}
/**
* deduce type of parent based on child's type
@ -183,19 +202,16 @@ public class Expression implements Serializable{
else {
parent.setType(type, null, inferer);
}
if (parent.referredEntity==null)
parent.referredEntity = parent.type;
if (parent.getReferredEntity()==null)
parent.setReferredEntity(parent.type);
}
private void setReferredEntity(Entity referredEntity) {
this.referredEntity = referredEntity;
if (this.referredEntity!=null)
this.referredEntityId = referredEntity.getId();
}
public Entity getReferredEntity() {
return referredEntity;
}
public void addDeducedTypeVar(VarEntity var) {
this.deducedTypeVars.add(var);
this.deducedTypeVarsId.add(var.getId());
@ -219,30 +235,6 @@ public class Expression implements Serializable{
}
}
public void reload(EntityRepo repo, ArrayList<Expression> expressionList) {
this.deducedTypeFunctions = new ArrayList<>();
this.deducedTypeVars = new ArrayList<>();
if (parentId!=-1) {
for (Expression expr:expressionList) {
if (expr.id==parentId) {
parent = expr;
break;
}
}
}
if (deducedTypeFunctionsId!=null) {
for (Integer funcId:this.deducedTypeFunctionsId) {
this.deducedTypeFunctions.add((FunctionEntity) repo.getEntity(funcId));
}
}
if (deducedTypeVarsId!=null) {
for (Integer varId:this.deducedTypeVarsId) {
this.deducedTypeVars.add((VarEntity) repo.getEntity(varId));
}
}
}
public GenericName getIdentifier() {
return this.identifier;
@ -259,17 +251,6 @@ public class Expression implements Serializable{
this.identifier = GenericName.build(name);
}
private boolean validName(String name) {
if (name==null) return false;
if (name.toLowerCase().equals("<literal>")) return true;
if (name.toLowerCase().equals("<built-in>")) return true;
boolean result = name.matches("([a-zA-Z0-9_]|(\\.)|(\\-))*");
// if (result==false) {
// System.err.println("expression name " + name);
// }
return true;
}
public void setIdentifier(GenericName name) {
if (name==null) return;
if (!validName(name.getName())){
@ -298,6 +279,110 @@ public class Expression implements Serializable{
public Expression getParent() {
return this.parent;
}
public void setText(String text) {
this.text = text;
}
public boolean isCall() {
return isCall;
}
public boolean isSet() {
return isSet;
}
public void setSet(boolean isSet) {
this.isSet = isSet;
}
public boolean isDot() {
return isDot;
}
public void setDot(boolean isDot) {
this.isDot = isDot;
}
public boolean isLogic() {
return isLogic;
}
public void setLogic(boolean isLogic) {
this.isLogic = isLogic;
}
public boolean isCreate() {
return isCreate;
}
public void setCreate(boolean isCreate) {
this.isCreate = isCreate;
}
public boolean isCast() {
return isCast;
}
public void setCast(boolean isCast) {
this.isCast = isCast;
}
public boolean isThrow() {
return isThrow;
}
public void setThrow(boolean isThrow) {
this.isThrow = isThrow;
}
public boolean isStatement() {
return isStatement;
}
public void setStatement(boolean isStatement) {
this.isStatement = isStatement;
}
public void setCall(boolean isCall) {
this.isCall = isCall;
}
public void disableDriveTypeFromChild() {
deriveTypeFromChild = false ;
}
public Entity getReferredEntity() {
return referredEntity;
}
public TypeEntity getType() {
return type;
}
private boolean validName(String name) {
if (name==null) return false;
if (name.toLowerCase().equals("<literal>")) return true;
if (name.toLowerCase().equals("<built-in>")) return true;
return true;
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append("[").append(text).append("]").append("|")
.append("rawType:").append(rawType).append("|")
.append("identifier:").append(identifier).append("|")
.append("prop:").append(isDot?"[dot]":"")
.append(isSet?"[set]":"")
.append(isLogic?"[bool]":"")
.append(isCall?"[call]":"")
.append(isCreate?"[new]":"")
.append(isThrow?"[throw]":"").append("|")
.append("parent:").append(parent==null?"nil":parent.text).append("|")
.append("type:").append(type).append("|");
return s.toString();
}
}

View File

@ -94,9 +94,6 @@ public class FunctionEntity extends ContainerEntity{
if (throwTypes.size()<throwTypesIdentifiers.size())
throwTypes = identiferToEntities(inferer,this.throwTypesIdentifiers);
super.inferLocalLevelEntities(inferer);
if (this.returnTypes.size()==0 && this.getLastExpressionType()!=null) {
this.returnTypes.add(this.getLastExpressionType());
}
}
@ -140,6 +137,13 @@ public class FunctionEntity extends ContainerEntity{
}
return super.lookupVarLocally(varName);
}
public void linkReturnToLastExpression() {
if (expressionList()==null) return;
for (int i = expressionList().size() - 1; i >= 0; i--) {
Expression expr = expressionList().get(i);
if (expr.isStatement())
expr.addDeducedTypeFunction(this);
}
}
}

View File

@ -62,11 +62,12 @@ public abstract class HandlerContext {
currentFileEntity = new FileEntity(fileName, idGenerator.generateId(),true);
pushToStack(currentFileEntity);
entityRepo.add(currentFileEntity);
entityRepo.addFile(currentFileEntity);
return currentFileEntity;
}
public void done() {
entityRepo.addFile(this.currentFile());
}
public TypeEntity foundNewType(GenericName name) {
TypeEntity currentTypeEntity = new TypeEntity(name, this.latestValidContainer(),

View File

@ -70,9 +70,6 @@ public class CppHandlerContext extends HandlerContext {
return functionEntity;
}
public void doneFile(FileEntity currentFile) {
entityRepo.addFile(currentFileEntity);
}
@Override
public FileEntity startFile(String fileName) {

View File

@ -90,6 +90,7 @@ public class CdtCppFileParser extends CppFileParser {
tu.accept(bridge);
fileEntity = entityRepo.getEntity(fileFullPath);
((FileEntity)fileEntity).cacheAllExpressions();
bridge.done();
return;
}

View File

@ -98,8 +98,6 @@ public class CppVisitor extends ASTVisitor {
@Override
public int visit(IASTTranslationUnit tu) {
context.doneFile(context.currentFile());
for (String incl:preprocessorHandler.getDirectIncludedFiles(tu.getAllPreprocessorStatements(),context.currentFile().getQualifiedName())) {
context.foundNewImport(new FileImport(incl));
}
@ -372,4 +370,8 @@ public class CppVisitor extends ASTVisitor {
}
return super.visit(parameterDeclaration);
}
public void done() {
context.done();
}
}

View File

@ -60,13 +60,13 @@ public class ExpressionUsage {
Expression parent = findParentInStack(ctx);
//If parent already a call
if (parent!=null ) {
if (ctx instanceof IASTIdExpression && (parent.isCall() || parent.isCast)) {
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
expression.setText( ctx.getRawSignature());
context.lastContainer().addExpression(ctx,expression);
expression.setParent(parent);
@ -76,13 +76,13 @@ public class ExpressionUsage {
return;
}
expression.isSet = isSet(ctx);
expression.setSet(isSet(ctx));
expression.setCall((ctx instanceof IASTFunctionCallExpression)?true:false);
expression.isLogic = isLogic(ctx);
expression.setLogic(isLogic(ctx));
if (ctx instanceof ICPPASTNewExpression){
expression.isCreate = true;
expression.setCreate(true);;
}
expression.isDot = isDot(ctx);
expression.setDot(isDot(ctx));
/**
* | expression bop='.'
@ -99,16 +99,16 @@ public class ExpressionUsage {
if (ctx instanceof ICPPASTNewExpression) {
expression.setRawType(GenericName.build(ASTStringUtilExt.getTypeIdString(((ICPPASTNewExpression)ctx).getTypeId())));
expression.setCall(true);
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
if (ctx instanceof IASTCastExpression) {
expression.isCast=true;
expression.setCast(true);
expression.setRawType(GenericName.build(ASTStringUtilExt.getTypeIdString(((IASTCastExpression)ctx).getTypeId())));
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
if (expression.isDot) {
if (expression.isDot()) {
IASTExpression op2 = ((IASTBinaryExpression)ctx).getOperand2();
if (op2 instanceof IASTIdExpression)
expression.setIdentifier(ASTStringUtilExt.getName(((IASTIdExpression)op2).getName()));

View File

@ -69,6 +69,7 @@ public class JavaFileParser implements depends.extractor.FileParser{
Entity fileEntity = entityRepo.getEntity(fileFullPath);
((FileEntity)fileEntity).cacheAllExpressions();
interpreter.clearDFA();
bridge.done();
}catch (Exception e) {
System.err.println("error encountered during parse..." );

View File

@ -361,6 +361,9 @@ public class JavaListener extends JavaParserBaseListener {
context.currentType().addTypeParameter(GenericName.build(typeParam.IDENTIFIER().getText()));
}
}
public void done() {
context.done();
}
}

View File

@ -56,12 +56,12 @@ public class ExpressionUsage {
return;
}
expression.isSet = isSet(ctx);
expression.setSet (isSet(ctx));
expression.setCall(ctx.methodCall()==null?false:true);
expression.isLogic = isLogic(ctx);
expression.isDot = isDot(ctx);
expression.setLogic (isLogic(ctx));
expression.setDot(isDot(ctx));
if (ctx.creator()!=null ||ctx.innerCreator()!=null){
expression.isCreate = true;
expression.setCreate( true);
}
/**
* | expression bop='.'
@ -82,26 +82,26 @@ public class ExpressionUsage {
if (ctx.NEW()!=null && ctx.creator()!=null) {
expression.setRawType(CreatorContextHelper.getCreatorType(ctx.creator()));
expression.setCall(true);
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
if (ctx.typeCast()!=null) {
expression.isCast=true;
expression.setCast(true);
expression.setRawType(ctx.typeCast().typeType().getText());
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
if (ctx.bop!=null && ctx.bop.getText().equals("instanceof")) {
expression.isCast=true;
expression.setCast(true);
expression.setRawType(ctx.typeType().getText());
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
if (ctx.creator()!=null) {
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
if (expression.isDot) {
if (expression.isDot()) {
if (ctx.IDENTIFIER()!=null)
expression.setIdentifier(ctx.IDENTIFIER().getText());
else if (ctx.methodCall()!=null)

View File

@ -74,7 +74,7 @@ public class PomFileParser implements FileParser {
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(bridge, parser.document());
fileEntity = entityRepo.getEntity(fileFullPath);
// fileEntity.inferEntities(inferer);
bridge.done();
((FileEntity)fileEntity).cacheAllExpressions();
}

View File

@ -164,5 +164,8 @@ public class PomListener extends XMLParserBaseListener {
return name;
}
public void done() {
context.done();
}
}

View File

@ -82,7 +82,7 @@ public class ExpressionUsage {
}else {
/* create expression and link it with parent*/
expression = new Expression(idGenerator.generateId());
expression.text = ctx.getText();
expression.setText(ctx.getText());
context.lastContainer().addExpression(ctx,expression);
expression.setParent(parent);
}
@ -91,7 +91,7 @@ public class ExpressionUsage {
if (ctx instanceof Expr_stmtContext) {
Expr_stmtContext exprAssign = (Expr_stmtContext)ctx;
if (exprAssign.assign_part()!=null) {
expression.isSet = true;
expression.setSet(true);
expression.setIdentifier(exprAssign.testlist_star_expr().getText());
if (isValidIdentifier(expression.getIdentifier())) {
makeSureVarExist(expression.getIdentifier());
@ -100,8 +100,7 @@ public class ExpressionUsage {
}
}
if (ctx instanceof Raise_stmtContext) {
expression.isThrow = true;
expression.deriveTypeFromChild = true;
expression.setThrow (true);
}
if (ctx instanceof Return_stmtContext) {
deduceReturnTypeInCaseOfReturn((Return_stmtContext)ctx,expression);
@ -141,7 +140,7 @@ public class ExpressionUsage {
//atom
Expression atomExpr = new Expression(idGenerator.generateId());
atomExpr.setParent(expression);
atomExpr.text = exprCtx.atom().getText();
atomExpr.setText(exprCtx.atom().getText());
atomExpr.setIdentifier(exprCtx.atom().getText());
context.lastContainer().addExpression(exprCtx.atom(),atomExpr);
processAtom(exprCtx.atom(),atomExpr);
@ -152,12 +151,12 @@ public class ExpressionUsage {
for (TrailerContext trailer:exprCtx.trailer()) {
if (trailer.name()!=null) {
Expression trailerExpr = new Expression(idGenerator.generateId());
trailerExpr.text = trailer.getText();
trailerExpr.setText(trailer.getText());
context.lastContainer().addExpression(trailer,trailerExpr);
trailerExpr.setParent(expression);
//doted name = member access or method call
trailerExpr.isDot = true;
trailerExpr.setDot(true);;
trailerExpr.setIdentifier(trailer.name().getText());
if (trailer.arguments()!=null) {
if (trailer.arguments().OPEN_PAREN()!=null) {
@ -218,7 +217,7 @@ public class ExpressionUsage {
}
Entity typeEntity = context.foundEntityWithName(funcName);
if (typeEntity instanceof TypeEntity && typeEntity.getId() > 0) {
theExpression.isCreate = true;
theExpression.setCreate(true);
theExpression.setType(typeEntity.getType(), typeEntity, inferer);
theExpression.setRawType(typeEntity.getRawName());
return;
@ -232,7 +231,7 @@ public class ExpressionUsage {
GenericName funcName = theExpression.getIdentifier();
Entity typeEntity = context.foundEntityWithName(funcName);
if (typeEntity instanceof TypeEntity && typeEntity.getId() > 0) {
theExpression.getParent().isCreate = true;
theExpression.getParent().setCreate(true);
theExpression.setType(typeEntity.getType(), typeEntity, inferer);
theExpression.getParent().setRawType(typeEntity.getRawName());
return;

View File

@ -384,5 +384,7 @@ public class PythonCodeListener extends PythonParserBaseListener{
expressionUsage.stopExpr();
super.exitAssert_stmt(ctx);
}
public void done() {
context.done();
}
}

View File

@ -50,10 +50,9 @@ public class PythonFileParser implements FileParser {
PythonCodeListener bridge = new PythonCodeListener(fileFullPath, entityRepo,inferer, includeFileLocator, processor);
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(bridge, parser.file_input());
fileEntity = entityRepo.getEntity(fileFullPath);
fileEntity.inferEntities(inferer);
((FileEntity)fileEntity).cacheAllExpressions();
bridge.done();
}
}

View File

@ -81,10 +81,10 @@ public class ExpressionUsage {
Expression parent = findParentInStack(ctx);
/* create expression and link it with parent */
expression = new Expression(idGenerator.generateId());
expression.text = ctx.toString();
expression.setText(ctx.toString());
expression.setParent(parent);
if (ctx instanceof NewlineNode) {
expression.isStatement = true;
expression.setStatement(true);
}
context.lastContainer().addExpression(ctx, expression);
@ -105,12 +105,12 @@ public class ExpressionUsage {
expression.setIdentifier(helper.getName(ctx));
}
if (ctx instanceof AssignableNode) {
expression.isSet = true;
expression.setSet(true);
} else if (helper.isFunctionCall(ctx)) {
String name = helper.getName(ctx);
expression.setCall(true);
if (name.equals("new")) {
expression.isCreate = true;
expression.setCreate(true);
List<Node> childNodes = ctx.childNodes();
if (childNodes.size() > 0) {
expression.setIdentifier(helper.getName(ctx.childNodes().get(0)));
@ -118,10 +118,9 @@ public class ExpressionUsage {
expression.setIdentifier(context.currentType().getRawName());
}
expression.setRawType(expression.getIdentifier());
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
} else if (name.equals("raise")) {
expression.isThrow = true;
expression.deriveTypeFromChild = true;
expression.setThrow (true);
} else if (helper.isArithMeticOperator(name)) {
expression.setIdentifier("<operator>");
expression.setRawType(Inferer.buildInType.getQualifiedName());
@ -129,11 +128,11 @@ public class ExpressionUsage {
expression.setIdentifier(name);
expression.setRawType(helper.getReciever(ctx));
if (expression.getRawType() != null) {
expression.isDot = true;
expression.setDot(true);
}
if (ctx instanceof VCallNode || ctx instanceof FCallNode) {
expression.deriveTypeFromChild = false;
expression.disableDriveTypeFromChild();
}
}
}

View File

@ -31,6 +31,7 @@ import java.util.concurrent.ExecutorService;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.jrubyparser.CompatVersion;
import org.jrubyparser.NodeVisitor;
import org.jrubyparser.Parser;
import org.jrubyparser.ast.Node;
import org.jrubyparser.parser.ParserConfiguration;
@ -79,10 +80,11 @@ public class JRubyFileParser implements FileParser {
ParserConfiguration config = new ParserConfiguration(0, version);
try {
Node node = rubyParser.parse("<code>", in, config);
node.accept(new JRubyVisitor(fileFullPath, entityRepo, includesFileLocator,executor,inferer,parserCreator));
JRubyVisitor parser = new JRubyVisitor(fileFullPath, entityRepo, includesFileLocator,executor,inferer,parserCreator);
node.accept(parser);
fileEntity = entityRepo.getEntity(fileFullPath);
fileEntity.inferEntities(inferer);
((FileEntity)fileEntity).cacheAllExpressions();
parser.done();
}catch(Exception e) {
System.err.println("parsing error in "+fileFullPath);
}

View File

@ -307,4 +307,8 @@ public class JRubyVisitor extends NoopVisitor {
expressionUsage.foundExpression(node);
return super.visit(node);
}
public void done() {
context.done();
}
}

View File

@ -342,5 +342,9 @@ public class Inferer {
this.isCollectUnsolvedBindings = isCollectUnsolvedBindings;
}
public EntityRepo getRepo() {
return repo;
}
}

View File

@ -86,8 +86,6 @@ public class RelationCounter {
private void computeContainerRelations(ContainerEntity entity) {
entity.reloadExpression(repo);
entity.resolveExpressions(inferer);
for (VarEntity var:entity.getVars()) {
if (var.getType()!=null)
entity.addRelation(buildRelation(DependencyType.CONTAIN,var.getType()));
@ -105,15 +103,18 @@ public class RelationCounter {
entity.addRelation(buildRelation(DependencyType.MIXIN,mixin));
}
entity.reloadExpression(repo);
if (!inferer.isEagerExpressionResolve())
{
entity.resolveExpressions(inferer);
}
for (Expression expression:entity.expressionList()){
if (expression.isStatement) {
if (expression.isStatement()) {
continue;
}
Entity referredEntity = expression.getReferredEntity();
addRelationFromExpression(entity, expression, referredEntity);
}
entity.clearExpressions();
}
@ -148,15 +149,15 @@ public class RelationCounter {
matched = true;
}
if (expression.isCreate) {
if (expression.isCreate()) {
entity.addRelation(buildRelation(DependencyType.CREATE,referredEntity));
matched = true;
}
if (expression.isThrow) {
if (expression.isThrow()) {
entity.addRelation(buildRelation(DependencyType.THROW,referredEntity));
matched = true;
}
if (expression.isCast) {
if (expression.isCast()) {
entity.addRelation(buildRelation(DependencyType.CAST,referredEntity));
matched = true;
}

View File

@ -27,6 +27,7 @@ public abstract class ParserTest {
for (Relation r:inEntity.getRelations()) {
if (r.getType().equals(dependencyType)) {
relation = r;
if (r.getEntity()==null) continue;
if (r.getEntity().getQualifiedName().equals(dependedEntityFullName))
return;
}

View File

@ -20,7 +20,7 @@ public class DuplicateDeclarationTest extends CppParserTest {
public void duplication_declaration_should_be_resolved() throws IOException {
String[] srcs = new String[] {
" ",
"./src/test/resources/cpp-code-examples/DuplicationDeclarationCouldBeResolved.cpp",
};
for (String src:srcs) {

View File

@ -6,7 +6,9 @@ import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import depends.deptypes.DependencyType;
import depends.entity.Entity;
import depends.relations.Inferer;
public class UsingTest extends CppParserTest{
@Before
@ -26,7 +28,10 @@ public class UsingTest extends CppParserTest{
}
inferer.resolveAllBindings();
Entity e = repo.getEntity("foo");
assertEquals(4,e.getRelations().size());
this.assertContainsRelation(e, DependencyType.RETURN, Inferer.buildInType.getQualifiedName());
this.assertContainsRelation(e, DependencyType.CONTAIN, "A.C");
this.assertContainsRelation(e, DependencyType.CONTAIN, "B.X");
}
@Test
@ -41,6 +46,8 @@ public class UsingTest extends CppParserTest{
}
inferer.resolveAllBindings();
Entity e = repo.getEntity("bar");
assertEquals(4,e.getRelations().size());
this.assertContainsRelation(e, DependencyType.RETURN, Inferer.buildInType.getQualifiedName());
this.assertContainsRelation(e, DependencyType.CONTAIN, "A.C");
this.assertContainsRelation(e, DependencyType.CONTAIN, "B.X");
}
}

View File

@ -86,7 +86,7 @@ public class JavaVarResolveTest extends JavaParserTest{
JavaFileParser parser = createParser(src);
parser.parse();
inferer.resolveAllBindings();
assertEquals(16,entityRepo.getEntity("ValidateAll.validate").getRelations().size());
assertEquals(13,entityRepo.getEntity("ValidateAll.validate").getRelations().size());
}
@Test

View File

@ -218,9 +218,9 @@ public class PythonImportTest extends PythonParserTest {
}
inferer.resolveAllBindings();
FunctionEntity func = (FunctionEntity)repo.getEntity(withPackageName(srcs[0],"in_the_forest"));
this.assertContainsRelation(func, DependencyType.CALL, withPackageName(srcs[1],"Duck.quack"));
this.assertContainsRelation(func, DependencyType.CALL, withPackageName(srcs[1],"Bird.quack"));
this.assertContainsRelation(func, DependencyType.CALL, withPackageName(srcs[1],"Doge.quack"));
this.assertContainsRelation(func, DependencyType.CALL, withPackageName(srcs[1],"Bird.quack"));
this.assertContainsRelation(func, DependencyType.CALL, withPackageName(srcs[1],"Duck.quack"));
}
@Test

View File

@ -30,9 +30,6 @@ public class RubyReturnTypeDedudceTest extends RubyParserTest {
function = (FunctionEntity)(entityRepo.getEntity("Class.implicitReturn"));
this.assertContainReturnType(function,"Class1");
}
}