Skip to content

Commit

Permalink
Form Parameter module to cohese all the internalType jabroney
Browse files Browse the repository at this point in the history
  • Loading branch information
gnidan committed Jun 4, 2023
1 parent b487a70 commit b2b453c
Show file tree
Hide file tree
Showing 4 changed files with 464 additions and 218 deletions.
177 changes: 92 additions & 85 deletions packages/abi-to-sol/src/declarations/find.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type * as Abi from "@truffle/abi-utils";
import { abiTupleSignature } from "@truffle/abi-utils";

import { Type, isType } from "../type";
import { Parameter, isParameter } from "../parameter";

import { Identifier } from "./identifier";
import { Kind, HasBindings } from "./kind";
Expand All @@ -13,113 +12,121 @@ export const find = (
): Kind<HasBindings> => {
const { type } = parameter;

if (!isType(type)) {
if (!isParameter(parameter)) {
throw new Error(
`Parameter type \`${type}\` is not a valid ABI type`
`Parameter type \`${parameter.type}\` is not a valid ABI type`
);
}

if (Type.isElementary(type)) {
const { internalType } = parameter;

const identifier = Identifier.fromInternalType(internalType);
if (type === internalType || !identifier) {
return {
type,
...(
internalType
? { hints: { internalType } }
: {}
)
};
}

const reference = Identifier.toReference(identifier);

const kind = declarations.byIdentifierReference[reference];
if (Parameter.isElementary(parameter)) {
return findElementary(parameter, declarations);
}

if (!kind) {
throw new Error(
`Unknown declaration with identifier reference ${reference}`
);
}
if (Parameter.isArray(parameter)) {
return findArray(parameter, declarations);
}

return kind;
if (Parameter.isTuple(parameter)) {
return findTuple(parameter, declarations);
}

if (Type.isArray(type)) {
const itemType = Type.Array.underlying(type);

const partial: Omit<Kind.Array<HasBindings>, "itemKind"> = Type.Array.isStatic(type)
? { length: Type.Array.length(type) }
: {};

let itemInternalType;
{
const { internalType = "" } = parameter;
const match = type.match(/^(.+)\[[^\]]*\]$/);
if (match) {
const [_, underlying] = match;
itemInternalType = underlying;
}
}
throw new Error(`Unknown type ${type}`);
}

const itemKind = find({
...parameter,
const findElementary = (
parameter: Parameter.Elementary,
declarations: Declarations<HasBindings>
): Kind<HasBindings> => {
if (!Parameter.isUserDefinedValueType(parameter)) {
const { type, internalType } = parameter;
return {
type,
...(
itemInternalType && itemInternalType !== "tuple"
? { internalType: itemInternalType }
internalType
? { hints: { internalType } }
: {}
),
type: itemType
}, declarations);
)
}
}

return {
...partial,
itemKind
};
const { name, scope } = Parameter.UserDefinedValueType.recognize(
parameter
);
const identifier = Identifier.UserDefinedValueType.create({ name, scope });
const reference = Identifier.toReference(identifier);

const kind = declarations.byIdentifierReference[reference];

if (!kind) {
throw new Error(
`Unknown declaration with identifier reference ${reference}`
);
}

if (Type.isTuple(type)) {
const {
internalType,
components = [] // default satisfies typechecker; value should exist
} = parameter;
const identifier = Identifier.fromInternalType(internalType);
const signature = abiTupleSignature(components);

if (identifier) {
const reference = Identifier.toReference(identifier);

const kind = declarations.byIdentifierReference[reference];
if (!kind) {
throw new Error(
`Unknown declaration with identifier reference ${reference}`
);
}

return kind;
}
return kind;
};

const findArray = (
parameter: Parameter.Array,
declarations: Declarations<HasBindings>
): Kind<HasBindings> => {
const itemParameter = Parameter.Array.item(parameter);

const itemKind = find(itemParameter, declarations);

return {
itemKind,
...(
Parameter.Array.isStatic(parameter)
? { length: Parameter.Array.Static.length(parameter) }
: {}
)
};
}

// reaching here guarantees no internalType specified for `parameter`
// so only match declarations that also have no internalType
const findTuple = (
parameter: Parameter.Tuple,
declarations: Declarations<HasBindings>
): Kind<HasBindings> => {
const {
signature,
name,
scope
} = Parameter.Tuple.recognize(parameter);

const kind = Object.values(declarations.byIdentifierReference)
.find(kind =>
Kind.isStruct(kind) &&
kind.signature === signature &&
!kind.hints?.internalType
)
const identifier = name
? Identifier.Struct.create({ name, scope })
: undefined;

if (identifier) {
const reference = Identifier.toReference(identifier);

const kind = declarations.byIdentifierReference[reference];

if (!kind) {
throw new Error(
`Unknown declaration with tuple signature ${signature}`
`Unknown declaration with identifier reference ${reference}`
);
}

return kind;
}

throw new Error(`Unknown type ${type}`);
// reaching here guarantees no internalType specified for `parameter`
// so only match declarations that also have no internalType

const kind = Object.values(declarations.byIdentifierReference)
.find(kind =>
Kind.isStruct(kind) &&
kind.signature === signature &&
!kind.hints?.internalType
)

if (!kind) {
throw new Error(
`Unknown declaration with tuple signature ${signature}`
);
}

return kind;
}
Loading

0 comments on commit b2b453c

Please sign in to comment.