def get_member(self, key: str, node: vy_ast.Attribute) -> EnumDefinition: if key in self.members: return self.from_annotation(node.value) suggestions_str = get_levenshtein_error_suggestions( key, self.members, 0.3) raise UnknownAttribute( f"{self} has no member '{key}'. {suggestions_str}", node)
def _add_import( node: Union[vy_ast.Import, vy_ast.ImportFrom], module: str, name: str, alias: str, interface_codes: InterfaceDict, namespace: dict, ) -> None: if module == "vyper.interfaces": interface_codes = _get_builtin_interfaces() if name not in interface_codes: suggestions_str = get_levenshtein_error_suggestions(name, _get_builtin_interfaces(), 1.0) raise UndeclaredDefinition(f"Unknown interface: {name}. {suggestions_str}", node) if interface_codes[name]["type"] == "vyper": interface_ast = vy_ast.parse_to_ast(interface_codes[name]["code"], contract_name=name) type_ = namespace["interface"].build_primitive_from_node(interface_ast) elif interface_codes[name]["type"] == "json": type_ = namespace["interface"].build_primitive_from_abi(name, interface_codes[name]["code"]) else: raise CompilerPanic(f"Unknown interface format: {interface_codes[name]['type']}") try: namespace[alias] = type_ except VyperException as exc: raise exc.with_annotation(node) from None
def get_type_from_annotation( node: vy_ast.VyperNode, location: DataLocation, is_constant: bool = False, is_public: bool = False, is_immutable: bool = False, ) -> BaseTypeDefinition: """ Return a type object for the given AST node. Arguments --------- node : VyperNode Vyper ast node from the `annotation` member of a `VariableDef` or `AnnAssign` node. Returns ------- BaseTypeDefinition Type definition object. """ namespace = get_namespace() if isinstance(node, vy_ast.Tuple): values = node.elements types = tuple( get_type_from_annotation(v, DataLocation.UNSET) for v in values) return TupleDefinition(types) try: # get id of leftmost `Name` node from the annotation type_name = next( i.id for i in node.get_descendants(vy_ast.Name, include_self=True)) except StopIteration: raise StructureException("Invalid syntax for type declaration", node) try: type_obj = namespace[type_name] except UndeclaredDefinition: suggestions_str = get_levenshtein_error_suggestions( type_name, namespace, 0.3) raise UnknownType( f"No builtin or user-defined type named '{type_name}'. {suggestions_str}", node) from None if (getattr(type_obj, "_as_array", False) and isinstance(node, vy_ast.Subscript) and node.value.get("id") != "DynArray"): # TODO: handle `is_immutable` for arrays # if type can be an array and node is a subscript, create an `ArrayDefinition` length = get_index_value(node.slice) value_type = get_type_from_annotation(node.value, location, is_constant, False, is_immutable) return ArrayDefinition(value_type, length, location, is_constant, is_public, is_immutable) try: return type_obj.from_annotation(node, location, is_constant, is_public, is_immutable) except AttributeError: raise InvalidType(f"'{type_name}' is not a valid type", node) from None
def get_member(self, key: str, node: vy_ast.VyperNode) -> BaseTypeDefinition: if key in self.members: return self.members[key] elif key in getattr(self, "_type_members", []): type_ = copy.deepcopy(self._type_members[key]) type_.location = self.location type_.is_constant = self.is_constant return type_ suggestions_str = get_levenshtein_error_suggestions( key, self.members, 0.3) raise UnknownAttribute( f"{self} has no member '{key}'. {suggestions_str}", node)
def types_from_Attribute(self, node): # variable attribute, e.g. `foo.bar` var = self.get_exact_type_from_node(node.value, only_definitions=False) name = node.attr try: return [var.get_member(name, node)] except UnknownAttribute: if node.get("value.id") != "self": raise if name in self.namespace: raise InvalidReference( f"'{name}' is not a storage variable, it should not be prepended with self", node, ) from None suggestions_str = get_levenshtein_error_suggestions( name, var.members, 0.4) raise UndeclaredDefinition( f"Storage variable '{name}' has not been declared. {suggestions_str}", node) from None
def fetch_call_return(self, node: vy_ast.Call) -> StructDefinition: validate_call_args(node, 1) if not isinstance(node.args[0], vy_ast.Dict): raise VariableDeclarationException( "Struct values must be declared via dictionary", node.args[0]) if next((i for i in self.members.values() if isinstance(i, MappingDefinition)), False): raise VariableDeclarationException( "Struct contains a mapping and so cannot be declared as a literal", node) members = self.members.copy() keys = list(self.members.keys()) for i, (key, value) in enumerate(zip(node.args[0].keys, node.args[0].values)): if key is None or key.get("id") not in members: suggestions_str = get_levenshtein_error_suggestions( key.get("id"), members, 1.0) raise UnknownAttribute( f"Unknown or duplicate struct member. {suggestions_str}", key or value) expected_key = keys[i] if key.id != expected_key: raise InvalidAttribute( "Struct keys are required to be in order, but got " f"`{key.id}` instead of `{expected_key}`. (Reminder: the " f"keys in this struct are {list(self.members.items())})", key, ) validate_expected_type(value, members.pop(key.id)) if members: raise VariableDeclarationException( f"Struct declaration does not define all fields: {', '.join(list(members))}", node) return StructDefinition(self._id, self.members)
def __getitem__(self, key): if key not in self: suggestions_str = get_levenshtein_error_suggestions(key, self, 0.2) raise UndeclaredDefinition( f"'{key}' has not been declared. {suggestions_str}") return super().__getitem__(key)