Adjustments for getTypeDef (#4944)

* Adjustments for getTypeDef

* Cleanup unneeded +

* Adjust sanitize replacers

* Ordering

* Adjust sanitize
This commit is contained in:
Jaco
2022-06-17 11:29:01 +03:00
committed by GitHub
parent 6149b6ca76
commit 51b583d9ea
7 changed files with 60 additions and 75 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import type { Registry } from '@polkadot/types/types';
import type { AnyString, Registry } from '@polkadot/types/types';
import type { TypeDef } from '@polkadot/types-create/types';
import Handlebars from 'handlebars';
@@ -270,7 +270,7 @@ const formatters: Record<TypeDefInfo, (registry: Registry, typeDef: TypeDef, def
*/
/** @internal */
// eslint-disable-next-line @typescript-eslint/ban-types
export function formatType (registry: Registry, definitions: Record<string, ModuleTypes>, type: string | String | TypeDef, imports: TypeImports, withShortcut = false): string {
export function formatType (registry: Registry, definitions: Record<string, ModuleTypes>, type: AnyString | TypeDef, imports: TypeImports, withShortcut = false): string {
let typeDef: TypeDef;
if (isString(type)) {
@@ -53,10 +53,6 @@ describe('sanitize', (): void => {
it('removes on embedded values (all)', (): void => {
expect(fn('(T::AccountId, slashing::SpanIndex)')).toEqual('(AccountId, SpanIndex)');
});
it('keeps with allowNamespaces', (): void => {
expect(fn('::slashing::SpanIndex', { allowNamespaces: true })).toEqual('slashing::SpanIndex');
});
});
describe('bounded', (): void => {
+19 -36
View File
@@ -1,11 +1,9 @@
// Copyright 2017-2022 @polkadot/types-codec authors & contributors
// SPDX-License-Identifier: Apache-2.0
interface SanitizeOptions {
allowNamespaces?: boolean;
}
import { AnyString } from '../types';
type Mapper = (value: string, options?: SanitizeOptions) => string;
type Mapper = (value: string) => string;
const BOUNDED = ['BTreeMap', 'BTreeSet', 'HashMap', 'Vec'];
const ALLOWED_BOXES = BOUNDED.concat(['Compact', 'DoNotConstruct', 'Int', 'Linkage', 'Range', 'RangeInclusive', 'Result', 'Option', 'UInt', 'WrapperKeepOpaque', 'WrapperOpaque']);
@@ -165,7 +163,7 @@ export function removeExtensions (type: string, isSized: boolean): Mapper {
}
export function removeColons (): Mapper {
return (value: string, { allowNamespaces }: SanitizeOptions = {}): string => {
return (value: string): string => {
let index = 0;
while (index !== -1) {
@@ -174,10 +172,6 @@ export function removeColons (): Mapper {
if (index === 0) {
value = value.substring(2);
} else if (index !== -1) {
if (allowNamespaces) {
return value;
}
let start = index;
while (start !== -1 && !BOX_PRECEDING.includes(value[start])) {
@@ -203,7 +197,7 @@ export function removeGenerics (): Mapper {
return (
(
start >= 0 &&
value.substring(start, start + box.length) === box
value.substring(start, index) === box
) && (
// make sure it is stand-alone, i.e. don't catch ElectionResult<...> as Result<...>
start === 0 ||
@@ -225,15 +219,12 @@ export function removeGenerics (): Mapper {
};
}
/** @internal */
function pairOfReplacer (v: string): string {
return `(${v},${v})`;
}
// remove the PairOf wrappers
export function removePairOf (): Mapper {
const replacer = (v: string) => `(${v},${v})`;
return (value: string) =>
replaceTagWith(value, 'PairOf<', pairOfReplacer);
replaceTagWith(value, 'PairOf<', replacer);
}
// remove the type traits
@@ -269,39 +260,31 @@ export function removeTraits (): Mapper {
};
}
/** @internal */
function wrapReplacer (v: string): string {
return v;
}
// remove wrapping values, i.e. Box<Proposal> -> Proposal
export function removeWrap (check: string): Mapper {
const replacer = (v: string) => v;
return (value: string) =>
replaceTagWith(value, check, wrapReplacer);
replaceTagWith(value, check, replacer);
}
const sanitizeMap = new Map<string, string>();
// eslint-disable-next-line @typescript-eslint/ban-types
export function sanitize (value: String | string, options?: SanitizeOptions): string {
export function sanitize (value: AnyString): string {
const startValue = value.toString();
const memoized = sanitizeMap.get(startValue);
if (memoized) {
return memoized;
}
let result = startValue;
if (!options) {
const memoized = sanitizeMap.get(startValue);
if (memoized) {
return memoized;
}
}
for (let i = 0; i < mappings.length; i++) {
result = mappings[i](result, options);
result = mappings[i](result);
}
if (!options) {
sanitizeMap.set(startValue, result);
}
sanitizeMap.set(startValue, result);
return result;
}
+6 -6
View File
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/types-create authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AnyString } from '@polkadot/types-codec/types';
import type { TypeDef } from '@polkadot/types-create/types';
import { sanitize } from '@polkadot/types-codec';
@@ -15,6 +16,8 @@ interface TypeDefOptions {
}
const MAX_NESTED = 64;
const MAX_FIX_LEN = 2048;
const MAX_BIT_LEN = 8192;
const KNOWN_INTERNALS = ['_alias', '_fallback'];
function getTypeString (typeOrObj: any): string {
@@ -132,8 +135,7 @@ function _decodeFixedVec (value: TypeDef, type: string, _: string, count: number
const [strLength, displayName] = type.substring(index + 1, max).split(';');
const length = parseInt(strLength.trim(), 10);
// as a first round, only u8 via u8aFixed, we can add more support
assert(length <= 256, () => `${type}: Only support for [Type; <length>], where length <= 256`);
assert(length <= MAX_FIX_LEN, () => `${type}: Only support for [Type; <length>], where length <= ${MAX_FIX_LEN}`);
value.displayName = displayName;
value.length = length;
@@ -157,8 +159,7 @@ function _decodeAnyInt (value: TypeDef, type: string, _: string, clazz: 'Int' |
const [strLength, displayName] = type.substring(clazz.length + 1, type.length - 1).split(',');
const length = parseInt(strLength.trim(), 10);
// as a first round, only u8 via u8aFixed, we can add more support
assert(length <= 8192 && (length % 8) === 0, () => `${type}: Only support for ${clazz}<bitLength>, where length <= 8192 and a power of 8, found ${length}`);
assert(length <= MAX_BIT_LEN && (length % 8) === 0, () => `${type}: Only support for ${clazz}<bitLength>, where length <= ${MAX_BIT_LEN} and a power of 8, found ${length}`);
value.displayName = displayName;
value.length = length;
@@ -216,8 +217,7 @@ function extractSubType (type: string, [start, end]: [string, string, TypeDefInf
return type.substring(start.length, type.length - end.length);
}
// eslint-disable-next-line @typescript-eslint/ban-types
export function getTypeDef (_type: String | string, { displayName, name }: TypeDefOptions = {}, count = 0): TypeDef {
export function getTypeDef (_type: AnyString, { displayName, name }: TypeDefOptions = {}, count = 0): TypeDef {
// create the type via Type, allowing types to be sanitized
const type = sanitize(_type);
const value: TypeDef = { displayName, info: TypeDefInfo.Plain, name, type };
@@ -36,13 +36,13 @@ describe('typeSplit', (): void => {
it('checks for unclosed vec', (): void => {
expect(
(): string[] => typeSplit('Text, Vec<u64')
() => typeSplit('Text, Vec<u64')
).toThrow(/Invalid definition/);
});
it('checks for unclosed tuple', (): void => {
expect(
(): string[] => typeSplit('Text, (u64, u32')
() => typeSplit('Text, (u64, u32')
).toThrow(/Invalid definition/);
});
});
+29 -24
View File
@@ -3,46 +3,51 @@
import { assert } from '@polkadot/util';
function isNotNested (...counters: number[]): boolean {
return !counters.some((counter): boolean => counter !== 0);
}
// safely split a string on ', ' while taking care of any nested occurences
export function typeSplit (type: string): string[] {
let [cDepth, fDepth, sDepth, tDepth, start] = [0, 0, 0, 0, 0];
const result = [];
const result: string[] = [];
const extract = (index: number): void => {
if (isNotNested(cDepth, fDepth, sDepth, tDepth)) {
result.push(type.substring(start, index).trim());
start = index + 1;
}
};
// these are the depths of the various tokens: <, [, {, (
let c = 0;
let f = 0;
let s = 0;
let t = 0;
for (let index = 0; index < type.length; index++) {
switch (type[index]) {
// current start position
let start = 0;
for (let i = 0; i < type.length; i++) {
switch (type[i]) {
// if we are not nested, add the type
case ',': extract(index); break;
case ',': {
if (!(c || f || s || t)) {
result.push(type.substring(start, i).trim());
start = i + 1;
}
break;
}
// adjust compact/vec (and friends) depth
case '<': cDepth++; break;
case '>': cDepth--; break;
case '<': c++; break;
case '>': c--; break;
// adjust fixed vec depths
case '[': fDepth++; break;
case ']': fDepth--; break;
case '[': f++; break;
case ']': f--; break;
// adjust struct depth
case '{': sDepth++; break;
case '}': sDepth--; break;
case '{': s++; break;
case '}': s--; break;
// adjust tuple depth
case '(': tDepth++; break;
case ')': tDepth--; break;
case '(': t++; break;
case ')': t--; break;
}
}
assert(isNotNested(cDepth, fDepth, sDepth, tDepth), () => `Invalid definition (missing terminators) found in ${type}`);
// ensure we have all the terminators taken care of
assert(!(c || f || s || t), () => `Invalid definition (missing terminators) found in ${type}`);
// the final leg of the journey
result.push(type.substring(start, type.length).trim());