Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use handlebars for code generation #2228

Merged
merged 12 commits into from
May 4, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
convert consts
  • Loading branch information
xlc committed May 4, 2020
commit 7f1a85f3970965f9f93aadcc4e981fc28eec88fb
79 changes: 40 additions & 39 deletions packages/typegen/src/generate/consts.ts
Original file line number Diff line number Diff line change
@@ -2,37 +2,18 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { ModuleMetadataLatest } from '@polkadot/types/interfaces/metadata';
import Handlebars from 'handlebars';

import staticData from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata/Metadata';
import { TypeRegistry } from '@polkadot/types/create';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { stringCamelCase } from '@polkadot/util';

import { FOOTER, HEADER, TypeImports, createDocComments, createImportCode, createImports, indent, registerDefinitions, setImports, writeFile } from '../util';
import { createImports, compareName, readTemplate, registerDefinitions, setImports, writeFile } from '../util';

// Generate types for one module
/** @internal */
function generateModule (allDefs: object, { constants, name }: ModuleMetadataLatest, imports: TypeImports, isStrict: boolean): string[] {
if (!constants.length) {
return [];
}

if (!isStrict) {
setImports(allDefs, imports, ['Codec']);
}

return [indent(4)(`${stringCamelCase(name.toString())}: {`)]
.concat(isStrict ? '' : indent(6)('[index: string]: AugmentedConst<object & Codec>;'))
.concat(constants.sort((a, b) => a.name.localeCompare(b.name.toString())).map(({ documentation, name, type }): string => {
setImports(allDefs, imports, [type.toString()]);

return createDocComments(6, documentation) +
indent(6)(`${stringCamelCase(name.toString())}: AugmentedConst<${type}>;`);
}))
.concat([indent(4)('};')]);
}
const template = readTemplate('consts');
const generateForMetaTemplate = Handlebars.compile(template);

/** @internal */
function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<string, Record<string, { types: Record<string, any> }>>, isStrict: boolean): void {
@@ -42,27 +23,47 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<strin
const allDefs = Object.entries(allTypes).reduce((defs, [path, obj]) => {
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [`${path}/${key}`]: value }), defs);
}, {});
const body = meta.asLatest.modules.sort((a, b) => a.name.localeCompare(b.name.toString())).reduce((acc, mod): string[] => {
return acc.concat(generateModule(allDefs, mod, imports, isStrict));
}, [] as string[]);
const header = createImportCode(HEADER('chain'), imports, [

const modules = meta.asLatest.modules
.sort(compareName)
.filter((mod) => mod.constants.length > 0)
.map(({ constants, name }) => {
if (!isStrict) {
setImports(allDefs, imports, ['Codec']);
}

const items = constants
.sort(compareName)
.map(({ documentation, name, type }) => {
setImports(allDefs, imports, [type.toString()]);

return {
docs: documentation.map((doc) => doc.trim()).filter((doc) => !!doc),
name: stringCamelCase(name.toString()),
type: type.toString()
};
});

return {
items,
name: stringCamelCase(name.toString())
};
});

const types = [
...Object.keys(imports.localTypes).sort().map((packagePath): { file: string; types: string[] } => ({
file: packagePath,
types: Object.keys(imports.localTypes[packagePath])
}))
]);
const interfaceStart = [
"declare module '@polkadot/metadata/Decorated/consts/types' {",
indent(2)('export interface Constants {\n')
].join('\n');
const interfaceEnd = `\n${indent(2)('}')}\n}`;
];

return header
.concat(interfaceStart)
.concat(isStrict ? '' : indent(4)('[index: string]: ModuleConstants;\n'))
.concat(body.join('\n'))
.concat(interfaceEnd)
.concat(FOOTER);
return generateForMetaTemplate({
headerType: 'chain',
imports,
isStrict,
modules,
types
});
});
}

47 changes: 25 additions & 22 deletions packages/typegen/src/generate/query.ts
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import { TypeRegistry } from '@polkadot/types/create';
import { stringCamelCase } from '@polkadot/util';

