package org.nlamah.QL.TypeChecker; import java.util.List; import org.nlamah.QL.Model.Form.Abstract.QLNode; import org.nlamah.QL.Error.CyclicDependencyError; import org.nlamah.QL.Error.OutOfScopeDeclarationError; import org.nlamah.QBase.Tools.ArrayTools; import org.nlamah.QBase.Tools.QLTools; import org.nlamah.QBase.TypeChecker.QBaseAbstractTypeChecker; import org.nlamah.QL.Interfaces.QLNodeVisitor; import org.nlamah.QL.Model.Expression.Binary.AddExpression; import org.nlamah.QL.Model.Expression.Binary.AndExpression; import org.nlamah.QL.Model.Expression.Binary.DivideExpression; import org.nlamah.QL.Model.Expression.Binary.EqualExpression; import org.nlamah.QL.Model.Expression.Binary.GreaterThanEqualExpression; import org.nlamah.QL.Model.Expression.Binary.GreaterThanExpression; import org.nlamah.QL.Model.Expression.Binary.MultiplyExpression; import org.nlamah.QL.Model.Expression.Binary.OrExpression; import org.nlamah.QL.Model.Expression.Binary.SmallerThanEqualExpression; import org.nlamah.QL.Model.Expression.Binary.SmallerThanExpression; import org.nlamah.QL.Model.Expression.Binary.SubtractExpression; import org.nlamah.QL.Model.Expression.Binary.UnEqualExpression; import org.nlamah.QL.Model.Expression.Literal.BooleanLiteral; import org.nlamah.QL.Model.Expression.Literal.IdentifierLiteral; import org.nlamah.QL.Model.Expression.Literal.NumberLiteral; import org.nlamah.QL.Model.Expression.Literal.TextLiteral; import org.nlamah.QL.Model.Expression.Unary.MinusExpression; import org.nlamah.QL.Model.Expression.Unary.NotExpression; import org.nlamah.QL.Model.Expression.Unary.PlusExpression; import org.nlamah.QL.Model.Form.ComputedQuestion; import org.nlamah.QL.Model.Form.ConditionalBlock; import org.nlamah.QL.Model.Form.ElseIfThenBlock; import org.nlamah.QL.Model.Form.ElseThenBlock; import org.nlamah.QL.Model.Form.Form; import org.nlamah.QL.Model.Form.IfThenBlock; import org.nlamah.QL.Model.Form.InputQuestion; import org.nlamah.QL.Model.Form.Abstract.FormElement; import org.nlamah.QL.Model.Form.Abstract.FormQuestion; public class OutOfScopeDeclarationChecker extends QBaseAbstractTypeChecker implements QLNodeVisitor { private IdentifierLiteral identifier; public OutOfScopeDeclarationChecker(IdentifierLiteral identifier) { this.identifier = identifier; identifier.accept(this); } private FormQuestion isIdentifierDeclaredHere(List<FormElement> childElements) { FormQuestion declaredQuestion = null; if (ArrayTools.arrayExistsAndHasElements(childElements)) { for (FormElement childElement : childElements) { if (childElement.identifier() != null) { if (childElement.identifier().equals(identifier)) { assert childElement instanceof FormQuestion; declaredQuestion = (FormQuestion)childElement; identifier.setCorrespondingQuestion(declaredQuestion); } } } } return declaredQuestion; } @Override public QLNode visit(AddExpression addExpression) { return addExpression.parentNode().accept(this); } @Override public QLNode visit(AndExpression andExpression) { return andExpression.parentNode().accept(this); } @Override public QLNode visit(DivideExpression divideExpression) { return divideExpression.parentNode().accept(this); } @Override public QLNode visit(EqualExpression equalExpression) { return equalExpression.parentNode().accept(this); } @Override public QLNode visit(GreaterThanExpression greaterThanExpression) { return greaterThanExpression.parentNode().accept(this); } @Override public QLNode visit(GreaterThanEqualExpression greaterThanEqualExpression) { return greaterThanEqualExpression.parentNode().accept(this); } @Override public QLNode visit(MultiplyExpression multiplyExpression) { return multiplyExpression.parentNode().accept(this); } @Override public QLNode visit(OrExpression orExpression) { return orExpression.parentNode().accept(this); } @Override public QLNode visit(SmallerThanExpression smallerThanExpression) { return smallerThanExpression.parentNode().accept(this); } @Override public QLNode visit(SmallerThanEqualExpression smallerThanEqualExpression) { return smallerThanEqualExpression.parentNode().accept(this); } @Override public QLNode visit(SubtractExpression subtractExpression) { return subtractExpression.parentNode().accept(this); } @Override public QLNode visit(UnEqualExpression unEqualExpression) { return unEqualExpression.parentNode().accept(this); } @Override public QLNode visit(BooleanLiteral booleanLiteral) { assert(false); return null; } @Override public QLNode visit(IdentifierLiteral identifierLiteral) { return identifierLiteral.parentNode().accept(this); } @Override public QLNode visit(NumberLiteral numberLiteral) { assert(false); return null; } @Override public QLNode visit(TextLiteral textLiteral) { assert(false); return null; } @Override public QLNode visit(MinusExpression minusExpression) { return minusExpression.parentNode().accept(this); } @Override public QLNode visit(NotExpression notExpression) { return notExpression.parentNode().accept(this); } @Override public QLNode visit(PlusExpression plusExpression) { return plusExpression.parentNode().accept(this); } @Override public QLNode visit(ConditionalBlock conditionalBlock) { return conditionalBlock.parentNode().accept(this); } @Override public QLNode visit(ElseIfThenBlock elseIfThenBlock) { FormQuestion declaredQuestion = isIdentifierDeclaredHere(elseIfThenBlock.childElements()); if (declaredQuestion != null) { return declaredQuestion; } return elseIfThenBlock.parentNode().accept(this); } @Override public QLNode visit(ElseThenBlock elseThenBlock) { FormQuestion declaredQuestion = isIdentifierDeclaredHere(elseThenBlock.childElements()); if (declaredQuestion != null) { return declaredQuestion; } return elseThenBlock.parentNode().accept(this); } @Override public QLNode visit(Form form) { FormQuestion declaredQuestion = isIdentifierDeclaredHere(form.childElements()); if (declaredQuestion == null) { FormQuestion outOfScopeQuestion = QLTools.getQuestionWithIdentifier(form.questions(), this.identifier); assert(outOfScopeQuestion != null); errors.add(new OutOfScopeDeclarationError(this.identifier, outOfScopeQuestion)); } return declaredQuestion; } @Override public QLNode visit(IfThenBlock ifThenBlock) { FormQuestion declaredQuestion = isIdentifierDeclaredHere(ifThenBlock.childElements()); if (declaredQuestion != null) { return declaredQuestion; } return ifThenBlock.parentNode().accept(this); } @Override public QLNode visit(InputQuestion inputQuestion) { assert(false); return null; } @Override public QLNode visit(ComputedQuestion computedQuestion) { if (computedQuestion.identifier().equals(identifier)) { errors.add(new CyclicDependencyError(identifier, computedQuestion)); } return computedQuestion.parentNode().accept(this); } }