diff --git a/js/scripts/build-rpc-markdown.js b/js/scripts/build-rpc-markdown.js
index a06f2ed49..2407cf208 100644
--- a/js/scripts/build-rpc-markdown.js
+++ b/js/scripts/build-rpc-markdown.js
@@ -16,11 +16,12 @@
import fs from 'fs';
import path from 'path';
-import chalk from 'chalk';
import { isPlainObject } from 'lodash';
+import { info, warn, error } from './helpers/log';
import { Dummy } from '../src/jsonrpc/helpers';
import interfaces from '../src/jsonrpc';
+import rustMethods from './helpers/parsed-rpc-traits';
const ROOT_DIR = path.join(__dirname, '../docs');
@@ -28,20 +29,13 @@ if (!fs.existsSync(ROOT_DIR)) {
fs.mkdirSync(ROOT_DIR);
}
-// INFO Logging helper
-function info (log) {
- console.log(chalk.blue(`INFO:\t${log}`));
-}
-
-// WARN Logging helper
-function warn (log) {
- console.warn(chalk.yellow(`WARN:\t${log}`));
-}
-
-// ERROR Logging helper
-function error (log) {
- console.error(chalk.red(`ERROR:\t${log}`));
-}
+Object.keys(rustMethods).forEach((group) => {
+ Object.keys(rustMethods[group]).forEach((method) => {
+ if (interfaces[group] == null || interfaces[group][method] == null) {
+ error(`${group}_${method} is defined in Rust traits, but not in js/src/jsonrpc/interfaces`);
+ }
+ });
+});
function printType (type) {
return type.print || `\`${type.name}\``;
@@ -291,7 +285,8 @@ Object.keys(interfaces).sort().forEach((group) => {
Object.keys(spec).sort(methodComparator).forEach((iname) => {
const method = spec[iname];
- const name = `${group.replace(/_.*$/, '')}_${iname}`;
+ const groupName = group.replace(/_.*$/, '');
+ const name = `${groupName}_${iname}`;
if (method.nodoc || method.deprecated) {
info(`Skipping ${name}: ${method.nodoc || 'Deprecated'}`);
@@ -299,6 +294,10 @@ Object.keys(interfaces).sort().forEach((group) => {
return;
}
+ if (rustMethods[groupName] == null || rustMethods[groupName][iname] == null) {
+ error(`${name} is defined in js/src/jsonrpc/interfaces, but not in Rust traits`);
+ }
+
const desc = method.desc;
const params = buildParameters(method.params);
const returns = `- ${formatType(method.returns)}`;
diff --git a/js/scripts/helpers/log.js b/js/scripts/helpers/log.js
new file mode 100644
index 000000000..dc4955649
--- /dev/null
+++ b/js/scripts/helpers/log.js
@@ -0,0 +1,32 @@
+// Copyright 2015-2017 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import chalk from 'chalk';
+
+// INFO Logging helper
+export function info (log) {
+ console.log(chalk.blue(`INFO:\t${log}`));
+}
+
+// WARN Logging helper
+export function warn (log) {
+ console.warn(chalk.yellow(`WARN:\t${log}`));
+}
+
+// ERROR Logging helper
+export function error (log) {
+ console.error(chalk.red(`ERROR:\t${log}`));
+}
diff --git a/js/scripts/helpers/parsed-rpc-traits.js b/js/scripts/helpers/parsed-rpc-traits.js
new file mode 100644
index 000000000..9f2d4ea8a
--- /dev/null
+++ b/js/scripts/helpers/parsed-rpc-traits.js
@@ -0,0 +1,81 @@
+// Copyright 2015-2017 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import fs from 'fs';
+import path from 'path';
+
+// ```js
+// rustMethods['eth']['call'] === true
+// ```
+const rustMethods = {};
+
+export default rustMethods;
+
+// Get a list of JSON-RPC from Rust trait source code
+function parseMethodsFromRust (source) {
+ // Matching the custom `rpc` attribute with it's doc comment
+ const attributePattern = /((?:\s*\/\/\/.*$)*)\s*#\[rpc\(([^)]+)\)]/gm;
+ const commentPattern = /\s*\/\/\/\s*/g;
+ const separatorPattern = /\s*,\s*/g;
+ const assignPattern = /([\S]+)\s*=\s*"([^"]*)"/;
+ const ignorePattern = /@(ignore|deprecated|unimplemented|alias)\b/i;
+
+ const methods = [];
+
+ source.toString().replace(attributePattern, (match, comment, props) => {
+ comment = comment.replace(commentPattern, '\n').trim();
+
+ // Skip deprecated methods
+ if (ignorePattern.test(comment)) {
+ return match;
+ }
+
+ props.split(separatorPattern).forEach((prop) => {
+ const [, key, value] = prop.split(assignPattern) || [];
+
+ if (key === 'name' && value != null) {
+ methods.push(value);
+ }
+ });
+
+ return match;
+ });
+
+ return methods;
+}
+
+// Get a list of all JSON-RPC methods from all defined traits
+function getMethodsFromRustTraits () {
+ const traitsDir = path.join(__dirname, '../../../rpc/src/v1/traits');
+
+ return fs.readdirSync(traitsDir)
+ .filter((name) => name !== 'mod.rs' && /\.rs$/.test(name))
+ .map((name) => fs.readFileSync(path.join(traitsDir, name)))
+ .map(parseMethodsFromRust)
+ .reduce((a, b) => a.concat(b));
+}
+
+getMethodsFromRustTraits().sort().forEach((method) => {
+ const [group, name] = method.split('_');
+
+ // Skip methods with malformed names
+ if (group == null || name == null) {
+ return;
+ }
+
+ rustMethods[group] = rustMethods[group] || {};
+ rustMethods[group][name] = true;
+});
diff --git a/js/src/jsonrpc/index.spec.js b/js/src/jsonrpc/index.spec.js
index 66988b664..af4afb9c9 100644
--- a/js/src/jsonrpc/index.spec.js
+++ b/js/src/jsonrpc/index.spec.js
@@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-import fs from 'fs';
-import path from 'path';
import interfaces from './';
import * as customTypes from './types';
@@ -27,91 +25,13 @@ function verifyType (obj) {
}
}
-// Get a list of JSON-RPC from Rust trait source code
-function parseMethodsFromRust (source) {
- // Matching the custom `rpc` attribute with it's doc comment
- const attributePattern = /((?:\s*\/\/\/.*$)*)\s*#\[rpc\(([^)]+)\)]/gm;
- const commentPattern = /\s*\/\/\/\s*/g;
- const separatorPattern = /\s*,\s*/g;
- const assignPattern = /([\S]+)\s*=\s*"([^"]*)"/;
- const ignorePattern = /@(ignore|deprecated|unimplemented|alias)\b/i;
-
- const methods = [];
-
- source.toString().replace(attributePattern, (match, comment, props) => {
- comment = comment.replace(commentPattern, '\n').trim();
-
- // Skip deprecated methods
- if (ignorePattern.test(comment)) {
- return match;
- }
-
- props.split(separatorPattern).forEach((prop) => {
- const [, key, value] = prop.split(assignPattern) || [];
-
- if (key === 'name' && value != null) {
- methods.push(value);
- }
- });
-
- return match;
- });
-
- return methods;
-}
-
-// Get a list of all JSON-RPC methods from all defined traits
-function getMethodsFromRustTraits () {
- const traitsDir = path.join(__dirname, '../../../rpc/src/v1/traits');
-
- return fs.readdirSync(traitsDir)
- .filter((name) => name !== 'mod.rs' && /\.rs$/.test(name))
- .map((name) => fs.readFileSync(path.join(traitsDir, name)))
- .map(parseMethodsFromRust)
- .reduce((a, b) => a.concat(b));
-}
-
-const rustMethods = {};
-
-getMethodsFromRustTraits().sort().forEach((method) => {
- const [group, name] = method.split('_');
-
- // Skip methods with malformed names
- if (group == null || name == null) {
- return;
- }
-
- rustMethods[group] = rustMethods[group] || {};
- rustMethods[group][name] = true;
-});
-
describe('jsonrpc/interfaces', () => {
- describe('Rust trait methods', () => {
- Object.keys(rustMethods).forEach((group) => {
- describe(group, () => {
- Object.keys(rustMethods[group]).forEach((name) => {
- describe(name, () => {
- it('has a defined JS interface', () => {
- expect(interfaces[group][name]).to.exist;
- });
- });
- });
- });
- });
- });
-
Object.keys(interfaces).forEach((group) => {
describe(group, () => {
Object.keys(interfaces[group]).forEach((name) => {
const method = interfaces[group][name];
describe(name, () => {
- if (!method.nodoc) {
- it('is present in Rust codebase', () => {
- expect(rustMethods[group][name]).to.exist;
- });
- }
-
it('has the correct interface', () => {
expect(method.desc).to.be.a('string');
expect(method.params).to.be.an('array');