import { TypeImports, createImports, formatType, getSimilarTypes, readTemplate, registerDefinitions, setImports, writeFile } from '../util';
import { TypeImports, createImports, compareName, formatType, getSimilarTypes, readTemplate, registerDefinitions, setImports, writeFile } from '../util';

// From a storage entry metadata, we return [args, returnType]
/** @internal */
@@ -74,32 +74,35 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [`${path}/${key}`]: value }), defs);
}, {});

const compareName = (a: { name: { toString(): string } }, b: { name: { toString(): string } }): number => a.name.toString().localeCompare(b.name.toString());

const modules = meta.asLatest.modules.sort(compareName).filter((mod) => !mod.storage.isNone).map(({ name, storage }) => {
const items = storage.unwrap().items.sort(compareName).map((storageEntry) => {
const [args, returnType] = entrySignature(allDefs, registry, storageEntry, imports);
let entryType = 'AugmentedQuery';

if (storageEntry.type.isDoubleMap) {
entryType = `${entryType}DoubleMap`;
}
const modules = meta.asLatest.modules
.sort(compareName)
.filter((mod) => !mod.storage.isNone)
.map(({ name, storage }) => {
const items = storage.unwrap().items
.sort(compareName)
.map((storageEntry) => {
const [args, returnType] = entrySignature(allDefs, registry, storageEntry, imports);
let entryType = 'AugmentedQuery';

if (storageEntry.type.isDoubleMap) {
entryType = `${entryType}DoubleMap`;
}

return {
args,
docs: storageEntry.documentation.map((doc) => doc.trim()).filter((doc) => !!doc),
entryType,
name: stringCamelCase(storageEntry.name.toString()),
returnType
};
});

return {
args,
docs: storageEntry.documentation.map((doc) => doc.trim()).filter((doc) => !!doc),
entryType,
name: stringCamelCase(storageEntry.name.toString()),
returnType
items,
name: stringCamelCase(name.toString())
};
});

return {
items,
name: stringCamelCase(name.toString())
};
});

imports.typesTypes.Observable = true;

const types = [
23 changes: 23 additions & 0 deletions packages/typegen/src/templates/consts.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{> header }}

{{{ imports }}}

declare module '@polkadot/metadata/Decorated/consts/types' {
export interface Constants {
{{#unless @root.isStrict}}
[index: string]: ModuleConstants;
{{/unless}}
{{#each modules}}
{{{name}}}: {
{{#unless @root.isStrict}}
[index: string]: AugmentedConst<object & Codec>;
{{/unless}}
{{~#each items}}
{{> docs}}
{{{name}}}: AugmentedConst<{{{type}}}>;
{{/each}}
};
{{/each}}
}
}
{{> footer }}
Empty file.
2 changes: 1 addition & 1 deletion packages/typegen/src/templates/query.hbs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
declare module '@polkadot/api/types/storage' {
export interface AugmentedQueries<ApiType> {
{{#each modules}}
{{name}}: {
{{{name}}}: {
{{#unless @root.isStrict}}
[index: string]: QueryableStorageEntry<ApiType>;
{{/unless}}
2 changes: 1 addition & 1 deletion packages/typegen/src/util/formatting.ts
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ export const HEADER = (type: 'chain' | 'defs'): string => `// Auto-generated via
export const FOOTER = '\n';

Handlebars.registerPartial({
footer: Handlebars.compile(''),
footer: Handlebars.compile(readTemplate('footer')),
header: Handlebars.compile(readTemplate('header'))
});

3 changes: 3 additions & 0 deletions packages/typegen/src/util/index.ts
Original file line number Diff line number Diff line change
@@ -8,3 +8,6 @@ export * from './file';
export * from './formatting';
export * from './imports';
export * from './register';

export const compareName = (a: { name: { toString(): string } }, b: { name: { toString(): string } }): number =>
a.name.toString().localeCompare(b.name.toString());