-
Notifications
You must be signed in to change notification settings - Fork 1
Home
First of all you may want to read my blog post with information about Design by Contract (DbC), DbC preconditions and the motivation behind the Call by Contract (CbC) JavaScript library. You can find it here:
http://knutkj.wordpress.com/2012/03/11/call-by-contract-cbc-javascript-library/
Call by Contract is a JavaScript library with function argument assertions, a function parser and assertion wrapper functionality. The interface is fluid and specially optimised for the Visual Studio JavaScript IntelliSense. The library can be installed in Visual Studio with the NuGet Package Manager Console like this:
Install-Package cbc
Include the JavaScript file Scripts\cbc.js
or the minified version Scripts\cbc.min.js
for all CbC functionality.
The current version contains these assertions:
-
defined
: asserts that the parameter has been specified, that the argument is notundefined
-
notNull
: asserts that the argument is notnull
-
bool
: asserts that the argument is of typeBoolean
if argument is notundefined
ornull
-
func
: same asbool
but asserts that the argument is of typeFunction
-
number
: same asbool
but asserts that the argument is of typeNumber
-
object
same asbool
but asserts that the argument is of typeObject
-
string
same asbool
but asserts that the argument is of typeString
-
notEmpty
may only be combined with thestring
assertion and asserts that the argument is not an empty string
function showMessage (message) {
cbc.assert.that.param("message", message).is // .that may be omitted
.defined()
.and.notNull()
.and.string()
.and.notEmpty(); // May only be specified after string assertion
alert(message);
}
function incrementCounter (num) {
$.assert.param("num", num).is // If jQuery is included
.defined().and.notNull().and.number();
counter += num;
}
The cbc.parse
namespace contains a function parser. The parser searches for function metadata. It returns a cbc.parse.FuncInfo
object. If there are any parameters the FuncInfo
object will have a list of cbc.parse.ParamInfo
objects. Use the get_params
method to get the list.
Here is the complete list of what the function parser searches for:
- Name of the function
- Function description (in Visual Studio JavaScript doc comments)
- Parameters:
- Name of parameter
- Type of parameter (in JavaScript doc comments)
- If the parameter may be null (in JavaScript doc comments)
- If the parameter is optional (in JavaScript doc comments)
- Parameter description (in JavaScript doc comments)
- Function return type (in JavaScript doc comments)
- Function return description (in JavaScript doc comments)
cbc.parse.func(cbc.parse.func).toString()
cbc.parse.func
function:
NAME func SYNOPSIS Parses the specified function. SYNTAX <[[FuncInfo object|cbc.parse.FuncInfo]]> func(Function func) PARAMETERS -func <Function> The function to parse. OUTPUTS <[[FuncInfo object|cbc.parse.FuncInfo]]> A FuncInfo object.
You may also use cbc.parse.getDoc
to get a function's Visual Studio doc comments:
NAME getDoc SYNOPSIS Get the function's Visual Studio JavaScript doc comments. SYNTAX <String> getDoc(String funcString) PARAMETERS -funcString <String> The result of a function's toString. OUTPUTS <String> The function's Visual Studio JavaScript doc comments.
The cbc.contract
namespace contains a wrapper function (cbc.contract.wrap
). The wrapper function creates a wrapper function with parameter assertions. It uses cbc.assert
for assertions. It uses Visual Studio JavaScript doc comments to find out which assertions to apply. It uses cbc.parse
to find the doc comments. Here is a sample of its usage:
function toBeWrapped (a) {
/// <param name="a" type="String" mayBeNull="false" optional="false" />
}
var wrapper = cbc.contract.wrap(toBeWrapped);
try { wrapper(); }
catch (e) { console.log(e.message); }
try { wrapper(null); }
catch (e) { console.log(e.message); }
try { wrapper(1); }
catch (e) { console.log(e.message); }
Here are the messages that was logged to the console:
Parameter a must be specified. Parameter a must not be null. Parameter a must be of type string.
The wrapper function looks like this:
function (a) {
/// <param name="a" type="String" mayBeNull="false" optional="false" />
cbc.assert.param("a", a).is.defined().and.notNull().and.string();
return func.apply(this, arguments);
}
Here is the cbc.contract.wrap
function's API documentation:
NAME wrap SYNOPSIS Wraps the specified function inside a contract. SYNTAX <Function> wrap(Function func) PARAMETERS -func <Function> The function to wrap inside a contract. OUTPUTS <Function> The wrapped function.