|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- /*
- MIT License
-
- Copyright (c) 2018-2019 Gang ZHANG
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
-
- package depends.extractor;
-
- import depends.entity.*;
- import depends.entity.repo.EntityRepo;
- import depends.entity.repo.IdGenerator;
- import depends.importtypes.Import;
- import depends.relations.IBindingResolver;
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Stack;
- import java.util.stream.Collectors;
-
- public abstract class HandlerContext {
- protected EntityRepo entityRepo;
- protected IdGenerator idGenerator;
-
- protected FileEntity currentFileEntity;
- protected IBindingResolver bindingResolver;
-
-
- public HandlerContext(EntityRepo entityRepo, IBindingResolver bindingResolver) {
- this.entityRepo = entityRepo;
- this.idGenerator = entityRepo;
- entityStack = new Stack<Entity>();
- this.bindingResolver = bindingResolver;
- }
-
- public FileEntity startFile(String fileName) {
- currentFileEntity = new FileEntity(fileName, idGenerator.generateId(),true);
- pushToStack(currentFileEntity);
- addToRepo(currentFileEntity);
- return currentFileEntity;
- }
-
- public TypeEntity foundNewType(GenericName name, Integer startLine) {
- TypeEntity currentTypeEntity = new TypeEntity(name, this.latestValidContainer(),
- idGenerator.generateId());
- currentTypeEntity.setLine(startLine);
- pushToStack(currentTypeEntity);
- addToRepo(currentTypeEntity);
- currentFileEntity.addType(currentTypeEntity);
- return currentTypeEntity;
- }
-
- /**
- * Tell the context object that a new type founded.
- * @param name
- * @param startLine
- * @return
- */
- public TypeEntity foundNewType(String name, Integer startLine) {
- return foundNewType(GenericName.build(name),startLine);
- }
-
- public AliasEntity foundNewAlias(String aliasName, String originalName) {
- if (aliasName.equals(originalName)) return null; //it is a tricky, we treat same name no different.
- //indeed it is not perfect -> the right match should depends on no-bare format like "struct a" instead of "a"
- AliasEntity currentTypeEntity = new AliasEntity(GenericName.build(aliasName), this.latestValidContainer(),
- idGenerator.generateId(),GenericName.build(originalName) );
- addToRepo(currentTypeEntity);
- return currentTypeEntity;
- }
-
- public AliasEntity foundNewAlias(GenericName aliasName, Entity referToEntity) {
- AliasEntity currentTypeEntity = new AliasEntity(aliasName, this.latestValidContainer(),
- idGenerator.generateId(),aliasName);
- currentTypeEntity.setReferToEntity(referToEntity);
- addToRepo(currentTypeEntity);
- return currentTypeEntity;
- }
-
- /**
- * Tell the context that a new method was found.
- * Do not forget to tell the context leave the method when you finish
- * the process of the method
- * @param methodName
- * @param returnType - if no return type information avaliable, keep it as null;
- * @param throwedType - if no throwed type information avaliable, keep it as empty list;
- * @return the new function enity
- */
- public FunctionEntity foundMethodDeclarator(String methodName, String returnType, List<String> throwedType, Integer startLine) {
- FunctionEntity functionEntity = new FunctionEntity(GenericName.build(methodName), this.latestValidContainer(),
- idGenerator.generateId(),GenericName.build(returnType));
- functionEntity.setLine(startLine);
- addToRepo(functionEntity);
- this.typeOrFileContainer().addFunction(functionEntity);
- pushToStack(functionEntity);
- functionEntity.addThrowTypes(throwedType.stream().map(item->GenericName.build(item)).collect(Collectors.toList()));
- return functionEntity;
- }
-
- public FunctionEntity foundMethodDeclarator(String methodName, Integer startLine) {
- FunctionEntity functionEntity = new FunctionEntity(GenericName.build(methodName), this.latestValidContainer(),
- idGenerator.generateId(),null);
- functionEntity.setLine(startLine);
- addToRepo(functionEntity);
- this.typeOrFileContainer().addFunction(functionEntity);
- pushToStack(functionEntity);
- return functionEntity;
- }
-
-
- public FunctionEntity foundMethodDeclarator(ContainerEntity containerEntity, String methodName, Integer startLine) {
- FunctionEntity functionEntity = new FunctionEntity(GenericName.build(methodName), containerEntity,
- idGenerator.generateId(),null);
- functionEntity.setLine(startLine);
- addToRepo(functionEntity);
- containerEntity.addFunction(functionEntity);
- pushToStack(functionEntity);
- functionEntity.addThrowTypes(new ArrayList<>());
- return functionEntity;
- }
-
- public void foundNewImport(Import imported) {
- currentFileEntity.addImport(imported);
- }
-
- public TypeEntity currentType() {
- for (int i = entityStack.size() - 1; i >= 0; i--) {
- Entity t = entityStack.get(i);
- if (t instanceof TypeEntity)
- return (TypeEntity) t;
- }
- return null;
- }
-
- public ContainerEntity typeOrFileContainer() {
- for (int i = entityStack.size() - 1; i >= 0; i--) {
- Entity t = entityStack.get(i);
- if (t instanceof TypeEntity)
- return (ContainerEntity) t;
- if (t instanceof FileEntity) {
- return (ContainerEntity)t;
- }
- }
- return null;
- }
-
-
- public FunctionEntity currentFunction() {
- for (int i = entityStack.size() - 1; i >= 0; i--) {
- Entity t = entityStack.get(i);
- if (t instanceof FunctionEntity)
- return (FunctionEntity) t;
- }
- return null;
- }
-
- public FileEntity currentFile() {
- return currentFileEntity;
- }
-
- public ContainerEntity globalScope() {
- Entity global = entityRepo.getEntity(EntityRepo.GLOBAL_SCOPE_NAME);
- if (global==null) {
- global = new PackageEntity(EntityRepo.GLOBAL_SCOPE_NAME,idGenerator.generateId());
- addToRepo(global);
- }
- return (ContainerEntity)global;
- }
-
- public Entity latestValidContainer() {
- for (int i = entityStack.size() - 1; i >= 0; i--) {
- Entity t = entityStack.get(i);
- if (t instanceof FunctionEntity)
- return t;
- if (t instanceof TypeEntity)
- return t;
- if (t instanceof FileEntity)
- return t;
- }
- return null;
- }
-
- public ContainerEntity lastContainer() {
- for (int i = entityStack.size() - 1; i >= 0; i--) {
- Entity t = entityStack.get(i);
- if (t instanceof ContainerEntity)
- return (ContainerEntity) t;
- }
- return null;
- }
-
- public void foundImplements(GenericName typeName) {
- currentType().addImplements(typeName);
- }
-
- public void foundExtends(String className) {
- foundExtends(GenericName.build(className));
- }
-
- public void foundExtends(GenericName typeName) {
- if (currentType()==null) {
- System.out.println("error: type do not exist");
- return ;
- }
- currentType().addExtends(typeName);
- }
-
- public void foundMixin(String name) {
- foundMixin(GenericName.build(name));
-
- }
-
- public void foundMixin(GenericName name) {
- lastContainer().addMixin(name);
-
- }
-
- public void foundTypeParametes(GenericName typeName) {
- lastContainer().addTypeParameter(typeName);
- }
-
-
- public List<VarEntity> foundVarDefinitions(List<String> varNames, String type, List<GenericName> typeArguments, Integer line) {
- return varNames.stream().map(item->foundVarDefinition(item,GenericName.build(type),typeArguments,line)).collect(Collectors.toList());
- }
-
- public VarEntity foundVarDefinition(ContainerEntity container,String varName,Integer line) {
- if (container==null) {
- System.out.println("fallback to file container for var " + varName + " in file "+ currentFile().getRawName());
- container = currentFile();
- }
-
- VarEntity var = getVarInLocalFile(container,GenericName.build(varName));
- if (var!=null) return var;
- var = new VarEntity(GenericName.build(varName), null, container, idGenerator.generateId());
- var.setLine(line);
- container.addVar(var);
- addToRepo(var);
-
- return var;
- }
-
- public VarEntity foundGlobalVarDefinition(ContainerEntity container,String varName,Integer line) {
- if (container==null) {
- System.out.println("fallback to file container for var " + varName + " in file "+ currentFile().getRawName());
- container = currentFile();
- }
-
- VarEntity var = getVarInLocalFile(container,GenericName.build(varName));
- if (var!=null) return var;
- var = new VarEntity(GenericName.build(varName), null, container, idGenerator.generateId());
- container.addVar(var);
- var.setLine(line);
- var.setQualifiedName(var.getRawName().toString());
- addToRepo(var);
- return var;
- }
-
- public VarEntity foundVarDefinition(String varName, GenericName type, List<GenericName> typeArguments,Integer line) {
- VarEntity var = new VarEntity(GenericName.build(varName), type, lastContainer(), idGenerator.generateId());
- var.setLine(line);
- var.addTypeParameter(typeArguments);
- lastContainer().addVar(var);
- addToRepo(var);
- return var;
- }
-
- public VarEntity addMethodParameter(String paramName) {
- if (currentFunction()==null) return null;
- VarEntity varEntity = new VarEntity(GenericName.build(paramName),null,currentFunction(),idGenerator.generateId());
- currentFunction().addParameter(varEntity);
- addToRepo(varEntity);
- return varEntity;
- }
-
- public VarEntity foundEnumConstDefinition(String varName,Integer line) {
- GenericName type = lastContainer().getRawName();
- return foundVarDefinition(varName,type,new ArrayList<>(),line);
- }
-
- protected Stack<Entity> entityStack = new Stack<Entity>();
-
- protected void pushToStack(Entity entity) {
- entityStack.push(entity);
- }
-
-
- public void exitLastedEntity() {
- //we never pop up the lastest one (FileEntity)
- if (entityStack.size()>1)
- entityStack.pop();
- }
-
- private VarEntity getVarInLocalFile(ContainerEntity container, GenericName varName) {
- Entity entity = bindingResolver.resolveName(container, varName, false);
- if (entity ==null ) return null;
- Entity fileEntity = entity.getAncestorOfType(FileEntity.class);
- if (fileEntity ==null ){
- //may not exist in fileEntity, for example global vars
- }else{
- if (!fileEntity.equals(currentFileEntity)) return null;
- if (entity instanceof VarEntity) return (VarEntity)entity;
- }
- return null;
- }
-
- public Entity foundEntityWithName(GenericName rawName) {
- return bindingResolver.resolveName(lastContainer(), rawName, true);
- }
-
- public void addToRepo(Entity entity) {
- entityRepo.add(entity);
- }
-
-
- }
|