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

fix[ux]: internal functions not in metadata #4328

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
44 changes: 44 additions & 0 deletions tests/unit/cli/vyper_json/test_output_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest

from vyper import compiler
from vyper.cli.vyper_json import TRANSLATE_MAP, get_output_formats
from vyper.exceptions import JSONError

Expand Down Expand Up @@ -76,3 +77,46 @@ def test_solc_style():
def test_metadata():
input_json = {"sources": {"foo.vy": ""}, "settings": {"outputSelection": {"*": ["metadata"]}}}
assert get_output_formats(input_json) == {PurePath("foo.vy"): ["metadata"]}


def test_metadata_contain_all_reachable_functions(make_input_bundle):
code_a = """
@internal
def foo() -> uint256:
return 43

@internal
def faa() -> uint256:
return 76
"""

code_b = """
import A

@internal
def foo() -> uint256:
return 43

@external
def bar():
self.foo()
A.foo()
assert 1 != 12
"""

input_bundle = make_input_bundle({"A.vy": code_a, "B.vy": code_b})

out = compiler.compile_code(code_b, input_bundle=input_bundle, output_formats=["metadata"])[
"metadata"
]["function_info"]

def has_suffix_key(data: dict, suffix: str) -> bool:
for key in data.keys():
if key.endswith(suffix):
return True
return False

assert has_suffix_key(out, "0: foo")
assert has_suffix_key(out, "bar")
assert has_suffix_key(out, "1: foo")
assert not has_suffix_key(out, "faa")
13 changes: 11 additions & 2 deletions vyper/compiler/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from vyper.exceptions import VyperException
from vyper.ir import compile_ir
from vyper.semantics.analysis.base import ModuleInfo
from vyper.semantics.types.function import FunctionVisibility, StateMutability
from vyper.semantics.types.function import ContractFunctionT, FunctionVisibility, StateMutability
from vyper.semantics.types.module import InterfaceT
from vyper.typing import StorageLayout
from vyper.utils import vyper_warn
Expand Down Expand Up @@ -206,7 +206,16 @@ def build_ir_runtime_dict_output(compiler_data: CompilerData) -> dict:


def build_metadata_output(compiler_data: CompilerData) -> dict:
sigs = compiler_data.function_signatures
# need ir info to be computed
_ = compiler_data.function_signatures
charles-cooper marked this conversation as resolved.
Show resolved Hide resolved
module_t = compiler_data.annotated_vyper_module._metadata["type"]
sigs = dict[str, ContractFunctionT]()

for fn_t in module_t.exposed_functions:
assert isinstance(fn_t.ast_def, vy_ast.FunctionDef)
for rif_t in fn_t.reachable_internal_functions:
sigs[str(rif_t._ir_info.func_t._function_id) + ": " + rif_t.name] = rif_t
sigs[fn_t.name] = fn_t

def _var_rec_dict(variable_record):
ret = vars(variable_record).copy()
Expand Down
Loading