Skip to content

Commit

Permalink
statically check whether a contract always fails
Browse files Browse the repository at this point in the history
  • Loading branch information
phpnode committed Dec 4, 2015
1 parent a7e2997 commit a3e4fb2
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
25 changes: 17 additions & 8 deletions src/index.js
Expand Up @@ -80,7 +80,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Function ${name}precondition failed: ${generate(condition.node).code}`);
}
path.replaceWith(guard({
condition,
condition: staticCheck(condition),
message
}));
return;
Expand All @@ -102,7 +102,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Function ${name}precondition failed: ${generate(condition.node).code}`);
}
statement.replaceWith(guard({
condition,
condition: staticCheck(condition),
message
}));
}
Expand Down Expand Up @@ -135,7 +135,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Function ${name}postcondition failed: ${generate(condition.node).code}`);
}
conditions.push(guard({
condition,
condition: staticCheck(condition),
message
}));
}
Expand Down Expand Up @@ -167,7 +167,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Function ${name}postcondition failed: ${generate(condition.node).code}`);
}
statement.replaceWith(guard({
condition,
condition: staticCheck(condition),
message
}));
}
Expand Down Expand Up @@ -206,7 +206,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Assertion failed: ${generate(condition.node).code}`);
}
path.replaceWith(guard({
condition,
condition: staticCheck(condition),
message
}));
return;
Expand All @@ -231,7 +231,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Assertion failed: ${generate(condition.node).code}`);
}
statement.replaceWith(guard({
condition,
condition: staticCheck(condition),
message
}));
}
Expand Down Expand Up @@ -263,7 +263,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Function ${name}invariant failed: ${generate(condition.node).code}`);
}
conditions.push(guard({
condition,
condition: staticCheck(condition),
message
}));
}
Expand All @@ -284,7 +284,7 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
message = t.stringLiteral(`Function ${name}invariant failed: ${generate(condition.node).code}`);
}
statement.replaceWith(guard({
condition,
condition: staticCheck(condition),
message
}));
}
Expand All @@ -311,6 +311,15 @@ export default function ({types: t, template, options}: PluginParams): Plugin {
};
}

function staticCheck (expression: NodePath): NodePath {
const {confident, value} = expression.evaluate();
if (confident && !value) {
throw expression.buildCodeFrameError(`Contract always fails.`);
}

return expression;
}

return {
visitor: {
Function (fn: NodePath, {opts}): void {
Expand Down
6 changes: 5 additions & 1 deletion test/fixtures/bad-assert-no-function.js
@@ -1,5 +1,9 @@
assert: false;
assert: fail();

export default function demo (input) {
assert: input.length > 0;
}

function fail () {
return false;
}
6 changes: 6 additions & 0 deletions test/fixtures/bad-precondition-always-false.js
@@ -0,0 +1,6 @@
export default function demo (input) {
pre: {
false;
}
return input.length;
}
3 changes: 2 additions & 1 deletion test/index.js
Expand Up @@ -12,6 +12,7 @@ else {
}

describe('Typecheck', function () {
failStatic('bad-precondition-always-false', 'foobar');
ok('class', 'first', 'second');
ok('old-value', 5, 5);
failWith(`Function "add5" postcondition failed: input === old(input) + 5`, 'old-value', 5, 10);
Expand All @@ -33,7 +34,7 @@ describe('Typecheck', function () {
ok('assert-with-message', 'hello');
failWith(`input cannot be empty`, 'assert-with-message', '');
ok('assert-no-function', 'hello');
failWith(`Assertion failed: false`, 'bad-assert-no-function', 'hello');
failWith(`Assertion failed: fail()`, 'bad-assert-no-function', 'hello');
ok('example-2', 1, 2);
ok('example-2', 1);
ok('example-2', 0, 2);
Expand Down

0 comments on commit a3e4fb2

Please sign in to comment.