You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ExpressionUsage.java 9.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. package depends.extractor.python.union;
  2. import depends.entity.*;
  3. import depends.entity.repo.IdGenerator;
  4. import depends.extractor.HandlerContext;
  5. import depends.extractor.python.PythonHandlerContext;
  6. import depends.extractor.python.PythonParser.*;
  7. import depends.extractor.python.PythonParserBaseVisitor;
  8. import depends.relations.IBindingResolver;
  9. import org.antlr.v4.runtime.ParserRuleContext;
  10. import org.antlr.v4.runtime.RuleContext;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import java.util.regex.Matcher;
  14. import java.util.regex.Pattern;
  15. public class ExpressionUsage {
  16. HandlerContext context;
  17. IdGenerator idGenerator;
  18. private boolean exprStarted=false;
  19. private IBindingResolver bindingResolver;
  20. public ExpressionUsage(PythonHandlerContext context, IdGenerator idGenerator, IBindingResolver bindingResolver) {
  21. this.context = context;
  22. this.idGenerator = idGenerator;
  23. this.bindingResolver = bindingResolver;
  24. }
  25. /**
  26. * Auto deduce variable type from assignment. for example: c = new C() then c is
  27. * type of C
  28. *
  29. */
  30. private void deduceVarTypeInCaseOfAssignment(Expr_stmtContext expr, Expression expression) {
  31. List<String> names = getName(expr.testlist_star_expr());
  32. // TODO: should handle list properly;
  33. String varName = null;
  34. if (names.size() == 1)
  35. varName = names.get(0);
  36. if (varName == null)
  37. return;
  38. VarEntity var = context.lastContainer().lookupVarLocally(varName);
  39. if (var != null) {
  40. expression.addDeducedTypeVar(var);
  41. }
  42. }
  43. private List<String> getName(Testlist_star_exprContext testlist_star_expr) {
  44. List<String> names = new ArrayList<>();
  45. testlist_star_expr.accept(new NameCollector(names));
  46. return names;
  47. }
  48. public void foundExpression(ParserRuleContext ctx) {
  49. if (!isStartOfContainerRule(ctx)) {
  50. return ;
  51. }
  52. if (context.lastContainer().containsExpression(ctx)) return;
  53. if (ctx.getParent() instanceof TrailerContext) return;
  54. Expression parent = findParentInStack(ctx);
  55. Expression expression = parent;
  56. if (ctx.getParent().getChildCount()==1 && parent!=null) {
  57. //如果就是自己,则无需创建新的Expression
  58. }else {
  59. /* create expression and link it with parent*/
  60. expression = new Expression(idGenerator.generateId());
  61. expression.setLine(ctx.getStart().getLine());
  62. expression.setText(ctx.getText());
  63. context.lastContainer().addExpression(ctx,expression);
  64. expression.setParent(parent);
  65. }
  66. if (ctx instanceof Expr_stmtContext) {
  67. Expr_stmtContext exprAssign = (Expr_stmtContext)ctx;
  68. if (exprAssign.assign_part()!=null) {
  69. expression.setSet(true);
  70. expression.setIdentifier(exprAssign.testlist_star_expr().getText());
  71. if (isValidIdentifier(expression.getIdentifier())) {
  72. makeSureVarExist(expression.getIdentifier(), ctx);
  73. }
  74. deduceVarTypeInCaseOfAssignment((Expr_stmtContext)ctx,expression);
  75. }
  76. }
  77. if (ctx instanceof Raise_stmtContext) {
  78. expression.setThrow (true);
  79. }
  80. if (ctx instanceof Return_stmtContext) {
  81. deduceReturnTypeInCaseOfReturn((Return_stmtContext)ctx,expression);
  82. }
  83. if (ctx instanceof ExprContext) {
  84. processExprContext((ExprContext)ctx, expression);
  85. }
  86. }
  87. private void deduceReturnTypeInCaseOfReturn(Return_stmtContext ctx, Expression expression) {
  88. FunctionEntity currentFunction = context.currentFunction();
  89. if (currentFunction == null)
  90. return;
  91. expression.addDeducedTypeFunction(currentFunction);
  92. }
  93. private void makeSureVarExist(GenericName identifier, ParserRuleContext ctx) {
  94. if (null==context.foundEntityWithName(identifier)) {
  95. VarEntity var = context.foundVarDefinition(context.lastContainer(), identifier.getName(),ctx.getStart().getLine());
  96. var.setLine(ctx.getStart().getLine());
  97. }
  98. }
  99. private boolean isValidIdentifier(GenericName identifier) {
  100. Pattern p = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*");
  101. Matcher m = p.matcher(identifier.getName());
  102. return m.matches();
  103. }
  104. private void processExprContext(ExprContext exprCtx, Expression expression) {
  105. //func_call, member_access, subscript member, and atom
  106. Expression lastExpression = null;
  107. if (exprCtx.atom()!=null) {
  108. //atom
  109. Expression atomExpr = new Expression(idGenerator.generateId());
  110. atomExpr.setLine(exprCtx.atom().getStart().getLine());
  111. atomExpr.setParent(expression);
  112. atomExpr.setText(exprCtx.atom().getText());
  113. atomExpr.setIdentifier(exprCtx.atom().getText());
  114. context.lastContainer().addExpression(exprCtx.atom(),atomExpr);
  115. processAtom(exprCtx.atom(),atomExpr);
  116. lastExpression = atomExpr;
  117. if (exprCtx.trailer()==null || exprCtx.trailer().size()==0) {
  118. //do nothing; it is just an id;
  119. }else {
  120. for (TrailerContext trailer:exprCtx.trailer()) {
  121. if (trailer.name()!=null) {
  122. Expression trailerExpr = new Expression(idGenerator.generateId());
  123. trailerExpr.setLine(trailer.getStart().getLine());
  124. trailerExpr.setText(trailer.getText());
  125. context.lastContainer().addExpression(trailer,trailerExpr);
  126. trailerExpr.setParent(expression);
  127. //doted name = member access or method call
  128. trailerExpr.setDot(true);;
  129. trailerExpr.setIdentifier(trailer.name().getText());
  130. if (trailer.arguments()!=null) {
  131. if (trailer.arguments().OPEN_PAREN()!=null) {
  132. foundCallStyleExpressionWithDot(trailerExpr,lastExpression.getIdentifier(), trailer);
  133. }else {
  134. //subscript list, do nothing
  135. }
  136. }
  137. lastExpression.setParent(trailerExpr);
  138. lastExpression = trailerExpr;
  139. }else {
  140. //direct call, or direct data access
  141. if (trailer.arguments()!=null) {
  142. if (trailer.arguments().OPEN_PAREN()!=null) {
  143. foundCallStyleExpressionWithoutDot(lastExpression, trailer.arguments());
  144. }else {
  145. //subscript list, do nothing
  146. }
  147. }
  148. }
  149. }
  150. }
  151. }else {
  152. /** expr
  153. | <assoc=right> expr op=POWER expr
  154. | op=(ADD | MINUS | NOT_OP) expr
  155. | expr op=(STAR | DIV | MOD | IDIV | AT) expr
  156. | expr op=(ADD | MINUS) expr
  157. | expr op=(LEFT_SHIFT | RIGHT_SHIFT) expr
  158. | expr op=AND_OP expr
  159. | expr op=XOR expr
  160. | expr op=OR_OP expr
  161. ;*/
  162. }
  163. }
  164. private boolean isStartOfContainerRule(ParserRuleContext ctx) {
  165. if (this.exprStarted) return true;
  166. return ctx instanceof ExprContext ||
  167. ctx instanceof Expr_stmtContext ||
  168. ctx instanceof Del_stmtContext ||
  169. ctx instanceof Return_stmtContext ||
  170. ctx instanceof Raise_stmtContext ||
  171. ctx instanceof Raise_stmtContext ||
  172. ctx instanceof Yield_stmtContext ||
  173. ctx instanceof Assert_stmtContext;
  174. }
  175. private void foundCallStyleExpressionWithDot(Expression theExpression, GenericName varName, ParserRuleContext ctx) {
  176. GenericName funcName = theExpression.getIdentifier();
  177. Entity prefixEntity = context.foundEntityWithName(varName);
  178. if (prefixEntity instanceof VarEntity) {
  179. ((VarEntity) prefixEntity).addFunctionCall(funcName);
  180. }
  181. Entity typeEntity = context.foundEntityWithName(funcName);
  182. if (typeEntity instanceof TypeEntity && typeEntity.getId() > 0) {
  183. theExpression.setCreate(true);
  184. theExpression.setType(typeEntity.getType(), typeEntity, bindingResolver);
  185. theExpression.setRawType(typeEntity.getRawName());
  186. return;
  187. }
  188. theExpression.setCall(true);
  189. }
  190. private void foundCallStyleExpressionWithoutDot(Expression theExpression, ParserRuleContext ctx) {
  191. GenericName funcName = theExpression.getIdentifier();
  192. Entity typeEntity = context.foundEntityWithName(funcName);
  193. if (typeEntity instanceof TypeEntity && typeEntity.getId() > 0) {
  194. theExpression.getParent().setCreate(true);
  195. theExpression.setType(typeEntity.getType(), typeEntity, bindingResolver);
  196. theExpression.getParent().setRawType(typeEntity.getRawName());
  197. return;
  198. }
  199. theExpression.setCall(true);
  200. }
  201. private void processAtom(AtomContext atom, Expression expression) {
  202. if (atom.name()!=null) {
  203. expression.setIdentifier(atom.getText());
  204. return;
  205. }
  206. if (atom.STRING()!=null
  207. || atom.NONE()!=null
  208. || atom.number()!=null) {
  209. expression.setRawType("<Built-in>");
  210. expression.setIdentifier("<Literal>");
  211. return;
  212. }
  213. if (atom.EXEC()!=null
  214. || atom.PRINT()!=null
  215. || atom.ELLIPSIS()!=null) {
  216. return;
  217. }
  218. // : OPEN_PAREN (yield_expr | testlist_comp)? CLOSE_PAREN
  219. // | OPEN_BRACKET testlist_comp? CLOSE_BRACKET
  220. // | OPEN_BRACE dictorsetmaker? CLOSE_BRACE
  221. // | REVERSE_QUOTE testlist COMMA? REVERSE_QUOTE
  222. return;
  223. }
  224. private Expression findParentInStack(RuleContext ctx) {
  225. if (ctx==null) return null;
  226. if (ctx.parent==null) return null;
  227. if (context.lastContainer()==null) {
  228. return null;
  229. }
  230. if (context.lastContainer().expressions().containsKey(ctx.parent))
  231. return context.lastContainer().expressions().get(ctx.parent);
  232. return findParentInStack(ctx.parent);
  233. }
  234. public void startExpr() {
  235. this.exprStarted = true;
  236. }
  237. public void stopExpr() {
  238. this.exprStarted = false;
  239. }
  240. }
  241. class NameCollector extends PythonParserBaseVisitor<Void>{
  242. private List<String> names;
  243. NameCollector(List<String> names){
  244. this.names = names;
  245. }
  246. @Override
  247. public Void visitAtom(AtomContext ctx) {
  248. if (ctx.name()!=null)
  249. names.add(ctx.name().getText());
  250. return super.visitAtom(ctx);
  251. }
  252. }

人工智能研发终端

Contributors (2)