package dev.peerat.parser.java; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import dev.peerat.parser.Token; import dev.peerat.parser.TokenType; import dev.peerat.parser.java.Annotation.Annotable; import dev.peerat.parser.java.Operation.OperationContainer; import dev.peerat.parser.java.Variable.VariableContainer; import dev.peerat.parser.java.value.Value; import dev.peerat.parser.java.value.Value.ValueContainer; import dev.peerat.parser.java.visitor.JavaVisitor; import dev.peerat.parser.visitor.VisitorBag; public class Function extends Annotable implements VariableContainer, OperationContainer, ValueContainer{ public static interface FunctionContainer{ void addFunction(Function function); } private int mod; private Token generic; private Token type; private Token name; private List parameters; private List throwables; private List elements; public Function(List annotations, int mod, Token type, Token name){ super(annotations); this.mod = mod; this.type = type; this.name = name; this.elements = new ArrayList<>(); } public Function(List annotations, int mod, Token generic, Token type, Token name){ this(annotations, mod, type, name); this.generic = generic; } public Function(List annotations, int mod, Token generic, Token type, Token name, List parameters){ this(annotations, mod, generic, type, name); this.parameters = parameters; } public Function(List annotations, int mod, Token generic, Token type, Token name, List parameters, List throwables){ this(annotations, mod, generic, type, name, parameters); this.throwables = throwables; } @Override public void addVariable(Variable variable) { this.elements.add(variable); } @Override public void addOperation(Operation operation) { this.elements.add(operation); } @Override public void addValue(Value value) { this.elements.add(value); } public int getModifier(){ return this.mod; } public Token getGeneric(){ return this.generic; } public Token getReturnType(){ return this.type; } public Token getName(){ return this.name; } public List getParameters(){ return this.parameters; } public List getThrowables(){ return this.throwables; } public List getElements(){ return this.elements; } @Override public void build(Builder builder) throws Exception{ super.build(builder); String mod = Modifier.toString(this.mod); builder.append(new Token(type.getLineNumber(), type.getCharacterNumber()-(mod.length()+1), mod, TokenType.GROUP)); builder.append(" "); if(generic != null){ builder.append(generic); builder.append(" "); } builder.append(type); builder.append(" "); builder.append(name); builder.append("("); if(parameters != null){ for(Variable param : this.parameters){ param.build(builder); } } builder.append(")"); if(throwables != null){ builder.append("throws"); for(Token token : throwables){ builder.append(token); } } builder.append("{"); if(elements != null){ for(JavaElement content : this.elements){ content.build(builder); } } builder.append("}"); } @Override public E find(java.util.function.Function finder){ E annotation = super.find(finder); if(annotation != null) return annotation; if(parameters != null){ for(Variable param : this.parameters){ if(finder.apply(param)) return (E) param; } } if(elements != null){ for(JavaElement content : this.elements){ if(finder.apply(content)) return (E) content; } } return null; } @Override public void findAll(java.util.function.Function finder, List list){ super.findAll(finder, list); if(parameters != null){ for(Variable param : this.parameters){ if(finder.apply(param)) list.add((E) param); param.findAll(finder, list); } } if(elements != null){ for(JavaElement content : this.elements){ if(finder.apply(content)) list.add((E) content); content.findAll(finder, list); } } } @Override public VisitorBag visit(JavaVisitor visitor){ if(visitor.canVisit(getClass())) return visitor.visit(this); VisitorBag bag = new VisitorBag(); List annotations = getAnnotations(); if(annotations != null) for(Annotation annotation : annotations){ bag.merge(annotation.visit(visitor)); } if(this.parameters != null) for(Variable variable : this.parameters){ bag.merge(variable.visit(visitor)); } for(JavaElement element : this.elements){ bag.merge(element.visit(visitor)); } return bag; } }