package me.tomassetti.turin.parser.ast.statements; import com.google.common.collect.ImmutableList; import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; import me.tomassetti.turin.resolvers.SymbolResolver; import me.tomassetti.turin.resolvers.jdk.ReflectionTypeDefinitionFactory; import me.tomassetti.turin.parser.ast.Node; import me.tomassetti.turin.parser.ast.expressions.Expression; import me.tomassetti.turin.typesystem.ReferenceTypeUsage; import me.tomassetti.turin.typesystem.TypeUsage; public class ThrowStatement extends Statement { private Expression exception; public ThrowStatement(Expression exception) { this.exception = exception; this.exception.setParent(this); } @Override public String toString() { return "ThrowStatement{" + "exception=" + exception + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ThrowStatement that = (ThrowStatement) o; if (!exception.equals(that.exception)) return false; return true; } @Override public int hashCode() { return exception.hashCode(); } @Override public Iterable<Node> getChildren() { return ImmutableList.of(exception); } public Expression getException() { return exception; } public static final String ERR_MESSAGE = "the throw statement should be used only with Exceptions"; @Override protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { TypeUsage exceptionType = getException().calcType(); if (!exceptionType.isReference()) { errorCollector.recordSemanticError(exception.getPosition(), ERR_MESSAGE); return false; } else { if (exceptionType.asReferenceTypeUsage().canBeAssignedTo(new ReferenceTypeUsage( ReflectionTypeDefinitionFactory.getInstance().getTypeDefinition(Exception.class, resolver)))) { return true; } else { errorCollector.recordSemanticError(exception.getPosition(), ERR_MESSAGE); return false; } } } }