-
Notifications
You must be signed in to change notification settings - Fork 118
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
Provide helpers to list inherited functions (and other items) #433
Comments
You're right this should be available out of the box, there is quite a bit of complexity. I've implemented this for OpenZeppelin Contracts so you can reuse that but adding this in your module.exports.inheritance = function ({ item, build }) {
if (!isNodeType('ContractDefinition', item)) {
throw new Error('used inherited-items on non-contract');
}
return item.linearizedBaseContracts
.map(id => build.deref('ContractDefinition', id))
.filter((c, i) => c.name !== 'Context' || i === 0);
};
module.exports['inherited-functions'] = function ({ item }) {
const { inheritance } = item;
const baseFunctions = new Set(inheritance.flatMap(c => c.functions.flatMap(f => f.baseFunctions ?? [])));
return inheritance.map((contract, i) => ({
contract,
functions: contract.functions.filter(f => !baseFunctions.has(f.id) && (f.name !== 'constructor' || i === 0)),
}));
}; Later use it in the |
Thanks a lot for your answer! I've been tinkering all day (it's my first serious contact with TypeScript) and this is what I came up with: export function allItems(this: DocItemWithContext, nodeTypeName: string) {
if (this.nodeType == 'ContractDefinition') {
const { deref } = this.__item_context.build;
const parents = this.linearizedBaseContracts.map(deref('ContractDefinition'));
let items: (EnumDefinition | ErrorDefinition | EventDefinition | FunctionDefinition | ModifierDefinition
| StructDefinition | UserDefinedValueTypeDefinition | VariableDeclaration)[] = [];
parents.forEach(p => {
p.nodes.forEach(n => {
// Filter out other types
if (n.nodeType == 'UsingForDirective' || n.nodeType != nodeTypeName) return;
// Filter out private fields
if ((n.nodeType == 'VariableDeclaration' || n.nodeType == 'FunctionDefinition') &&
(n.visibility != 'public' && n.visibility != 'external')) return;
if (n.nodeType == 'FunctionDefinition' && n.virtual) return;
// If this item already exists do not add it again.
// linearizedBaseContracts returned the children first and then the parents, so if the item
// already exists it means that it is an override, and we want to keep those (if they had any docs).
const prev = items.find(i => i.name == n.name);
const prevDocs = prev && (
prev.nodeType == 'ErrorDefinition' ||
prev.nodeType == 'EventDefinition' ||
prev.nodeType == 'FunctionDefinition') ? prev.documentation : null;
if (!prev || !prevDocs)
items.push(n);
});
});
items.sort((a, b) => a.name < b.name ? -1 : 1);
return items;
}
} I've added this to |
I can't find a simple way of retrieving all the methods available in a contract, including inherited ones.
I'm currently working on a helper method that iterates over all
linearizedBaseContracts
, retrieves their methods and merges them. But I need to take into account visibility, overrides... it starts to look like a lot of work and I kind of think such a basic thing should be available out of the box.What am I missing?
The text was updated successfully, but these errors were encountered: