Resolves #13 - Exclusion based on type in ArgumentValidator

This commit is contained in:
Mike Cifelli 2017-03-02 11:39:07 -05:00
parent ef4c03a672
commit d55ebdd22f
4 changed files with 58 additions and 43 deletions

View File

@ -12,18 +12,20 @@ public class ArgumentValidator {
private Class<? extends SExpression> firstArgumentType; private Class<? extends SExpression> firstArgumentType;
private Class<? extends SExpression> trailingArgumentType; private Class<? extends SExpression> trailingArgumentType;
private Class<? extends SExpression> excludedFirstArgumentType;
private Class<? extends SExpression> excludedTrailingArgumentType;
private String functionName; private String functionName;
private BigInteger maximumNumberOfArguments; private BigInteger maximumNumberOfArguments;
private BigInteger minimumNumberOfArguments; private BigInteger minimumNumberOfArguments;
private boolean isNilAcceptable;
public ArgumentValidator(String functionName) { public ArgumentValidator(String functionName) {
this.firstArgumentType = SExpression.class; this.firstArgumentType = SExpression.class;
this.trailingArgumentType = SExpression.class; this.trailingArgumentType = SExpression.class;
this.excludedFirstArgumentType = null;
this.excludedTrailingArgumentType = null;
this.functionName = functionName; this.functionName = functionName;
this.minimumNumberOfArguments = null; this.minimumNumberOfArguments = null;
this.maximumNumberOfArguments = null; this.maximumNumberOfArguments = null;
this.isNilAcceptable = true;
} }
public void setFirstArgumentExpectedType(Class<? extends SExpression> argumentType) { public void setFirstArgumentExpectedType(Class<? extends SExpression> argumentType) {
@ -38,6 +40,19 @@ public class ArgumentValidator {
this.firstArgumentType = argumentType; this.firstArgumentType = argumentType;
this.trailingArgumentType = argumentType; this.trailingArgumentType = argumentType;
} }
public void setFirstArgumentExcludedType(Class<? extends SExpression> argumentType) {
this.excludedFirstArgumentType = argumentType;
}
public void setTrailingArgumentExcludedType(Class<? extends SExpression> argumentType) {
this.excludedTrailingArgumentType = argumentType;
}
public void setEveryArgumentExcludedType(Class<? extends SExpression> argumentType) {
this.excludedFirstArgumentType = argumentType;
this.excludedTrailingArgumentType = argumentType;
}
public void setMaximumNumberOfArguments(int maximumNumberOfArguments) { public void setMaximumNumberOfArguments(int maximumNumberOfArguments) {
this.maximumNumberOfArguments = BigInteger.valueOf(maximumNumberOfArguments); this.maximumNumberOfArguments = BigInteger.valueOf(maximumNumberOfArguments);
@ -52,10 +67,6 @@ public class ArgumentValidator {
this.maximumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments); this.maximumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments);
} }
public void doNotAcceptNil() {
this.isNilAcceptable = false;
}
public void validate(Cons argumentList) { public void validate(Cons argumentList) {
validateListNotDotted(argumentList); validateListNotDotted(argumentList);
validateListLength(argumentList); validateListLength(argumentList);
@ -118,11 +129,11 @@ public class ArgumentValidator {
} }
private boolean isExpectedFirstArgumentType(SExpression firstArgument) { private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
return firstArgumentType.isInstance(firstArgument) && !isDisallowedNil(firstArgument); return firstArgumentType.isInstance(firstArgument) && !isExcludedFirstArgumentType(firstArgument);
} }
private boolean isDisallowedNil(SExpression argument) { private boolean isExcludedFirstArgumentType(SExpression firstArgument) {
return !isNilAcceptable && argument.isNull(); return excludedFirstArgumentType != null && excludedFirstArgumentType.isInstance(firstArgument);
} }
private void validateTrailingArguments(Cons argumentList) { private void validateTrailingArguments(Cons argumentList) {
@ -132,7 +143,11 @@ public class ArgumentValidator {
} }
private boolean isExpectedTrailingArgumentType(SExpression trailingArgument) { private boolean isExpectedTrailingArgumentType(SExpression trailingArgument) {
return trailingArgumentType.isInstance(trailingArgument) && !isDisallowedNil(trailingArgument); return trailingArgumentType.isInstance(trailingArgument) && !isExcludedTrailingArgumentType(trailingArgument);
}
private boolean isExcludedTrailingArgumentType(SExpression trailingArgument) {
return excludedTrailingArgumentType != null && excludedTrailingArgumentType.isInstance(trailingArgument);
} }
public static class TooFewArgumentsException extends LispException { public static class TooFewArgumentsException extends LispException {

View File

@ -17,7 +17,7 @@ public class CASE extends LispSpecialFunction {
this.argumentValidator = new ArgumentValidator("CASE"); this.argumentValidator = new ArgumentValidator("CASE");
this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setTrailingArgumentExpectedType(Cons.class); this.argumentValidator.setTrailingArgumentExpectedType(Cons.class);
this.argumentValidator.doNotAcceptNil(); this.argumentValidator.setTrailingArgumentExcludedType(Nil.class);
} }
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {

View File

@ -14,7 +14,7 @@ public class COND extends LispSpecialFunction {
public COND() { public COND() {
this.argumentValidator = new ArgumentValidator("COND"); this.argumentValidator = new ArgumentValidator("COND");
this.argumentValidator.setEveryArgumentExpectedType(Cons.class); this.argumentValidator.setEveryArgumentExpectedType(Cons.class);
this.argumentValidator.doNotAcceptNil(); this.argumentValidator.setEveryArgumentExcludedType(Nil.class);
} }
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {

View File

@ -74,46 +74,28 @@ public class ArgumentValidatorTester {
} }
@Test @Test
public void tooManyArgumentsException_HasCorrectSeverity() { public void tooManyArgumentsException_HasCorrectAttributes() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL); TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
}
@Test
public void tooManyArgumentsException_HasMessageText() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL);
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0); assertTrue(e.getMessage().length() > 0);
} }
@Test @Test
public void tooFewArgumentsException_HasCorrectSeverity() { public void tooFewArgumentsException_HasCorrectAttributes() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL); TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
}
@Test
public void tooFewArgumentsException_HasMessageText() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL);
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0); assertTrue(e.getMessage().length() > 0);
} }
@Test @Test
public void BadArgumentTypeException_HasCorrectSeverity() { public void badArgumentTypeException_HasCorrectAttributes() {
BadArgumentTypeException e = new BadArgumentTypeException("TEST", NIL, SExpression.class); BadArgumentTypeException e = new BadArgumentTypeException("TEST", NIL, SExpression.class);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
}
@Test
public void BadArgumentTypeException_HasMessageText() {
BadArgumentTypeException e = new BadArgumentTypeException("TEST", NIL, SExpression.class);
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0); assertTrue(e.getMessage().length() > 0);
} }
@ -201,22 +183,40 @@ public class ArgumentValidatorTester {
assertTrue(e.getMessage().length() > 0); assertTrue(e.getMessage().length() > 0);
} }
@Test(expected = BadArgumentTypeException.class) @Test
public void doNotAcceptNil_ThrowsExceptionOnNilArgument() { public void excludedFirstArgumentType_DoesNotAffectTrailingArguments() {
validator.doNotAcceptNil(); validator.setFirstArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(NIL, NIL))); validator.validate(new Cons(T, new Cons(NIL, NIL)));
} }
@Test @Test
public void doNotAcceptNil_AllowsEmptyArgumentList() { public void excludedTrailingArgumentType_DoesNotAffectFirstArgument() {
validator.doNotAcceptNil(); validator.setTrailingArgumentExcludedType(Nil.class);
validator.validate(NIL); validator.validate(new Cons(NIL, new Cons(T, NIL)));
} }
@Test @Test(expected = BadArgumentTypeException.class)
public void doNotAcceptNil_AllowsProperList() { public void excludedFirstArgumentType_ThrowsException() {
validator.doNotAcceptNil(); validator.setFirstArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(T, NIL))); validator.validate(new Cons(NIL, new Cons(T, NIL)));
}
@Test(expected = BadArgumentTypeException.class)
public void excludedTrailingArgumentType_ThrowsException() {
validator.setTrailingArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(NIL, NIL)));
}
@Test(expected = BadArgumentTypeException.class)
public void excludedArgumentType_ThrowsExceptionOnFirstArgument() {
validator.setEveryArgumentExcludedType(Nil.class);
validator.validate(new Cons(NIL, new Cons(T, NIL)));
}
@Test(expected = BadArgumentTypeException.class)
public void excludedArgumentType_ThrowsExceptionOnTrailingArgument() {
validator.setEveryArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(NIL, NIL)));
} }
} }