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.

HandlerContext.java 11 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. MIT License
  3. Copyright (c) 2018-2019 Gang ZHANG
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in all
  11. copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18. SOFTWARE.
  19. */
  20. package depends.extractor;
  21. import depends.entity.*;
  22. import depends.entity.repo.EntityRepo;
  23. import depends.entity.repo.IdGenerator;
  24. import depends.importtypes.Import;
  25. import depends.relations.IBindingResolver;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.util.Stack;
  29. import java.util.stream.Collectors;
  30. public abstract class HandlerContext {
  31. protected EntityRepo entityRepo;
  32. protected IdGenerator idGenerator;
  33. protected FileEntity currentFileEntity;
  34. protected IBindingResolver bindingResolver;
  35. public HandlerContext(EntityRepo entityRepo, IBindingResolver bindingResolver) {
  36. this.entityRepo = entityRepo;
  37. this.idGenerator = entityRepo;
  38. entityStack = new Stack<Entity>();
  39. this.bindingResolver = bindingResolver;
  40. }
  41. public FileEntity startFile(String fileName) {
  42. currentFileEntity = new FileEntity(fileName, idGenerator.generateId(),true);
  43. pushToStack(currentFileEntity);
  44. addToRepo(currentFileEntity);
  45. return currentFileEntity;
  46. }
  47. public TypeEntity foundNewType(GenericName name, Integer startLine) {
  48. TypeEntity currentTypeEntity = new TypeEntity(name, this.latestValidContainer(),
  49. idGenerator.generateId());
  50. currentTypeEntity.setLine(startLine);
  51. pushToStack(currentTypeEntity);
  52. addToRepo(currentTypeEntity);
  53. currentFileEntity.addType(currentTypeEntity);
  54. return currentTypeEntity;
  55. }
  56. /**
  57. * Tell the context object that a new type founded.
  58. * @param name
  59. * @param startLine
  60. * @return
  61. */
  62. public TypeEntity foundNewType(String name, Integer startLine) {
  63. return foundNewType(GenericName.build(name),startLine);
  64. }
  65. public AliasEntity foundNewAlias(String aliasName, String originalName) {
  66. if (aliasName.equals(originalName)) return null; //it is a tricky, we treat same name no different.
  67. //indeed it is not perfect -> the right match should depends on no-bare format like "struct a" instead of "a"
  68. AliasEntity currentTypeEntity = new AliasEntity(GenericName.build(aliasName), this.latestValidContainer(),
  69. idGenerator.generateId(),GenericName.build(originalName) );
  70. addToRepo(currentTypeEntity);
  71. return currentTypeEntity;
  72. }
  73. public AliasEntity foundNewAlias(GenericName aliasName, Entity referToEntity) {
  74. AliasEntity currentTypeEntity = new AliasEntity(aliasName, this.latestValidContainer(),
  75. idGenerator.generateId(),aliasName);
  76. currentTypeEntity.setReferToEntity(referToEntity);
  77. addToRepo(currentTypeEntity);
  78. return currentTypeEntity;
  79. }
  80. /**
  81. * Tell the context that a new method was found.
  82. * Do not forget to tell the context leave the method when you finish
  83. * the process of the method
  84. * @param methodName
  85. * @param returnType - if no return type information avaliable, keep it as null;
  86. * @param throwedType - if no throwed type information avaliable, keep it as empty list;
  87. * @return the new function enity
  88. */
  89. public FunctionEntity foundMethodDeclarator(String methodName, String returnType, List<String> throwedType, Integer startLine) {
  90. FunctionEntity functionEntity = new FunctionEntity(GenericName.build(methodName), this.latestValidContainer(),
  91. idGenerator.generateId(),GenericName.build(returnType));
  92. functionEntity.setLine(startLine);
  93. addToRepo(functionEntity);
  94. this.typeOrFileContainer().addFunction(functionEntity);
  95. pushToStack(functionEntity);
  96. functionEntity.addThrowTypes(throwedType.stream().map(item->GenericName.build(item)).collect(Collectors.toList()));
  97. return functionEntity;
  98. }
  99. public FunctionEntity foundMethodDeclarator(String methodName, Integer startLine) {
  100. FunctionEntity functionEntity = new FunctionEntity(GenericName.build(methodName), this.latestValidContainer(),
  101. idGenerator.generateId(),null);
  102. functionEntity.setLine(startLine);
  103. addToRepo(functionEntity);
  104. this.typeOrFileContainer().addFunction(functionEntity);
  105. pushToStack(functionEntity);
  106. return functionEntity;
  107. }
  108. public FunctionEntity foundMethodDeclarator(ContainerEntity containerEntity, String methodName, Integer startLine) {
  109. FunctionEntity functionEntity = new FunctionEntity(GenericName.build(methodName), containerEntity,
  110. idGenerator.generateId(),null);
  111. functionEntity.setLine(startLine);
  112. addToRepo(functionEntity);
  113. containerEntity.addFunction(functionEntity);
  114. pushToStack(functionEntity);
  115. functionEntity.addThrowTypes(new ArrayList<>());
  116. return functionEntity;
  117. }
  118. public void foundNewImport(Import imported) {
  119. currentFileEntity.addImport(imported);
  120. }
  121. public TypeEntity currentType() {
  122. for (int i = entityStack.size() - 1; i >= 0; i--) {
  123. Entity t = entityStack.get(i);
  124. if (t instanceof TypeEntity)
  125. return (TypeEntity) t;
  126. }
  127. return null;
  128. }
  129. public ContainerEntity typeOrFileContainer() {
  130. for (int i = entityStack.size() - 1; i >= 0; i--) {
  131. Entity t = entityStack.get(i);
  132. if (t instanceof TypeEntity)
  133. return (ContainerEntity) t;
  134. if (t instanceof FileEntity) {
  135. return (ContainerEntity)t;
  136. }
  137. }
  138. return null;
  139. }
  140. public FunctionEntity currentFunction() {
  141. for (int i = entityStack.size() - 1; i >= 0; i--) {
  142. Entity t = entityStack.get(i);
  143. if (t instanceof FunctionEntity)
  144. return (FunctionEntity) t;
  145. }
  146. return null;
  147. }
  148. public FileEntity currentFile() {
  149. return currentFileEntity;
  150. }
  151. public ContainerEntity globalScope() {
  152. Entity global = entityRepo.getEntity(EntityRepo.GLOBAL_SCOPE_NAME);
  153. if (global==null) {
  154. global = new PackageEntity(EntityRepo.GLOBAL_SCOPE_NAME,idGenerator.generateId());
  155. addToRepo(global);
  156. }
  157. return (ContainerEntity)global;
  158. }
  159. public Entity latestValidContainer() {
  160. for (int i = entityStack.size() - 1; i >= 0; i--) {
  161. Entity t = entityStack.get(i);
  162. if (t instanceof FunctionEntity)
  163. return t;
  164. if (t instanceof TypeEntity)
  165. return t;
  166. if (t instanceof FileEntity)
  167. return t;
  168. }
  169. return null;
  170. }
  171. public ContainerEntity lastContainer() {
  172. for (int i = entityStack.size() - 1; i >= 0; i--) {
  173. Entity t = entityStack.get(i);
  174. if (t instanceof ContainerEntity)
  175. return (ContainerEntity) t;
  176. }
  177. return null;
  178. }
  179. public void foundImplements(GenericName typeName) {
  180. currentType().addImplements(typeName);
  181. }
  182. public void foundExtends(String className) {
  183. foundExtends(GenericName.build(className));
  184. }
  185. public void foundExtends(GenericName typeName) {
  186. if (currentType()==null) {
  187. System.out.println("error: type do not exist");
  188. return ;
  189. }
  190. currentType().addExtends(typeName);
  191. }
  192. public void foundMixin(String name) {
  193. foundMixin(GenericName.build(name));
  194. }
  195. public void foundMixin(GenericName name) {
  196. lastContainer().addMixin(name);
  197. }
  198. public void foundTypeParametes(GenericName typeName) {
  199. lastContainer().addTypeParameter(typeName);
  200. }
  201. public List<VarEntity> foundVarDefinitions(List<String> varNames, String type, List<GenericName> typeArguments, Integer line) {
  202. return varNames.stream().map(item->foundVarDefinition(item,GenericName.build(type),typeArguments,line)).collect(Collectors.toList());
  203. }
  204. public VarEntity foundVarDefinition(ContainerEntity container,String varName,Integer line) {
  205. if (container==null) {
  206. System.out.println("fallback to file container for var " + varName + " in file "+ currentFile().getRawName());
  207. container = currentFile();
  208. }
  209. VarEntity var = getVarInLocalFile(container,GenericName.build(varName));
  210. if (var!=null) return var;
  211. var = new VarEntity(GenericName.build(varName), null, container, idGenerator.generateId());
  212. var.setLine(line);
  213. container.addVar(var);
  214. addToRepo(var);
  215. return var;
  216. }
  217. public VarEntity foundGlobalVarDefinition(ContainerEntity container,String varName,Integer line) {
  218. if (container==null) {
  219. System.out.println("fallback to file container for var " + varName + " in file "+ currentFile().getRawName());
  220. container = currentFile();
  221. }
  222. VarEntity var = getVarInLocalFile(container,GenericName.build(varName));
  223. if (var!=null) return var;
  224. var = new VarEntity(GenericName.build(varName), null, container, idGenerator.generateId());
  225. container.addVar(var);
  226. var.setLine(line);
  227. var.setQualifiedName(var.getRawName().toString());
  228. addToRepo(var);
  229. return var;
  230. }
  231. public VarEntity foundVarDefinition(String varName, GenericName type, List<GenericName> typeArguments,Integer line) {
  232. VarEntity var = new VarEntity(GenericName.build(varName), type, lastContainer(), idGenerator.generateId());
  233. var.setLine(line);
  234. var.addTypeParameter(typeArguments);
  235. lastContainer().addVar(var);
  236. addToRepo(var);
  237. return var;
  238. }
  239. public VarEntity addMethodParameter(String paramName) {
  240. if (currentFunction()==null) return null;
  241. VarEntity varEntity = new VarEntity(GenericName.build(paramName),null,currentFunction(),idGenerator.generateId());
  242. currentFunction().addParameter(varEntity);
  243. addToRepo(varEntity);
  244. return varEntity;
  245. }
  246. public VarEntity foundEnumConstDefinition(String varName,Integer line) {
  247. GenericName type = lastContainer().getRawName();
  248. return foundVarDefinition(varName,type,new ArrayList<>(),line);
  249. }
  250. protected Stack<Entity> entityStack = new Stack<Entity>();
  251. protected void pushToStack(Entity entity) {
  252. entityStack.push(entity);
  253. }
  254. public void exitLastedEntity() {
  255. //we never pop up the lastest one (FileEntity)
  256. if (entityStack.size()>1)
  257. entityStack.pop();
  258. }
  259. private VarEntity getVarInLocalFile(ContainerEntity container, GenericName varName) {
  260. Entity entity = bindingResolver.resolveName(container, varName, false);
  261. if (entity ==null ) return null;
  262. Entity fileEntity = entity.getAncestorOfType(FileEntity.class);
  263. if (fileEntity ==null ){
  264. //may not exist in fileEntity, for example global vars
  265. }else{
  266. if (!fileEntity.equals(currentFileEntity)) return null;
  267. if (entity instanceof VarEntity) return (VarEntity)entity;
  268. }
  269. return null;
  270. }
  271. public Entity foundEntityWithName(GenericName rawName) {
  272. return bindingResolver.resolveName(lastContainer(), rawName, true);
  273. }
  274. public void addToRepo(Entity entity) {
  275. entityRepo.add(entity);
  276. }
  277. }