From 71a51ff82941a3b04bb718e1e74c94d1800148b3 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 08:55:45 +0300 Subject: [PATCH 01/20] chore: add `phase` to each expression during type checking No functional changes, preparatory pull request as part of the expression lifting escapade. To support expression lifting, the type checker now records the phase of each expression during type checking and makes it available through `get_expr_phase`. Additionally, turn the variable component of `StmtKind::Assignment` from a simple `Symbol` to an `Expr` in order for it to also hold type and phase information. The JSII importer accidentally imported structs as `preflight` while they should be phase-independent. Misc: strip excess newlines when adding a line to `CodeMaker`. --- libs/wingc/src/closure_transform.rs | 33 +- libs/wingc/src/fold.rs | 2 +- libs/wingc/src/jsify/codemaker.rs | 7 +- libs/wingc/src/parser.rs | 8 +- libs/wingc/src/type_check.rs | 281 +++++++++++------- .../wingc/src/type_check/class_fields_init.rs | 23 +- libs/wingc/src/type_check/jsii_importer.rs | 8 +- libs/wingc/src/visit.rs | 2 +- 8 files changed, 219 insertions(+), 145 deletions(-) diff --git a/libs/wingc/src/closure_transform.rs b/libs/wingc/src/closure_transform.rs index e01ff30f388..5721bde1a68 100644 --- a/libs/wingc/src/closure_transform.rs +++ b/libs/wingc/src/closure_transform.rs @@ -177,21 +177,24 @@ impl Fold for ClosureTransformer { let class_init_body = vec![Stmt { idx: 0, kind: StmtKind::Assignment { - variable: Reference::InstanceMember { - object: Box::new(Expr::new( - ExprKind::Reference(Reference::InstanceMember { - object: Box::new(Expr::new( - ExprKind::Reference(Reference::Identifier(Symbol::new("this", WingSpan::default()))), - WingSpan::default(), - )), - property: Symbol::new("display", WingSpan::default()), - optional_accessor: false, - }), - WingSpan::default(), - )), - property: Symbol::new("hidden", WingSpan::default()), - optional_accessor: false, - }, + variable: Expr::new( + ExprKind::Reference(Reference::InstanceMember { + object: Box::new(Expr::new( + ExprKind::Reference(Reference::InstanceMember { + object: Box::new(Expr::new( + ExprKind::Reference(Reference::Identifier(Symbol::new("this", WingSpan::default()))), + WingSpan::default(), + )), + property: Symbol::new("display", WingSpan::default()), + optional_accessor: false, + }), + WingSpan::default(), + )), + property: Symbol::new("hidden", WingSpan::default()), + optional_accessor: false, + }), + WingSpan::default(), + ), value: Expr::new(ExprKind::Literal(Literal::Boolean(true)), WingSpan::default()), }, span: WingSpan::default(), diff --git a/libs/wingc/src/fold.rs b/libs/wingc/src/fold.rs index ea265838b74..1b8f4536d96 100644 --- a/libs/wingc/src/fold.rs +++ b/libs/wingc/src/fold.rs @@ -141,7 +141,7 @@ where StmtKind::Return(value) => StmtKind::Return(value.map(|value| f.fold_expr(value))), StmtKind::Expression(expr) => StmtKind::Expression(f.fold_expr(expr)), StmtKind::Assignment { variable, value } => StmtKind::Assignment { - variable: f.fold_reference(variable), + variable: f.fold_expr(variable), value: f.fold_expr(value), }, StmtKind::Scope(scope) => StmtKind::Scope(f.fold_scope(scope)), diff --git a/libs/wingc/src/jsify/codemaker.rs b/libs/wingc/src/jsify/codemaker.rs index eef3d72a1b1..995ad46306c 100644 --- a/libs/wingc/src/jsify/codemaker.rs +++ b/libs/wingc/src/jsify/codemaker.rs @@ -23,8 +23,13 @@ impl CodeMaker { /// Emits a line of code with the current indent. pub fn line>(&mut self, line: S) { + let line: String = line.into(); + + // remove trailing newline + let line = line.strip_suffix("\n").unwrap_or(&line); + // if the line has newlines in it, consider each line separately - for subline in line.into().split('\n') { + for subline in line.split('\n') { self.lines.push((self.indent, subline.into())); } } diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index bb77ddf18a8..8f1e33faa3c 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -392,7 +392,7 @@ impl<'s> Parser<'s> { let reference = self.build_reference(&statement_node.child_by_field_name("name").unwrap(), phase)?; if let ExprKind::Reference(r) = reference.kind { Ok(StmtKind::Assignment { - variable: r, + variable: Expr::new(ExprKind::Reference(r), reference.span), value: self.build_expression(&statement_node.child_by_field_name("value").unwrap(), phase)?, }) } else { @@ -590,7 +590,7 @@ impl<'s> Parser<'s> { .err(); } - let return_type = Box::new(TypeAnnotation { + let init_return_type = Box::new(TypeAnnotation { kind: TypeAnnotationKind::UserDefined(UserDefinedType { root: name.clone(), fields: vec![], @@ -606,7 +606,7 @@ impl<'s> Parser<'s> { ), signature: FunctionSignature { parameters, - return_type, + return_type: init_return_type, phase: Phase::Inflight, }, is_static: false, @@ -620,7 +620,7 @@ impl<'s> Parser<'s> { is_static: false, signature: FunctionSignature { parameters, - return_type, + return_type: init_return_type, phase: Phase::Preflight, }, span: self.node_span(&class_element), diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index fadd05c2d9e..aff4dfe98fa 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -983,6 +983,10 @@ impl Debug for TypeRef { } } +struct ResolvedExpression { + type_: TypeRef, + phase: Phase, +} pub struct Types { // TODO: Remove the box and change TypeRef and NamespaceRef to just be indices into the types array and namespaces array respectively // Note: we need the box so reallocations of the vec while growing won't change the addresses of the types since they are referenced from the TypeRef struct @@ -1000,7 +1004,7 @@ pub struct Types { nil_idx: usize, err_idx: usize, - type_for_expr: Vec>, + type_for_expr: Vec>, resource_base_type: Option, } @@ -1144,18 +1148,28 @@ impl Types { } /// Stores the type of a given expression node. - pub fn assign_type_to_expr(&mut self, expr: &Expr, type_: TypeRef) { + pub fn assign_type_to_expr(&mut self, expr: &Expr, type_: TypeRef, phase: Phase) { let expr_idx = expr.id; if self.type_for_expr.len() <= expr_idx { self.type_for_expr.resize_with(expr_idx + 1, || None); } - self.type_for_expr[expr_idx] = Some(type_); + self.type_for_expr[expr_idx] = Some(ResolvedExpression { type_, phase }); } /// Obtain the type of a given expression node. Returns None if the expression has not been type checked yet. If /// this is called after type checking, it should always return Some. pub fn get_expr_type(&self, expr: &Expr) -> Option { - self.type_for_expr.get(expr.id).and_then(|t| *t) + self + .type_for_expr + .get(expr.id) + .and_then(|t| t.as_ref().map(|t| t.type_)) + } + + pub fn get_expr_phase(&self, expr: &Expr) -> Option { + self + .type_for_expr + .get(expr.id) + .and_then(|t| t.as_ref().map(|t| t.phase)) } } @@ -1256,49 +1270,50 @@ impl<'a> TypeChecker<'a> { } // Validates types in the expression make sense and returns the expression's inferred type - fn type_check_exp(&mut self, exp: &Expr, env: &SymbolEnv) -> TypeRef { + fn type_check_exp(&mut self, exp: &Expr, env: &SymbolEnv) -> (TypeRef, Phase) { CompilationContext::set(CompilationPhase::TypeChecking, &exp.span); - let t = self.type_check_exp_helper(&exp, env); - self.types.assign_type_to_expr(exp, t); - t + let (t, phase) = self.type_check_exp_helper(&exp, env); + self.types.assign_type_to_expr(exp, t, phase); + (t, phase) } /// Helper function for type_check_exp. This is needed because we want to be able to `return` /// and break early, while still setting the evaluated type on the expression. /// /// Do not use this function directly, use `type_check_exp` instead. - fn type_check_exp_helper(&mut self, exp: &Expr, env: &SymbolEnv) -> TypeRef { + fn type_check_exp_helper(&mut self, exp: &Expr, env: &SymbolEnv) -> (TypeRef, Phase) { match &exp.kind { ExprKind::Literal(lit) => match lit { - Literal::String(_) => self.types.string(), - Literal::Nil => self.types.nil(), + Literal::String(_) => (self.types.string(), Phase::Independent), + Literal::Nil => (self.types.nil(), Phase::Independent), Literal::InterpolatedString(s) => { s.parts.iter().for_each(|part| { if let InterpolatedStringPart::Expr(interpolated_expr) = part { - let exp_type = self.type_check_exp(interpolated_expr, env); + let (exp_type, _) = self.type_check_exp(interpolated_expr, env); self.validate_type_in(exp_type, &self.types.stringables(), interpolated_expr); } }); - self.types.string() + // TODO: do we need to determine the phase based on the inner expressions? + (self.types.string(), Phase::Independent) } - Literal::Number(_) => self.types.number(), - Literal::Boolean(_) => self.types.bool(), + Literal::Number(_) => (self.types.number(), Phase::Independent), + Literal::Boolean(_) => (self.types.bool(), Phase::Independent), }, ExprKind::Binary { op, left, right } => { - let ltype = self.type_check_exp(left, env); - let rtype = self.type_check_exp(right, env); + let (ltype, ltype_phase) = self.type_check_exp(left, env); + let (rtype, _) = self.type_check_exp(right, env); match op { BinaryOperator::LogicalAnd | BinaryOperator::LogicalOr => { self.validate_type(ltype, self.types.bool(), left); self.validate_type(rtype, self.types.bool(), right); - self.types.bool() + (self.types.bool(), Phase::Independent) } BinaryOperator::AddOrConcat => { if ltype.is_subtype_of(&self.types.number()) && rtype.is_subtype_of(&self.types.number()) { - self.types.number() + (self.types.number(), Phase::Independent) } else if ltype.is_subtype_of(&self.types.string()) && rtype.is_subtype_of(&self.types.string()) { - self.types.string() + (self.types.string(), Phase::Independent) } else { // If any of the types are unresolved (error) then don't report this assuming the error has already been reported if !ltype.is_unresolved() && !rtype.is_unresolved() { @@ -1310,7 +1325,7 @@ impl<'a> TypeChecker<'a> { ), ); } - self.types.error() + self.resolved_error() } } BinaryOperator::Sub @@ -1321,11 +1336,11 @@ impl<'a> TypeChecker<'a> { | BinaryOperator::Power => { self.validate_type(ltype, self.types.number(), left); self.validate_type(rtype, self.types.number(), right); - self.types.number() + (self.types.number(), Phase::Independent) } BinaryOperator::Equal | BinaryOperator::NotEqual => { self.validate_type(rtype, ltype, exp); - self.types.bool() + (self.types.bool(), Phase::Independent) } BinaryOperator::Less | BinaryOperator::LessOrEqual @@ -1333,33 +1348,33 @@ impl<'a> TypeChecker<'a> { | BinaryOperator::GreaterOrEqual => { self.validate_type(ltype, self.types.number(), left); self.validate_type(rtype, self.types.number(), right); - self.types.bool() + (self.types.bool(), Phase::Independent) } BinaryOperator::UnwrapOr => { // Left argument must be an optional type if !ltype.is_option() { self.spanned_error(left, format!("Expected optional type, found \"{}\"", ltype)); - ltype + (ltype, ltype_phase) } else { // Right argument must be a subtype of the inner type of the left argument let inner_type = ltype.maybe_unwrap_option(); self.validate_type(rtype, inner_type, right); - inner_type + (inner_type, ltype_phase) } } } } ExprKind::Unary { op, exp: unary_exp } => { - let type_ = self.type_check_exp(unary_exp, env); + let (type_, phase) = self.type_check_exp(unary_exp, env); match op { - UnaryOperator::Not => self.validate_type(type_, self.types.bool(), unary_exp), - UnaryOperator::Minus => self.validate_type(type_, self.types.number(), unary_exp), + UnaryOperator::Not => (self.validate_type(type_, self.types.bool(), unary_exp), phase), + UnaryOperator::Minus => (self.validate_type(type_, self.types.number(), unary_exp), phase), UnaryOperator::OptionalTest => { if !type_.is_option() { self.spanned_error(unary_exp, format!("Expected optional type, found \"{}\"", type_)); } - self.types.bool() + (self.types.bool(), phase) } } } @@ -1368,14 +1383,17 @@ impl<'a> TypeChecker<'a> { inclusive: _, end, } => { - let stype = self.type_check_exp(start, env); - let etype = self.type_check_exp(end, env); + let (stype, stype_phase) = self.type_check_exp(start, env); + let (etype, _) = self.type_check_exp(end, env); self.validate_type(stype, self.types.number(), start); self.validate_type(etype, self.types.number(), end); - self.types.add_type(Type::Array(stype)) + (self.types.add_type(Type::Array(stype)), stype_phase) + } + ExprKind::Reference(_ref) => { + let (vi, phase) = self.resolve_reference(_ref, env); + (vi.type_, phase) } - ExprKind::Reference(_ref) => self.resolve_reference(_ref, env).type_, ExprKind::New { class, obj_id, @@ -1399,26 +1417,26 @@ impl<'a> TypeChecker<'a> { class.phase, class.name, env.phase ), ); - return self.types.error(); + return (self.types.error(), Phase::Independent); } } // If type is anything we have to assume it's ok to initialize it - Type::Anything => return self.types.anything(), + Type::Anything => return (self.types.anything(), Phase::Independent), // If type is error, we assume the error was already reported and evauate the new expression to error as well - Type::Unresolved => return self.types.error(), + Type::Unresolved => return self.resolved_error(), Type::Struct(_) => { self.spanned_error( class, format!("Cannot instantiate type \"{}\" because it is a struct and not a class. Use struct instantiation instead.", type_), ); - return self.types.error(); + return self.resolved_error(); } _ => { self.spanned_error( class, format!("Cannot instantiate type \"{}\" because it is not a class", type_), ); - return self.types.error(); + return self.resolved_error(); } }; @@ -1440,7 +1458,7 @@ impl<'a> TypeChecker<'a> { span: class_symbol.span.clone(), }, )); - return self.types.error(); + return self.resolved_error(); }; let constructor_sig = constructor_type .as_function_sig() @@ -1452,8 +1470,8 @@ impl<'a> TypeChecker<'a> { self.type_check_arg_list_against_function_sig(&arg_list, &constructor_sig, exp, arg_list_types); // Type check the scope and id - let obj_scope_type = obj_scope.as_ref().map(|x| self.type_check_exp(x, env)); - let obj_id_type = obj_id.as_ref().map(|x| self.type_check_exp(x, env)); + let obj_scope_type = obj_scope.as_ref().map(|x| self.type_check_exp(x, env).0); + let obj_id_type = obj_id.as_ref().map(|x| self.type_check_exp(x, env).0); let non_std_args = !type_.as_class().unwrap().std_construct_args; @@ -1513,22 +1531,23 @@ impl<'a> TypeChecker<'a> { self.spanned_error(obj_id, "Inflight classes cannot have an id"); } } - type_ + + (type_, env.phase) } ExprKind::Call { callee, arg_list } => { // Resolve the function's reference (either a method in the class's env or a function in the current env) - let func_type = self.type_check_exp(callee, env); + let (func_type, callee_phase) = self.type_check_exp(callee, env); let arg_list_types = self.type_check_arg_list(arg_list, env); // If the callee's signature type is unknown, just evaluate the entire call expression as an error if func_type.is_unresolved() { - return self.types.error(); + return self.resolved_error(); } // If the caller's signature is `any`, then just evaluate the entire call expression as `any` if func_type.is_anything() { - return self.types.anything(); + return (self.types.anything(), Phase::Independent); } // Make sure this is a function signature type @@ -1541,20 +1560,20 @@ impl<'a> TypeChecker<'a> { method.type_ } else { self.spanned_error(callee, "Expected a function or method"); - return self.types.error(); + return self.resolved_error(); }; if let Some(sig_type) = handle_type.as_function_sig() { sig_type.clone() } else { self.spanned_error(callee, "Expected a function or method"); - return self.types.error(); + return self.resolved_error(); } } else { self.spanned_error( callee, format!("Expected a function or method, found \"{}\"", func_type), ); - return self.types.error(); + return self.resolved_error(); }; if !env.phase.can_call_to(&func_sig.phase) { @@ -1564,8 +1583,15 @@ impl<'a> TypeChecker<'a> { ); } + // if the function is phase independent, then inherit from the callee + let func_phase = if func_sig.phase == Phase::Independent { + callee_phase + } else { + func_sig.phase + }; + if let Some(value) = self.type_check_arg_list_against_function_sig(arg_list, &func_sig, exp, arg_list_types) { - return value; + return (value, func_phase); } // If the function is "wingc_env", then print out the current environment @@ -1576,14 +1602,14 @@ impl<'a> TypeChecker<'a> { } } - func_sig.return_type + (func_sig.return_type, func_phase) } ExprKind::ArrayLiteral { type_, items } => { // Infer type based on either the explicit type or the value in one of the items let container_type = if let Some(type_) = type_ { self.resolve_type_annotation(type_, env) } else if !items.is_empty() { - let some_val_type = self.type_check_exp(items.iter().next().unwrap(), env); + let (some_val_type, _) = self.type_check_exp(items.iter().next().unwrap(), env); self.types.add_type(Type::Array(some_val_type)) } else { if self.in_json > 0 { @@ -1605,11 +1631,11 @@ impl<'a> TypeChecker<'a> { // Verify all types are the same as the inferred type for v in items.iter() { - let t = self.type_check_exp(v, env); + let (t, _) = self.type_check_exp(v, env); self.check_json_serializable_or_validate_type(t, element_type, v); } - container_type + (container_type, env.phase) } ExprKind::StructLiteral { type_, fields } => { // Find this struct's type in the environment @@ -1619,14 +1645,14 @@ impl<'a> TypeChecker<'a> { let field_types: IndexMap = fields .iter() .map(|(name, exp)| { - let t = self.type_check_exp(exp, env); + let (t, _) = self.type_check_exp(exp, env); (name.clone(), t) }) .collect(); // If we don't have type information for the struct we don't need to validate the fields if struct_type.is_anything() || struct_type.is_unresolved() { - return struct_type; + return (struct_type, env.phase); } // Make sure it really is a struct type @@ -1660,7 +1686,7 @@ impl<'a> TypeChecker<'a> { } } - struct_type + (struct_type, env.phase) } ExprKind::JsonLiteral { is_mut, element } => { if *is_mut { @@ -1677,9 +1703,9 @@ impl<'a> TypeChecker<'a> { } if *is_mut { - self.types.mut_json() + (self.types.mut_json(), env.phase) } else { - self.types.json() + (self.types.json(), env.phase) } } ExprKind::JsonMapLiteral { fields } => { @@ -1725,7 +1751,7 @@ impl<'a> TypeChecker<'a> { let container_type = if let Some(type_) = type_ { self.resolve_type_annotation(type_, env) } else if !fields.is_empty() { - let some_val_type = self.type_check_exp(fields.iter().next().unwrap().1, env); + let (some_val_type, _) = self.type_check_exp(fields.iter().next().unwrap().1, env); self.types.add_type(Type::Map(some_val_type)) } else { self.spanned_error(exp, "Cannot infer type of empty map"); @@ -1743,18 +1769,18 @@ impl<'a> TypeChecker<'a> { // Verify all types are the same as the inferred type for (_, v) in fields.iter() { - let t = self.type_check_exp(v, env); + let (t, _) = self.type_check_exp(v, env); self.validate_type(t, value_type, v); } - container_type + (container_type, env.phase) } ExprKind::SetLiteral { type_, items } => { // Infer type based on either the explicit type or the value in one of the items let container_type = if let Some(type_) = type_ { self.resolve_type_annotation(type_, env) } else if !items.is_empty() { - let some_val_type = self.type_check_exp(items.iter().next().unwrap(), env); + let (some_val_type, _) = self.type_check_exp(items.iter().next().unwrap(), env); self.types.add_type(Type::Set(some_val_type)) } else { self.spanned_error(exp, "Cannot infer type of empty set"); @@ -1772,24 +1798,31 @@ impl<'a> TypeChecker<'a> { // Verify all types are the same as the inferred type for v in items.iter() { - let t = self.type_check_exp(v, env); + let (t, _) = self.type_check_exp(v, env); self.validate_type(t, element_type, v); } - container_type + (container_type, env.phase) } ExprKind::FunctionClosure(func_def) => self.type_check_closure(func_def, env), ExprKind::CompilerDebugPanic => { // Handle the debug panic expression (during type-checking) dbg_panic!(); - self.type_error(TypeError { - message: "Panic expression".to_string(), - span: exp.span.clone(), - }) + ( + self.type_error(TypeError { + message: "Panic expression".to_string(), + span: exp.span.clone(), + }), + env.phase, + ) } } } + fn resolved_error(&mut self) -> (UnsafeRef, Phase) { + (self.types.error(), Phase::Independent) + } + fn type_check_arg_list_against_function_sig( &mut self, arg_list: &ArgList, @@ -1865,7 +1898,7 @@ impl<'a> TypeChecker<'a> { None } - fn type_check_closure(&mut self, func_def: &ast::FunctionDefinition, env: &SymbolEnv) -> UnsafeRef { + fn type_check_closure(&mut self, func_def: &ast::FunctionDefinition, env: &SymbolEnv) -> (UnsafeRef, Phase) { // TODO: make sure this function returns on all control paths when there's a return type (can be done by recursively traversing the statements and making sure there's a "return" statements in all control paths) // https://github.com/winglang/wing/issues/457 // Create a type_checker function signature from the AST function definition @@ -1889,9 +1922,9 @@ impl<'a> TypeChecker<'a> { self.inner_scopes.push(scope); - function_type + (function_type, sig.phase) } else { - function_type + (function_type, sig.phase) } } @@ -2129,7 +2162,7 @@ impl<'a> TypeChecker<'a> { let pos_arg_types = arg_list .pos_args .iter() - .map(|pos_arg| self.type_check_exp(pos_arg, env)) + .map(|pos_arg| self.type_check_exp(pos_arg, env).0) .collect(); // Type check the named arguments, e.g. fn(named_arg1: exp4, named_arg2: exp5) @@ -2137,7 +2170,7 @@ impl<'a> TypeChecker<'a> { .named_args .iter() .map(|(sym, expr)| { - let arg_type = self.type_check_exp(&expr, env); + let arg_type = self.type_check_exp(&expr, env).0; (sym.clone(), arg_type) }) .collect::>(); @@ -2164,7 +2197,7 @@ impl<'a> TypeChecker<'a> { type_, } => { let explicit_type = type_.as_ref().map(|t| self.resolve_type_annotation(t, env)); - let inferred_type = self.type_check_exp(initial_value, env); + let (inferred_type, _) = self.type_check_exp(initial_value, env); if inferred_type.is_void() { self.spanned_error( var_name, @@ -2208,7 +2241,7 @@ impl<'a> TypeChecker<'a> { statements, } => { // TODO: Expression must be iterable - let exp_type = self.type_check_exp(iterable, env); + let (exp_type, _) = self.type_check_exp(iterable, env); if !exp_type.is_iterable() { self.spanned_error(iterable, format!("Unable to iterate over \"{}\"", &exp_type)); @@ -2240,7 +2273,7 @@ impl<'a> TypeChecker<'a> { self.inner_scopes.push(statements); } StmtKind::While { condition, statements } => { - let cond_type = self.type_check_exp(condition, env); + let (cond_type, _) = self.type_check_exp(condition, env); self.validate_type(cond_type, self.types.bool(), condition); statements.set_env(SymbolEnv::new( @@ -2261,7 +2294,7 @@ impl<'a> TypeChecker<'a> { var_name, else_statements, } => { - let cond_type = self.type_check_exp(value, env); + let (cond_type, _) = self.type_check_exp(value, env); if !cond_type.is_option() { report_diagnostic(Diagnostic { @@ -2311,7 +2344,7 @@ impl<'a> TypeChecker<'a> { elif_statements, else_statements, } => { - let cond_type = self.type_check_exp(condition, env); + let (cond_type, _) = self.type_check_exp(condition, env); self.validate_type(cond_type, self.types.bool(), condition); statements.set_env(SymbolEnv::new( @@ -2325,7 +2358,7 @@ impl<'a> TypeChecker<'a> { self.inner_scopes.push(statements); for elif_scope in elif_statements { - let cond_type = self.type_check_exp(&elif_scope.condition, env); + let (cond_type, _) = self.type_check_exp(&elif_scope.condition, env); self.validate_type(cond_type, self.types.bool(), condition); (&elif_scope.statements).set_env(SymbolEnv::new( @@ -2355,12 +2388,23 @@ impl<'a> TypeChecker<'a> { self.type_check_exp(e, env); } StmtKind::Assignment { variable, value } => { - let exp_type = self.type_check_exp(value, env); - let var_info = self.resolve_reference(variable, env); - if !var_info.type_.is_unresolved() && !var_info.reassignable { - self.spanned_error(stmt, format!("Variable {} is not reassignable ", variable)); + let (exp_type, _) = self.type_check_exp(value, env); + let (var_type, var_phase) = self.type_check_exp(variable, env); + + // check if the variable can be reassigned + + if let ExprKind::Reference(r) = &variable.kind { + let (var, _) = self.resolve_reference(&r, env); + if var_phase == Phase::Preflight && env.phase == Phase::Inflight { + self.spanned_error(stmt, format!("Variable cannot be reassigned from inflight")); + } else { + if !var_type.is_unresolved() && !var.reassignable { + self.spanned_error(stmt, format!("Variable is not reassignable")); + } + } } - self.validate_type(exp_type, var_info.type_, value); + + self.validate_type(exp_type, var_type, value); } StmtKind::Bring { module_name, @@ -2432,7 +2476,7 @@ impl<'a> TypeChecker<'a> { } StmtKind::Return(exp) => { if let Some(return_expression) = exp { - let return_type = self.type_check_exp(return_expression, env); + let (return_type, _) = self.type_check_exp(return_expression, env); if !env.return_type.is_void() { self.validate_type(return_type, env.return_type, return_expression); } else if env.is_in_function() { @@ -3482,19 +3526,20 @@ impl<'a> TypeChecker<'a> { .map(|_| base_udt) } - fn resolve_reference(&mut self, reference: &Reference, env: &SymbolEnv) -> VariableInfo { + fn resolve_reference(&mut self, reference: &Reference, env: &SymbolEnv) -> (VariableInfo, Phase) { match reference { Reference::Identifier(symbol) => { let lookup_res = env.lookup_ext(symbol, Some(self.statement_idx)); if let LookupResult::Found(var, _) = lookup_res { if let Some(var) = var.as_variable() { - var + let phase = var.phase; + (var, phase) } else { self.spanned_error( symbol, format!("Expected identifier \"{symbol}\" to be a variable, but it's a {var}",), ); - self.make_error_variable_info(false) + (self.make_error_variable_info(false), Phase::Independent) } } else { // Give a specific error message if someone tries to write "print" instead of "log" @@ -3503,7 +3548,7 @@ impl<'a> TypeChecker<'a> { } else { self.type_error(lookup_result_to_type_error(lookup_res, symbol)); } - self.make_error_variable_info(false) + (self.make_error_variable_info(false), Phase::Independent) } } Reference::InstanceMember { @@ -3548,13 +3593,21 @@ impl<'a> TypeChecker<'a> { } } - let instance_type = self.type_check_exp(object, env); + let (instance_type, instance_phase) = self.type_check_exp(object, env); + // If resolving the object's type failed, we can't resolve the property either if instance_type.is_unresolved() { - return self.make_error_variable_info(false); + return (self.make_error_variable_info(false), Phase::Independent); } - let res = self.resolve_variable_from_instance_type(instance_type, property, env, object); + let property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); + + // if the object is `this`, then use the property's phase instead of the object phase + let property_phase = if property_variable.phase == Phase::Independent { + instance_phase + } else { + property_variable.phase + }; // Check if the object is an optional type. If it is ensure the use of optional chaining. let object_type = self.types.get_expr_type(object).unwrap(); @@ -3571,12 +3624,15 @@ impl<'a> TypeChecker<'a> { } if force_reassignable { - VariableInfo { - reassignable: true, - ..res - } + ( + VariableInfo { + reassignable: true, + ..property_variable + }, + property_phase, + ) } else { - res + (property_variable, property_phase) } } Reference::TypeMember { type_, property } => { @@ -3586,26 +3642,29 @@ impl<'a> TypeChecker<'a> { match *type_ { Type::Enum(ref e) => { if e.values.contains(property) { - VariableInfo { - name: property.clone(), - type_, - reassignable: false, - phase: Phase::Independent, - is_static: true, - is_member: true, - } + ( + VariableInfo { + name: property.clone(), + type_, + reassignable: false, + phase: Phase::Independent, + is_static: true, + is_member: true, + }, + Phase::Independent, + ) } else { self.spanned_error( property, format!("Enum \"{}\" does not contain value \"{}\"", type_, property.name), ); - self.make_error_variable_info(true) + (self.make_error_variable_info(true), Phase::Independent) } } Type::Class(ref c) => match c.env.lookup(&property, None) { Some(SymbolKind::Variable(v)) => { if v.is_static { - v.clone() + (v.clone(), v.phase) } else { self.spanned_error( property, @@ -3614,7 +3673,7 @@ impl<'a> TypeChecker<'a> { type_, property.name ), ); - self.make_error_variable_info(true) + (self.make_error_variable_info(true), Phase::Independent) } } _ => { @@ -3622,12 +3681,12 @@ impl<'a> TypeChecker<'a> { property, format!("No member \"{}\" in class \"{}\"", property.name, type_), ); - self.make_error_variable_info(true) + (self.make_error_variable_info(true), Phase::Independent) } }, _ => { self.spanned_error(property, format!("\"{}\" not a valid reference", reference)); - self.make_error_variable_info(true) + (self.make_error_variable_info(true), Phase::Independent) } } } diff --git a/libs/wingc/src/type_check/class_fields_init.rs b/libs/wingc/src/type_check/class_fields_init.rs index 31f2fba5ded..4d82fd7670d 100644 --- a/libs/wingc/src/type_check/class_fields_init.rs +++ b/libs/wingc/src/type_check/class_fields_init.rs @@ -1,5 +1,5 @@ use crate::{ - ast::{Reference, Stmt, StmtKind, Symbol}, + ast::{ExprKind, Reference, Stmt, StmtKind, Symbol}, visit::{self, Visit}, }; @@ -20,15 +20,18 @@ impl VisitClassInit { impl Visit<'_> for VisitClassInit { fn visit_stmt(&mut self, node: &Stmt) { match &node.kind { - StmtKind::Assignment { variable, value: _ } => match &variable { - Reference::InstanceMember { - property, - object: _, - optional_accessor: _, - } => self.fields.push(Symbol { - name: property.name.clone(), - span: property.span.clone(), - }), + StmtKind::Assignment { variable, value: _ } => match &variable.kind { + ExprKind::Reference(r) => match r { + Reference::InstanceMember { + property, + object: _, + optional_accessor: _, + } => self.fields.push(Symbol { + name: property.name.clone(), + span: property.span.clone(), + }), + _ => (), + }, _ => (), }, _ => (), diff --git a/libs/wingc/src/type_check/jsii_importer.rs b/libs/wingc/src/type_check/jsii_importer.rs index a33fd9fe08d..53cc4eda6a2 100644 --- a/libs/wingc/src/type_check/jsii_importer.rs +++ b/libs/wingc/src/type_check/jsii_importer.rs @@ -312,7 +312,11 @@ impl<'a> JsiiImporter<'a> { self.wing_types.void(), false, false, - Phase::Preflight, + if is_struct { + Phase::Independent + } else { + Phase::Preflight + }, self.jsii_spec.import_statement_idx, ); let new_type_symbol = Self::jsii_name_to_symbol(&type_name, &jsii_interface.location_in_module); @@ -326,7 +330,7 @@ impl<'a> JsiiImporter<'a> { self.wing_types.void(), false, false, - iface_env.phase, + Phase::Independent, // structs are phase-independent self.jsii_spec.import_statement_idx, ), // Dummy env, will be replaced below })), diff --git a/libs/wingc/src/visit.rs b/libs/wingc/src/visit.rs index 713c623382d..dfef1f317af 100644 --- a/libs/wingc/src/visit.rs +++ b/libs/wingc/src/visit.rs @@ -170,7 +170,7 @@ where v.visit_expr(&expr); } StmtKind::Assignment { variable, value } => { - v.visit_reference(variable); + v.visit_expr(variable); v.visit_expr(value); } StmtKind::Return(expr) => { From e9f2b5de4e157a4913e1c7c0fa8ceb67d311a514 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 09:06:29 +0300 Subject: [PATCH 02/20] left overs --- libs/wingc/src/ast.rs | 2 +- libs/wingc/src/jsify.rs | 2 +- libs/wingc/src/type_check.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index 3cb6fce9aea..caa83cc0fc0 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -372,7 +372,7 @@ pub enum StmtKind { Return(Option), Expression(Expr), Assignment { - variable: Reference, + variable: Expr, value: Expr, }, Scope(Scope), diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index 15985d40502..ed63b24333d 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -722,7 +722,7 @@ impl<'a> JSifier<'a> { StmtKind::Expression(e) => CodeMaker::one_line(format!("{};", self.jsify_expression(e, ctx))), StmtKind::Assignment { variable, value } => CodeMaker::one_line(format!( "{} = {};", - self.jsify_reference(&variable, ctx), + self.jsify_expression(variable, ctx), self.jsify_expression(value, ctx) )), StmtKind::Scope(scope) => { diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index aff4dfe98fa..341a04d3803 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -1710,7 +1710,7 @@ impl<'a> TypeChecker<'a> { } ExprKind::JsonMapLiteral { fields } => { fields.iter().for_each(|(_, v)| { - let t = self.type_check_exp(v, env); + let (t, _) = self.type_check_exp(v, env); // Ensure we dont allow MutJson to Json or vice versa match *t { Type::Json => { @@ -1744,7 +1744,7 @@ impl<'a> TypeChecker<'a> { } }); - self.types.json() + (self.types.json(), env.phase) } ExprKind::MapLiteral { fields, type_ } => { // Infer type based on either the explicit type or the value in one of the fields From 59b72d365806b2b48a6c9ba3e70cb622e225f54f Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 30 Jun 2023 06:32:07 +0000 Subject: [PATCH 03/20] chore: self mutation Signed-off-by: monada-bot[bot] --- libs/wingc/src/type_check.rs | 4 +- tools/hangar/__snapshots__/invalid.ts.snap | 52 +++++++++++++++++----- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 341a04d3803..71aa15e4c24 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -2396,10 +2396,10 @@ impl<'a> TypeChecker<'a> { if let ExprKind::Reference(r) = &variable.kind { let (var, _) = self.resolve_reference(&r, env); if var_phase == Phase::Preflight && env.phase == Phase::Inflight { - self.spanned_error(stmt, format!("Variable cannot be reassigned from inflight")); + self.spanned_error(stmt, "Variable cannot be reassigned from inflight".to_string()); } else { if !var_type.is_unresolved() && !var.reassignable { - self.spanned_error(stmt, format!("Variable is not reassignable")); + self.spanned_error(stmt, "Variable is not reassignable".to_string()); } } } diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 1906fb28c40..76032313034 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -44,6 +44,20 @@ error: Unknown symbol \\"this\\" | ^^^^ Unknown symbol \\"this\\" +error: Unknown symbol \\"this\\" + --> ../../../examples/tests/invalid/access_static_from_instance.w:7:5 + | +7 | this.instanceField = 1; // Can't access instance fields from static methods + | ^^^^ Unknown symbol \\"this\\" + + +error: Unknown symbol \\"this\\" + --> ../../../examples/tests/invalid/access_static_from_instance.w:8:5 + | +8 | this.f = 1; // Can't access static fields through \`this\` + | ^^^^ Unknown symbol \\"this\\" + + error: Unknown symbol \\"this\\" --> ../../../examples/tests/invalid/access_static_from_instance.w:8:5 | @@ -336,6 +350,13 @@ error: Expected type to be \\"num\\", but got \\"str\\" instead | ^^^^ Expected type to be \\"num\\", but got \\"str\\" instead +error: Variable cannot be reassigned from inflight + --> ../../../examples/tests/invalid/class.w:61:5 + | +61 | this.y = 1; + | ^^^^^^^^^^^ Variable cannot be reassigned from inflight + + Tests 1 failed (1) @@ -1237,11 +1258,11 @@ error: Expected type to be \\"str\\", but got \\"str?\\" instead | ^^^^^^^^^^^^^^^^^^ Expected type to be \\"str\\", but got \\"str?\\" instead -error: Variable hi is not reassignable +error: Variable is not reassignable --> ../../../examples/tests/invalid/optionals.w:46:3 | 46 | hi = \\"bye\\"; - | ^^^^^^^^^^^ Variable hi is not reassignable + | ^^^^^^^^^^^ Variable is not reassignable @@ -1320,39 +1341,39 @@ Duration " `; exports[`reassign_to_nonreassignable.w 1`] = ` -"error: Variable x is not reassignable +"error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:3:1 | 3 | x = x + 1; - | ^^^^^^^^^^ Variable x is not reassignable + | ^^^^^^^^^^ Variable is not reassignable -error: Variable this.f is not reassignable +error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:28:5 | 28 | this.f = this.f + 1; - | ^^^^^^^^^^^^^^^^^^^^ Variable this.f is not reassignable + | ^^^^^^^^^^^^^^^^^^^^ Variable is not reassignable -error: Variable this.innerR.inner is not reassignable +error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:5 | 30 | this.innerR.inner = 2; - | ^^^^^^^^^^^^^^^^^^^^^^ Variable this.innerR.inner is not reassignable + | ^^^^^^^^^^^^^^^^^^^^^^ Variable is not reassignable -error: Variable this.inflightF is not reassignable +error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:35:5 | 35 | this.inflightF = this.inflightF + 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Variable this.inflightF is not reassignable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Variable is not reassignable -error: Variable arg is not reassignable +error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:42:3 | 42 | arg = 0; - | ^^^^^^^^ Variable arg is not reassignable + | ^^^^^^^^ Variable is not reassignable @@ -1908,6 +1929,13 @@ error: Unknown symbol \\"unknown\\" | ^^^^^^^ Unknown symbol \\"unknown\\" +error: Unknown symbol \\"unknown\\" + --> ../../../examples/tests/invalid/unknown_symbol.w:32:1 + | +32 | unknown = 1; + | ^^^^^^^ Unknown symbol \\"unknown\\" + + error: Unknown symbol \\"assert\\" --> ../../../examples/tests/invalid/unknown_symbol.w:20:17 | From 460f6333e735beccc8355cda5a644d398019e92b Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 15:59:56 +0300 Subject: [PATCH 04/20] Type references --- examples/tests/invalid/enums.w | 6 +- examples/tests/valid/custom_obj_id.w | 7 + libs/wingc/src/ast.rs | 50 +++- libs/wingc/src/closure_transform.rs | 18 +- libs/wingc/src/docs.rs | 4 +- libs/wingc/src/fold.rs | 9 +- libs/wingc/src/jsify.rs | 124 ++++----- libs/wingc/src/lsp/completions.rs | 88 ++++--- libs/wingc/src/lsp/hover.rs | 75 +++--- libs/wingc/src/lsp/signature.rs | 13 +- .../hovers/builtin_instance_method.snap | 2 +- .../lsp/snapshots/hovers/class_property.snap | 2 +- libs/wingc/src/parser.rs | 85 +++++-- libs/wingc/src/type_check.rs | 236 ++++++++++++------ libs/wingc/src/visit.rs | 13 +- tools/hangar/__snapshots__/invalid.ts.snap | 81 ++---- 16 files changed, 494 insertions(+), 319 deletions(-) create mode 100644 examples/tests/valid/custom_obj_id.w diff --git a/examples/tests/invalid/enums.w b/examples/tests/invalid/enums.w index f78f3aa9f35..1ad4331794e 100644 --- a/examples/tests/invalid/enums.w +++ b/examples/tests/invalid/enums.w @@ -2,8 +2,8 @@ enum SomeEnum { ONE, TWO, THREE } -let four = SomeEnum.FOUR; -// ERR ^^^^ enum value does not exist +// let four = SomeEnum.FOUR; +// ERR ^^^^ Enum "SomeEnum" does not contain value "FOUR" let two = SomeEnum.TWO.TWO; -// ERR ^^^ +// ERR ^^^ Property not found diff --git a/examples/tests/valid/custom_obj_id.w b/examples/tests/valid/custom_obj_id.w new file mode 100644 index 00000000000..0e54afe2229 --- /dev/null +++ b/examples/tests/valid/custom_obj_id.w @@ -0,0 +1,7 @@ +class Foo { } + +let foo1 = new Foo(); +let bar2 = new Foo() as "bar2"; + +assert(foo1.node.id == "Foo"); +assert(bar2.node.id == "bar2"); diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index caa83cc0fc0..a528f25dc45 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -164,6 +164,13 @@ impl UserDefinedType { pub fn full_path_str(&self) -> String { self.full_path().iter().join(".") } + + pub fn to_expression(&self) -> Expr { + Expr::new( + ExprKind::Reference(Reference::TypeReference(self.clone())), + self.span.clone(), + ) + } } impl Display for UserDefinedType { @@ -319,11 +326,30 @@ pub struct Class { pub methods: Vec<(Symbol, FunctionDefinition)>, pub initializer: FunctionDefinition, pub inflight_initializer: FunctionDefinition, - pub parent: Option, + pub parent: Option, // the expression must be a reference to a user defined type pub implements: Vec, pub phase: Phase, } +impl Class { + /// Returns the `UserDefinedType` of the parent class, if any. + pub fn parent_udt(&self) -> Option { + let Some(expr) = &self.parent else { + return None; + }; + + let ExprKind::Reference(ref r) = expr.kind else { + return None; + }; + + let Reference::TypeReference(t) = r else { + return None; + }; + + Some(t.clone()) + } +} + #[derive(Debug)] pub struct Interface { pub name: Symbol, @@ -419,7 +445,7 @@ pub struct StructField { #[derive(Debug)] pub enum ExprKind { New { - class: TypeAnnotation, + class: Box, // expression must be a reference to a user defined type obj_id: Option>, obj_scope: Option>, arg_list: ArgList, @@ -592,8 +618,12 @@ pub enum Reference { property: Symbol, optional_accessor: bool, }, + TypeReference(UserDefinedType), /// A reference to a member inside a type: `MyType.x` or `MyEnum.A` - TypeMember { type_: UserDefinedType, property: Symbol }, + TypeMember { + typeobject: Box, + property: Symbol, + }, } impl Display for Reference { @@ -611,13 +641,13 @@ impl Display for Reference { }; write!(f, "{}.{}", obj_str, property.name) } - Reference::TypeMember { type_, property } => { - write!( - f, - "{}.{}", - TypeAnnotationKind::UserDefined(type_.clone()), - property.name - ) + Reference::TypeReference(type_) => write!(f, "{}", type_), + Reference::TypeMember { typeobject, property } => { + let ExprKind::Reference(ref r) = typeobject.kind else { + return write!(f, ".{}", property.name); + }; + + write!(f, "{}.{}", r, property.name) } } } diff --git a/libs/wingc/src/closure_transform.rs b/libs/wingc/src/closure_transform.rs index 5721bde1a68..42bed9baf5f 100644 --- a/libs/wingc/src/closure_transform.rs +++ b/libs/wingc/src/closure_transform.rs @@ -139,12 +139,14 @@ impl Fold for ClosureTransformer { span: WingSpan::default(), }; + let class_udt = UserDefinedType { + root: new_class_name.clone(), + fields: vec![], + span: WingSpan::default(), + }; + let class_type_annotation = TypeAnnotation { - kind: TypeAnnotationKind::UserDefined(UserDefinedType { - root: new_class_name.clone(), - fields: vec![], - span: WingSpan::default(), - }), + kind: TypeAnnotationKind::UserDefined(class_udt.clone()), span: WingSpan::default(), }; @@ -275,7 +277,7 @@ impl Fold for ClosureTransformer { // ``` let new_class_instance = Expr::new( ExprKind::New { - class: class_type_annotation, + class: Box::new(class_udt.to_expression()), arg_list: ArgList { named_args: IndexMap::new(), pos_args: vec![], @@ -336,7 +338,9 @@ impl<'a> Fold for RenameThisTransformer<'a> { Reference::Identifier(ident) } } - Reference::InstanceMember { .. } | Reference::TypeMember { .. } => fold::fold_reference(self, node), + Reference::InstanceMember { .. } | Reference::TypeMember { .. } | Reference::TypeReference(_) => { + fold::fold_reference(self, node) + } } } } diff --git a/libs/wingc/src/docs.rs b/libs/wingc/src/docs.rs index 3a979dff8cf..0fbc01e82fb 100644 --- a/libs/wingc/src/docs.rs +++ b/libs/wingc/src/docs.rs @@ -7,7 +7,7 @@ use crate::{ jsify::codemaker::CodeMaker, type_check::{ jsii_importer::is_construct_base, Class, FunctionSignature, Interface, Namespace, Struct, SymbolKind, Type, - TypeRef, VariableInfo, + TypeRef, VariableInfo, VariableKind, }, }; @@ -94,7 +94,7 @@ impl Documented for VariableInfo { fn render_docs(&self) -> String { let mut modifiers = vec![]; - if self.is_member && self.is_static { + if let VariableKind::StaticMember = self.kind { modifiers.push("static"); } diff --git a/libs/wingc/src/fold.rs b/libs/wingc/src/fold.rs index 1b8f4536d96..af769e77837 100644 --- a/libs/wingc/src/fold.rs +++ b/libs/wingc/src/fold.rs @@ -193,7 +193,7 @@ where .map(|(name, def)| (f.fold_symbol(name), f.fold_function_definition(def))) .collect(), initializer: f.fold_function_definition(node.initializer), - parent: node.parent.map(|parent| f.fold_user_defined_type(parent)), + parent: node.parent.map(|parent| f.fold_expr(parent)), implements: node .implements .into_iter() @@ -257,7 +257,7 @@ where obj_scope, arg_list, } => ExprKind::New { - class: f.fold_type_annotation(class), + class: Box::new(f.fold_expr(*class)), obj_id, obj_scope: obj_scope.map(|scope| Box::new(f.fold_expr(*scope))), arg_list: f.fold_args(arg_list), @@ -364,8 +364,9 @@ where property: f.fold_symbol(property), optional_accessor, }, - Reference::TypeMember { type_, property } => Reference::TypeMember { - type_: f.fold_user_defined_type(type_), + Reference::TypeReference(udt) => Reference::TypeReference(f.fold_user_defined_type(udt)), + Reference::TypeMember { typeobject, property } => Reference::TypeMember { + typeobject: Box::new(f.fold_expr(*typeobject)), property: f.fold_symbol(property), }, } diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index ed63b24333d..995eb1baf79 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -17,17 +17,18 @@ use std::{ use crate::{ ast::{ ArgList, BinaryOperator, Class as AstClass, ClassField, Expr, ExprKind, FunctionBody, FunctionDefinition, - InterpolatedStringPart, Literal, Phase, Reference, Scope, Stmt, StmtKind, Symbol, TypeAnnotation, - TypeAnnotationKind, UnaryOperator, + InterpolatedStringPart, Literal, Phase, Reference, Scope, Stmt, StmtKind, Symbol, TypeAnnotationKind, + UnaryOperator, }, comp_ctx::{CompilationContext, CompilationPhase}, dbg_panic, debug, diagnostic::{report_diagnostic, Diagnostic, WingSpan}, files::Files, type_check::{ - resolve_user_defined_type, + resolve_udt_from_expr, resolve_user_defined_type, symbol_env::{LookupResult, SymbolEnv, SymbolEnvRef}, - ClassLike, SymbolKind, Type, TypeRef, Types, UnsafeRef, VariableInfo, CLASS_INFLIGHT_INIT_NAME, HANDLE_METHOD_NAME, + ClassLike, SymbolKind, Type, TypeRef, Types, UnsafeRef, VariableInfo, VariableKind, CLASS_INFLIGHT_INIT_NAME, + HANDLE_METHOD_NAME, }, visit::{self, Visit}, MACRO_REPLACE_ARGS, MACRO_REPLACE_ARGS_TEXT, MACRO_REPLACE_SELF, WINGSDK_ASSEMBLY_NAME, WINGSDK_RESOURCE, @@ -222,8 +223,10 @@ impl<'a> JSifier<'a> { property, optional_accessor: _, } => self.jsify_expression(object, ctx) + "." + &property.to_string(), - Reference::TypeMember { type_, property } => { - self.jsify_type(&TypeAnnotationKind::UserDefined(type_.clone()), ctx) + "." + &property.to_string() + Reference::TypeReference(udt) => self.jsify_type(&TypeAnnotationKind::UserDefined(udt.clone()), ctx), + Reference::TypeMember { typeobject, property } => { + let typename = self.jsify_expression(typeobject, ctx); + typename + "." + &property.to_string() } } } @@ -309,7 +312,7 @@ impl<'a> JSifier<'a> { // user-defined types), we simply instantiate the type directly (maybe in the future we will // allow customizations of user-defined types as well, but for now we don't). - let ctor = self.jsify_type(&class.kind, ctx); + let ctor = self.jsify_expression(class, ctx); let scope = if is_preflight_class && class_type.std_construct_args { if let Some(scope) = obj_scope { @@ -955,8 +958,9 @@ impl<'a> JSifier<'a> { let (mut captured_types, captured_vars) = self.scan_captures(class, &inflight_methods); if let Some(parent) = &class.parent { - let parent_type = resolve_user_defined_type(&parent, env, 0).unwrap(); - captured_types.insert(parent.full_path(), parent_type); + let parent_type_udt = resolve_udt_from_expr(&parent).unwrap(); + let parent_type = resolve_user_defined_type(&parent_type_udt, env, 0).unwrap(); + captured_types.insert(parent_type_udt.full_path(), parent_type); } // Get all references between inflight methods and preflight values @@ -988,7 +992,7 @@ impl<'a> JSifier<'a> { // default base class for preflight classes is `core.Resource` let extends = if let Some(parent) = &class.parent { - format!(" extends {}", jsify_type_name(&parent.full_path(), ctx.phase)) + format!(" extends {}", self.jsify_expression(&parent, ctx)) } else { format!(" extends {}", STDLIB_CORE_RESOURCE) }; @@ -1260,7 +1264,8 @@ impl<'a> JSifier<'a> { // Handle parent class: Need to call super and pass its captured fields (we assume the parent client is already written) let mut lifted_by_parent = vec![]; if let Some(parent) = &class.parent { - if let Ok(parent_type) = resolve_user_defined_type(parent, env, 0) { + let parent_udt = resolve_udt_from_expr(parent).unwrap(); + if let Ok(parent_type) = resolve_user_defined_type(&parent_udt, env, 0) { lifted_by_parent.extend(self.get_lifted_fields(parent_type)); } } @@ -1278,7 +1283,7 @@ impl<'a> JSifier<'a> { class_code.open(format!( "class {name}{} {{", if let Some(parent) = &class.parent { - format!(" extends {}", jsify_type_name(&parent.full_path(), ctx.phase)) + format!(" extends {}", self.jsify_expression(&parent, ctx)) } else { "".to_string() } @@ -1432,14 +1437,16 @@ impl<'a> JSifier<'a> { let refs = refs .iter() .filter(|(m, _)| { - (*m == CLASS_INFLIGHT_INIT_NAME - || !class_type - .as_class() - .unwrap() - .get_method(&m.as_str().into()) - .expect(&format!("method {m} doesn't exist in {class_name}")) - .is_static) - ^ (matches!(bind_method_kind, BindMethod::Type)) + *m == CLASS_INFLIGHT_INIT_NAME + || !(matches!( + class_type + .as_class() + .unwrap() + .get_method(&m.as_str().into()) + .expect(&format!("method {m} doesn't exist in {class_name}")) + .kind, + VariableKind::StaticMember + )) ^ (matches!(bind_method_kind, BindMethod::Type)) }) .collect_vec(); @@ -1765,6 +1772,25 @@ impl<'a> FieldReferenceVisitor<'a> { kind: ComponentKind::Member(var), }]; } + Reference::TypeReference(type_) => { + let env = self.env.unwrap(); + + // Get the type we're accessing a member of + let Ok(t) = resolve_user_defined_type(type_, &env, self.statement_index) else { + return vec![]; + }; + + // If the type we're referencing isn't a preflight class then skip it + if t.as_preflight_class().is_none() { + return vec![]; + }; + + return vec![Component { + text: format!("{type_}"), + span: type_.span.clone(), + kind: ComponentKind::ClassType(t), + }]; + } Reference::InstanceMember { object, property, @@ -1784,13 +1810,17 @@ impl<'a> FieldReferenceVisitor<'a> { let obj = self.analyze_expr(&object); return [obj, prop].concat(); } - Reference::TypeMember { type_, property } => { - let env = self.env.unwrap(); + Reference::TypeMember { typeobject, property } => { + let obj = self.analyze_expr(&typeobject); - // Get the type we're accessing a member of - let Ok(t) = resolve_user_defined_type(type_, &env, self.statement_index) else { + let Some(first) = obj.first() else { + return vec![]; + }; + + let ComponentKind::ClassType(t) = first.kind else { return vec![]; }; + // If the type we're referencing isn't a preflight class then skip it let Some(class) = t.as_preflight_class() else { return vec![]; @@ -1805,18 +1835,13 @@ impl<'a> FieldReferenceVisitor<'a> { .as_variable() .expect("variable"); - return vec![ - Component { - text: format!("{type_}"), - span: type_.span.clone(), - kind: ComponentKind::ClassType(t), - }, - Component { - text: property.name.clone(), - span: property.span.clone(), - kind: ComponentKind::Member(var), - }, - ]; + let prop = vec![Component { + text: property.name.clone(), + span: property.span.clone(), + kind: ComponentKind::Member(var), + }]; + + [obj, prop].concat() } } } @@ -1945,23 +1970,6 @@ impl<'a> CaptureScanner<'a> { } impl<'ast> Visit<'ast> for CaptureScanner<'ast> { - fn visit_expr_new( - &mut self, - node: &'ast Expr, - class: &'ast TypeAnnotation, - obj_id: &'ast Option>, - obj_scope: &'ast Option>, - arg_list: &'ast ArgList, - ) { - // we want to only capture the type annotation in the case of "new X" because - // other cases of type annotation are actually erased in the javascript code. - if let TypeAnnotationKind::UserDefined(u) = &class.kind { - self.consider_reference(&u.full_path()); - } - - visit::visit_expr_new(self, node, class, obj_id, obj_scope, arg_list); - } - fn visit_reference(&mut self, node: &'ast Reference) { match node { Reference::Identifier(symb) => { @@ -1972,12 +1980,12 @@ impl<'ast> Visit<'ast> for CaptureScanner<'ast> { self.consider_reference(&vec![symb.clone()]); } - Reference::TypeMember { type_, .. } => { - self.consider_reference(&type_.full_path()); - } - // this is the case of "object.property". if we need to capture "object", it will be captured - // as an identifier, so we can skip it here. + Reference::TypeReference(t) => self.consider_reference(&t.full_path()), + + // this is the case of "object.property" (or `Type.property`). if we need to capture "object", + // it will be captured as an identifier, so we can skip it here. + Reference::TypeMember { .. } => {} Reference::InstanceMember { .. } => {} } diff --git a/libs/wingc/src/lsp/completions.rs b/libs/wingc/src/lsp/completions.rs index fd3cb6cb7d0..0886aae78a1 100644 --- a/libs/wingc/src/lsp/completions.rs +++ b/libs/wingc/src/lsp/completions.rs @@ -5,7 +5,7 @@ use lsp_types::{ use std::cmp::max; use tree_sitter::Point; -use crate::ast::{Expr, ExprKind, Phase, Scope, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType}; +use crate::ast::{Expr, Phase, Scope, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType}; use crate::closure_transform::{CLOSURE_CLASS_PREFIX, PARENT_THIS_NAME}; use crate::diagnostic::WingSpan; use crate::docs::Documented; @@ -13,7 +13,7 @@ use crate::lsp::sync::{FILES, JSII_TYPES}; use crate::type_check::symbol_env::{LookupResult, StatementIdx}; use crate::type_check::{ import_udt_from_jsii, resolve_user_defined_type, ClassLike, Namespace, SymbolKind, Type, Types, UnsafeRef, - CLASS_INFLIGHT_INIT_NAME, CLASS_INIT_NAME, + VariableKind, CLASS_INFLIGHT_INIT_NAME, CLASS_INIT_NAME, }; use crate::visit::{visit_expr, visit_type_annotation, Visit}; use crate::wasm_util::{ptr_to_string, string_to_combined_ptr, WASM_RETURN_ERROR}; @@ -96,11 +96,40 @@ pub fn on_completion(params: lsp_types::CompletionParams) -> CompletionResponse } } + let is_new_expression = if let Some(parent) = parent.parent() { + parent.kind() == "new_expression" + } else { + false + }; + + let filter_completions = |completions: Vec| { + if !is_new_expression { + completions + } else { + completions + .iter() + .filter(|c| { + matches!( + c.kind, + Some(CompletionItemKind::CLASS) | Some(CompletionItemKind::MODULE) + ) + }) + .cloned() + .map(|mut c| { + if c.kind == Some(CompletionItemKind::CLASS) { + convert_to_call_completion(&mut c); + } + c + }) + .collect() + } + }; + if let Some(nearest_type_annotation) = scope_visitor.nearest_type_annotation { if let TypeAnnotationKind::UserDefined(udt) = &nearest_type_annotation.kind { let type_lookup = resolve_user_defined_type(udt, found_env, scope_visitor.found_stmt_index.unwrap_or(0)); - let mut completions = if let Ok(type_lookup) = type_lookup { + let completions = if let Ok(type_lookup) = type_lookup { get_completions_from_type(&type_lookup, types, Some(found_env.phase), false) } else { // this is probably a namespace, let's look it up @@ -116,26 +145,7 @@ pub fn on_completion(params: lsp_types::CompletionParams) -> CompletionResponse } }; - if parent.parent().expect("custom_type must have a parent node").kind() == "new_expression" { - completions = completions - .iter() - .filter(|c| { - matches!( - c.kind, - Some(CompletionItemKind::CLASS) | Some(CompletionItemKind::MODULE) - ) - }) - .cloned() - .map(|mut c| { - if c.kind == Some(CompletionItemKind::CLASS) { - convert_to_call_completion(&mut c); - } - c - }) - .collect(); - } - - return completions; + return filter_completions(completions); } } @@ -149,11 +159,9 @@ pub fn on_completion(params: lsp_types::CompletionParams) -> CompletionResponse .lookup_nested_str(&reference_text, scope_visitor.found_stmt_index) .ok() { - match lookup_thing { - SymbolKind::Type(t) => { - return get_completions_from_type(&t, types, Some(found_env.phase), false); - } - SymbolKind::Variable(v) => return get_completions_from_type(&v.type_, types, Some(found_env.phase), false), + let completions = match lookup_thing { + SymbolKind::Type(t) => get_completions_from_type(&t, types, Some(found_env.phase), false), + SymbolKind::Variable(v) => get_completions_from_type(&v.type_, types, Some(found_env.phase), false), SymbolKind::Namespace(n) => { // If the types in this namespace aren't loaded yet, load them now to get completions if !n.loaded { @@ -170,9 +178,11 @@ pub fn on_completion(params: lsp_types::CompletionParams) -> CompletionResponse import_udt_from_jsii(&mut file_data.types, &mut jsii_types, &udt, &file_data.jsii_imports); }); } - return get_completions_from_namespace(&n, Some(found_env.phase)); + get_completions_from_namespace(&n, Some(found_env.phase)) } - } + }; + + return filter_completions(completions); } return vec![]; @@ -493,7 +503,14 @@ fn get_completions_from_class( .1 .as_variable() .expect("Symbols in classes are always variables"); - if variable.is_static == is_instance { + + let is_static = if let VariableKind::StaticMember = variable.kind { + true + } else { + false + }; + + if is_static == is_instance { return None; } @@ -686,9 +703,9 @@ impl<'a> Visit<'a> for ScopeVisitor<'a> { // We don't want to visit the children of a reference expression // as that will actually be a less useful piece of information // e.g. With `a.b.c.` we are interested in `a.b.c` and not `a.b` - if !matches!(&node.kind, ExprKind::Reference(_)) { - visit_expr(self, node); - } + visit_expr(self, node); + // if !matches!(&node.kind, ExprKind::Reference(_)) { + // } } fn visit_type_annotation(&mut self, node: &'a TypeAnnotation) { @@ -718,6 +735,9 @@ mod tests { ($name:ident, $code:literal, $($assertion:stmt)*) => { #[test] fn $name() { + // NOTE: this is needed for debugging to work regardless of where you run the test + std::env::set_current_dir(env!("CARGO_MANIFEST_DIR")).unwrap(); + let text_document_position = load_file_with_contents($code); let completion = on_completion(CompletionParams { context: None, diff --git a/libs/wingc/src/lsp/hover.rs b/libs/wingc/src/lsp/hover.rs index f2440988dd6..162e4edaac1 100644 --- a/libs/wingc/src/lsp/hover.rs +++ b/libs/wingc/src/lsp/hover.rs @@ -1,5 +1,3 @@ -use lsp_types::{Hover, HoverContents, MarkupContent, MarkupKind, Position}; - use crate::ast::{ Class, Expr, FunctionBody, FunctionDefinition, Reference, Scope, Stmt, StmtKind, Symbol, TypeAnnotation, TypeAnnotationKind, @@ -12,6 +10,7 @@ use crate::type_check::Types; use crate::visit::{self, Visit}; use crate::wasm_util::WASM_RETURN_ERROR; use crate::wasm_util::{ptr_to_string, string_to_combined_ptr}; +use lsp_types::{Hover, HoverContents, MarkupContent, MarkupKind, Position}; pub struct HoverVisitor<'a> { position: Position, @@ -73,6 +72,33 @@ impl<'a> HoverVisitor<'a> { self.current_scope = last_scope; } } + + fn visit_reference_with_member(&mut self, object: &Expr, property: &Symbol) { + if let Some(obj_type) = self.types.get_expr_type(object) { + if property.span.contains(&self.position) { + let new_span = WingSpan { + start: property.span.start, //<<< + end: property.span.end, + file_id: property.span.file_id.clone(), + }; + + if let Some(c) = obj_type.as_class() { + if let Some(v) = c.env.lookup(property, None) { + let docs = v.render_docs(); + self.found = Some((new_span, Some(docs))); + } + } else { + self.found = Some(( + new_span, + self + .types + .get_expr_type(self.current_expr.unwrap()) + .map(|t| t.render_docs()), + )); + } + } + } + } } impl<'a> Visit<'a> for HoverVisitor<'a> { @@ -236,45 +262,13 @@ impl<'a> Visit<'a> for HoverVisitor<'a> { self.found = Some((sym.span.clone(), self.lookup_docs(&sym.name, None))); } } - Reference::InstanceMember { - object, - property, - optional_accessor: _, - } => { - if let Some(obj_type) = self.types.get_expr_type(object) { - if property.span.contains(&self.position) { - let new_span = WingSpan { - start: object.span.start, - end: property.span.end, - file_id: property.span.file_id.clone(), - }; - - if let Some(c) = obj_type.as_class() { - if let Some(v) = c.env.lookup(property, None) { - let docs = v.render_docs(); - self.found = Some((new_span, Some(docs))); - } - } else { - self.found = Some(( - new_span, - self - .types - .get_expr_type(self.current_expr.unwrap()) - .map(|t| t.render_docs()), - )); - } - } - } - } - Reference::TypeMember { type_, property } => { - if property.span.contains(&self.position) { - // lookup type in environment - self.found = Some(( - property.span.clone(), - self.lookup_docs(&type_.full_path_str(), Some(property)), - )); + Reference::TypeReference(t) => { + if t.span.contains(&self.position) { + self.found = Some((t.span.clone(), self.lookup_docs(&t.full_path_str(), None))); } } + Reference::InstanceMember { object, property, .. } => self.visit_reference_with_member(object, property), + Reference::TypeMember { typeobject, property } => self.visit_reference_with_member(&typeobject, property), } visit::visit_reference(self, node); @@ -348,6 +342,9 @@ mod tests { ($name:ident, $code:literal, $($assertion:stmt)*) => { #[test] fn $name() { + // NOTE: this is needed for debugging to work regardless of where you run the test + std::env::set_current_dir(env!("CARGO_MANIFEST_DIR")).unwrap(); + let text_document_position_params = load_file_with_contents($code); let hover = on_hover(HoverParams { text_document_position_params, diff --git a/libs/wingc/src/lsp/signature.rs b/libs/wingc/src/lsp/signature.rs index daef216c379..54c426d51a5 100644 --- a/libs/wingc/src/lsp/signature.rs +++ b/libs/wingc/src/lsp/signature.rs @@ -4,11 +4,11 @@ use lsp_types::{ SignatureInformation, }; -use crate::ast::{Expr, ExprKind, Symbol, TypeAnnotationKind}; +use crate::ast::{Expr, ExprKind, Symbol}; use crate::docs::Documented; use crate::lsp::sync::FILES; -use crate::type_check::{resolve_user_defined_type, CLASS_INIT_NAME}; +use crate::type_check::{resolve_udt_from_expr, resolve_user_defined_type, CLASS_INIT_NAME}; use crate::visit::{visit_expr, Visit}; use crate::wasm_util::{ptr_to_string, string_to_combined_ptr, WASM_RETURN_ERROR}; @@ -43,11 +43,14 @@ pub fn on_signature_help(params: lsp_types::SignatureHelpParams) -> Option { - let t = if let TypeAnnotationKind::UserDefined(udt) = &class.kind { - resolve_user_defined_type(udt, root_scope.env.borrow().as_ref()?, 0).ok()? - } else { + let Some(udt) = resolve_udt_from_expr(class).ok() else { return None; }; + + let Some(t) = resolve_user_defined_type(&udt, root_scope.env.borrow().as_ref()?, 0).ok() else { + return None; + }; + let init_lookup = t.as_class()?.env.lookup( &Symbol { name: CLASS_INIT_NAME.into(), diff --git a/libs/wingc/src/lsp/snapshots/hovers/builtin_instance_method.snap b/libs/wingc/src/lsp/snapshots/hovers/builtin_instance_method.snap index 2d31b78dc7e..ab7bb69bc8f 100644 --- a/libs/wingc/src/lsp/snapshots/hovers/builtin_instance_method.snap +++ b/libs/wingc/src/lsp/snapshots/hovers/builtin_instance_method.snap @@ -7,7 +7,7 @@ contents: range: start: line: 1 - character: 0 + character: 8 end: line: 1 character: 18 diff --git a/libs/wingc/src/lsp/snapshots/hovers/class_property.snap b/libs/wingc/src/lsp/snapshots/hovers/class_property.snap index 1ac0390773e..e5c5ebf01d5 100644 --- a/libs/wingc/src/lsp/snapshots/hovers/class_property.snap +++ b/libs/wingc/src/lsp/snapshots/hovers/class_property.snap @@ -7,7 +7,7 @@ contents: range: start: line: 4 - character: 0 + character: 7 end: line: 4 character: 16 diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index 8f1e33faa3c..c919bf43e80 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -686,7 +686,10 @@ impl<'s> Parser<'s> { let parent = if let Some(parent_node) = statement_node.child_by_field_name("parent") { let parent_type = self.build_type_annotation(&parent_node, class_phase)?; match parent_type.kind { - TypeAnnotationKind::UserDefined(parent_type) => Some(parent_type), + TypeAnnotationKind::UserDefined(parent_type) => Some(Expr::new( + ExprKind::Reference(Reference::TypeReference(parent_type)), + self.node_span(&parent_node), + )), _ => { self.add_error::( format!("Parent type must be a user defined type, found {}", parent_type), @@ -887,6 +890,51 @@ impl<'s> Parser<'s> { Ok(res) } + fn build_udt(&self, type_node: &Node) -> DiagnosticResult { + match type_node.kind() { + "custom_type" => { + // check if last node is a "." + let last_child = type_node + .child(type_node.child_count() - 1) + .expect("If node is a custom type, it will have at least one child"); + + if last_child.kind() == "." { + // even though we're missing a field, we can still parse the rest of the type + let _ = self.add_error::<()>("Expected namespaced type", &last_child); + } + + let mut cursor = type_node.walk(); + let udt = UserDefinedType { + root: self.node_symbol(&type_node.child_by_field_name("object").unwrap())?, + fields: type_node + .children_by_field_name("fields", &mut cursor) + .map(|n| self.node_symbol(&n).unwrap()) + .collect(), + span: self.node_span(&type_node), + }; + + Ok(udt) + } + "mutable_container_type" | "immutable_container_type" => { + let container_type = self.node_text(&type_node.child_by_field_name("collection_type").unwrap()); + match container_type { + "ERROR" => self.add_error("Expected builtin container type", type_node)?, + builtin => { + let udt = UserDefinedType { + root: Symbol::global(WINGSDK_STD_MODULE), + fields: vec![Symbol { + name: builtin.to_string(), + span: self.node_span(&type_node), + }], + span: self.node_span(&type_node), + }; + Ok(udt) + } + } + } + other => self.add_error(format!("Expected class. Found {}", other), type_node), + } + } fn build_type_annotation(&self, type_node: &Node, phase: Phase) -> DiagnosticResult { let span = self.node_span(type_node); @@ -1018,14 +1066,14 @@ impl<'s> Parser<'s> { let object_expr = if object_expr.kind() == "json_container_type" { Expr::new( ExprKind::Reference(Reference::TypeMember { - type_: UserDefinedType { - root: Symbol { - name: WINGSDK_STD_MODULE.to_string(), - span: Default::default(), - }, - fields: vec![self.node_symbol(&object_expr)?], - span: self.node_span(&object_expr), - }, + typeobject: Box::new( + UserDefinedType { + root: Symbol::global(WINGSDK_STD_MODULE), + fields: vec![self.node_symbol(&object_expr)?], + span: self.node_span(&object_expr), + } + .to_expression(), + ), property: self.node_symbol(&property)?, }), self.node_span(&object_expr), @@ -1147,7 +1195,11 @@ impl<'s> Parser<'s> { let expression_node = &self.check_error(*exp_node, "expression")?; match expression_node.kind() { "new_expression" => { - let class = self.build_type_annotation(&expression_node.child_by_field_name("class").unwrap(), phase)?; + let class_udt = self.build_udt(&expression_node.child_by_field_name("class").unwrap())?; + let class_udt_exp = Expr::new( + ExprKind::Reference(Reference::TypeReference(class_udt)), + expression_span.clone(), + ); let arg_list = if let Ok(args_node) = self.get_child_field(expression_node, "args") { self.build_arg_list(&args_node, phase) @@ -1165,9 +1217,10 @@ impl<'s> Parser<'s> { } else { None }; + Ok(Expr::new( ExprKind::New { - class, + class: Box::new(class_udt_exp), obj_id, arg_list: arg_list?, obj_scope, @@ -1632,14 +1685,14 @@ impl<'s> Parser<'s> { let type_span = self.node_span(&statement_node.child(0).unwrap()); Ok(StmtKind::Expression(Expr::new( ExprKind::New { - class: TypeAnnotation { - kind: TypeAnnotationKind::UserDefined(UserDefinedType { + class: Box::new(Expr::new( + ExprKind::Reference(Reference::TypeReference(UserDefinedType { root: Symbol::global(WINGSDK_STD_MODULE), fields: vec![Symbol::global(WINGSDK_TEST_CLASS_NAME)], span: type_span.clone(), - }), - span: type_span.clone(), - }, + })), + type_span.clone(), + )), obj_id: Some(test_id), obj_scope: None, arg_list: ArgList { diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 71aa15e4c24..ab4a15d7ba5 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -74,6 +74,27 @@ pub enum SymbolKind { Namespace(NamespaceRef), } +#[derive(Debug, Clone)] +pub enum VariableKind { + /// a free variable not associated with a specific type + Free, + + /// an instance member (either of classes or of structs) + InstanceMember, + + /// a class member (or an enum member) + StaticMember, + + /// a type (e.g. `std.Json`) + Type, + + /// a namespace (e.g. `cloud`) + Namespace, + + /// an error placeholder + Error, +} + /// Information about a variable in the environment #[derive(Debug, Clone)] pub struct VariableInfo { @@ -81,14 +102,12 @@ pub struct VariableInfo { pub name: Symbol, /// Type of the variable pub type_: TypeRef, - /// Can the variable be reassigned? + /// Can the variable be reassigned? (only applies to variables and fields) pub reassignable: bool, /// The phase in which this variable exists pub phase: Phase, - /// Is this a member of a class/struct/interface or a free floating variable? - pub is_member: bool, - /// Is this a static or instance variable? (free variables are always static) - pub is_static: bool, + /// The kind of variable + pub kind: VariableKind, } impl SymbolKind { @@ -98,8 +117,11 @@ impl SymbolKind { type_, reassignable, phase, - is_static, - is_member: true, + kind: if is_static { + VariableKind::StaticMember + } else { + VariableKind::InstanceMember + }, }) } @@ -109,8 +131,7 @@ impl SymbolKind { type_, reassignable, phase, - is_static: true, - is_member: false, + kind: VariableKind::Free, }) } @@ -1258,14 +1279,13 @@ impl<'a> TypeChecker<'a> { self.types.error() } - fn make_error_variable_info(&self, is_static: bool) -> VariableInfo { + fn make_error_variable_info(&self) -> VariableInfo { VariableInfo { name: "".into(), type_: self.types.error(), reassignable: false, phase: Phase::Independent, - is_static, - is_member: false, + kind: VariableKind::Error, } } @@ -1400,12 +1420,24 @@ impl<'a> TypeChecker<'a> { arg_list, obj_scope, } => { - // Type check the arguments + // Type check everything + let class_type = self.type_check_exp(&class, env).0; + let obj_scope_type = obj_scope.as_ref().map(|x| self.type_check_exp(x, env).0); + let obj_id_type = obj_id.as_ref().map(|x| self.type_check_exp(x, env).0); let arg_list_types = self.type_check_arg_list(arg_list, env); + let ExprKind::Reference(ref r) = class.kind else { + self.spanned_error(exp,"Must be a reference to a class"); + return (self.types.error(), Phase::Independent); + }; + + let Reference::TypeReference(_) = r else { + self.spanned_error(exp,"Must be a type reference to a class"); + return (self.types.error(), Phase::Independent); + }; + // Lookup the class's type in the env - let type_ = self.resolve_type_annotation(class, env); - let (class_env, class_symbol) = match &*type_ { + let (class_env, class_symbol) = match *class_type { Type::Class(ref class) => { if class.phase == Phase::Independent || env.phase == class.phase { (&class.env, &class.name) @@ -1427,14 +1459,14 @@ impl<'a> TypeChecker<'a> { Type::Struct(_) => { self.spanned_error( class, - format!("Cannot instantiate type \"{}\" because it is a struct and not a class. Use struct instantiation instead.", type_), + format!("Cannot instantiate type \"{}\" because it is a struct and not a class. Use struct instantiation instead.", class_type), ); return self.resolved_error(); } _ => { self.spanned_error( class, - format!("Cannot instantiate type \"{}\" because it is not a class", type_), + format!("Cannot instantiate type \"{}\" because it is not a class", class_type), ); return self.resolved_error(); } @@ -1465,18 +1497,14 @@ impl<'a> TypeChecker<'a> { .expect("Expected constructor to be a function signature"); // Verify return type (This should never fail since we define the constructors return type during AST building) - self.validate_type(constructor_sig.return_type, type_, exp); + self.validate_type(constructor_sig.return_type, class_type, exp); self.type_check_arg_list_against_function_sig(&arg_list, &constructor_sig, exp, arg_list_types); - // Type check the scope and id - let obj_scope_type = obj_scope.as_ref().map(|x| self.type_check_exp(x, env).0); - let obj_id_type = obj_id.as_ref().map(|x| self.type_check_exp(x, env).0); - - let non_std_args = !type_.as_class().unwrap().std_construct_args; + let non_std_args = !class_type.as_class().unwrap().std_construct_args; // If this is a preflight class make sure the object's scope and id are of correct type - if type_.is_preflight_class() { + if class_type.is_preflight_class() { // Get reference to resource object's scope let obj_scope_type = if obj_scope_type.is_none() { // If this returns None, this means we're instantiating a preflight object in the global scope, which is valid @@ -1490,7 +1518,7 @@ impl<'a> TypeChecker<'a> { obj_scope.as_ref().unwrap(), format!( "Cannot set scope of non-standard preflight class \"{}\" using `in`", - type_ + class_type ), ); } @@ -1518,7 +1546,10 @@ impl<'a> TypeChecker<'a> { if non_std_args { self.spanned_error( obj_id.as_ref().unwrap(), - format!("Cannot set id of non-standard preflight class \"{}\" using `as`", type_), + format!( + "Cannot set id of non-standard preflight class \"{}\" using `as`", + class_type + ), ); } } @@ -1532,7 +1563,7 @@ impl<'a> TypeChecker<'a> { } } - (type_, env.phase) + (class_type, env.phase) } ExprKind::Call { callee, arg_list } => { // Resolve the function's reference (either a method in the class's env or a function in the current env) @@ -2509,7 +2540,7 @@ impl<'a> TypeChecker<'a> { self.spanned_error(stmt, format!("Cannot declare a {} class in {} scope", phase, env.phase)); } // Verify parent is a known class and get their env - let (parent_class, parent_class_env) = self.extract_parent_class(parent.as_ref(), *phase, name, env, stmt); + let (parent_class, parent_class_env) = self.extract_parent_class(parent.as_ref(), *phase, name, env); // Create environment representing this class, for now it'll be empty just so we can support referencing ourselves from the class definition. let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); @@ -3293,8 +3324,8 @@ impl<'a> TypeChecker<'a> { type_: v, reassignable, phase: flight, - is_static, - is_member: _, + kind, + .. }) => { // Replace type params in function signatures if let Some(sig) = v.as_function_sig() { @@ -3333,7 +3364,7 @@ impl<'a> TypeChecker<'a> { sym.clone(), self.types.add_type(Type::Function(new_sig)), *reassignable, - *is_static, + matches!(kind, VariableKind::StaticMember), *flight, ), StatementIdx::Top, @@ -3349,7 +3380,13 @@ impl<'a> TypeChecker<'a> { match new_type_class.env.define( // TODO: Original symbol is not available. SymbolKind::Variable should probably expose it &var_name, - SymbolKind::make_member_variable(var_name.clone(), new_var_type, *reassignable, *is_static, *flight), + SymbolKind::make_member_variable( + var_name.clone(), + new_var_type, + *reassignable, + matches!(kind, VariableKind::StaticMember), + *flight, + ), StatementIdx::Top, ) { Err(type_error) => { @@ -3466,12 +3503,14 @@ impl<'a> TypeChecker<'a> { _ => return None, } } - Reference::TypeMember { type_, .. } => { - if path.is_empty() { - return Some(type_.clone()); - } else { - // Type property references cannot be a type name because they have a property - return None; + Reference::TypeReference(type_) => { + return Some(type_.clone()); + } + Reference::TypeMember { typeobject, property } => { + path.push(property.clone()); + current_reference = match &typeobject.kind { + ExprKind::Reference(r) => r, + _ => return None, } } } @@ -3539,7 +3578,7 @@ impl<'a> TypeChecker<'a> { symbol, format!("Expected identifier \"{symbol}\" to be a variable, but it's a {var}",), ); - (self.make_error_variable_info(false), Phase::Independent) + (self.make_error_variable_info(), Phase::Independent) } } else { // Give a specific error message if someone tries to write "print" instead of "log" @@ -3548,7 +3587,7 @@ impl<'a> TypeChecker<'a> { } else { self.type_error(lookup_result_to_type_error(lookup_res, symbol)); } - (self.make_error_variable_info(false), Phase::Independent) + (self.make_error_variable_info(), Phase::Independent) } } Reference::InstanceMember { @@ -3566,7 +3605,7 @@ impl<'a> TypeChecker<'a> { // Create a type reference out of this nested reference and call ourselves again let new_ref = Reference::TypeMember { - type_: user_type_annotation, + typeobject: Box::new(user_type_annotation.to_expression()), property: property.clone(), }; // Replace the reference with the new one, this is unsafe because `reference` isn't mutable and theoretically someone may @@ -3597,7 +3636,7 @@ impl<'a> TypeChecker<'a> { // If resolving the object's type failed, we can't resolve the property either if instance_type.is_unresolved() { - return (self.make_error_variable_info(false), Phase::Independent); + return (self.make_error_variable_info(), Phase::Independent); } let property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); @@ -3635,21 +3674,51 @@ impl<'a> TypeChecker<'a> { (property_variable, property_phase) } } - Reference::TypeMember { type_, property } => { - let type_ = self - .resolve_user_defined_type(type_, env, self.statement_idx) - .expect("Type annotation should have been verified by `expr_maybe_type`"); + Reference::TypeReference(udt) => { + let Ok(t) = self.resolve_user_defined_type(udt, env, self.statement_idx) else { + return (self.make_error_variable_info(), Phase::Independent); + }; + + let phase = if let Some(c) = t.as_class() { + c.phase + } else { + Phase::Independent + }; + + ( + VariableInfo { + name: Symbol::global(udt.full_path_str()), + type_: t, + reassignable: false, + phase: phase.clone(), + kind: VariableKind::Type, + }, + phase, + ) + } + Reference::TypeMember { typeobject, property } => { + let (type_, _) = self.type_check_exp(typeobject, env); + + let ExprKind::Reference(typeref) = &typeobject.kind else { + self.spanned_error(typeobject, "Expecting a reference"); + return (self.make_error_variable_info(), Phase::Independent); + }; + + let Reference::TypeReference(_) = typeref else { + self.spanned_error(typeobject, "Expecting a reference to a type"); + return (self.make_error_variable_info(), Phase::Independent); + }; + match *type_ { Type::Enum(ref e) => { if e.values.contains(property) { ( VariableInfo { name: property.clone(), + kind: VariableKind::StaticMember, type_, reassignable: false, phase: Phase::Independent, - is_static: true, - is_member: true, }, Phase::Independent, ) @@ -3658,12 +3727,12 @@ impl<'a> TypeChecker<'a> { property, format!("Enum \"{}\" does not contain value \"{}\"", type_, property.name), ); - (self.make_error_variable_info(true), Phase::Independent) + (self.make_error_variable_info(), Phase::Independent) } } Type::Class(ref c) => match c.env.lookup(&property, None) { Some(SymbolKind::Variable(v)) => { - if v.is_static { + if let VariableKind::StaticMember = v.kind { (v.clone(), v.phase) } else { self.spanned_error( @@ -3673,7 +3742,7 @@ impl<'a> TypeChecker<'a> { type_, property.name ), ); - (self.make_error_variable_info(true), Phase::Independent) + (self.make_error_variable_info(), Phase::Independent) } } _ => { @@ -3681,12 +3750,12 @@ impl<'a> TypeChecker<'a> { property, format!("No member \"{}\" in class \"{}\"", property.name, type_), ); - (self.make_error_variable_info(true), Phase::Independent) + (self.make_error_variable_info(), Phase::Independent) } }, _ => { self.spanned_error(property, format!("\"{}\" not a valid reference", reference)); - (self.make_error_variable_info(true), Phase::Independent) + (self.make_error_variable_info(), Phase::Independent) } } } @@ -3709,8 +3778,7 @@ impl<'a> TypeChecker<'a> { type_: instance_type, reassignable: false, phase: env.phase, - is_static: false, - is_member: true, + kind: VariableKind::InstanceMember, }, // Lookup wingsdk std types, hydrating generics if necessary @@ -3784,11 +3852,8 @@ impl<'a> TypeChecker<'a> { ), Type::Struct(ref s) => self.get_property_from_class_like(s, property), _ => { - self.spanned_error( - object, - format!("Property access unsupported on type \"{}\"", instance_type), - ); - self.make_error_variable_info(false) + self.spanned_error(property, format!("Property not found")); + self.make_error_variable_info() } } } @@ -3798,18 +3863,18 @@ impl<'a> TypeChecker<'a> { let lookup_res = class.get_env().lookup_ext(property, None); if let LookupResult::Found(field, _) = lookup_res { let var = field.as_variable().expect("Expected property to be a variable"); - if var.is_static { + if let VariableKind::StaticMember = var.kind { self.spanned_error( property, format!("Cannot access static property \"{property}\" from instance"), ); - self.make_error_variable_info(false) + self.make_error_variable_info() } else { var } } else { self.type_error(lookup_result_to_type_error(lookup_res, property)); - self.make_error_variable_info(false) + self.make_error_variable_info() } } @@ -3838,13 +3903,12 @@ impl<'a> TypeChecker<'a> { fn extract_parent_class( &mut self, - parent_udt: Option<&UserDefinedType>, + parent_expr: Option<&Expr>, phase: Phase, name: &Symbol, env: &mut SymbolEnv, - stmt: &Stmt, ) -> (Option, Option) { - if parent_udt.is_none() { + let Some(parent_expr) = parent_expr else { if phase == Phase::Preflight { // if this is a preflight and we don't have a parent, then we implicitly set it to `std.Resource` let t = self.types.resource_base_type(); @@ -3853,24 +3917,18 @@ impl<'a> TypeChecker<'a> { } else { return (None, None); } - } + }; + + let (parent_type, _) = self.type_check_exp(&parent_expr, env); + // Safety: we return from the function above so parent_udt cannot be None - let parent_udt = parent_udt.unwrap(); + let parent_udt = resolve_udt_from_expr(parent_expr).unwrap(); if &parent_udt.root == name && parent_udt.fields.is_empty() { self.spanned_error(parent_udt, "Class cannot extend itself".to_string()); return (None, None); } - let parent_type = self.resolve_user_defined_type(parent_udt, env, stmt.idx); - let parent_type = match parent_type { - Ok(t) => t, - Err(e) => { - self.type_error(e); - return (None, None); - } - }; - if let Some(parent_class) = parent_type.as_class() { if parent_class.phase == phase { (Some(parent_type), Some(parent_class.env.get_ref())) @@ -3880,14 +3938,14 @@ impl<'a> TypeChecker<'a> { "{} class {} cannot extend {} class \"{}\"", phase, name, parent_class.phase, parent_class.name ), - span: Some(parent_udt.span.clone()), + span: Some(parent_expr.span.clone()), }); (None, None) } } else { report_diagnostic(Diagnostic { message: format!("Base class \"{}\" is not a class", parent_type), - span: Some(parent_udt.span.clone()), + span: Some(parent_expr.span.clone()), }); (None, None) } @@ -4022,6 +4080,25 @@ where TypeError { message, span } } +/// Resolves a user defined type (e.g. `Foo.Bar.Baz`) to a type reference +pub fn resolve_udt_from_expr(expr: &Expr) -> Result<&UserDefinedType, TypeError> { + let ExprKind::Reference(ref r) = expr.kind else { + return Err(TypeError { + message: format!("Expected expression to be a reference"), + span: expr.span.clone(), + }); + }; + + let Reference::TypeReference(udt) = r else { + return Err(TypeError { + message: format!("Expected reference to be a reference to a type"), + span: expr.span.clone(), + }); + }; + + Ok(udt) +} + /// Resolves a user defined type (e.g. `Foo.Bar.Baz`) to a type reference pub fn resolve_user_defined_type( user_defined_type: &UserDefinedType, @@ -4033,6 +4110,7 @@ pub fn resolve_user_defined_type( nested_name.extend(user_defined_type.fields.iter().collect_vec()); let lookup_result = env.lookup_nested(&nested_name, Some(statement_idx)); + if let LookupResult::Found(symb_kind, _) = lookup_result { if let SymbolKind::Type(t) = symb_kind { Ok(*t) diff --git a/libs/wingc/src/visit.rs b/libs/wingc/src/visit.rs index dfef1f317af..c3dcf428b55 100644 --- a/libs/wingc/src/visit.rs +++ b/libs/wingc/src/visit.rs @@ -51,7 +51,7 @@ pub trait Visit<'ast> { fn visit_expr_new( &mut self, node: &'ast Expr, - class: &'ast TypeAnnotation, + class: &'ast Expr, obj_id: &'ast Option>, obj_scope: &'ast Option>, arg_list: &'ast ArgList, @@ -247,7 +247,7 @@ where } if let Some(extend) = &node.parent { - v.visit_user_defined_type(&extend); + v.visit_expr(&extend); } for implement in &node.implements { @@ -274,14 +274,14 @@ where pub fn visit_expr_new<'ast, V>( v: &mut V, _node: &'ast Expr, - class: &'ast TypeAnnotation, + class: &'ast Expr, obj_id: &'ast Option>, obj_scope: &'ast Option>, arg_list: &'ast ArgList, ) where V: Visit<'ast> + ?Sized, { - v.visit_type_annotation(class); + v.visit_expr(class); v.visit_args(arg_list); if let Some(id) = obj_id { v.visit_expr(&id); @@ -413,8 +413,11 @@ where v.visit_expr(object); v.visit_symbol(property); } - Reference::TypeMember { type_, property } => { + Reference::TypeReference(type_) => { v.visit_user_defined_type(type_); + } + Reference::TypeMember { typeobject, property } => { + v.visit_expr(typeobject); v.visit_symbol(property); } } diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 76032313034..df41860e19e 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -1,20 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`access_hidden_namespace.w 1`] = ` -"error: Unknown symbol \\"core\\" - --> ../../../examples/tests/invalid/access_hidden_namespace.w:7:5 - | -7 | new core.NodeJsCode(\\"/tmp/test.txt\\"); // This should fail even though \`fs.TextFile\` extends \`core.FileBase\` because we didn't bring in \`core\` explicitly. - | ^^^^ Unknown symbol \\"core\\" - - - - -Tests 1 failed (1) -Test Files 1 failed (1) -Duration " -`; - exports[`access_static_from_instance.w 1`] = ` "error: Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 --> ../../../examples/tests/invalid/access_static_from_instance.w:4:3 @@ -294,11 +279,11 @@ error: Preflight field \\"y\\" is not initialized | ^ Preflight field \\"y\\" is not initialized -error: Expected \\"x\\" to be a type but it's a variable +error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/class.w:68:18 | 68 | class C7 extends x { - | ^ Expected \\"x\\" to be a type but it's a variable + | ^ Base class \\"unresolved\\" is not a class error: Base class \\"S1\\" is not a class @@ -308,11 +293,11 @@ error: Base class \\"S1\\" is not a class | ^^ Base class \\"S1\\" is not a class -error: Class cannot extend itself +error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/class.w:78:19 | 78 | class C11 extends C11 { - | ^^^ Class cannot extend itself + | ^^^ Base class \\"unresolved\\" is not a class error: Expected type to be \\"num\\", but got \\"str\\" instead @@ -535,18 +520,11 @@ Duration " `; exports[`enums.w 1`] = ` -"error: Enum \\"SomeEnum\\" does not contain value \\"FOUR\\" - --> ../../../examples/tests/invalid/enums.w:5:21 - | -5 | let four = SomeEnum.FOUR; - | ^^^^ Enum \\"SomeEnum\\" does not contain value \\"FOUR\\" - - -error: Property access unsupported on type \\"SomeEnum\\" - --> ../../../examples/tests/invalid/enums.w:8:11 +"error: Property not found + --> ../../../examples/tests/invalid/enums.w:8:24 | 8 | let two = SomeEnum.TWO.TWO; - | ^^^^^^^^^^^^ Property access unsupported on type \\"SomeEnum\\" + | ^^^ Property not found @@ -1558,11 +1536,11 @@ exports[`sorted_errors_no_span.w 1`] = ` | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead -error: Expected \\"b\\" to be a type but it's a variable +error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/sorted_errors_no_span.w:3:26 | 3 | inflight class c extends b {} - | ^ Expected \\"b\\" to be a type but it's a variable + | ^ Base class \\"unresolved\\" is not a class error: Expected type to be \\"num\\", but got \\"str\\" instead @@ -1572,11 +1550,11 @@ error: Expected type to be \\"num\\", but got \\"str\\" instead | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead -error: Expected \\"b\\" to be a type but it's a variable +error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/sorted_errors_no_span.w:5:26 | 5 | inflight class e extends b {} - | ^ Expected \\"b\\" to be a type but it's a variable + | ^ Base class \\"unresolved\\" is not a class @@ -1768,10 +1746,10 @@ error: Struct \\"Showtime\\" extends \\"Dazzle\\" which introduces a conflicting error: Cannot instantiate type \\"BucketProps\\" because it is a struct and not a class. Use struct instantiation instead. - --> ../../../examples/tests/invalid/structs.w:47:13 + --> ../../../examples/tests/invalid/structs.w:47:9 | 47 | let x = new cloud.BucketProps(1); - | ^^^^^^^^^^^^^^^^^ Cannot instantiate type \\"BucketProps\\" because it is a struct and not a class. Use struct instantiation instead. + | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot instantiate type \\"BucketProps\\" because it is a struct and not a class. Use struct instantiation instead. @@ -1894,32 +1872,25 @@ Duration " `; exports[`unknown_symbol.w 1`] = ` -"error: Unknown symbol \\"clod\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:3:18 - | -3 | let bucket = new clod.Bucket(); - | ^^^^ Unknown symbol \\"clod\\" - - -error: Unknown symbol \\"cloudy\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:6:17 - | -6 | let funky = new cloudy.Funktion(inflight () => { }); - | ^^^^^^ Unknown symbol \\"cloudy\\" - - -error: Unknown symbol \\"y\\" +"error: Unknown symbol \\"y\\" --> ../../../examples/tests/invalid/unknown_symbol.w:9:13 | 9 | let x = 2 + y; | ^ Unknown symbol \\"y\\" -error: Unknown symbol \\"B\\" +error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/unknown_symbol.w:28:17 | 28 | class A extends B { - | ^ Unknown symbol \\"B\\" + | ^ Base class \\"unresolved\\" is not a class + + +error: Unknown symbol \\"unknown\\" + --> ../../../examples/tests/invalid/unknown_symbol.w:32:1 + | +32 | unknown = 1; + | ^^^^^^^ Unknown symbol \\"unknown\\" error: Unknown symbol \\"unknown\\" @@ -2002,11 +1973,11 @@ Duration " `; exports[`void_in_expression_position.w 1`] = ` -"error: Property access unsupported on type \\"void\\" - --> ../../../examples/tests/invalid/void_in_expression_position.w:1:1 +"error: Property not found + --> ../../../examples/tests/invalid/void_in_expression_position.w:1:12 | 1 | log(\\"hey\\").get(\\"x\\"); - | ^^^^^^^^^^ Property access unsupported on type \\"void\\" + | ^^^ Property not found error: Binary operator '+' cannot be applied to operands of type 'num' and 'void'; only (num, num) and (str, str) are supported From 74de1b77d4933ceb12bb57c1380f5923633644ef Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 15:42:37 +0300 Subject: [PATCH 05/20] fix(cli): `wing test` returns 0 exit code upon failure (#3176) Fixes #2916 by returning exit code 0 when tests fail. ## Misc Tweaks to a bunch of tests. ## Checklist - [x] Title matches [Winglang's style guide](https://docs.winglang.io/contributing/pull_requests#how-are-pull-request-titles-formatted) - [x] Description explains motivation and solution - [x] Tests added (always) - [x] Docs updated (only required for features) - [x] Added `pr/e2e-full` label if this feature requires end-to-end testing *By submitting this pull request, I confirm that my contribution is made under the terms of the [Monada Contribution License](https://docs.winglang.io/terms-and-policies/contribution-license.html)*. --- apps/wing/src/cli.ts | 12 +- apps/wing/src/commands/test.ts | 19 +- .../invalid/inflight_class_capture_mutable.w | 31 -- examples/tests/sdk_tests/bucket/events.w | 2 +- examples/tests/sdk_tests/bucket/public_url.w | 3 +- examples/tests/valid/enums.w | 5 + examples/tests/valid/resource_call_static.w | 15 + tools/hangar/__snapshots__/invalid.ts.snap | 9 - .../bucket/events.w_compile_tf-aws.md | 4 +- .../bucket/public_url.w_compile_tf-aws.md | 5 +- .../valid/enums.w_compile_tf-aws.md | 162 +++++++++- .../test_corpus/valid/enums.w_test_sim.md | 2 +- .../resource_call_static.w_compile_tf-aws.md | 287 ++++++++++++++++++ .../valid/resource_call_static.w_test_sim.md | 12 + tools/hangar/src/error.test.ts | 2 +- tools/hangar/src/invalid.test.ts | 2 +- tools/hangar/src/unsupported.test.ts | 5 +- tools/hangar/src/utils.ts | 15 +- 18 files changed, 518 insertions(+), 74 deletions(-) delete mode 100644 examples/tests/invalid/inflight_class_capture_mutable.w create mode 100644 examples/tests/valid/resource_call_static.w create mode 100644 tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_test_sim.md diff --git a/apps/wing/src/cli.ts b/apps/wing/src/cli.ts index 3915272b9cd..86868ebae30 100644 --- a/apps/wing/src/cli.ts +++ b/apps/wing/src/cli.ts @@ -14,11 +14,17 @@ if (!SUPPORTED_NODE_VERSION) { } function actionErrorHandler(fn: (...args: any[]) => Promise) { - return (...args: any[]) => - fn(...args).catch((err: Error) => { + return async (...args: any[]) => { + try { + const exitCode = await fn(...args); + if (exitCode === 1) { + process.exit(1); + } + } catch (err) { console.error(err); process.exit(1); - }); + } + }; } async function main() { diff --git a/apps/wing/src/commands/test.ts b/apps/wing/src/commands/test.ts index ae0be9aaf65..2e83e96874e 100644 --- a/apps/wing/src/commands/test.ts +++ b/apps/wing/src/commands/test.ts @@ -27,7 +27,7 @@ const generateTestName = (path: string) => path.split(sep).slice(-2).join("/"); */ export interface TestOptions extends CompileOptions {} -export async function test(entrypoints: string[], options: TestOptions) { +export async function test(entrypoints: string[], options: TestOptions): Promise { const startTime = Date.now(); const results: { testName: string; results: sdk.cloud.TestResult[] }[] = []; for (const entrypoint of entrypoints) { @@ -44,6 +44,17 @@ export async function test(entrypoints: string[], options: TestOptions) { } } printResults(results, Date.now() - startTime); + + // if we have any failures, exit with 1 + for (const test of results) { + for (const r of test.results) { + if (r.error) { + return 1; + } + } + } + + return 0; } function printResults( @@ -92,16 +103,14 @@ function printResults( // prints a summary of how many tests passed and failed results.push(" "); results.push( - `${chalk.dim("Tests")}${failingTestsNumber ? chalk.red(` ${failingTestsNumber} failed`) : ""}${ - failingTestsNumber && passingTestsNumber ? chalk.dim(" |") : "" + `${chalk.dim("Tests")}${failingTestsNumber ? chalk.red(` ${failingTestsNumber} failed`) : ""}${failingTestsNumber && passingTestsNumber ? chalk.dim(" |") : "" }${passingTestsNumber ? chalk.green(` ${passingTestsNumber} passed`) : ""} ${chalk.dim( `(${failingTestsNumber + passingTestsNumber})` )}` ); // prints a summary of how many tests files passed and failed results.push( - `${chalk.dim("Test Files")}${failing.length ? chalk.red(` ${failing.length} failed`) : ""}${ - failing.length && passing.length ? chalk.dim(" |") : "" + `${chalk.dim("Test Files")}${failing.length ? chalk.red(` ${failing.length} failed`) : ""}${failing.length && passing.length ? chalk.dim(" |") : "" }${passing.length ? chalk.green(` ${passing.length} passed`) : ""} ${chalk.dim( `(${totalSum})` )}` diff --git a/examples/tests/invalid/inflight_class_capture_mutable.w b/examples/tests/invalid/inflight_class_capture_mutable.w deleted file mode 100644 index 9b8ad221e1a..00000000000 --- a/examples/tests/invalid/inflight_class_capture_mutable.w +++ /dev/null @@ -1,31 +0,0 @@ -let x = MutArray["hello", "world"]; - -inflight class Foo { - foo() { - log(x.at(0)); -// ^ Cannot capture field 'x' with non-capturable type 'MutArray' - } -} - -let var foo = 12; - -inflight class Goo { - goo(): num { - return foo; -// ^^^ Cannot capture reassignable field 'foo' - } -} - -// TODO: https://github.com/winglang/wing/issues/2757 (this should fail) -// test "t" { -// let var x = "foo"; - -// class C1 { -// f() { -// x = "bar"; -// } -// } - -// new C1().f(); -// log(x); -// } diff --git a/examples/tests/sdk_tests/bucket/events.w b/examples/tests/sdk_tests/bucket/events.w index 9429aff7daf..ef9175e1a5f 100644 --- a/examples/tests/sdk_tests/bucket/events.w +++ b/examples/tests/sdk_tests/bucket/events.w @@ -106,4 +106,4 @@ new std.Test(inflight () => { assert(wait(checkHitCount(key: "b", type: "UPDATE", source: Source.onEvent, count: 1))); assert(wait(checkHitCount(key: "c", type: "DELETE", source: Source.onEvent, count: 1))); -}, std.TestProps { timeout: 8m }) as "hitCount is incremented according to the bucket event"; +}, timeout: 8m) as "hitCount is incremented according to the bucket event"; diff --git a/examples/tests/sdk_tests/bucket/public_url.w b/examples/tests/sdk_tests/bucket/public_url.w index 46bc763720d..024e064a353 100644 --- a/examples/tests/sdk_tests/bucket/public_url.w +++ b/examples/tests/sdk_tests/bucket/public_url.w @@ -1,7 +1,6 @@ bring cloud; -let bucketProps = cloud.BucketProps{public: true}; -let publicBucket = new cloud.Bucket(bucketProps) as "publicBucket"; +let publicBucket = new cloud.Bucket(public: true) as "publicBucket"; let privateBucket = new cloud.Bucket() as "privateBucket"; test "publicUrl" { diff --git a/examples/tests/valid/enums.w b/examples/tests/valid/enums.w index b63a89a9f33..0dd9f064b6f 100644 --- a/examples/tests/valid/enums.w +++ b/examples/tests/valid/enums.w @@ -4,3 +4,8 @@ enum SomeEnum { let one = SomeEnum.ONE; let two: SomeEnum = SomeEnum.TWO; // Try with explicit type annotation + +test "inflight" { + assert(one == SomeEnum.ONE); + assert(two == SomeEnum.TWO); +} \ No newline at end of file diff --git a/examples/tests/valid/resource_call_static.w b/examples/tests/valid/resource_call_static.w new file mode 100644 index 00000000000..f9427b190a7 --- /dev/null +++ b/examples/tests/valid/resource_call_static.w @@ -0,0 +1,15 @@ +bring cloud; + +let globalCounter = new cloud.Counter(); + +class Another { + static inflight myStaticMethod(): num { + return globalCounter.peek(); + } +} + +test "access cloud resource through static methods only" { + // Call a static method which access a (global) cloud resource + // the capturing should work through the Type binding mechanism + assert(Another.myStaticMethod() == 0); +} \ No newline at end of file diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index df41860e19e..b752fc07ca3 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -658,15 +658,6 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_class_capture_mutable.w 1`] = ` -"pass ─ inflight_class_capture_mutable.wsim (no tests) - - -Tests 1 passed (1) -Test Files 1 passed (1) -Duration " -`; - exports[`inflight_class_created_in_preflight.w 1`] = ` "error: Cannot create inflight class \\"Foo\\" in preflight phase --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:3:1 diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/events.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/events.w_compile_tf-aws.md index f39790b5eb3..3297fd100b8 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/events.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/events.w_compile_tf-aws.md @@ -1476,9 +1476,7 @@ class $Root extends $stdlib.std.Resource { (b.onEvent(new $Closure5(this,"$Closure5"))); const wait = new $Closure6(this,"$Closure6"); const checkHitCount = new $Closure7(this,"$Closure7"); - this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"hitCount is incremented according to the bucket event",new $Closure8(this,"$Closure8"),{ - "timeout": (std.Duration.fromSeconds(480)),} - ); + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"hitCount is incremented according to the bucket event",new $Closure8(this,"$Closure8"),{ timeout: (std.Duration.fromSeconds(480)) }); } } class $App extends $AppBase { diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.w_compile_tf-aws.md index 546b9c2cd79..a2d4a961971 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.w_compile_tf-aws.md @@ -301,10 +301,7 @@ class $Root extends $stdlib.std.Resource { super._registerBind(host, ops); } } - const bucketProps = { - "public": true,} - ; - const publicBucket = this.node.root.newAbstract("@winglang/sdk.cloud.Bucket",this,"publicBucket",bucketProps); + const publicBucket = this.node.root.newAbstract("@winglang/sdk.cloud.Bucket",this,"publicBucket",{ public: true }); const privateBucket = this.node.root.newAbstract("@winglang/sdk.cloud.Bucket",this,"privateBucket"); this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:publicUrl",new $Closure1(this,"$Closure1")); } diff --git a/tools/hangar/__snapshots__/test_corpus/valid/enums.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/enums.w_compile_tf-aws.md index 2d7c37e2648..210d3b0c54f 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/enums.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/enums.w_compile_tf-aws.md @@ -1,5 +1,26 @@ # [enums.w](../../../../../examples/tests/valid/enums.w) | compile | tf-aws +## inflight.$Closure1.js +```js +module.exports = function({ one, two, SomeEnum }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async $inflight_init() { + } + async handle() { + {((cond) => {if (!cond) throw new Error("assertion failed: one == SomeEnum.ONE")})((one === SomeEnum.ONE))}; + {((cond) => {if (!cond) throw new Error("assertion failed: two == SomeEnum.TWO")})((two === SomeEnum.TWO))}; + } + } + return $Closure1; +} + +``` + ## main.tf.json ```json { @@ -21,13 +42,102 @@ }, "output": { "WING_TEST_RUNNER_FUNCTION_ARNS": { - "value": "[]" + "value": "[[\"root/Default/Default/test:inflight\",\"${aws_lambda_function.root_testinflight_Handler_75584D7C.arn}\"]]" } }, "provider": { "aws": [ {} ] + }, + "resource": { + "aws_iam_role": { + "root_testinflight_Handler_IamRole_52AF7859": { + "//": { + "metadata": { + "path": "root/Default/Default/test:inflight/Handler/IamRole", + "uniqueId": "root_testinflight_Handler_IamRole_52AF7859" + } + }, + "assume_role_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Effect\":\"Allow\"}]}" + } + }, + "aws_iam_role_policy": { + "root_testinflight_Handler_IamRolePolicy_877E2F83": { + "//": { + "metadata": { + "path": "root/Default/Default/test:inflight/Handler/IamRolePolicy", + "uniqueId": "root_testinflight_Handler_IamRolePolicy_877E2F83" + } + }, + "policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"none:null\",\"Resource\":\"*\"}]}", + "role": "${aws_iam_role.root_testinflight_Handler_IamRole_52AF7859.name}" + } + }, + "aws_iam_role_policy_attachment": { + "root_testinflight_Handler_IamRolePolicyAttachment_C597EE77": { + "//": { + "metadata": { + "path": "root/Default/Default/test:inflight/Handler/IamRolePolicyAttachment", + "uniqueId": "root_testinflight_Handler_IamRolePolicyAttachment_C597EE77" + } + }, + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "${aws_iam_role.root_testinflight_Handler_IamRole_52AF7859.name}" + } + }, + "aws_lambda_function": { + "root_testinflight_Handler_75584D7C": { + "//": { + "metadata": { + "path": "root/Default/Default/test:inflight/Handler/Default", + "uniqueId": "root_testinflight_Handler_75584D7C" + } + }, + "environment": { + "variables": { + "WING_FUNCTION_NAME": "Handler-c85726ab", + "WING_TARGET": "tf-aws" + } + }, + "function_name": "Handler-c85726ab", + "handler": "index.handler", + "publish": true, + "role": "${aws_iam_role.root_testinflight_Handler_IamRole_52AF7859.arn}", + "runtime": "nodejs18.x", + "s3_bucket": "${aws_s3_bucket.root_Code_02F3C603.bucket}", + "s3_key": "${aws_s3_object.root_testinflight_Handler_S3Object_62C42629.key}", + "timeout": 30, + "vpc_config": { + "security_group_ids": [], + "subnet_ids": [] + } + } + }, + "aws_s3_bucket": { + "root_Code_02F3C603": { + "//": { + "metadata": { + "path": "root/Default/Code", + "uniqueId": "root_Code_02F3C603" + } + }, + "bucket_prefix": "code-c84a50b1-" + } + }, + "aws_s3_object": { + "root_testinflight_Handler_S3Object_62C42629": { + "//": { + "metadata": { + "path": "root/Default/Default/test:inflight/Handler/S3Object", + "uniqueId": "root_testinflight_Handler_S3Object_62C42629" + } + }, + "bucket": "${aws_s3_bucket.root_Code_02F3C603.bucket}", + "key": "", + "source": "" + } + } } } ``` @@ -42,6 +152,55 @@ const $AppBase = $stdlib.core.App.for(process.env.WING_TARGET); class $Root extends $stdlib.std.Resource { constructor(scope, id) { super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + this.display.hidden = true; + this._addInflightOps("handle"); + } + static _toInflightType(context) { + const self_client_path = "././inflight.$Closure1.js"; + const one_client = context._lift(one); + const two_client = context._lift(two); + const SomeEnumClient = $stdlib.core.NodeJsCode.fromInline(` + Object.freeze((function (tmp) { + tmp[tmp["ONE"] = 0] = "ONE"; + tmp[tmp["TWO"] = 1] = "TWO"; + tmp[tmp["THREE"] = 2] = "THREE"; + return tmp; + })({})) + `); + return $stdlib.core.NodeJsCode.fromInline(` + require("${self_client_path}")({ + one: ${one_client}, + two: ${two_client}, + SomeEnum: ${SomeEnumClient.text}, + }) + `); + } + _toInflight() { + return $stdlib.core.NodeJsCode.fromInline(` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this).text}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `); + } + _registerBind(host, ops) { + if (ops.includes("$inflight_init")) { + $Closure1._registerBindObject(one, host, []); + $Closure1._registerBindObject(two, host, []); + } + if (ops.includes("handle")) { + $Closure1._registerBindObject(one, host, []); + $Closure1._registerBindObject(two, host, []); + } + super._registerBind(host, ops); + } + } const SomeEnum = Object.freeze((function (tmp) { tmp[tmp["ONE"] = 0] = "ONE"; @@ -52,6 +211,7 @@ class $Root extends $stdlib.std.Resource { ; const one = SomeEnum.ONE; const two = SomeEnum.TWO; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight",new $Closure1(this,"$Closure1")); } } class $App extends $AppBase { diff --git a/tools/hangar/__snapshots__/test_corpus/valid/enums.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/enums.w_test_sim.md index de8b9baefae..cf07ed95bd2 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/enums.w_test_sim.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/enums.w_test_sim.md @@ -2,7 +2,7 @@ ## stdout.log ```log -pass ─ enums.wsim (no tests) +pass ─ enums.wsim » root/env0/test:inflight Tests 1 passed (1) diff --git a/tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_compile_tf-aws.md new file mode 100644 index 00000000000..ae5a3a06230 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_compile_tf-aws.md @@ -0,0 +1,287 @@ +# [resource_call_static.w](../../../../../examples/tests/valid/resource_call_static.w) | compile | tf-aws + +## inflight.$Closure1.js +```js +module.exports = function({ Another }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async $inflight_init() { + } + async handle() { + {((cond) => {if (!cond) throw new Error("assertion failed: Another.myStaticMethod() == 0")})(((await Another.myStaticMethod()) === 0))}; + } + } + return $Closure1; +} + +``` + +## inflight.Another.js +```js +module.exports = function({ globalCounter }) { + class Another { + constructor({ }) { + } + async $inflight_init() { + } + static async myStaticMethod() { + return (await globalCounter.peek()); + } + } + return Another; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.15.2" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[[\"root/Default/Default/test:access cloud resource through static methods only\",\"${aws_lambda_function.root_testaccesscloudresourcethroughstaticmethodsonly_Handler_90784797.arn}\"]]" + } + }, + "provider": { + "aws": [ + {} + ] + }, + "resource": { + "aws_dynamodb_table": { + "root_cloudCounter_E0AC1263": { + "//": { + "metadata": { + "path": "root/Default/Default/cloud.Counter/Default", + "uniqueId": "root_cloudCounter_E0AC1263" + } + }, + "attribute": [ + { + "name": "id", + "type": "S" + } + ], + "billing_mode": "PAY_PER_REQUEST", + "hash_key": "id", + "name": "wing-counter-cloud.Counter-c866f225" + } + }, + "aws_iam_role": { + "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRole_6B8CBEFD": { + "//": { + "metadata": { + "path": "root/Default/Default/test:access cloud resource through static methods only/Handler/IamRole", + "uniqueId": "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRole_6B8CBEFD" + } + }, + "assume_role_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Effect\":\"Allow\"}]}" + } + }, + "aws_iam_role_policy": { + "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRolePolicy_2AD210AF": { + "//": { + "metadata": { + "path": "root/Default/Default/test:access cloud resource through static methods only/Handler/IamRolePolicy", + "uniqueId": "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRolePolicy_2AD210AF" + } + }, + "policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"dynamodb:GetItem\"],\"Resource\":[\"${aws_dynamodb_table.root_cloudCounter_E0AC1263.arn}\"],\"Effect\":\"Allow\"}]}", + "role": "${aws_iam_role.root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRole_6B8CBEFD.name}" + } + }, + "aws_iam_role_policy_attachment": { + "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRolePolicyAttachment_B013CEF2": { + "//": { + "metadata": { + "path": "root/Default/Default/test:access cloud resource through static methods only/Handler/IamRolePolicyAttachment", + "uniqueId": "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRolePolicyAttachment_B013CEF2" + } + }, + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "${aws_iam_role.root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRole_6B8CBEFD.name}" + } + }, + "aws_lambda_function": { + "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_90784797": { + "//": { + "metadata": { + "path": "root/Default/Default/test:access cloud resource through static methods only/Handler/Default", + "uniqueId": "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_90784797" + } + }, + "environment": { + "variables": { + "DYNAMODB_TABLE_NAME_49baa65c": "${aws_dynamodb_table.root_cloudCounter_E0AC1263.name}", + "WING_FUNCTION_NAME": "Handler-c8de1ef1", + "WING_TARGET": "tf-aws" + } + }, + "function_name": "Handler-c8de1ef1", + "handler": "index.handler", + "publish": true, + "role": "${aws_iam_role.root_testaccesscloudresourcethroughstaticmethodsonly_Handler_IamRole_6B8CBEFD.arn}", + "runtime": "nodejs18.x", + "s3_bucket": "${aws_s3_bucket.root_Code_02F3C603.bucket}", + "s3_key": "${aws_s3_object.root_testaccesscloudresourcethroughstaticmethodsonly_Handler_S3Object_2C11A1C8.key}", + "timeout": 30, + "vpc_config": { + "security_group_ids": [], + "subnet_ids": [] + } + } + }, + "aws_s3_bucket": { + "root_Code_02F3C603": { + "//": { + "metadata": { + "path": "root/Default/Code", + "uniqueId": "root_Code_02F3C603" + } + }, + "bucket_prefix": "code-c84a50b1-" + } + }, + "aws_s3_object": { + "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_S3Object_2C11A1C8": { + "//": { + "metadata": { + "path": "root/Default/Default/test:access cloud resource through static methods only/Handler/S3Object", + "uniqueId": "root_testaccesscloudresourcethroughstaticmethodsonly_Handler_S3Object_2C11A1C8" + } + }, + "bucket": "${aws_s3_bucket.root_Code_02F3C603.bucket}", + "key": "", + "source": "" + } + } + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const std = $stdlib.std; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const $AppBase = $stdlib.core.App.for(process.env.WING_TARGET); +const cloud = require('@winglang/sdk').cloud; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class Another extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + this._addInflightOps("myStaticMethod"); + } + static _toInflightType(context) { + const self_client_path = "././inflight.Another.js"; + const globalCounter_client = context._lift(globalCounter); + return $stdlib.core.NodeJsCode.fromInline(` + require("${self_client_path}")({ + globalCounter: ${globalCounter_client}, + }) + `); + } + _toInflight() { + return $stdlib.core.NodeJsCode.fromInline(` + (await (async () => { + const AnotherClient = ${Another._toInflightType(this).text}; + const client = new AnotherClient({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `); + } + _registerBind(host, ops) { + if (ops.includes("$inflight_init")) { + Another._registerBindObject(globalCounter, host, []); + } + super._registerBind(host, ops); + } + static _registerTypeBind(host, ops) { + if (ops.includes("myStaticMethod")) { + Another._registerBindObject(globalCounter, host, ["peek"]); + } + super._registerTypeBind(host, ops); + } + } + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + this.display.hidden = true; + this._addInflightOps("handle"); + } + static _toInflightType(context) { + const self_client_path = "././inflight.$Closure1.js"; + const AnotherClient = Another._toInflightType(context); + return $stdlib.core.NodeJsCode.fromInline(` + require("${self_client_path}")({ + Another: ${AnotherClient.text}, + }) + `); + } + _toInflight() { + return $stdlib.core.NodeJsCode.fromInline(` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this).text}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `); + } + _registerBind(host, ops) { + if (ops.includes("$inflight_init")) { + } + if (ops.includes("handle")) { + $Closure1._registerBindObject(Another, host, ["myStaticMethod"]); + } + super._registerBind(host, ops); + } + } + const globalCounter = this.node.root.newAbstract("@winglang/sdk.cloud.Counter",this,"cloud.Counter"); + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:access cloud resource through static methods only",new $Closure1(this,"$Closure1")); + } +} +class $App extends $AppBase { + constructor() { + super({ outdir: $outdir, name: "resource_call_static", plugins: $plugins, isTestEnvironment: $wing_is_test }); + if ($wing_is_test) { + new $Root(this, "env0"); + const $test_runner = this.testRunner; + const $tests = $test_runner.findTests(); + for (let $i = 1; $i < $tests.length; $i++) { + new $Root(this, "env" + $i); + } + } else { + new $Root(this, "Default"); + } + } +} +new $App().synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_test_sim.md new file mode 100644 index 00000000000..4b97c360306 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/resource_call_static.w_test_sim.md @@ -0,0 +1,12 @@ +# [resource_call_static.w](../../../../../examples/tests/valid/resource_call_static.w) | test | sim + +## stdout.log +```log +pass ─ resource_call_static.wsim » root/env0/test:access cloud resource through static methods only + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/src/error.test.ts b/tools/hangar/src/error.test.ts index d34e6b9ea9a..7431fea4450 100644 --- a/tools/hangar/src/error.test.ts +++ b/tools/hangar/src/error.test.ts @@ -16,7 +16,7 @@ errorWingFiles.forEach((wingFile) => { cwd: tmpDir, wingFile: relativeWingFile, args, - expectStdErr: false, + expectFailure: true, }); const stdout = out.stdout; diff --git a/tools/hangar/src/invalid.test.ts b/tools/hangar/src/invalid.test.ts index ca071512423..a7f14ff73f8 100644 --- a/tools/hangar/src/invalid.test.ts +++ b/tools/hangar/src/invalid.test.ts @@ -21,7 +21,7 @@ invalidWingFiles.forEach((wingFile) => { cwd: tmpDir, wingFile: relativeWingFile, args, - expectStdErr: false, + expectFailure: true, env: metaComment?.env, }); diff --git a/tools/hangar/src/unsupported.test.ts b/tools/hangar/src/unsupported.test.ts index 4bcedceb9c1..3b3a02cb4cf 100644 --- a/tools/hangar/src/unsupported.test.ts +++ b/tools/hangar/src/unsupported.test.ts @@ -22,7 +22,7 @@ test("unsupported resource in target", async ({ expect }) => { cwd: workdir, wingFile: entrypoint, args: ["compile", "--target", "tf-gcp"], - expectStdErr: true, + expectFailure: true, env: { GOOGLE_PROJECT_ID: "test-project", GOOGLE_STORAGE_LOCATION: "us-central1", @@ -39,7 +39,8 @@ test("unsupported resource in target", async ({ expect }) => { } } - at compile " + at compile + at async Command. " `); }); diff --git a/tools/hangar/src/utils.ts b/tools/hangar/src/utils.ts index 25e0322ad68..770bb4c2f68 100644 --- a/tools/hangar/src/utils.ts +++ b/tools/hangar/src/utils.ts @@ -8,7 +8,7 @@ export interface RunWingCommandOptions { cwd: string; wingFile: string; args: string[]; - expectStdErr: boolean; + expectFailure: boolean; plugins?: string[]; env?: Record; } @@ -25,18 +25,13 @@ export async function runWingCommand(options: RunWingCommandOptions) { env: options.env, } ); - if (options.expectStdErr) { + + if (options.expectFailure) { expect(out.exitCode).not.toBe(0); - expect(out.stderr).not.toBe(""); } else { - if ( - // when this env var is on, we allow the on-demand-panic-char (😱), right now panic writes to stderr (will be changed in the future) - options?.env?.WINGC_DEBUG_PANIC !== "type-checking" && - (out.exitCode !== 0 || out.stderr !== "") - ) { - expect.fail(out.stderr); - } + expect(out.exitCode).toBe(0); } + out.stderr = sanitizeOutput(out.stderr); out.stdout = sanitizeOutput(out.stdout); return out; From 7394012e041fd64fdb54f962276bca995eda0ac0 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 16:10:50 +0300 Subject: [PATCH 06/20] merge --- docs/04-reference/wingsdk-api.md | 3894 +++++++++++++++++ .../tests/valid/inflight_ref_resource_field.w | 16 + .../valid/inflight_ref_resource_userdefined.w | 25 + .../tests/valid/inflight_ref_unknown_op.w | 19 + libs/wingsdk/API.md | 3887 ++++++++++++++++ .../valid/custom_obj_id.w_compile_tf-aws.md | 116 + .../valid/custom_obj_id.w_test_sim.md | 12 + 7 files changed, 7969 insertions(+) create mode 100644 docs/04-reference/wingsdk-api.md create mode 100644 examples/tests/valid/inflight_ref_resource_field.w create mode 100644 examples/tests/valid/inflight_ref_resource_userdefined.w create mode 100644 examples/tests/valid/inflight_ref_unknown_op.w create mode 100644 libs/wingsdk/API.md create mode 100644 tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_test_sim.md diff --git a/docs/04-reference/wingsdk-api.md b/docs/04-reference/wingsdk-api.md new file mode 100644 index 00000000000..8d7a8bce3c5 --- /dev/null +++ b/docs/04-reference/wingsdk-api.md @@ -0,0 +1,3894 @@ +--- +title: API Reference +id: sdk +description: Wing SDK API Reference +keywords: [Wing sdk, sdk, Wing API Reference] +--- + +# API Reference + +## Resources + +### Bucket + +**Inflight client:** [@winglang/sdk.cloud.IBucketClient](#@winglang/sdk.cloud.IBucketClient) + +Represents a cloud object store. + +#### Initializers + +```wing +bring cloud; + +new cloud.Bucket(props?: BucketProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | BucketProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* BucketProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_object | Add a file to the bucket that is uploaded when the app is deployed. | + +--- + +##### `add_object` + +```wing +add_object(key: str, body: str): void +``` + +Add a file to the bucket that is uploaded when the app is deployed. + +TODO: In the future this will support uploading any `Blob` type or +referencing a file from the local filesystem. + +###### `key`Required + +- *Type:* str + +--- + +###### `body`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### BucketBase + +Functionality shared between all `Bucket` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.BucketBase(props: BucketProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | BucketProps | *No description.* | + +--- + +##### `props`Required + +- *Type:* BucketProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_object | Add a file to the bucket that is uploaded when the app is deployed. | + +--- + +##### `add_object` + +```wing +add_object(key: str, body: str): void +``` + +Add a file to the bucket that is uploaded when the app is deployed. + +TODO: In the future this will support uploading any `Blob` type or +referencing a file from the local filesystem. + +###### `key`Required + +- *Type:* str + +--- + +###### `body`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### Counter + +**Inflight client:** [@winglang/sdk.cloud.ICounterClient](#@winglang/sdk.cloud.ICounterClient) + +Represents a distributed atomic counter. + +#### Initializers + +```wing +bring cloud; + +new cloud.Counter(props?: CounterProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | CounterProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* CounterProps + +--- + + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| initial | num | The initial value of the counter. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `initial`Required + +```wing +initial: num; +``` + +- *Type:* num + +The initial value of the counter. + +--- + + +### CounterBase + +Functionality shared between all `Counter` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.CounterBase(props?: CounterProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | CounterProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* CounterProps + +--- + + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| initial | num | The initial value of the counter. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `initial`Required + +```wing +initial: num; +``` + +- *Type:* num + +The initial value of the counter. + +--- + + +### Function + +**Inflight client:** [@winglang/sdk.cloud.IFunctionClient](#@winglang/sdk.cloud.IFunctionClient) + +Represents a function. + +#### Initializers + +```wing +bring cloud; + +new cloud.Function(inflight: ~Inflight, props?: FunctionProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| inflight | Inflight | *No description.* | +| props | FunctionProps | *No description.* | + +--- + +##### `inflight`Required + +- *Type:* Inflight + +--- + +##### `props`Optional + +- *Type:* FunctionProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_environment | Add an environment variable to the function. | + +--- + +##### `add_environment` + +```wing +add_environment(_key: str, _value: str): void +``` + +Add an environment variable to the function. + +###### `_key`Required + +- *Type:* str + +--- + +###### `_value`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| env | MutMap<str> | Returns the set of environment variables for this function. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `env`Required + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> + +Returns the set of environment variables for this function. + +--- + + +### FunctionBase + +- *Implements:* IInflightHost + +Functionality shared between all `Function` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.FunctionBase(inflight: ~Inflight, props: FunctionProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| inflight | Inflight | *No description.* | +| props | FunctionProps | *No description.* | + +--- + +##### `inflight`Required + +- *Type:* Inflight + +--- + +##### `props`Required + +- *Type:* FunctionProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_environment | Add an environment variable to the function. | + +--- + +##### `add_environment` + +```wing +add_environment(name: str, value: str): void +``` + +Add an environment variable to the function. + +###### `name`Required + +- *Type:* str + +--- + +###### `value`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| env | MutMap<str> | Returns the set of environment variables for this function. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `env`Required + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> + +Returns the set of environment variables for this function. + +--- + + +### JsonFile + +Represents a text file that should be synthesized in the app's outdir. + +#### Initializers + +```wing +bring fs; + +new fs.JsonFile(file_path: str, props: JsonFileProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| file_path | str | *No description.* | +| props | JsonFileProps | *No description.* | + +--- + +##### `file_path`Required + +- *Type:* str + +--- + +##### `props`Required + +- *Type:* JsonFileProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| save | Render the contents of the file and save it to the user's file system. | + +--- + +##### `save` + +```wing +save(outdir: str): void +``` + +Render the contents of the file and save it to the user's file system. + +###### `outdir`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| file_path | str | The file's relative path to the output directory. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `file_path`Required + +```wing +file_path: str; +``` + +- *Type:* str + +The file's relative path to the output directory. + +--- + + +### Logger + +**Inflight client:** [@winglang/sdk.cloud.ILoggerClient](#@winglang/sdk.cloud.ILoggerClient) + +A cloud logging facility. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| print | Logs a message (preflight). | + +--- + +##### `print` + +```wing +print(message: str): void +``` + +Logs a message (preflight). + +###### `message`Required + +- *Type:* str + +The message to log. + +--- + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| register | Create a logger and register it to the given scope. | + +--- + +##### `register` + +```wing +bring cloud; + +cloud.Logger.register() +``` + +Create a logger and register it to the given scope. + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### LoggerBase + +Functionality shared between all `Logger` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.LoggerBase() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| print | Logs a message (preflight). | + +--- + +##### `print` + +```wing +print(message: str): void +``` + +Logs a message (preflight). + +###### `message`Required + +- *Type:* str + +The message to log. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### Queue + +**Inflight client:** [@winglang/sdk.cloud.IQueueClient](#@winglang/sdk.cloud.IQueueClient) + +Represents a queue. + +#### Initializers + +```wing +bring cloud; + +new cloud.Queue(props?: QueueProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | QueueProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* QueueProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Create a function to consume messages from this queue. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function +``` + +Create a function to consume messages from this queue. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* QueueOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### QueueBase + +Functionality shared between all `Queue` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.QueueBase(props?: QueueProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | QueueProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* QueueProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Create a function to consume messages from this queue. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function +``` + +Create a function to consume messages from this queue. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* QueueOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### Schedule + +**Inflight client:** [@winglang/sdk.cloud.IScheduleClient](#@winglang/sdk.cloud.IScheduleClient) + +Represents a schedule. + +#### Initializers + +```wing +bring cloud; + +new cloud.Schedule(props?: ScheduleProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | ScheduleProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* ScheduleProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_tick | Create a function that runs when receiving the scheduled event. | + +--- + +##### `on_tick` + +```wing +on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function +``` + +Create a function that runs when receiving the scheduled event. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* ScheduleOnTickProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### ScheduleBase + +Functionality shared between all `Schedule` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.ScheduleBase(props?: ScheduleProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | ScheduleProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* ScheduleProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_tick | Create a function that runs when receiving the scheduled event. | + +--- + +##### `on_tick` + +```wing +on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function +``` + +Create a function that runs when receiving the scheduled event. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* ScheduleOnTickProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### TextFile + +Represents a text file that should be synthesized in the app's outdir. + +#### Initializers + +```wing +bring fs; + +new fs.TextFile(file_path: str, props?: TextFileProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| file_path | str | *No description.* | +| props | TextFileProps | *No description.* | + +--- + +##### `file_path`Required + +- *Type:* str + +--- + +##### `props`Optional + +- *Type:* TextFileProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| save | Render the contents of the file and save it to the user's file system. | +| add_line | Append a line to the text file's contents. | + +--- + +##### `save` + +```wing +save(outdir: str): void +``` + +Render the contents of the file and save it to the user's file system. + +###### `outdir`Required + +- *Type:* str + +--- + +##### `add_line` + +```wing +add_line(line: str): void +``` + +Append a line to the text file's contents. + +###### `line`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| file_path | str | The file's relative path to the output directory. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `file_path`Required + +```wing +file_path: str; +``` + +- *Type:* str + +The file's relative path to the output directory. + +--- + + +### Topic + +**Inflight client:** [@winglang/sdk.cloud.ITopicClient](#@winglang/sdk.cloud.ITopicClient) + +Represents a topic. + +#### Initializers + +```wing +bring cloud; + +new cloud.Topic(props?: TopicProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | TopicProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* TopicProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Run an inflight whenever an message is published to the topic. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function +``` + +Run an inflight whenever an message is published to the topic. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* TopicOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### TopicBase + +Topic base class. + +#### Initializers + +```wing +bring cloud; + +new cloud.TopicBase(props?: TopicProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | TopicProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* TopicProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Run an inflight whenever an message is published to the topic. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function +``` + +Run an inflight whenever an message is published to the topic. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* TopicOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +## Structs + +### BucketDeleteOptions + +Interface for delete method inside `Bucket`. + +#### Initializer + +```wing +bring cloud; + +let bucket_delete_options = cloud.BucketDeleteOptions{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| must_exist | bool | Check failures on the method and retrieve errors if any. | + +--- + +##### `must_exist`Optional + +```wing +must_exist: bool; +``` + +- *Type:* bool +- *Default:* false + +Check failures on the method and retrieve errors if any. + +--- + +### BucketProps + +Properties for `Bucket`. + +#### Initializer + +```wing +bring cloud; + +let bucket_props = cloud.BucketProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| public | bool | Whether the bucket's objects should be publicly accessible. | + +--- + +##### `public`Optional + +```wing +public: bool; +``` + +- *Type:* bool +- *Default:* false + +Whether the bucket's objects should be publicly accessible. + +--- + +### CounterProps + +Properties for `Counter`. + +#### Initializer + +```wing +bring cloud; + +let counter_props = cloud.CounterProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| initial | num | The initial value of the counter. | + +--- + +##### `initial`Optional + +```wing +initial: num; +``` + +- *Type:* num +- *Default:* 0 + +The initial value of the counter. + +--- + +### FunctionProps + +Properties for `Function`. + +This is the type users see when constructing a cloud.Function instance. + +#### Initializer + +```wing +bring cloud; + +let function_props = cloud.FunctionProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| env | MutMap<str> | Environment variables to pass to the function. | +| memory | num | The amount of memory to allocate to the function, in MB. | +| timeout | Duration | The maximum amount of time the function can run. | + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* No environment variables. + +Environment variables to pass to the function. + +--- + +##### `memory`Optional + +```wing +memory: num; +``` + +- *Type:* num +- *Default:* 128 + +The amount of memory to allocate to the function, in MB. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* 1m + +The maximum amount of time the function can run. + +--- + +### JsonFileProps + +Props for `JsonFile`. + +#### Initializer + +```wing +bring fs; + +let json_file_props = fs.JsonFileProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| obj | any | The object that will be serialized into the file during synthesis. | + +--- + +##### `obj`Required + +```wing +obj: any; +``` + +- *Type:* any + +The object that will be serialized into the file during synthesis. + +--- + +### QueueOnMessageProps + +Options for Queue.onMessage. + +#### Initializer + +```wing +bring cloud; + +let queue_on_message_props = cloud.QueueOnMessageProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| env | MutMap<str> | Environment variables to pass to the function. | +| memory | num | The amount of memory to allocate to the function, in MB. | +| timeout | Duration | The maximum amount of time the function can run. | +| batch_size | num | The maximum number of messages to send to subscribers at once. | + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* No environment variables. + +Environment variables to pass to the function. + +--- + +##### `memory`Optional + +```wing +memory: num; +``` + +- *Type:* num +- *Default:* 128 + +The amount of memory to allocate to the function, in MB. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* 1m + +The maximum amount of time the function can run. + +--- + +##### `batch_size`Optional + +```wing +batch_size: num; +``` + +- *Type:* num +- *Default:* 1 + +The maximum number of messages to send to subscribers at once. + +--- + +### QueueProps + +Properties for `Queue`. + +#### Initializer + +```wing +bring cloud; + +let queue_props = cloud.QueueProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| initial_messages | MutArray<str> | Initialize the queue with a set of messages. | +| timeout | Duration | How long a queue's consumers have to process a message. | + +--- + +##### `initial_messages`Optional + +```wing +initial_messages: MutArray; +``` + +- *Type:* MutArray<str> +- *Default:* [] + +Initialize the queue with a set of messages. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* Duration.fromSeconds(10) + +How long a queue's consumers have to process a message. + +--- + +### ScheduleOnTickProps + +Options for Schedule.onTick. + +#### Initializer + +```wing +bring cloud; + +let schedule_on_tick_props = cloud.ScheduleOnTickProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| env | MutMap<str> | Environment variables to pass to the function. | +| memory | num | The amount of memory to allocate to the function, in MB. | +| timeout | Duration | The maximum amount of time the function can run. | + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* No environment variables. + +Environment variables to pass to the function. + +--- + +##### `memory`Optional + +```wing +memory: num; +``` + +- *Type:* num +- *Default:* 128 + +The amount of memory to allocate to the function, in MB. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* 1m + +The maximum amount of time the function can run. + +--- + +### ScheduleProps + +Properties for `Schedule`. + +#### Initializer + +```wing +bring cloud; + +let schedule_props = cloud.ScheduleProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| cron | str | Trigger events according to a cron schedule using the UNIX cron format. | +| rate | Duration | Trigger events at a periodic rate. | + +--- + +##### `cron`Optional + +```wing +cron: str; +``` + +- *Type:* str +- *Default:* undefined + +Trigger events according to a cron schedule using the UNIX cron format. + +[minute] [hour] [day of month] [month] [day of week] + +--- + +*Example* + +```wing +"0/1 * ? * *" +``` + + +##### `rate`Optional + +```wing +rate: Duration; +``` + +- *Type:* Duration +- *Default:* undefined + +Trigger events at a periodic rate. + +--- + +*Example* + +```wing +1m +``` + + +### TextFileProps + +Props for `TextFile`. + +#### Initializer + +```wing +bring fs; + +let text_file_props = fs.TextFileProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| lines | MutArray<str> | The lines of text that will be serialized into the file during synthesis. | + +--- + +##### `lines`Optional + +```wing +lines: MutArray; +``` + +- *Type:* MutArray<str> +- *Default:* [] + +The lines of text that will be serialized into the file during synthesis. + +They will be joined with newline characters. + +--- + +### TopicOnMessageProps + +Options for `Topic.onMessage`. + +#### Initializer + +```wing +bring cloud; + +let topic_on_message_props = cloud.TopicOnMessageProps{ ... } +``` + + +### TopicProps + +Properties for `Topic`. + +#### Initializer + +```wing +bring cloud; + +let topic_props = cloud.TopicProps{ ... } +``` + + +## Classes + +### CounterClientBase + +- *Implements:* ICounterClient + +Functionality shared between all `CounterClient` implementations regardless of the target. + +#### Initializers + +```wing +bring cloud; + +new cloud.CounterClientBase() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| dec | Decrement the counter, returning the previous value. | +| inc | Increments the counter atomically by a certain amount and returns the previous value. | +| peek | Get the current value of the counter. | +| reset | Reset a counter to a given value. | + +--- + +##### `dec` + +```wing +dec(amount?: num): num +``` + +Decrement the counter, returning the previous value. + +###### `amount`Optional + +- *Type:* num + +--- + +##### `inc` + +```wing +inc(amount?: num): num +``` + +Increments the counter atomically by a certain amount and returns the previous value. + +###### `amount`Optional + +- *Type:* num + +--- + +##### `peek` + +```wing +peek(): num +``` + +Get the current value of the counter. + +Using this API may introduce race conditions since the value can change between +the time it is read and the time it is used in your code. + +##### `reset` + +```wing +reset(value?: num): void +``` + +Reset a counter to a given value. + +###### `value`Optional + +- *Type:* num + +--- + + + + +### Duration + +Represents a length of time. + + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| from_hours | Create a Duration representing an amount of hours. | +| from_minutes | Create a Duration representing an amount of minutes. | +| from_seconds | Create a Duration representing an amount of seconds. | + +--- + +##### `from_hours` + +```wing +bring std; + +std.Duration.from_hours(amount: num) +``` + +Create a Duration representing an amount of hours. + +###### `amount`Required + +- *Type:* num + +the amount of Hours the `Duration` will represent. + +--- + +##### `from_minutes` + +```wing +bring std; + +std.Duration.from_minutes(amount: num) +``` + +Create a Duration representing an amount of minutes. + +###### `amount`Required + +- *Type:* num + +the amount of Minutes the `Duration` will represent. + +--- + +##### `from_seconds` + +```wing +bring std; + +std.Duration.from_seconds(amount: num) +``` + +Create a Duration representing an amount of seconds. + +###### `amount`Required + +- *Type:* num + +the amount of Seconds the `Duration` will represent. + +--- + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| hours | num | Return the total number of hours in this Duration. | +| minutes | num | Return the total number of minutes in this Duration. | +| seconds | num | Return the total number of seconds in this Duration. | + +--- + +##### `hours`Required + +```wing +hours: num; +``` + +- *Type:* num + +Return the total number of hours in this Duration. + +--- + +##### `minutes`Required + +```wing +minutes: num; +``` + +- *Type:* num + +Return the total number of minutes in this Duration. + +--- + +##### `seconds`Required + +```wing +seconds: num; +``` + +- *Type:* num + +Return the total number of seconds in this Duration. + +--- + + +### ImmutableArray + +Immutable Array. + +#### Initializers + +```wing +bring std; + +new std.ImmutableArray() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| at | Get the value at the given index. | +| copy | Create an immutable shallow copy of this array. | +| copy_mut | Create a mutable shallow copy of this array. | + +--- + +##### `at` + +```wing +at(index: num): T1 +``` + +Get the value at the given index. + +###### `index`Required + +- *Type:* num + +index of the value to get. + +--- + +##### `copy` + +```wing +copy(): ImmutableArray +``` + +Create an immutable shallow copy of this array. + +##### `copy_mut` + +```wing +copy_mut(): MutableArray +``` + +Create a mutable shallow copy of this array. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| length | num | The length of the array. | + +--- + +##### `length`Required + +```wing +length: num; +``` + +- *Type:* num + +The length of the array. + +--- + + +### ImmutableMap + +Immutable Map. + +#### Initializers + +```wing +bring std; + +new std.ImmutableMap() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this map. | +| copy_mut | Create a mutable shallow copy of this map. | +| get | Returns a specified element from the map. | +| has | Returns a boolean indicating whether an element with the specified key exists or not. | +| size | Returns the number of elements in the map. | + +--- + +##### `copy` + +```wing +copy(): ImmutableMap +``` + +Create an immutable shallow copy of this map. + +##### `copy_mut` + +```wing +copy_mut(): MutableMap +``` + +Create a mutable shallow copy of this map. + +##### `get` + +```wing +get(key: str): T1 +``` + +Returns a specified element from the map. + +If the value that is associated to the provided key is an object, then you will get a reference +to that object and any change made to that object will effectively modify it inside the map. + +###### `key`Required + +- *Type:* str + +The key of the element to return. + +--- + +##### `has` + +```wing +has(key: str): bool +``` + +Returns a boolean indicating whether an element with the specified key exists or not. + +###### `key`Required + +- *Type:* str + +The key of the element to test for presence. + +--- + +##### `size` + +```wing +size(): num +``` + +Returns the number of elements in the map. + +TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 + + + + +### ImmutableSet + +Immutable Set. + +#### Initializers + +```wing +bring std; + +new std.ImmutableSet() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this set. | +| copy_mut | Create a mutable shallow copy of this set. | +| has | Returns a boolean indicating whether an element with the specified value exists in the set. | + +--- + +##### `copy` + +```wing +copy(): ImmutableSet +``` + +Create an immutable shallow copy of this set. + +##### `copy_mut` + +```wing +copy_mut(): MutableSet +``` + +Create a mutable shallow copy of this set. + +##### `has` + +```wing +has(value: T1): bool +``` + +Returns a boolean indicating whether an element with the specified value exists in the set. + +###### `value`Required + +- *Type:* T1 + +The value to test for presence in the Set object. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| size | num | The length of the set. | + +--- + +##### `size`Required + +```wing +size: num; +``` + +- *Type:* num + +The length of the set. + +--- + + +### MutableArray + +Mutable Array. + +#### Initializers + +```wing +bring std; + +new std.MutableArray() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| at | Get the value at the given index. | +| copy | Create an immutable shallow copy of this array. | +| copy_mut | Create a mutable shallow copy of this array. | +| pop | Remove value from end of array. | +| push | Add value to end of array. | + +--- + +##### `at` + +```wing +at(index: num): T1 +``` + +Get the value at the given index. + +###### `index`Required + +- *Type:* num + +index of the value to get. + +--- + +##### `copy` + +```wing +copy(): ImmutableArray +``` + +Create an immutable shallow copy of this array. + +##### `copy_mut` + +```wing +copy_mut(): MutableArray +``` + +Create a mutable shallow copy of this array. + +##### `pop` + +```wing +pop(): T1 +``` + +Remove value from end of array. + +##### `push` + +```wing +push(value: T1): void +``` + +Add value to end of array. + +###### `value`Required + +- *Type:* T1 + +value to add. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| length | num | The length of the array. | + +--- + +##### `length`Required + +```wing +length: num; +``` + +- *Type:* num + +The length of the array. + +--- + + +### MutableMap + +Mutable Map. + +#### Initializers + +```wing +bring std; + +new std.MutableMap() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this map. | +| copy_mut | Create a mutable shallow copy of this map. | +| get | Returns a specified element from the map. | +| has | Returns a boolean indicating whether an element with the specified key exists or not. | +| size | Returns the number of elements in the map. | +| clear | Removes all elements. | +| delete | Removes the specified element from a map. | +| set | Adds or updates an entry in a Map object with a specified key and a value. | + +--- + +##### `copy` + +```wing +copy(): ImmutableMap +``` + +Create an immutable shallow copy of this map. + +##### `copy_mut` + +```wing +copy_mut(): MutableMap +``` + +Create a mutable shallow copy of this map. + +##### `get` + +```wing +get(key: str): T1 +``` + +Returns a specified element from the map. + +If the value that is associated to the provided key is an object, then you will get a reference +to that object and any change made to that object will effectively modify it inside the map. + +###### `key`Required + +- *Type:* str + +The key of the element to return. + +--- + +##### `has` + +```wing +has(key: str): bool +``` + +Returns a boolean indicating whether an element with the specified key exists or not. + +###### `key`Required + +- *Type:* str + +The key of the element to test for presence. + +--- + +##### `size` + +```wing +size(): num +``` + +Returns the number of elements in the map. + +TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 + +##### `clear` + +```wing +clear(): void +``` + +Removes all elements. + +##### `delete` + +```wing +delete(key: str): bool +``` + +Removes the specified element from a map. + +###### `key`Required + +- *Type:* str + +The key. + +--- + +##### `set` + +```wing +set(key: str, value: T1): void +``` + +Adds or updates an entry in a Map object with a specified key and a value. + +TODO: revisit this macro after we support indexed args https://github.com/winglang/wing/issues/1659 + +###### `key`Required + +- *Type:* str + +The key of the element to add. + +--- + +###### `value`Required + +- *Type:* T1 + +The value of the element to add. + +--- + + + + +### MutableSet + +Mutable Set. + +#### Initializers + +```wing +bring std; + +new std.MutableSet() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this set. | +| copy_mut | Create a mutable shallow copy of this set. | +| has | Returns a boolean indicating whether an element with the specified value exists in the set. | +| add | Add value to set. | +| clear | The clear() method removes all elements from a set. | +| delete | Removes a specified value from a set, if it is in the set. | + +--- + +##### `copy` + +```wing +copy(): ImmutableSet +``` + +Create an immutable shallow copy of this set. + +##### `copy_mut` + +```wing +copy_mut(): MutableSet +``` + +Create a mutable shallow copy of this set. + +##### `has` + +```wing +has(value: T1): bool +``` + +Returns a boolean indicating whether an element with the specified value exists in the set. + +###### `value`Required + +- *Type:* T1 + +The value to test for presence in the Set object. + +--- + +##### `add` + +```wing +add(value: T1): MutableSet +``` + +Add value to set. + +###### `value`Required + +- *Type:* T1 + +value to add. + +--- + +##### `clear` + +```wing +clear(): void +``` + +The clear() method removes all elements from a set. + +##### `delete` + +```wing +delete(value: T1): bool +``` + +Removes a specified value from a set, if it is in the set. + +###### `value`Required + +- *Type:* T1 + +The value to remove from the set. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| size | num | The length of the set. | + +--- + +##### `size`Required + +```wing +size: num; +``` + +- *Type:* num + +The length of the set. + +--- + + +### String + +String. + +#### Initializers + +```wing +bring std; + +new std.String() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| at | Returns the character at the specified index. | +| concat | Combines the text of two (or more) strings and returns a new string. | +| contains | Checks if string includes substring. | +| ends | Does this string end with the given searchString? | +| index_of | Returns the index of the first occurrence of searchString found. | +| lowercase | Returns this string in lower case. | +| split | Splits string by separator. | +| starts | Does this string start with the given searchString? | +| substring | Returns a string between indexStart, indexEnd. | +| trim | Removes white spaces from start and end of this string. | +| uppercase | Returns this string in upper case. | + +--- + +##### `at` + +```wing +at(index: num): str +``` + +Returns the character at the specified index. + +###### `index`Required + +- *Type:* num + +position of the character. + +--- + +##### `concat` + +```wing +concat(str_n: str): str +``` + +Combines the text of two (or more) strings and returns a new string. + +###### `str_n`Required + +- *Type:* str + +one or more strings to concatenate to this string. + +--- + +##### `contains` + +```wing +contains(search_string: str): bool +``` + +Checks if string includes substring. + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `ends` + +```wing +ends(search_string: str): bool +``` + +Does this string end with the given searchString? + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `index_of` + +```wing +index_of(search_string: str): num +``` + +Returns the index of the first occurrence of searchString found. + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `lowercase` + +```wing +lowercase(): str +``` + +Returns this string in lower case. + +##### `split` + +```wing +split(separator: str): MutArray +``` + +Splits string by separator. + +###### `separator`Required + +- *Type:* str + +separator to split by. + +--- + +##### `starts` + +```wing +starts(search_string: str): bool +``` + +Does this string start with the given searchString? + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `substring` + +```wing +substring(index_start: num, index_end?: num): str +``` + +Returns a string between indexStart, indexEnd. + +###### `index_start`Required + +- *Type:* num + +index of the character we slice at. + +--- + +###### `index_end`Optional + +- *Type:* num + +optional - index of the character we end slicing at. + +--- + +##### `trim` + +```wing +trim(): str +``` + +Removes white spaces from start and end of this string. + +##### `uppercase` + +```wing +uppercase(): str +``` + +Returns this string in upper case. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| length | num | The length of the string. | + +--- + +##### `length`Required + +```wing +length: num; +``` + +- *Type:* num + +The length of the string. + +--- + + +### T1 + +Generic type argument. + +This type is replaced at compile time. + +#### Initializers + +```wing +bring std; + +new std.T1() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + + + + + +## Protocols + +### IBucketClient + +- *Implemented By:* IBucketClient + +Inflight interface for `Bucket`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| delete | Delete an existing object using a key from the bucket. | +| get | Retrieve an object from the bucket. | +| list | Retrieve existing objects keys from the bucket. | +| put | Put an object in the bucket. | + +--- + +##### `delete` + +```wing +delete(key: str, opts?: BucketDeleteOptions): void +``` + +**Inflight client:** [true](#true) + +Delete an existing object using a key from the bucket. + +###### `key`Required + +- *Type:* str + +Key of the object. + +--- + +###### `opts`Optional + +- *Type:* BucketDeleteOptions + +Options available for delete an item from a bucket. + +--- + +##### `get` + +```wing +get(key: str): str +``` + +**Inflight client:** [true](#true) + +Retrieve an object from the bucket. + +###### `key`Required + +- *Type:* str + +Key of the object. + +--- + +##### `list` + +```wing +list(prefix?: str): MutArray +``` + +**Inflight client:** [true](#true) + +Retrieve existing objects keys from the bucket. + +###### `prefix`Optional + +- *Type:* str + +Limits the response to keys that begin with the specified prefix. + +--- + +##### `put` + +```wing +put(key: str, body: str): void +``` + +**Inflight client:** [true](#true) + +Put an object in the bucket. + +###### `key`Required + +- *Type:* str + +Key of the object. + +--- + +###### `body`Required + +- *Type:* str + +Content of the object we want to store into the bucket. + +--- + + +### ICounterClient + +- *Implemented By:* CounterClientBase, ICounterClient + +Inflight interface for `Counter`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| dec | Decrement the counter, returning the previous value. | +| inc | Increments the counter atomically by a certain amount and returns the previous value. | +| peek | Get the current value of the counter. | +| reset | Reset a counter to a given value. | + +--- + +##### `dec` + +```wing +dec(amount?: num): num +``` + +**Inflight client:** [true](#true) + +Decrement the counter, returning the previous value. + +###### `amount`Optional + +- *Type:* num + +amount to decrement (default is 1). + +--- + +##### `inc` + +```wing +inc(amount?: num): num +``` + +**Inflight client:** [true](#true) + +Increments the counter atomically by a certain amount and returns the previous value. + +###### `amount`Optional + +- *Type:* num + +amount to increment (default is 1). + +--- + +##### `peek` + +```wing +peek(): num +``` + +**Inflight client:** [true](#true) + +Get the current value of the counter. + +Using this API may introduce race conditions since the value can change between +the time it is read and the time it is used in your code. + +##### `reset` + +```wing +reset(value?: num): void +``` + +**Inflight client:** [true](#true) + +Reset a counter to a given value. + +###### `value`Optional + +- *Type:* num + +value to reset (default is 0). + +--- + + +### IFunctionClient + +- *Implemented By:* IFunctionClient + +Inflight interface for `Function`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| invoke | Invoke the function asynchronously with a given payload. | + +--- + +##### `invoke` + +```wing +invoke(payload: str): str +``` + +**Inflight client:** [true](#true) + +Invoke the function asynchronously with a given payload. + +###### `payload`Required + +- *Type:* str + +--- + + +### IFunctionHandler + +- *Extends:* IResource + +- *Implemented By:* IFunctionHandler + +**Inflight client:** [wingsdk.cloud.IFunctionHandlerClient](#wingsdk.cloud.IFunctionHandlerClient) + +Represents a resource with an inflight "handle" method that can be used to create a `cloud.Function`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### IFunctionHandlerClient + +- *Implemented By:* IFunctionHandlerClient + +Inflight client for `IFunctionHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Entrypoint function that will be called when the cloud function is invoked. | + +--- + +##### `handle` + +```wing +handle(event: str): void +``` + +**Inflight client:** [true](#true) + +Entrypoint function that will be called when the cloud function is invoked. + +###### `event`Required + +- *Type:* str + +--- + + +### ILoggerClient + +- *Implemented By:* ILoggerClient + +Inflight interface for `Logger`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| print | Logs a message. The log will be associated with whichever resource is running the inflight code. | + +--- + +##### `print` + +```wing +print(message: str): void +``` + +**Inflight client:** [true](#true) + +Logs a message. The log will be associated with whichever resource is running the inflight code. + +NOTICE: this is not an async function because it is wrapped by `console.log()`. + +###### `message`Required + +- *Type:* str + +The message to print. + +--- + + +### IQueueClient + +- *Implemented By:* IQueueClient + +Inflight interface for `Queue`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| approx_size | Retrieve the approximate number of messages in the queue. | +| purge | Purge all of the messages in the queue. | +| push | Push a message to the queue. | + +--- + +##### `approx_size` + +```wing +approx_size(): num +``` + +**Inflight client:** [true](#true) + +Retrieve the approximate number of messages in the queue. + +##### `purge` + +```wing +purge(): void +``` + +**Inflight client:** [true](#true) + +Purge all of the messages in the queue. + +##### `push` + +```wing +push(message: str): void +``` + +**Inflight client:** [true](#true) + +Push a message to the queue. + +###### `message`Required + +- *Type:* str + +Payload to send to the queue. + +--- + + +### IQueueOnMessageHandler + +- *Extends:* IResource + +- *Implemented By:* IQueueOnMessageHandler + +**Inflight client:** [wingsdk.cloud.IQueueOnMessageHandlerClient](#wingsdk.cloud.IQueueOnMessageHandlerClient) + +Represents a resource with an inflight "handle" method that can be passed to `Queue.on_message`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### IQueueOnMessageHandlerClient + +- *Implemented By:* IQueueOnMessageHandlerClient + +Inflight client for `IQueueOnMessageHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Function that will be called when a message is received from the queue. | + +--- + +##### `handle` + +```wing +handle(message: str): void +``` + +**Inflight client:** [true](#true) + +Function that will be called when a message is received from the queue. + +###### `message`Required + +- *Type:* str + +--- + + +### IScheduleOnTickHandler + +- *Extends:* IResource + +- *Implemented By:* IScheduleOnTickHandler + +**Inflight client:** [wingsdk.cloud.IScheduleOnTickHandlerClient](#wingsdk.cloud.IScheduleOnTickHandlerClient) + +Represents a resource with an inflight "handle" method that can be passed to `Schedule.on_tick`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### IScheduleOnTickHandlerClient + +- *Implemented By:* IScheduleOnTickHandlerClient + +Inflight client for `IScheduleOnTickHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Function that will be called when a message is received from the schedule. | + +--- + +##### `handle` + +```wing +handle(): void +``` + +**Inflight client:** [true](#true) + +Function that will be called when a message is received from the schedule. + + +### ITopicClient + +- *Implemented By:* ITopicClient + +Inflight interface for `Topic`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| publish | Publish message to topic. | + +--- + +##### `publish` + +```wing +publish(message: str): void +``` + +**Inflight client:** [true](#true) + +Publish message to topic. + +###### `message`Required + +- *Type:* str + +Payload to publish to Topic. + +--- + + +### ITopicOnMessageHandler + +- *Extends:* IResource + +- *Implemented By:* ITopicOnMessageHandler + +**Inflight client:** [wingsdk.cloud.ITopicOnMessageHandlerClient](#wingsdk.cloud.ITopicOnMessageHandlerClient) + +Represents a resource with an inflight "handle" method that can be passed to `Topic.on_message`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### ITopicOnMessageHandlerClient + +- *Implemented By:* ITopicOnMessageHandlerClient + +Inflight client for `ITopicOnMessageHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Function that will be called when a message is received from the topic. | + +--- + +##### `handle` + +```wing +handle(event: str): void +``` + +**Inflight client:** [true](#true) + +Function that will be called when a message is received from the topic. + +###### `event`Required + +- *Type:* str + +--- + + diff --git a/examples/tests/valid/inflight_ref_resource_field.w b/examples/tests/valid/inflight_ref_resource_field.w new file mode 100644 index 00000000000..271d3659045 --- /dev/null +++ b/examples/tests/valid/inflight_ref_resource_field.w @@ -0,0 +1,16 @@ +bring cloud; + +resource Test { + my_field: str; + + init () { + this.my_field = "hello"; + } + + inflight test(): str { + assert(this.my_field == "hello"); + } +} + +let f = new Test(); +new cloud.Function(inflight () => { f.test(); }) as "test"; \ No newline at end of file diff --git a/examples/tests/valid/inflight_ref_resource_userdefined.w b/examples/tests/valid/inflight_ref_resource_userdefined.w new file mode 100644 index 00000000000..60458ca4aaf --- /dev/null +++ b/examples/tests/valid/inflight_ref_resource_userdefined.w @@ -0,0 +1,25 @@ +bring cloud; + +resource Another { + init () { } + + inflight func(): str { + return "hello"; + } +} + +resource Test { + another: Another; + + init() { + this.another = new Another(); + } + + inflight test() { + let res = this.another.func(); + assert(res == "hello"); + } +} + +let f = new Test(); +new cloud.Function(inflight () => { f.test(); }) as "test"; \ No newline at end of file diff --git a/examples/tests/valid/inflight_ref_unknown_op.w b/examples/tests/valid/inflight_ref_unknown_op.w new file mode 100644 index 00000000000..602d6583bb8 --- /dev/null +++ b/examples/tests/valid/inflight_ref_unknown_op.w @@ -0,0 +1,19 @@ +// NOTE: this test is supposed to fail once https://github.com/winglang/wing/pull/1610 is complete + +bring cloud; + +resource Test { + b: cloud.Bucket; + + init() { + this.b = new cloud.Bucket(); + } + + inflight test() { + let x = this.b; + x.put("hello", "world"); + } +} + +let f = new Test(); +new cloud.Function(inflight () => { f.test(); }) as "test"; \ No newline at end of file diff --git a/libs/wingsdk/API.md b/libs/wingsdk/API.md new file mode 100644 index 00000000000..3f7ec4d317e --- /dev/null +++ b/libs/wingsdk/API.md @@ -0,0 +1,3887 @@ +# API Reference + +## Resources + +### Bucket + +**Inflight client:** [@winglang/sdk.cloud.IBucketClient](#@winglang/sdk.cloud.IBucketClient) + +Represents a cloud object store. + +#### Initializers + +```wing +bring cloud; + +new cloud.Bucket(props?: BucketProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | BucketProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* BucketProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_object | Add a file to the bucket that is uploaded when the app is deployed. | + +--- + +##### `add_object` + +```wing +add_object(key: str, body: str): void +``` + +Add a file to the bucket that is uploaded when the app is deployed. + +TODO: In the future this will support uploading any `Blob` type or +referencing a file from the local filesystem. + +###### `key`Required + +- *Type:* str + +--- + +###### `body`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### BucketBase + +Functionality shared between all `Bucket` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.BucketBase(props: BucketProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | BucketProps | *No description.* | + +--- + +##### `props`Required + +- *Type:* BucketProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_object | Add a file to the bucket that is uploaded when the app is deployed. | + +--- + +##### `add_object` + +```wing +add_object(key: str, body: str): void +``` + +Add a file to the bucket that is uploaded when the app is deployed. + +TODO: In the future this will support uploading any `Blob` type or +referencing a file from the local filesystem. + +###### `key`Required + +- *Type:* str + +--- + +###### `body`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### Counter + +**Inflight client:** [@winglang/sdk.cloud.ICounterClient](#@winglang/sdk.cloud.ICounterClient) + +Represents a distributed atomic counter. + +#### Initializers + +```wing +bring cloud; + +new cloud.Counter(props?: CounterProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | CounterProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* CounterProps + +--- + + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| initial | num | The initial value of the counter. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `initial`Required + +```wing +initial: num; +``` + +- *Type:* num + +The initial value of the counter. + +--- + + +### CounterBase + +Functionality shared between all `Counter` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.CounterBase(props?: CounterProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | CounterProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* CounterProps + +--- + + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| initial | num | The initial value of the counter. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `initial`Required + +```wing +initial: num; +``` + +- *Type:* num + +The initial value of the counter. + +--- + + +### Function + +**Inflight client:** [@winglang/sdk.cloud.IFunctionClient](#@winglang/sdk.cloud.IFunctionClient) + +Represents a function. + +#### Initializers + +```wing +bring cloud; + +new cloud.Function(inflight: ~Inflight, props?: FunctionProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| inflight | Inflight | *No description.* | +| props | FunctionProps | *No description.* | + +--- + +##### `inflight`Required + +- *Type:* Inflight + +--- + +##### `props`Optional + +- *Type:* FunctionProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_environment | Add an environment variable to the function. | + +--- + +##### `add_environment` + +```wing +add_environment(_key: str, _value: str): void +``` + +Add an environment variable to the function. + +###### `_key`Required + +- *Type:* str + +--- + +###### `_value`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| env | MutMap<str> | Returns the set of environment variables for this function. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `env`Required + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> + +Returns the set of environment variables for this function. + +--- + + +### FunctionBase + +- *Implements:* IInflightHost + +Functionality shared between all `Function` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.FunctionBase(inflight: ~Inflight, props: FunctionProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| inflight | Inflight | *No description.* | +| props | FunctionProps | *No description.* | + +--- + +##### `inflight`Required + +- *Type:* Inflight + +--- + +##### `props`Required + +- *Type:* FunctionProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| add_environment | Add an environment variable to the function. | + +--- + +##### `add_environment` + +```wing +add_environment(name: str, value: str): void +``` + +Add an environment variable to the function. + +###### `name`Required + +- *Type:* str + +--- + +###### `value`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | +| env | MutMap<str> | Returns the set of environment variables for this function. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + +##### `env`Required + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> + +Returns the set of environment variables for this function. + +--- + + +### JsonFile + +Represents a text file that should be synthesized in the app's outdir. + +#### Initializers + +```wing +bring fs; + +new fs.JsonFile(file_path: str, props: JsonFileProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| file_path | str | *No description.* | +| props | JsonFileProps | *No description.* | + +--- + +##### `file_path`Required + +- *Type:* str + +--- + +##### `props`Required + +- *Type:* JsonFileProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| save | Render the contents of the file and save it to the user's file system. | + +--- + +##### `save` + +```wing +save(outdir: str): void +``` + +Render the contents of the file and save it to the user's file system. + +###### `outdir`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| file_path | str | The file's relative path to the output directory. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `file_path`Required + +```wing +file_path: str; +``` + +- *Type:* str + +The file's relative path to the output directory. + +--- + + +### Logger + +**Inflight client:** [@winglang/sdk.cloud.ILoggerClient](#@winglang/sdk.cloud.ILoggerClient) + +A cloud logging facility. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| print | Logs a message (preflight). | + +--- + +##### `print` + +```wing +print(message: str): void +``` + +Logs a message (preflight). + +###### `message`Required + +- *Type:* str + +The message to log. + +--- + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| register | Create a logger and register it to the given scope. | + +--- + +##### `register` + +```wing +bring cloud; + +cloud.Logger.register() +``` + +Create a logger and register it to the given scope. + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### LoggerBase + +Functionality shared between all `Logger` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.LoggerBase() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| print | Logs a message (preflight). | + +--- + +##### `print` + +```wing +print(message: str): void +``` + +Logs a message (preflight). + +###### `message`Required + +- *Type:* str + +The message to log. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### Queue + +**Inflight client:** [@winglang/sdk.cloud.IQueueClient](#@winglang/sdk.cloud.IQueueClient) + +Represents a queue. + +#### Initializers + +```wing +bring cloud; + +new cloud.Queue(props?: QueueProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | QueueProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* QueueProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Create a function to consume messages from this queue. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function +``` + +Create a function to consume messages from this queue. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* QueueOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### QueueBase + +Functionality shared between all `Queue` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.QueueBase(props?: QueueProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | QueueProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* QueueProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Create a function to consume messages from this queue. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function +``` + +Create a function to consume messages from this queue. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* QueueOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### Schedule + +**Inflight client:** [@winglang/sdk.cloud.IScheduleClient](#@winglang/sdk.cloud.IScheduleClient) + +Represents a schedule. + +#### Initializers + +```wing +bring cloud; + +new cloud.Schedule(props?: ScheduleProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | ScheduleProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* ScheduleProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_tick | Create a function that runs when receiving the scheduled event. | + +--- + +##### `on_tick` + +```wing +on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function +``` + +Create a function that runs when receiving the scheduled event. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* ScheduleOnTickProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### ScheduleBase + +Functionality shared between all `Schedule` implementations. + +#### Initializers + +```wing +bring cloud; + +new cloud.ScheduleBase(props?: ScheduleProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | ScheduleProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* ScheduleProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_tick | Create a function that runs when receiving the scheduled event. | + +--- + +##### `on_tick` + +```wing +on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function +``` + +Create a function that runs when receiving the scheduled event. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* ScheduleOnTickProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### TextFile + +Represents a text file that should be synthesized in the app's outdir. + +#### Initializers + +```wing +bring fs; + +new fs.TextFile(file_path: str, props?: TextFileProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| file_path | str | *No description.* | +| props | TextFileProps | *No description.* | + +--- + +##### `file_path`Required + +- *Type:* str + +--- + +##### `props`Optional + +- *Type:* TextFileProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| save | Render the contents of the file and save it to the user's file system. | +| add_line | Append a line to the text file's contents. | + +--- + +##### `save` + +```wing +save(outdir: str): void +``` + +Render the contents of the file and save it to the user's file system. + +###### `outdir`Required + +- *Type:* str + +--- + +##### `add_line` + +```wing +add_line(line: str): void +``` + +Append a line to the text file's contents. + +###### `line`Required + +- *Type:* str + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| file_path | str | The file's relative path to the output directory. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `file_path`Required + +```wing +file_path: str; +``` + +- *Type:* str + +The file's relative path to the output directory. + +--- + + +### Topic + +**Inflight client:** [@winglang/sdk.cloud.ITopicClient](#@winglang/sdk.cloud.ITopicClient) + +Represents a topic. + +#### Initializers + +```wing +bring cloud; + +new cloud.Topic(props?: TopicProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | TopicProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* TopicProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Run an inflight whenever an message is published to the topic. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function +``` + +Run an inflight whenever an message is published to the topic. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* TopicOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +### TopicBase + +Topic base class. + +#### Initializers + +```wing +bring cloud; + +new cloud.TopicBase(props?: TopicProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | TopicProps | *No description.* | + +--- + +##### `props`Optional + +- *Type:* TopicProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| on_message | Run an inflight whenever an message is published to the topic. | + +--- + +##### `on_message` + +```wing +on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function +``` + +Run an inflight whenever an message is published to the topic. + +###### `inflight`Required + +- *Type:* Inflight + +--- + +###### `props`Optional + +- *Type:* TopicOnMessageProps + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | +| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +##### `stateful`Required + +```wing +stateful: bool; +``` + +- *Type:* bool + +Whether a resource is stateful, i.e. it stores information that is not defined by your application. + +A non-stateful resource does not remember information about past +transactions or events, and can typically be replaced by a cloud provider +with a fresh copy without any consequences. + +--- + + +## Structs + +### BucketDeleteOptions + +Interface for delete method inside `Bucket`. + +#### Initializer + +```wing +bring cloud; + +let bucket_delete_options = cloud.BucketDeleteOptions{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| must_exist | bool | Check failures on the method and retrieve errors if any. | + +--- + +##### `must_exist`Optional + +```wing +must_exist: bool; +``` + +- *Type:* bool +- *Default:* false + +Check failures on the method and retrieve errors if any. + +--- + +### BucketProps + +Properties for `Bucket`. + +#### Initializer + +```wing +bring cloud; + +let bucket_props = cloud.BucketProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| public | bool | Whether the bucket's objects should be publicly accessible. | + +--- + +##### `public`Optional + +```wing +public: bool; +``` + +- *Type:* bool +- *Default:* false + +Whether the bucket's objects should be publicly accessible. + +--- + +### CounterProps + +Properties for `Counter`. + +#### Initializer + +```wing +bring cloud; + +let counter_props = cloud.CounterProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| initial | num | The initial value of the counter. | + +--- + +##### `initial`Optional + +```wing +initial: num; +``` + +- *Type:* num +- *Default:* 0 + +The initial value of the counter. + +--- + +### FunctionProps + +Properties for `Function`. + +This is the type users see when constructing a cloud.Function instance. + +#### Initializer + +```wing +bring cloud; + +let function_props = cloud.FunctionProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| env | MutMap<str> | Environment variables to pass to the function. | +| memory | num | The amount of memory to allocate to the function, in MB. | +| timeout | Duration | The maximum amount of time the function can run. | + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* No environment variables. + +Environment variables to pass to the function. + +--- + +##### `memory`Optional + +```wing +memory: num; +``` + +- *Type:* num +- *Default:* 128 + +The amount of memory to allocate to the function, in MB. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* 1m + +The maximum amount of time the function can run. + +--- + +### JsonFileProps + +Props for `JsonFile`. + +#### Initializer + +```wing +bring fs; + +let json_file_props = fs.JsonFileProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| obj | any | The object that will be serialized into the file during synthesis. | + +--- + +##### `obj`Required + +```wing +obj: any; +``` + +- *Type:* any + +The object that will be serialized into the file during synthesis. + +--- + +### QueueOnMessageProps + +Options for Queue.onMessage. + +#### Initializer + +```wing +bring cloud; + +let queue_on_message_props = cloud.QueueOnMessageProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| env | MutMap<str> | Environment variables to pass to the function. | +| memory | num | The amount of memory to allocate to the function, in MB. | +| timeout | Duration | The maximum amount of time the function can run. | +| batch_size | num | The maximum number of messages to send to subscribers at once. | + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* No environment variables. + +Environment variables to pass to the function. + +--- + +##### `memory`Optional + +```wing +memory: num; +``` + +- *Type:* num +- *Default:* 128 + +The amount of memory to allocate to the function, in MB. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* 1m + +The maximum amount of time the function can run. + +--- + +##### `batch_size`Optional + +```wing +batch_size: num; +``` + +- *Type:* num +- *Default:* 1 + +The maximum number of messages to send to subscribers at once. + +--- + +### QueueProps + +Properties for `Queue`. + +#### Initializer + +```wing +bring cloud; + +let queue_props = cloud.QueueProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| initial_messages | MutArray<str> | Initialize the queue with a set of messages. | +| timeout | Duration | How long a queue's consumers have to process a message. | + +--- + +##### `initial_messages`Optional + +```wing +initial_messages: MutArray; +``` + +- *Type:* MutArray<str> +- *Default:* [] + +Initialize the queue with a set of messages. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* Duration.fromSeconds(10) + +How long a queue's consumers have to process a message. + +--- + +### ScheduleOnTickProps + +Options for Schedule.onTick. + +#### Initializer + +```wing +bring cloud; + +let schedule_on_tick_props = cloud.ScheduleOnTickProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| env | MutMap<str> | Environment variables to pass to the function. | +| memory | num | The amount of memory to allocate to the function, in MB. | +| timeout | Duration | The maximum amount of time the function can run. | + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* No environment variables. + +Environment variables to pass to the function. + +--- + +##### `memory`Optional + +```wing +memory: num; +``` + +- *Type:* num +- *Default:* 128 + +The amount of memory to allocate to the function, in MB. + +--- + +##### `timeout`Optional + +```wing +timeout: Duration; +``` + +- *Type:* Duration +- *Default:* 1m + +The maximum amount of time the function can run. + +--- + +### ScheduleProps + +Properties for `Schedule`. + +#### Initializer + +```wing +bring cloud; + +let schedule_props = cloud.ScheduleProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| cron | str | Trigger events according to a cron schedule using the UNIX cron format. | +| rate | Duration | Trigger events at a periodic rate. | + +--- + +##### `cron`Optional + +```wing +cron: str; +``` + +- *Type:* str +- *Default:* undefined + +Trigger events according to a cron schedule using the UNIX cron format. + +[minute] [hour] [day of month] [month] [day of week] + +--- + +*Example* + +```wing +"0/1 * ? * *" +``` + + +##### `rate`Optional + +```wing +rate: Duration; +``` + +- *Type:* Duration +- *Default:* undefined + +Trigger events at a periodic rate. + +--- + +*Example* + +```wing +1m +``` + + +### TextFileProps + +Props for `TextFile`. + +#### Initializer + +```wing +bring fs; + +let text_file_props = fs.TextFileProps{ ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| lines | MutArray<str> | The lines of text that will be serialized into the file during synthesis. | + +--- + +##### `lines`Optional + +```wing +lines: MutArray; +``` + +- *Type:* MutArray<str> +- *Default:* [] + +The lines of text that will be serialized into the file during synthesis. + +They will be joined with newline characters. + +--- + +### TopicOnMessageProps + +Options for `Topic.onMessage`. + +#### Initializer + +```wing +bring cloud; + +let topic_on_message_props = cloud.TopicOnMessageProps{ ... } +``` + + +### TopicProps + +Properties for `Topic`. + +#### Initializer + +```wing +bring cloud; + +let topic_props = cloud.TopicProps{ ... } +``` + + +## Classes + +### CounterClientBase + +- *Implements:* ICounterClient + +Functionality shared between all `CounterClient` implementations regardless of the target. + +#### Initializers + +```wing +bring cloud; + +new cloud.CounterClientBase() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| dec | Decrement the counter, returning the previous value. | +| inc | Increments the counter atomically by a certain amount and returns the previous value. | +| peek | Get the current value of the counter. | +| reset | Reset a counter to a given value. | + +--- + +##### `dec` + +```wing +dec(amount?: num): num +``` + +Decrement the counter, returning the previous value. + +###### `amount`Optional + +- *Type:* num + +--- + +##### `inc` + +```wing +inc(amount?: num): num +``` + +Increments the counter atomically by a certain amount and returns the previous value. + +###### `amount`Optional + +- *Type:* num + +--- + +##### `peek` + +```wing +peek(): num +``` + +Get the current value of the counter. + +Using this API may introduce race conditions since the value can change between +the time it is read and the time it is used in your code. + +##### `reset` + +```wing +reset(value?: num): void +``` + +Reset a counter to a given value. + +###### `value`Optional + +- *Type:* num + +--- + + + + +### Duration + +Represents a length of time. + + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| from_hours | Create a Duration representing an amount of hours. | +| from_minutes | Create a Duration representing an amount of minutes. | +| from_seconds | Create a Duration representing an amount of seconds. | + +--- + +##### `from_hours` + +```wing +bring std; + +std.Duration.from_hours(amount: num) +``` + +Create a Duration representing an amount of hours. + +###### `amount`Required + +- *Type:* num + +the amount of Hours the `Duration` will represent. + +--- + +##### `from_minutes` + +```wing +bring std; + +std.Duration.from_minutes(amount: num) +``` + +Create a Duration representing an amount of minutes. + +###### `amount`Required + +- *Type:* num + +the amount of Minutes the `Duration` will represent. + +--- + +##### `from_seconds` + +```wing +bring std; + +std.Duration.from_seconds(amount: num) +``` + +Create a Duration representing an amount of seconds. + +###### `amount`Required + +- *Type:* num + +the amount of Seconds the `Duration` will represent. + +--- + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| hours | num | Return the total number of hours in this Duration. | +| minutes | num | Return the total number of minutes in this Duration. | +| seconds | num | Return the total number of seconds in this Duration. | + +--- + +##### `hours`Required + +```wing +hours: num; +``` + +- *Type:* num + +Return the total number of hours in this Duration. + +--- + +##### `minutes`Required + +```wing +minutes: num; +``` + +- *Type:* num + +Return the total number of minutes in this Duration. + +--- + +##### `seconds`Required + +```wing +seconds: num; +``` + +- *Type:* num + +Return the total number of seconds in this Duration. + +--- + + +### ImmutableArray + +Immutable Array. + +#### Initializers + +```wing +bring std; + +new std.ImmutableArray() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| at | Get the value at the given index. | +| copy | Create an immutable shallow copy of this array. | +| copy_mut | Create a mutable shallow copy of this array. | + +--- + +##### `at` + +```wing +at(index: num): T1 +``` + +Get the value at the given index. + +###### `index`Required + +- *Type:* num + +index of the value to get. + +--- + +##### `copy` + +```wing +copy(): ImmutableArray +``` + +Create an immutable shallow copy of this array. + +##### `copy_mut` + +```wing +copy_mut(): MutableArray +``` + +Create a mutable shallow copy of this array. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| length | num | The length of the array. | + +--- + +##### `length`Required + +```wing +length: num; +``` + +- *Type:* num + +The length of the array. + +--- + + +### ImmutableMap + +Immutable Map. + +#### Initializers + +```wing +bring std; + +new std.ImmutableMap() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this map. | +| copy_mut | Create a mutable shallow copy of this map. | +| get | Returns a specified element from the map. | +| has | Returns a boolean indicating whether an element with the specified key exists or not. | +| size | Returns the number of elements in the map. | + +--- + +##### `copy` + +```wing +copy(): ImmutableMap +``` + +Create an immutable shallow copy of this map. + +##### `copy_mut` + +```wing +copy_mut(): MutableMap +``` + +Create a mutable shallow copy of this map. + +##### `get` + +```wing +get(key: str): T1 +``` + +Returns a specified element from the map. + +If the value that is associated to the provided key is an object, then you will get a reference +to that object and any change made to that object will effectively modify it inside the map. + +###### `key`Required + +- *Type:* str + +The key of the element to return. + +--- + +##### `has` + +```wing +has(key: str): bool +``` + +Returns a boolean indicating whether an element with the specified key exists or not. + +###### `key`Required + +- *Type:* str + +The key of the element to test for presence. + +--- + +##### `size` + +```wing +size(): num +``` + +Returns the number of elements in the map. + +TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 + + + + +### ImmutableSet + +Immutable Set. + +#### Initializers + +```wing +bring std; + +new std.ImmutableSet() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this set. | +| copy_mut | Create a mutable shallow copy of this set. | +| has | Returns a boolean indicating whether an element with the specified value exists in the set. | + +--- + +##### `copy` + +```wing +copy(): ImmutableSet +``` + +Create an immutable shallow copy of this set. + +##### `copy_mut` + +```wing +copy_mut(): MutableSet +``` + +Create a mutable shallow copy of this set. + +##### `has` + +```wing +has(value: T1): bool +``` + +Returns a boolean indicating whether an element with the specified value exists in the set. + +###### `value`Required + +- *Type:* T1 + +The value to test for presence in the Set object. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| size | num | The length of the set. | + +--- + +##### `size`Required + +```wing +size: num; +``` + +- *Type:* num + +The length of the set. + +--- + + +### MutableArray + +Mutable Array. + +#### Initializers + +```wing +bring std; + +new std.MutableArray() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| at | Get the value at the given index. | +| copy | Create an immutable shallow copy of this array. | +| copy_mut | Create a mutable shallow copy of this array. | +| pop | Remove value from end of array. | +| push | Add value to end of array. | + +--- + +##### `at` + +```wing +at(index: num): T1 +``` + +Get the value at the given index. + +###### `index`Required + +- *Type:* num + +index of the value to get. + +--- + +##### `copy` + +```wing +copy(): ImmutableArray +``` + +Create an immutable shallow copy of this array. + +##### `copy_mut` + +```wing +copy_mut(): MutableArray +``` + +Create a mutable shallow copy of this array. + +##### `pop` + +```wing +pop(): T1 +``` + +Remove value from end of array. + +##### `push` + +```wing +push(value: T1): void +``` + +Add value to end of array. + +###### `value`Required + +- *Type:* T1 + +value to add. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| length | num | The length of the array. | + +--- + +##### `length`Required + +```wing +length: num; +``` + +- *Type:* num + +The length of the array. + +--- + + +### MutableMap + +Mutable Map. + +#### Initializers + +```wing +bring std; + +new std.MutableMap() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this map. | +| copy_mut | Create a mutable shallow copy of this map. | +| get | Returns a specified element from the map. | +| has | Returns a boolean indicating whether an element with the specified key exists or not. | +| size | Returns the number of elements in the map. | +| clear | Removes all elements. | +| delete | Removes the specified element from a map. | +| set | Adds or updates an entry in a Map object with a specified key and a value. | + +--- + +##### `copy` + +```wing +copy(): ImmutableMap +``` + +Create an immutable shallow copy of this map. + +##### `copy_mut` + +```wing +copy_mut(): MutableMap +``` + +Create a mutable shallow copy of this map. + +##### `get` + +```wing +get(key: str): T1 +``` + +Returns a specified element from the map. + +If the value that is associated to the provided key is an object, then you will get a reference +to that object and any change made to that object will effectively modify it inside the map. + +###### `key`Required + +- *Type:* str + +The key of the element to return. + +--- + +##### `has` + +```wing +has(key: str): bool +``` + +Returns a boolean indicating whether an element with the specified key exists or not. + +###### `key`Required + +- *Type:* str + +The key of the element to test for presence. + +--- + +##### `size` + +```wing +size(): num +``` + +Returns the number of elements in the map. + +TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 + +##### `clear` + +```wing +clear(): void +``` + +Removes all elements. + +##### `delete` + +```wing +delete(key: str): bool +``` + +Removes the specified element from a map. + +###### `key`Required + +- *Type:* str + +The key. + +--- + +##### `set` + +```wing +set(key: str, value: T1): void +``` + +Adds or updates an entry in a Map object with a specified key and a value. + +TODO: revisit this macro after we support indexed args https://github.com/winglang/wing/issues/1659 + +###### `key`Required + +- *Type:* str + +The key of the element to add. + +--- + +###### `value`Required + +- *Type:* T1 + +The value of the element to add. + +--- + + + + +### MutableSet + +Mutable Set. + +#### Initializers + +```wing +bring std; + +new std.MutableSet() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| copy | Create an immutable shallow copy of this set. | +| copy_mut | Create a mutable shallow copy of this set. | +| has | Returns a boolean indicating whether an element with the specified value exists in the set. | +| add | Add value to set. | +| clear | The clear() method removes all elements from a set. | +| delete | Removes a specified value from a set, if it is in the set. | + +--- + +##### `copy` + +```wing +copy(): ImmutableSet +``` + +Create an immutable shallow copy of this set. + +##### `copy_mut` + +```wing +copy_mut(): MutableSet +``` + +Create a mutable shallow copy of this set. + +##### `has` + +```wing +has(value: T1): bool +``` + +Returns a boolean indicating whether an element with the specified value exists in the set. + +###### `value`Required + +- *Type:* T1 + +The value to test for presence in the Set object. + +--- + +##### `add` + +```wing +add(value: T1): MutableSet +``` + +Add value to set. + +###### `value`Required + +- *Type:* T1 + +value to add. + +--- + +##### `clear` + +```wing +clear(): void +``` + +The clear() method removes all elements from a set. + +##### `delete` + +```wing +delete(value: T1): bool +``` + +Removes a specified value from a set, if it is in the set. + +###### `value`Required + +- *Type:* T1 + +The value to remove from the set. + +--- + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| size | num | The length of the set. | + +--- + +##### `size`Required + +```wing +size: num; +``` + +- *Type:* num + +The length of the set. + +--- + + +### String + +String. + +#### Initializers + +```wing +bring std; + +new std.String() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| at | Returns the character at the specified index. | +| concat | Combines the text of two (or more) strings and returns a new string. | +| contains | Checks if string includes substring. | +| ends | Does this string end with the given searchString? | +| index_of | Returns the index of the first occurrence of searchString found. | +| lowercase | Returns this string in lower case. | +| split | Splits string by separator. | +| starts | Does this string start with the given searchString? | +| substring | Returns a string between indexStart, indexEnd. | +| trim | Removes white spaces from start and end of this string. | +| uppercase | Returns this string in upper case. | + +--- + +##### `at` + +```wing +at(index: num): str +``` + +Returns the character at the specified index. + +###### `index`Required + +- *Type:* num + +position of the character. + +--- + +##### `concat` + +```wing +concat(str_n: str): str +``` + +Combines the text of two (or more) strings and returns a new string. + +###### `str_n`Required + +- *Type:* str + +one or more strings to concatenate to this string. + +--- + +##### `contains` + +```wing +contains(search_string: str): bool +``` + +Checks if string includes substring. + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `ends` + +```wing +ends(search_string: str): bool +``` + +Does this string end with the given searchString? + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `index_of` + +```wing +index_of(search_string: str): num +``` + +Returns the index of the first occurrence of searchString found. + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `lowercase` + +```wing +lowercase(): str +``` + +Returns this string in lower case. + +##### `split` + +```wing +split(separator: str): MutArray +``` + +Splits string by separator. + +###### `separator`Required + +- *Type:* str + +separator to split by. + +--- + +##### `starts` + +```wing +starts(search_string: str): bool +``` + +Does this string start with the given searchString? + +###### `search_string`Required + +- *Type:* str + +substring to search for. + +--- + +##### `substring` + +```wing +substring(index_start: num, index_end?: num): str +``` + +Returns a string between indexStart, indexEnd. + +###### `index_start`Required + +- *Type:* num + +index of the character we slice at. + +--- + +###### `index_end`Optional + +- *Type:* num + +optional - index of the character we end slicing at. + +--- + +##### `trim` + +```wing +trim(): str +``` + +Removes white spaces from start and end of this string. + +##### `uppercase` + +```wing +uppercase(): str +``` + +Returns this string in upper case. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| length | num | The length of the string. | + +--- + +##### `length`Required + +```wing +length: num; +``` + +- *Type:* num + +The length of the string. + +--- + + +### T1 + +Generic type argument. + +This type is replaced at compile time. + +#### Initializers + +```wing +bring std; + +new std.T1() +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + + + + + +## Protocols + +### IBucketClient + +- *Implemented By:* IBucketClient + +Inflight interface for `Bucket`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| delete | Delete an existing object using a key from the bucket. | +| get | Retrieve an object from the bucket. | +| list | Retrieve existing objects keys from the bucket. | +| put | Put an object in the bucket. | + +--- + +##### `delete` + +```wing +delete(key: str, opts?: BucketDeleteOptions): void +``` + +**Inflight client:** [true](#true) + +Delete an existing object using a key from the bucket. + +###### `key`Required + +- *Type:* str + +Key of the object. + +--- + +###### `opts`Optional + +- *Type:* BucketDeleteOptions + +Options available for delete an item from a bucket. + +--- + +##### `get` + +```wing +get(key: str): str +``` + +**Inflight client:** [true](#true) + +Retrieve an object from the bucket. + +###### `key`Required + +- *Type:* str + +Key of the object. + +--- + +##### `list` + +```wing +list(prefix?: str): MutArray +``` + +**Inflight client:** [true](#true) + +Retrieve existing objects keys from the bucket. + +###### `prefix`Optional + +- *Type:* str + +Limits the response to keys that begin with the specified prefix. + +--- + +##### `put` + +```wing +put(key: str, body: str): void +``` + +**Inflight client:** [true](#true) + +Put an object in the bucket. + +###### `key`Required + +- *Type:* str + +Key of the object. + +--- + +###### `body`Required + +- *Type:* str + +Content of the object we want to store into the bucket. + +--- + + +### ICounterClient + +- *Implemented By:* CounterClientBase, ICounterClient + +Inflight interface for `Counter`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| dec | Decrement the counter, returning the previous value. | +| inc | Increments the counter atomically by a certain amount and returns the previous value. | +| peek | Get the current value of the counter. | +| reset | Reset a counter to a given value. | + +--- + +##### `dec` + +```wing +dec(amount?: num): num +``` + +**Inflight client:** [true](#true) + +Decrement the counter, returning the previous value. + +###### `amount`Optional + +- *Type:* num + +amount to decrement (default is 1). + +--- + +##### `inc` + +```wing +inc(amount?: num): num +``` + +**Inflight client:** [true](#true) + +Increments the counter atomically by a certain amount and returns the previous value. + +###### `amount`Optional + +- *Type:* num + +amount to increment (default is 1). + +--- + +##### `peek` + +```wing +peek(): num +``` + +**Inflight client:** [true](#true) + +Get the current value of the counter. + +Using this API may introduce race conditions since the value can change between +the time it is read and the time it is used in your code. + +##### `reset` + +```wing +reset(value?: num): void +``` + +**Inflight client:** [true](#true) + +Reset a counter to a given value. + +###### `value`Optional + +- *Type:* num + +value to reset (default is 0). + +--- + + +### IFunctionClient + +- *Implemented By:* IFunctionClient + +Inflight interface for `Function`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| invoke | Invoke the function asynchronously with a given payload. | + +--- + +##### `invoke` + +```wing +invoke(payload: str): str +``` + +**Inflight client:** [true](#true) + +Invoke the function asynchronously with a given payload. + +###### `payload`Required + +- *Type:* str + +--- + + +### IFunctionHandler + +- *Extends:* IResource + +- *Implemented By:* IFunctionHandler + +**Inflight client:** [wingsdk.cloud.IFunctionHandlerClient](#wingsdk.cloud.IFunctionHandlerClient) + +Represents a resource with an inflight "handle" method that can be used to create a `cloud.Function`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### IFunctionHandlerClient + +- *Implemented By:* IFunctionHandlerClient + +Inflight client for `IFunctionHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Entrypoint function that will be called when the cloud function is invoked. | + +--- + +##### `handle` + +```wing +handle(event: str): void +``` + +**Inflight client:** [true](#true) + +Entrypoint function that will be called when the cloud function is invoked. + +###### `event`Required + +- *Type:* str + +--- + + +### ILoggerClient + +- *Implemented By:* ILoggerClient + +Inflight interface for `Logger`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| print | Logs a message. The log will be associated with whichever resource is running the inflight code. | + +--- + +##### `print` + +```wing +print(message: str): void +``` + +**Inflight client:** [true](#true) + +Logs a message. The log will be associated with whichever resource is running the inflight code. + +NOTICE: this is not an async function because it is wrapped by `console.log()`. + +###### `message`Required + +- *Type:* str + +The message to print. + +--- + + +### IQueueClient + +- *Implemented By:* IQueueClient + +Inflight interface for `Queue`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| approx_size | Retrieve the approximate number of messages in the queue. | +| purge | Purge all of the messages in the queue. | +| push | Push a message to the queue. | + +--- + +##### `approx_size` + +```wing +approx_size(): num +``` + +**Inflight client:** [true](#true) + +Retrieve the approximate number of messages in the queue. + +##### `purge` + +```wing +purge(): void +``` + +**Inflight client:** [true](#true) + +Purge all of the messages in the queue. + +##### `push` + +```wing +push(message: str): void +``` + +**Inflight client:** [true](#true) + +Push a message to the queue. + +###### `message`Required + +- *Type:* str + +Payload to send to the queue. + +--- + + +### IQueueOnMessageHandler + +- *Extends:* IResource + +- *Implemented By:* IQueueOnMessageHandler + +**Inflight client:** [wingsdk.cloud.IQueueOnMessageHandlerClient](#wingsdk.cloud.IQueueOnMessageHandlerClient) + +Represents a resource with an inflight "handle" method that can be passed to `Queue.on_message`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### IQueueOnMessageHandlerClient + +- *Implemented By:* IQueueOnMessageHandlerClient + +Inflight client for `IQueueOnMessageHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Function that will be called when a message is received from the queue. | + +--- + +##### `handle` + +```wing +handle(message: str): void +``` + +**Inflight client:** [true](#true) + +Function that will be called when a message is received from the queue. + +###### `message`Required + +- *Type:* str + +--- + + +### IScheduleOnTickHandler + +- *Extends:* IResource + +- *Implemented By:* IScheduleOnTickHandler + +**Inflight client:** [wingsdk.cloud.IScheduleOnTickHandlerClient](#wingsdk.cloud.IScheduleOnTickHandlerClient) + +Represents a resource with an inflight "handle" method that can be passed to `Schedule.on_tick`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### IScheduleOnTickHandlerClient + +- *Implemented By:* IScheduleOnTickHandlerClient + +Inflight client for `IScheduleOnTickHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Function that will be called when a message is received from the schedule. | + +--- + +##### `handle` + +```wing +handle(): void +``` + +**Inflight client:** [true](#true) + +Function that will be called when a message is received from the schedule. + + +### ITopicClient + +- *Implemented By:* ITopicClient + +Inflight interface for `Topic`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| publish | Publish message to topic. | + +--- + +##### `publish` + +```wing +publish(message: str): void +``` + +**Inflight client:** [true](#true) + +Publish message to topic. + +###### `message`Required + +- *Type:* str + +Payload to publish to Topic. + +--- + + +### ITopicOnMessageHandler + +- *Extends:* IResource + +- *Implemented By:* ITopicOnMessageHandler + +**Inflight client:** [wingsdk.cloud.ITopicOnMessageHandlerClient](#wingsdk.cloud.ITopicOnMessageHandlerClient) + +Represents a resource with an inflight "handle" method that can be passed to `Topic.on_message`. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| display | Display | Information on how to display a resource in the UI. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `display`Required + +```wing +display: Display; +``` + +- *Type:* Display + +Information on how to display a resource in the UI. + +--- + +### ITopicOnMessageHandlerClient + +- *Implemented By:* ITopicOnMessageHandlerClient + +Inflight client for `ITopicOnMessageHandler`. + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| handle | Function that will be called when a message is received from the topic. | + +--- + +##### `handle` + +```wing +handle(event: str): void +``` + +**Inflight client:** [true](#true) + +Function that will be called when a message is received from the topic. + +###### `event`Required + +- *Type:* str + +--- + + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md new file mode 100644 index 00000000000..3f56acad94f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md @@ -0,0 +1,116 @@ +# [custom_obj_id.w](../../../../../examples/tests/valid/custom_obj_id.w) | compile | tf-aws + +## inflight.Foo.js +```js +module.exports = function({ }) { + class Foo { + constructor({ }) { + } + async $inflight_init() { + } + } + return Foo; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.15.2" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const std = $stdlib.std; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const $AppBase = $stdlib.core.App.for(process.env.WING_TARGET); +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class Foo extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + } + static _toInflightType(context) { + const self_client_path = "././inflight.Foo.js"; + return $stdlib.core.NodeJsCode.fromInline(` + require("${self_client_path}")({ + }) + `); + } + _toInflight() { + return $stdlib.core.NodeJsCode.fromInline(` + (await (async () => { + const FooClient = ${Foo._toInflightType(this).text}; + const client = new FooClient({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `); + } + _registerBind(host, ops) { + if (ops.includes("$inflight_init")) { + } + super._registerBind(host, ops); + } + static _registerTypeBind(host, ops) { + if (ops.includes("$inflight_init")) { + } + super._registerTypeBind(host, ops); + } + } + const foo1 = new Foo(this,"Foo"); + const bar2 = new Foo(this,"bar2"); + {((cond) => {if (!cond) throw new Error("assertion failed: foo1.node.id == \"Foo\"")})((foo1.node.id === "Foo"))}; + {((cond) => {if (!cond) throw new Error("assertion failed: bar2.node.id == \"bar2\"")})((bar2.node.id === "bar2"))}; + } +} +class $App extends $AppBase { + constructor() { + super({ outdir: $outdir, name: "custom_obj_id", plugins: $plugins, isTestEnvironment: $wing_is_test }); + if ($wing_is_test) { + new $Root(this, "env0"); + const $test_runner = this.testRunner; + const $tests = $test_runner.findTests(); + for (let $i = 1; $i < $tests.length; $i++) { + new $Root(this, "env" + $i); + } + } else { + new $Root(this, "Default"); + } + } +} +new $App().synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_test_sim.md new file mode 100644 index 00000000000..3916e3df375 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_test_sim.md @@ -0,0 +1,12 @@ +# [custom_obj_id.w](../../../../../examples/tests/valid/custom_obj_id.w) | test | sim + +## stdout.log +```log +pass ─ custom_obj_id.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + From 84933dbe9e7dcc532bb8db3c94a79e053991f7c4 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 16:36:48 +0300 Subject: [PATCH 07/20] remove stale files from previous lift --- docs/04-reference/wingsdk-api.md | 3894 ----------------- .../tests/valid/inflight_ref_resource_field.w | 16 - .../valid/inflight_ref_resource_userdefined.w | 25 - .../tests/valid/inflight_ref_unknown_op.w | 19 - 4 files changed, 3954 deletions(-) delete mode 100644 docs/04-reference/wingsdk-api.md delete mode 100644 examples/tests/valid/inflight_ref_resource_field.w delete mode 100644 examples/tests/valid/inflight_ref_resource_userdefined.w delete mode 100644 examples/tests/valid/inflight_ref_unknown_op.w diff --git a/docs/04-reference/wingsdk-api.md b/docs/04-reference/wingsdk-api.md deleted file mode 100644 index 8d7a8bce3c5..00000000000 --- a/docs/04-reference/wingsdk-api.md +++ /dev/null @@ -1,3894 +0,0 @@ ---- -title: API Reference -id: sdk -description: Wing SDK API Reference -keywords: [Wing sdk, sdk, Wing API Reference] ---- - -# API Reference - -## Resources - -### Bucket - -**Inflight client:** [@winglang/sdk.cloud.IBucketClient](#@winglang/sdk.cloud.IBucketClient) - -Represents a cloud object store. - -#### Initializers - -```wing -bring cloud; - -new cloud.Bucket(props?: BucketProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | BucketProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* BucketProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_object | Add a file to the bucket that is uploaded when the app is deployed. | - ---- - -##### `add_object` - -```wing -add_object(key: str, body: str): void -``` - -Add a file to the bucket that is uploaded when the app is deployed. - -TODO: In the future this will support uploading any `Blob` type or -referencing a file from the local filesystem. - -###### `key`Required - -- *Type:* str - ---- - -###### `body`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### BucketBase - -Functionality shared between all `Bucket` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.BucketBase(props: BucketProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | BucketProps | *No description.* | - ---- - -##### `props`Required - -- *Type:* BucketProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_object | Add a file to the bucket that is uploaded when the app is deployed. | - ---- - -##### `add_object` - -```wing -add_object(key: str, body: str): void -``` - -Add a file to the bucket that is uploaded when the app is deployed. - -TODO: In the future this will support uploading any `Blob` type or -referencing a file from the local filesystem. - -###### `key`Required - -- *Type:* str - ---- - -###### `body`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### Counter - -**Inflight client:** [@winglang/sdk.cloud.ICounterClient](#@winglang/sdk.cloud.ICounterClient) - -Represents a distributed atomic counter. - -#### Initializers - -```wing -bring cloud; - -new cloud.Counter(props?: CounterProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | CounterProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* CounterProps - ---- - - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| initial | num | The initial value of the counter. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `initial`Required - -```wing -initial: num; -``` - -- *Type:* num - -The initial value of the counter. - ---- - - -### CounterBase - -Functionality shared between all `Counter` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.CounterBase(props?: CounterProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | CounterProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* CounterProps - ---- - - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| initial | num | The initial value of the counter. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `initial`Required - -```wing -initial: num; -``` - -- *Type:* num - -The initial value of the counter. - ---- - - -### Function - -**Inflight client:** [@winglang/sdk.cloud.IFunctionClient](#@winglang/sdk.cloud.IFunctionClient) - -Represents a function. - -#### Initializers - -```wing -bring cloud; - -new cloud.Function(inflight: ~Inflight, props?: FunctionProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| inflight | Inflight | *No description.* | -| props | FunctionProps | *No description.* | - ---- - -##### `inflight`Required - -- *Type:* Inflight - ---- - -##### `props`Optional - -- *Type:* FunctionProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_environment | Add an environment variable to the function. | - ---- - -##### `add_environment` - -```wing -add_environment(_key: str, _value: str): void -``` - -Add an environment variable to the function. - -###### `_key`Required - -- *Type:* str - ---- - -###### `_value`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| env | MutMap<str> | Returns the set of environment variables for this function. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `env`Required - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> - -Returns the set of environment variables for this function. - ---- - - -### FunctionBase - -- *Implements:* IInflightHost - -Functionality shared between all `Function` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.FunctionBase(inflight: ~Inflight, props: FunctionProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| inflight | Inflight | *No description.* | -| props | FunctionProps | *No description.* | - ---- - -##### `inflight`Required - -- *Type:* Inflight - ---- - -##### `props`Required - -- *Type:* FunctionProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_environment | Add an environment variable to the function. | - ---- - -##### `add_environment` - -```wing -add_environment(name: str, value: str): void -``` - -Add an environment variable to the function. - -###### `name`Required - -- *Type:* str - ---- - -###### `value`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| env | MutMap<str> | Returns the set of environment variables for this function. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `env`Required - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> - -Returns the set of environment variables for this function. - ---- - - -### JsonFile - -Represents a text file that should be synthesized in the app's outdir. - -#### Initializers - -```wing -bring fs; - -new fs.JsonFile(file_path: str, props: JsonFileProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| file_path | str | *No description.* | -| props | JsonFileProps | *No description.* | - ---- - -##### `file_path`Required - -- *Type:* str - ---- - -##### `props`Required - -- *Type:* JsonFileProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| save | Render the contents of the file and save it to the user's file system. | - ---- - -##### `save` - -```wing -save(outdir: str): void -``` - -Render the contents of the file and save it to the user's file system. - -###### `outdir`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| file_path | str | The file's relative path to the output directory. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `file_path`Required - -```wing -file_path: str; -``` - -- *Type:* str - -The file's relative path to the output directory. - ---- - - -### Logger - -**Inflight client:** [@winglang/sdk.cloud.ILoggerClient](#@winglang/sdk.cloud.ILoggerClient) - -A cloud logging facility. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| print | Logs a message (preflight). | - ---- - -##### `print` - -```wing -print(message: str): void -``` - -Logs a message (preflight). - -###### `message`Required - -- *Type:* str - -The message to log. - ---- - -#### Static Functions - -| **Name** | **Description** | -| --- | --- | -| register | Create a logger and register it to the given scope. | - ---- - -##### `register` - -```wing -bring cloud; - -cloud.Logger.register() -``` - -Create a logger and register it to the given scope. - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### LoggerBase - -Functionality shared between all `Logger` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.LoggerBase() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| print | Logs a message (preflight). | - ---- - -##### `print` - -```wing -print(message: str): void -``` - -Logs a message (preflight). - -###### `message`Required - -- *Type:* str - -The message to log. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### Queue - -**Inflight client:** [@winglang/sdk.cloud.IQueueClient](#@winglang/sdk.cloud.IQueueClient) - -Represents a queue. - -#### Initializers - -```wing -bring cloud; - -new cloud.Queue(props?: QueueProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | QueueProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* QueueProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Create a function to consume messages from this queue. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function -``` - -Create a function to consume messages from this queue. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* QueueOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### QueueBase - -Functionality shared between all `Queue` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.QueueBase(props?: QueueProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | QueueProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* QueueProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Create a function to consume messages from this queue. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function -``` - -Create a function to consume messages from this queue. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* QueueOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### Schedule - -**Inflight client:** [@winglang/sdk.cloud.IScheduleClient](#@winglang/sdk.cloud.IScheduleClient) - -Represents a schedule. - -#### Initializers - -```wing -bring cloud; - -new cloud.Schedule(props?: ScheduleProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | ScheduleProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* ScheduleProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_tick | Create a function that runs when receiving the scheduled event. | - ---- - -##### `on_tick` - -```wing -on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function -``` - -Create a function that runs when receiving the scheduled event. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* ScheduleOnTickProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### ScheduleBase - -Functionality shared between all `Schedule` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.ScheduleBase(props?: ScheduleProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | ScheduleProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* ScheduleProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_tick | Create a function that runs when receiving the scheduled event. | - ---- - -##### `on_tick` - -```wing -on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function -``` - -Create a function that runs when receiving the scheduled event. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* ScheduleOnTickProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### TextFile - -Represents a text file that should be synthesized in the app's outdir. - -#### Initializers - -```wing -bring fs; - -new fs.TextFile(file_path: str, props?: TextFileProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| file_path | str | *No description.* | -| props | TextFileProps | *No description.* | - ---- - -##### `file_path`Required - -- *Type:* str - ---- - -##### `props`Optional - -- *Type:* TextFileProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| save | Render the contents of the file and save it to the user's file system. | -| add_line | Append a line to the text file's contents. | - ---- - -##### `save` - -```wing -save(outdir: str): void -``` - -Render the contents of the file and save it to the user's file system. - -###### `outdir`Required - -- *Type:* str - ---- - -##### `add_line` - -```wing -add_line(line: str): void -``` - -Append a line to the text file's contents. - -###### `line`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| file_path | str | The file's relative path to the output directory. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `file_path`Required - -```wing -file_path: str; -``` - -- *Type:* str - -The file's relative path to the output directory. - ---- - - -### Topic - -**Inflight client:** [@winglang/sdk.cloud.ITopicClient](#@winglang/sdk.cloud.ITopicClient) - -Represents a topic. - -#### Initializers - -```wing -bring cloud; - -new cloud.Topic(props?: TopicProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | TopicProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* TopicProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Run an inflight whenever an message is published to the topic. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function -``` - -Run an inflight whenever an message is published to the topic. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* TopicOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### TopicBase - -Topic base class. - -#### Initializers - -```wing -bring cloud; - -new cloud.TopicBase(props?: TopicProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | TopicProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* TopicProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Run an inflight whenever an message is published to the topic. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function -``` - -Run an inflight whenever an message is published to the topic. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* TopicOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -## Structs - -### BucketDeleteOptions - -Interface for delete method inside `Bucket`. - -#### Initializer - -```wing -bring cloud; - -let bucket_delete_options = cloud.BucketDeleteOptions{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| must_exist | bool | Check failures on the method and retrieve errors if any. | - ---- - -##### `must_exist`Optional - -```wing -must_exist: bool; -``` - -- *Type:* bool -- *Default:* false - -Check failures on the method and retrieve errors if any. - ---- - -### BucketProps - -Properties for `Bucket`. - -#### Initializer - -```wing -bring cloud; - -let bucket_props = cloud.BucketProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| public | bool | Whether the bucket's objects should be publicly accessible. | - ---- - -##### `public`Optional - -```wing -public: bool; -``` - -- *Type:* bool -- *Default:* false - -Whether the bucket's objects should be publicly accessible. - ---- - -### CounterProps - -Properties for `Counter`. - -#### Initializer - -```wing -bring cloud; - -let counter_props = cloud.CounterProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| initial | num | The initial value of the counter. | - ---- - -##### `initial`Optional - -```wing -initial: num; -``` - -- *Type:* num -- *Default:* 0 - -The initial value of the counter. - ---- - -### FunctionProps - -Properties for `Function`. - -This is the type users see when constructing a cloud.Function instance. - -#### Initializer - -```wing -bring cloud; - -let function_props = cloud.FunctionProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| env | MutMap<str> | Environment variables to pass to the function. | -| memory | num | The amount of memory to allocate to the function, in MB. | -| timeout | Duration | The maximum amount of time the function can run. | - ---- - -##### `env`Optional - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> -- *Default:* No environment variables. - -Environment variables to pass to the function. - ---- - -##### `memory`Optional - -```wing -memory: num; -``` - -- *Type:* num -- *Default:* 128 - -The amount of memory to allocate to the function, in MB. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* 1m - -The maximum amount of time the function can run. - ---- - -### JsonFileProps - -Props for `JsonFile`. - -#### Initializer - -```wing -bring fs; - -let json_file_props = fs.JsonFileProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| obj | any | The object that will be serialized into the file during synthesis. | - ---- - -##### `obj`Required - -```wing -obj: any; -``` - -- *Type:* any - -The object that will be serialized into the file during synthesis. - ---- - -### QueueOnMessageProps - -Options for Queue.onMessage. - -#### Initializer - -```wing -bring cloud; - -let queue_on_message_props = cloud.QueueOnMessageProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| env | MutMap<str> | Environment variables to pass to the function. | -| memory | num | The amount of memory to allocate to the function, in MB. | -| timeout | Duration | The maximum amount of time the function can run. | -| batch_size | num | The maximum number of messages to send to subscribers at once. | - ---- - -##### `env`Optional - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> -- *Default:* No environment variables. - -Environment variables to pass to the function. - ---- - -##### `memory`Optional - -```wing -memory: num; -``` - -- *Type:* num -- *Default:* 128 - -The amount of memory to allocate to the function, in MB. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* 1m - -The maximum amount of time the function can run. - ---- - -##### `batch_size`Optional - -```wing -batch_size: num; -``` - -- *Type:* num -- *Default:* 1 - -The maximum number of messages to send to subscribers at once. - ---- - -### QueueProps - -Properties for `Queue`. - -#### Initializer - -```wing -bring cloud; - -let queue_props = cloud.QueueProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| initial_messages | MutArray<str> | Initialize the queue with a set of messages. | -| timeout | Duration | How long a queue's consumers have to process a message. | - ---- - -##### `initial_messages`Optional - -```wing -initial_messages: MutArray; -``` - -- *Type:* MutArray<str> -- *Default:* [] - -Initialize the queue with a set of messages. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* Duration.fromSeconds(10) - -How long a queue's consumers have to process a message. - ---- - -### ScheduleOnTickProps - -Options for Schedule.onTick. - -#### Initializer - -```wing -bring cloud; - -let schedule_on_tick_props = cloud.ScheduleOnTickProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| env | MutMap<str> | Environment variables to pass to the function. | -| memory | num | The amount of memory to allocate to the function, in MB. | -| timeout | Duration | The maximum amount of time the function can run. | - ---- - -##### `env`Optional - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> -- *Default:* No environment variables. - -Environment variables to pass to the function. - ---- - -##### `memory`Optional - -```wing -memory: num; -``` - -- *Type:* num -- *Default:* 128 - -The amount of memory to allocate to the function, in MB. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* 1m - -The maximum amount of time the function can run. - ---- - -### ScheduleProps - -Properties for `Schedule`. - -#### Initializer - -```wing -bring cloud; - -let schedule_props = cloud.ScheduleProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| cron | str | Trigger events according to a cron schedule using the UNIX cron format. | -| rate | Duration | Trigger events at a periodic rate. | - ---- - -##### `cron`Optional - -```wing -cron: str; -``` - -- *Type:* str -- *Default:* undefined - -Trigger events according to a cron schedule using the UNIX cron format. - -[minute] [hour] [day of month] [month] [day of week] - ---- - -*Example* - -```wing -"0/1 * ? * *" -``` - - -##### `rate`Optional - -```wing -rate: Duration; -``` - -- *Type:* Duration -- *Default:* undefined - -Trigger events at a periodic rate. - ---- - -*Example* - -```wing -1m -``` - - -### TextFileProps - -Props for `TextFile`. - -#### Initializer - -```wing -bring fs; - -let text_file_props = fs.TextFileProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| lines | MutArray<str> | The lines of text that will be serialized into the file during synthesis. | - ---- - -##### `lines`Optional - -```wing -lines: MutArray; -``` - -- *Type:* MutArray<str> -- *Default:* [] - -The lines of text that will be serialized into the file during synthesis. - -They will be joined with newline characters. - ---- - -### TopicOnMessageProps - -Options for `Topic.onMessage`. - -#### Initializer - -```wing -bring cloud; - -let topic_on_message_props = cloud.TopicOnMessageProps{ ... } -``` - - -### TopicProps - -Properties for `Topic`. - -#### Initializer - -```wing -bring cloud; - -let topic_props = cloud.TopicProps{ ... } -``` - - -## Classes - -### CounterClientBase - -- *Implements:* ICounterClient - -Functionality shared between all `CounterClient` implementations regardless of the target. - -#### Initializers - -```wing -bring cloud; - -new cloud.CounterClientBase() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| dec | Decrement the counter, returning the previous value. | -| inc | Increments the counter atomically by a certain amount and returns the previous value. | -| peek | Get the current value of the counter. | -| reset | Reset a counter to a given value. | - ---- - -##### `dec` - -```wing -dec(amount?: num): num -``` - -Decrement the counter, returning the previous value. - -###### `amount`Optional - -- *Type:* num - ---- - -##### `inc` - -```wing -inc(amount?: num): num -``` - -Increments the counter atomically by a certain amount and returns the previous value. - -###### `amount`Optional - -- *Type:* num - ---- - -##### `peek` - -```wing -peek(): num -``` - -Get the current value of the counter. - -Using this API may introduce race conditions since the value can change between -the time it is read and the time it is used in your code. - -##### `reset` - -```wing -reset(value?: num): void -``` - -Reset a counter to a given value. - -###### `value`Optional - -- *Type:* num - ---- - - - - -### Duration - -Represents a length of time. - - -#### Static Functions - -| **Name** | **Description** | -| --- | --- | -| from_hours | Create a Duration representing an amount of hours. | -| from_minutes | Create a Duration representing an amount of minutes. | -| from_seconds | Create a Duration representing an amount of seconds. | - ---- - -##### `from_hours` - -```wing -bring std; - -std.Duration.from_hours(amount: num) -``` - -Create a Duration representing an amount of hours. - -###### `amount`Required - -- *Type:* num - -the amount of Hours the `Duration` will represent. - ---- - -##### `from_minutes` - -```wing -bring std; - -std.Duration.from_minutes(amount: num) -``` - -Create a Duration representing an amount of minutes. - -###### `amount`Required - -- *Type:* num - -the amount of Minutes the `Duration` will represent. - ---- - -##### `from_seconds` - -```wing -bring std; - -std.Duration.from_seconds(amount: num) -``` - -Create a Duration representing an amount of seconds. - -###### `amount`Required - -- *Type:* num - -the amount of Seconds the `Duration` will represent. - ---- - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| hours | num | Return the total number of hours in this Duration. | -| minutes | num | Return the total number of minutes in this Duration. | -| seconds | num | Return the total number of seconds in this Duration. | - ---- - -##### `hours`Required - -```wing -hours: num; -``` - -- *Type:* num - -Return the total number of hours in this Duration. - ---- - -##### `minutes`Required - -```wing -minutes: num; -``` - -- *Type:* num - -Return the total number of minutes in this Duration. - ---- - -##### `seconds`Required - -```wing -seconds: num; -``` - -- *Type:* num - -Return the total number of seconds in this Duration. - ---- - - -### ImmutableArray - -Immutable Array. - -#### Initializers - -```wing -bring std; - -new std.ImmutableArray() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| at | Get the value at the given index. | -| copy | Create an immutable shallow copy of this array. | -| copy_mut | Create a mutable shallow copy of this array. | - ---- - -##### `at` - -```wing -at(index: num): T1 -``` - -Get the value at the given index. - -###### `index`Required - -- *Type:* num - -index of the value to get. - ---- - -##### `copy` - -```wing -copy(): ImmutableArray -``` - -Create an immutable shallow copy of this array. - -##### `copy_mut` - -```wing -copy_mut(): MutableArray -``` - -Create a mutable shallow copy of this array. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| length | num | The length of the array. | - ---- - -##### `length`Required - -```wing -length: num; -``` - -- *Type:* num - -The length of the array. - ---- - - -### ImmutableMap - -Immutable Map. - -#### Initializers - -```wing -bring std; - -new std.ImmutableMap() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this map. | -| copy_mut | Create a mutable shallow copy of this map. | -| get | Returns a specified element from the map. | -| has | Returns a boolean indicating whether an element with the specified key exists or not. | -| size | Returns the number of elements in the map. | - ---- - -##### `copy` - -```wing -copy(): ImmutableMap -``` - -Create an immutable shallow copy of this map. - -##### `copy_mut` - -```wing -copy_mut(): MutableMap -``` - -Create a mutable shallow copy of this map. - -##### `get` - -```wing -get(key: str): T1 -``` - -Returns a specified element from the map. - -If the value that is associated to the provided key is an object, then you will get a reference -to that object and any change made to that object will effectively modify it inside the map. - -###### `key`Required - -- *Type:* str - -The key of the element to return. - ---- - -##### `has` - -```wing -has(key: str): bool -``` - -Returns a boolean indicating whether an element with the specified key exists or not. - -###### `key`Required - -- *Type:* str - -The key of the element to test for presence. - ---- - -##### `size` - -```wing -size(): num -``` - -Returns the number of elements in the map. - -TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 - - - - -### ImmutableSet - -Immutable Set. - -#### Initializers - -```wing -bring std; - -new std.ImmutableSet() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this set. | -| copy_mut | Create a mutable shallow copy of this set. | -| has | Returns a boolean indicating whether an element with the specified value exists in the set. | - ---- - -##### `copy` - -```wing -copy(): ImmutableSet -``` - -Create an immutable shallow copy of this set. - -##### `copy_mut` - -```wing -copy_mut(): MutableSet -``` - -Create a mutable shallow copy of this set. - -##### `has` - -```wing -has(value: T1): bool -``` - -Returns a boolean indicating whether an element with the specified value exists in the set. - -###### `value`Required - -- *Type:* T1 - -The value to test for presence in the Set object. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| size | num | The length of the set. | - ---- - -##### `size`Required - -```wing -size: num; -``` - -- *Type:* num - -The length of the set. - ---- - - -### MutableArray - -Mutable Array. - -#### Initializers - -```wing -bring std; - -new std.MutableArray() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| at | Get the value at the given index. | -| copy | Create an immutable shallow copy of this array. | -| copy_mut | Create a mutable shallow copy of this array. | -| pop | Remove value from end of array. | -| push | Add value to end of array. | - ---- - -##### `at` - -```wing -at(index: num): T1 -``` - -Get the value at the given index. - -###### `index`Required - -- *Type:* num - -index of the value to get. - ---- - -##### `copy` - -```wing -copy(): ImmutableArray -``` - -Create an immutable shallow copy of this array. - -##### `copy_mut` - -```wing -copy_mut(): MutableArray -``` - -Create a mutable shallow copy of this array. - -##### `pop` - -```wing -pop(): T1 -``` - -Remove value from end of array. - -##### `push` - -```wing -push(value: T1): void -``` - -Add value to end of array. - -###### `value`Required - -- *Type:* T1 - -value to add. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| length | num | The length of the array. | - ---- - -##### `length`Required - -```wing -length: num; -``` - -- *Type:* num - -The length of the array. - ---- - - -### MutableMap - -Mutable Map. - -#### Initializers - -```wing -bring std; - -new std.MutableMap() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this map. | -| copy_mut | Create a mutable shallow copy of this map. | -| get | Returns a specified element from the map. | -| has | Returns a boolean indicating whether an element with the specified key exists or not. | -| size | Returns the number of elements in the map. | -| clear | Removes all elements. | -| delete | Removes the specified element from a map. | -| set | Adds or updates an entry in a Map object with a specified key and a value. | - ---- - -##### `copy` - -```wing -copy(): ImmutableMap -``` - -Create an immutable shallow copy of this map. - -##### `copy_mut` - -```wing -copy_mut(): MutableMap -``` - -Create a mutable shallow copy of this map. - -##### `get` - -```wing -get(key: str): T1 -``` - -Returns a specified element from the map. - -If the value that is associated to the provided key is an object, then you will get a reference -to that object and any change made to that object will effectively modify it inside the map. - -###### `key`Required - -- *Type:* str - -The key of the element to return. - ---- - -##### `has` - -```wing -has(key: str): bool -``` - -Returns a boolean indicating whether an element with the specified key exists or not. - -###### `key`Required - -- *Type:* str - -The key of the element to test for presence. - ---- - -##### `size` - -```wing -size(): num -``` - -Returns the number of elements in the map. - -TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 - -##### `clear` - -```wing -clear(): void -``` - -Removes all elements. - -##### `delete` - -```wing -delete(key: str): bool -``` - -Removes the specified element from a map. - -###### `key`Required - -- *Type:* str - -The key. - ---- - -##### `set` - -```wing -set(key: str, value: T1): void -``` - -Adds or updates an entry in a Map object with a specified key and a value. - -TODO: revisit this macro after we support indexed args https://github.com/winglang/wing/issues/1659 - -###### `key`Required - -- *Type:* str - -The key of the element to add. - ---- - -###### `value`Required - -- *Type:* T1 - -The value of the element to add. - ---- - - - - -### MutableSet - -Mutable Set. - -#### Initializers - -```wing -bring std; - -new std.MutableSet() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this set. | -| copy_mut | Create a mutable shallow copy of this set. | -| has | Returns a boolean indicating whether an element with the specified value exists in the set. | -| add | Add value to set. | -| clear | The clear() method removes all elements from a set. | -| delete | Removes a specified value from a set, if it is in the set. | - ---- - -##### `copy` - -```wing -copy(): ImmutableSet -``` - -Create an immutable shallow copy of this set. - -##### `copy_mut` - -```wing -copy_mut(): MutableSet -``` - -Create a mutable shallow copy of this set. - -##### `has` - -```wing -has(value: T1): bool -``` - -Returns a boolean indicating whether an element with the specified value exists in the set. - -###### `value`Required - -- *Type:* T1 - -The value to test for presence in the Set object. - ---- - -##### `add` - -```wing -add(value: T1): MutableSet -``` - -Add value to set. - -###### `value`Required - -- *Type:* T1 - -value to add. - ---- - -##### `clear` - -```wing -clear(): void -``` - -The clear() method removes all elements from a set. - -##### `delete` - -```wing -delete(value: T1): bool -``` - -Removes a specified value from a set, if it is in the set. - -###### `value`Required - -- *Type:* T1 - -The value to remove from the set. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| size | num | The length of the set. | - ---- - -##### `size`Required - -```wing -size: num; -``` - -- *Type:* num - -The length of the set. - ---- - - -### String - -String. - -#### Initializers - -```wing -bring std; - -new std.String() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| at | Returns the character at the specified index. | -| concat | Combines the text of two (or more) strings and returns a new string. | -| contains | Checks if string includes substring. | -| ends | Does this string end with the given searchString? | -| index_of | Returns the index of the first occurrence of searchString found. | -| lowercase | Returns this string in lower case. | -| split | Splits string by separator. | -| starts | Does this string start with the given searchString? | -| substring | Returns a string between indexStart, indexEnd. | -| trim | Removes white spaces from start and end of this string. | -| uppercase | Returns this string in upper case. | - ---- - -##### `at` - -```wing -at(index: num): str -``` - -Returns the character at the specified index. - -###### `index`Required - -- *Type:* num - -position of the character. - ---- - -##### `concat` - -```wing -concat(str_n: str): str -``` - -Combines the text of two (or more) strings and returns a new string. - -###### `str_n`Required - -- *Type:* str - -one or more strings to concatenate to this string. - ---- - -##### `contains` - -```wing -contains(search_string: str): bool -``` - -Checks if string includes substring. - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `ends` - -```wing -ends(search_string: str): bool -``` - -Does this string end with the given searchString? - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `index_of` - -```wing -index_of(search_string: str): num -``` - -Returns the index of the first occurrence of searchString found. - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `lowercase` - -```wing -lowercase(): str -``` - -Returns this string in lower case. - -##### `split` - -```wing -split(separator: str): MutArray -``` - -Splits string by separator. - -###### `separator`Required - -- *Type:* str - -separator to split by. - ---- - -##### `starts` - -```wing -starts(search_string: str): bool -``` - -Does this string start with the given searchString? - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `substring` - -```wing -substring(index_start: num, index_end?: num): str -``` - -Returns a string between indexStart, indexEnd. - -###### `index_start`Required - -- *Type:* num - -index of the character we slice at. - ---- - -###### `index_end`Optional - -- *Type:* num - -optional - index of the character we end slicing at. - ---- - -##### `trim` - -```wing -trim(): str -``` - -Removes white spaces from start and end of this string. - -##### `uppercase` - -```wing -uppercase(): str -``` - -Returns this string in upper case. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| length | num | The length of the string. | - ---- - -##### `length`Required - -```wing -length: num; -``` - -- *Type:* num - -The length of the string. - ---- - - -### T1 - -Generic type argument. - -This type is replaced at compile time. - -#### Initializers - -```wing -bring std; - -new std.T1() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - - - - - -## Protocols - -### IBucketClient - -- *Implemented By:* IBucketClient - -Inflight interface for `Bucket`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| delete | Delete an existing object using a key from the bucket. | -| get | Retrieve an object from the bucket. | -| list | Retrieve existing objects keys from the bucket. | -| put | Put an object in the bucket. | - ---- - -##### `delete` - -```wing -delete(key: str, opts?: BucketDeleteOptions): void -``` - -**Inflight client:** [true](#true) - -Delete an existing object using a key from the bucket. - -###### `key`Required - -- *Type:* str - -Key of the object. - ---- - -###### `opts`Optional - -- *Type:* BucketDeleteOptions - -Options available for delete an item from a bucket. - ---- - -##### `get` - -```wing -get(key: str): str -``` - -**Inflight client:** [true](#true) - -Retrieve an object from the bucket. - -###### `key`Required - -- *Type:* str - -Key of the object. - ---- - -##### `list` - -```wing -list(prefix?: str): MutArray -``` - -**Inflight client:** [true](#true) - -Retrieve existing objects keys from the bucket. - -###### `prefix`Optional - -- *Type:* str - -Limits the response to keys that begin with the specified prefix. - ---- - -##### `put` - -```wing -put(key: str, body: str): void -``` - -**Inflight client:** [true](#true) - -Put an object in the bucket. - -###### `key`Required - -- *Type:* str - -Key of the object. - ---- - -###### `body`Required - -- *Type:* str - -Content of the object we want to store into the bucket. - ---- - - -### ICounterClient - -- *Implemented By:* CounterClientBase, ICounterClient - -Inflight interface for `Counter`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| dec | Decrement the counter, returning the previous value. | -| inc | Increments the counter atomically by a certain amount and returns the previous value. | -| peek | Get the current value of the counter. | -| reset | Reset a counter to a given value. | - ---- - -##### `dec` - -```wing -dec(amount?: num): num -``` - -**Inflight client:** [true](#true) - -Decrement the counter, returning the previous value. - -###### `amount`Optional - -- *Type:* num - -amount to decrement (default is 1). - ---- - -##### `inc` - -```wing -inc(amount?: num): num -``` - -**Inflight client:** [true](#true) - -Increments the counter atomically by a certain amount and returns the previous value. - -###### `amount`Optional - -- *Type:* num - -amount to increment (default is 1). - ---- - -##### `peek` - -```wing -peek(): num -``` - -**Inflight client:** [true](#true) - -Get the current value of the counter. - -Using this API may introduce race conditions since the value can change between -the time it is read and the time it is used in your code. - -##### `reset` - -```wing -reset(value?: num): void -``` - -**Inflight client:** [true](#true) - -Reset a counter to a given value. - -###### `value`Optional - -- *Type:* num - -value to reset (default is 0). - ---- - - -### IFunctionClient - -- *Implemented By:* IFunctionClient - -Inflight interface for `Function`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| invoke | Invoke the function asynchronously with a given payload. | - ---- - -##### `invoke` - -```wing -invoke(payload: str): str -``` - -**Inflight client:** [true](#true) - -Invoke the function asynchronously with a given payload. - -###### `payload`Required - -- *Type:* str - ---- - - -### IFunctionHandler - -- *Extends:* IResource - -- *Implemented By:* IFunctionHandler - -**Inflight client:** [wingsdk.cloud.IFunctionHandlerClient](#wingsdk.cloud.IFunctionHandlerClient) - -Represents a resource with an inflight "handle" method that can be used to create a `cloud.Function`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### IFunctionHandlerClient - -- *Implemented By:* IFunctionHandlerClient - -Inflight client for `IFunctionHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Entrypoint function that will be called when the cloud function is invoked. | - ---- - -##### `handle` - -```wing -handle(event: str): void -``` - -**Inflight client:** [true](#true) - -Entrypoint function that will be called when the cloud function is invoked. - -###### `event`Required - -- *Type:* str - ---- - - -### ILoggerClient - -- *Implemented By:* ILoggerClient - -Inflight interface for `Logger`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| print | Logs a message. The log will be associated with whichever resource is running the inflight code. | - ---- - -##### `print` - -```wing -print(message: str): void -``` - -**Inflight client:** [true](#true) - -Logs a message. The log will be associated with whichever resource is running the inflight code. - -NOTICE: this is not an async function because it is wrapped by `console.log()`. - -###### `message`Required - -- *Type:* str - -The message to print. - ---- - - -### IQueueClient - -- *Implemented By:* IQueueClient - -Inflight interface for `Queue`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| approx_size | Retrieve the approximate number of messages in the queue. | -| purge | Purge all of the messages in the queue. | -| push | Push a message to the queue. | - ---- - -##### `approx_size` - -```wing -approx_size(): num -``` - -**Inflight client:** [true](#true) - -Retrieve the approximate number of messages in the queue. - -##### `purge` - -```wing -purge(): void -``` - -**Inflight client:** [true](#true) - -Purge all of the messages in the queue. - -##### `push` - -```wing -push(message: str): void -``` - -**Inflight client:** [true](#true) - -Push a message to the queue. - -###### `message`Required - -- *Type:* str - -Payload to send to the queue. - ---- - - -### IQueueOnMessageHandler - -- *Extends:* IResource - -- *Implemented By:* IQueueOnMessageHandler - -**Inflight client:** [wingsdk.cloud.IQueueOnMessageHandlerClient](#wingsdk.cloud.IQueueOnMessageHandlerClient) - -Represents a resource with an inflight "handle" method that can be passed to `Queue.on_message`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### IQueueOnMessageHandlerClient - -- *Implemented By:* IQueueOnMessageHandlerClient - -Inflight client for `IQueueOnMessageHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Function that will be called when a message is received from the queue. | - ---- - -##### `handle` - -```wing -handle(message: str): void -``` - -**Inflight client:** [true](#true) - -Function that will be called when a message is received from the queue. - -###### `message`Required - -- *Type:* str - ---- - - -### IScheduleOnTickHandler - -- *Extends:* IResource - -- *Implemented By:* IScheduleOnTickHandler - -**Inflight client:** [wingsdk.cloud.IScheduleOnTickHandlerClient](#wingsdk.cloud.IScheduleOnTickHandlerClient) - -Represents a resource with an inflight "handle" method that can be passed to `Schedule.on_tick`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### IScheduleOnTickHandlerClient - -- *Implemented By:* IScheduleOnTickHandlerClient - -Inflight client for `IScheduleOnTickHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Function that will be called when a message is received from the schedule. | - ---- - -##### `handle` - -```wing -handle(): void -``` - -**Inflight client:** [true](#true) - -Function that will be called when a message is received from the schedule. - - -### ITopicClient - -- *Implemented By:* ITopicClient - -Inflight interface for `Topic`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| publish | Publish message to topic. | - ---- - -##### `publish` - -```wing -publish(message: str): void -``` - -**Inflight client:** [true](#true) - -Publish message to topic. - -###### `message`Required - -- *Type:* str - -Payload to publish to Topic. - ---- - - -### ITopicOnMessageHandler - -- *Extends:* IResource - -- *Implemented By:* ITopicOnMessageHandler - -**Inflight client:** [wingsdk.cloud.ITopicOnMessageHandlerClient](#wingsdk.cloud.ITopicOnMessageHandlerClient) - -Represents a resource with an inflight "handle" method that can be passed to `Topic.on_message`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### ITopicOnMessageHandlerClient - -- *Implemented By:* ITopicOnMessageHandlerClient - -Inflight client for `ITopicOnMessageHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Function that will be called when a message is received from the topic. | - ---- - -##### `handle` - -```wing -handle(event: str): void -``` - -**Inflight client:** [true](#true) - -Function that will be called when a message is received from the topic. - -###### `event`Required - -- *Type:* str - ---- - - diff --git a/examples/tests/valid/inflight_ref_resource_field.w b/examples/tests/valid/inflight_ref_resource_field.w deleted file mode 100644 index 271d3659045..00000000000 --- a/examples/tests/valid/inflight_ref_resource_field.w +++ /dev/null @@ -1,16 +0,0 @@ -bring cloud; - -resource Test { - my_field: str; - - init () { - this.my_field = "hello"; - } - - inflight test(): str { - assert(this.my_field == "hello"); - } -} - -let f = new Test(); -new cloud.Function(inflight () => { f.test(); }) as "test"; \ No newline at end of file diff --git a/examples/tests/valid/inflight_ref_resource_userdefined.w b/examples/tests/valid/inflight_ref_resource_userdefined.w deleted file mode 100644 index 60458ca4aaf..00000000000 --- a/examples/tests/valid/inflight_ref_resource_userdefined.w +++ /dev/null @@ -1,25 +0,0 @@ -bring cloud; - -resource Another { - init () { } - - inflight func(): str { - return "hello"; - } -} - -resource Test { - another: Another; - - init() { - this.another = new Another(); - } - - inflight test() { - let res = this.another.func(); - assert(res == "hello"); - } -} - -let f = new Test(); -new cloud.Function(inflight () => { f.test(); }) as "test"; \ No newline at end of file diff --git a/examples/tests/valid/inflight_ref_unknown_op.w b/examples/tests/valid/inflight_ref_unknown_op.w deleted file mode 100644 index 602d6583bb8..00000000000 --- a/examples/tests/valid/inflight_ref_unknown_op.w +++ /dev/null @@ -1,19 +0,0 @@ -// NOTE: this test is supposed to fail once https://github.com/winglang/wing/pull/1610 is complete - -bring cloud; - -resource Test { - b: cloud.Bucket; - - init() { - this.b = new cloud.Bucket(); - } - - inflight test() { - let x = this.b; - x.put("hello", "world"); - } -} - -let f = new Test(); -new cloud.Function(inflight () => { f.test(); }) as "test"; \ No newline at end of file From fa903ff112fa6563ab22f22598eff9aa5ae66373 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 16:40:02 +0300 Subject: [PATCH 08/20] fix invalid logic --- libs/wingc/src/jsify.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index 995eb1baf79..b02fda10671 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -1437,16 +1437,14 @@ impl<'a> JSifier<'a> { let refs = refs .iter() .filter(|(m, _)| { - *m == CLASS_INFLIGHT_INIT_NAME - || !(matches!( - class_type - .as_class() - .unwrap() - .get_method(&m.as_str().into()) - .expect(&format!("method {m} doesn't exist in {class_name}")) - .kind, - VariableKind::StaticMember - )) ^ (matches!(bind_method_kind, BindMethod::Type)) + let var_kind = class_type + .as_class() + .unwrap() + .get_method(&m.as_str().into()) + .expect(&format!("method {m} doesn't exist in {class_name}")) + .kind; + let is_static = matches!(var_kind, VariableKind::StaticMember); + (*m == CLASS_INFLIGHT_INIT_NAME || !is_static) ^ (matches!(bind_method_kind, BindMethod::Type)) }) .collect_vec(); From 6fcd257b5ac03ad176d13a2b0007324b472a9577 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 17:07:52 +0300 Subject: [PATCH 09/20] tweaks --- libs/wingc/src/type_check.rs | 64 ++++++++-------- tools/hangar/__snapshots__/invalid.ts.snap | 75 ++++++++++++++++--- .../valid/custom_obj_id.w_compile_tf-aws.md | 5 -- 3 files changed, 96 insertions(+), 48 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index ab4a15d7ba5..64277589390 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -1255,6 +1255,15 @@ impl<'a> TypeChecker<'a> { ); } + fn spanned_error_with_var>(&self, spanned: &impl Spanned, message: S) -> (VariableInfo, Phase) { + report_diagnostic(Diagnostic { + message: message.into(), + span: Some(spanned.span()), + }); + + (self.make_error_variable_info(), Phase::Independent) + } + fn spanned_error>(&self, spanned: &impl Spanned, message: S) { report_diagnostic(Diagnostic { message: message.into(), @@ -3574,11 +3583,10 @@ impl<'a> TypeChecker<'a> { let phase = var.phase; (var, phase) } else { - self.spanned_error( + self.spanned_error_with_var( symbol, format!("Expected identifier \"{symbol}\" to be a variable, but it's a {var}",), - ); - (self.make_error_variable_info(), Phase::Independent) + ) } } else { // Give a specific error message if someone tries to write "print" instead of "log" @@ -3676,7 +3684,7 @@ impl<'a> TypeChecker<'a> { } Reference::TypeReference(udt) => { let Ok(t) = self.resolve_user_defined_type(udt, env, self.statement_idx) else { - return (self.make_error_variable_info(), Phase::Independent); + return self.spanned_error_with_var(udt, format!("Unable to resolve type \"{}\"", udt)); }; let phase = if let Some(c) = t.as_class() { @@ -3700,13 +3708,11 @@ impl<'a> TypeChecker<'a> { let (type_, _) = self.type_check_exp(typeobject, env); let ExprKind::Reference(typeref) = &typeobject.kind else { - self.spanned_error(typeobject, "Expecting a reference"); - return (self.make_error_variable_info(), Phase::Independent); + return self.spanned_error_with_var(typeobject, "Expecting a reference"); }; let Reference::TypeReference(_) = typeref else { - self.spanned_error(typeobject, "Expecting a reference to a type"); - return (self.make_error_variable_info(), Phase::Independent); + return self.spanned_error_with_var(typeobject, "Expecting a reference to a type"); }; match *type_ { @@ -3723,11 +3729,10 @@ impl<'a> TypeChecker<'a> { Phase::Independent, ) } else { - self.spanned_error( + self.spanned_error_with_var( property, format!("Enum \"{}\" does not contain value \"{}\"", type_, property.name), - ); - (self.make_error_variable_info(), Phase::Independent) + ) } } Type::Class(ref c) => match c.env.lookup(&property, None) { @@ -3735,28 +3740,21 @@ impl<'a> TypeChecker<'a> { if let VariableKind::StaticMember = v.kind { (v.clone(), v.phase) } else { - self.spanned_error( + self.spanned_error_with_var( property, format!( "Class \"{}\" contains a member \"{}\" but it is not static", type_, property.name ), - ); - (self.make_error_variable_info(), Phase::Independent) + ) } } - _ => { - self.spanned_error( - property, - format!("No member \"{}\" in class \"{}\"", property.name, type_), - ); - (self.make_error_variable_info(), Phase::Independent) - } + _ => self.spanned_error_with_var( + property, + format!("No member \"{}\" in class \"{}\"", property.name, type_), + ), }, - _ => { - self.spanned_error(property, format!("\"{}\" not a valid reference", reference)); - (self.make_error_variable_info(), Phase::Independent) - } + _ => self.spanned_error_with_var(property, format!("\"{}\" not a valid reference", reference)), } } } @@ -3851,10 +3849,7 @@ impl<'a> TypeChecker<'a> { property, ), Type::Struct(ref s) => self.get_property_from_class_like(s, property), - _ => { - self.spanned_error(property, format!("Property not found")); - self.make_error_variable_info() - } + _ => self.spanned_error_with_var(property, format!("Property not found")).0, } } @@ -3864,11 +3859,12 @@ impl<'a> TypeChecker<'a> { if let LookupResult::Found(field, _) = lookup_res { let var = field.as_variable().expect("Expected property to be a variable"); if let VariableKind::StaticMember = var.kind { - self.spanned_error( - property, - format!("Cannot access static property \"{property}\" from instance"), - ); - self.make_error_variable_info() + self + .spanned_error_with_var( + property, + format!("Cannot access static property \"{property}\" from instance"), + ) + .0 } else { var } diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index b752fc07ca3..d13469760af 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -1,5 +1,20 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`access_hidden_namespace.w 1`] = ` +"error: Unable to resolve type \\"core.NodeJsCode\\" + --> ../../../examples/tests/invalid/access_hidden_namespace.w:7:5 + | +7 | new core.NodeJsCode(\\"/tmp/test.txt\\"); // This should fail even though \`fs.TextFile\` extends \`core.FileBase\` because we didn't bring in \`core\` explicitly. + | ^^^^^^^^^^^^^^^ Unable to resolve type \\"core.NodeJsCode\\" + + + + +Tests 1 failed (1) +Test Files 1 failed (1) +Duration " +`; + exports[`access_static_from_instance.w 1`] = ` "error: Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 --> ../../../examples/tests/invalid/access_static_from_instance.w:4:3 @@ -279,6 +294,13 @@ error: Preflight field \\"y\\" is not initialized | ^ Preflight field \\"y\\" is not initialized +error: Unable to resolve type \\"x\\" + --> ../../../examples/tests/invalid/class.w:68:18 + | +68 | class C7 extends x { + | ^ Unable to resolve type \\"x\\" + + error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/class.w:68:18 | @@ -293,11 +315,18 @@ error: Base class \\"S1\\" is not a class | ^^ Base class \\"S1\\" is not a class -error: Base class \\"unresolved\\" is not a class +error: Unable to resolve type \\"C11\\" + --> ../../../examples/tests/invalid/class.w:78:19 + | +78 | class C11 extends C11 { + | ^^^ Unable to resolve type \\"C11\\" + + +error: Class cannot extend itself --> ../../../examples/tests/invalid/class.w:78:19 | 78 | class C11 extends C11 { - | ^^^ Base class \\"unresolved\\" is not a class + | ^^^ Class cannot extend itself error: Expected type to be \\"num\\", but got \\"str\\" instead @@ -1527,6 +1556,13 @@ exports[`sorted_errors_no_span.w 1`] = ` | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead +error: Unable to resolve type \\"b\\" + --> ../../../examples/tests/invalid/sorted_errors_no_span.w:3:26 + | +3 | inflight class c extends b {} + | ^ Unable to resolve type \\"b\\" + + error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/sorted_errors_no_span.w:3:26 | @@ -1541,6 +1577,13 @@ error: Expected type to be \\"num\\", but got \\"str\\" instead | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead +error: Unable to resolve type \\"b\\" + --> ../../../examples/tests/invalid/sorted_errors_no_span.w:5:26 + | +5 | inflight class e extends b {} + | ^ Unable to resolve type \\"b\\" + + error: Base class \\"unresolved\\" is not a class --> ../../../examples/tests/invalid/sorted_errors_no_span.w:5:26 | @@ -1863,25 +1906,39 @@ Duration " `; exports[`unknown_symbol.w 1`] = ` -"error: Unknown symbol \\"y\\" +"error: Unable to resolve type \\"clod.Bucket\\" + --> ../../../examples/tests/invalid/unknown_symbol.w:3:18 + | +3 | let bucket = new clod.Bucket(); + | ^^^^^^^^^^^ Unable to resolve type \\"clod.Bucket\\" + + +error: Unable to resolve type \\"cloudy.Funktion\\" + --> ../../../examples/tests/invalid/unknown_symbol.w:6:17 + | +6 | let funky = new cloudy.Funktion(inflight () => { }); + | ^^^^^^^^^^^^^^^ Unable to resolve type \\"cloudy.Funktion\\" + + +error: Unknown symbol \\"y\\" --> ../../../examples/tests/invalid/unknown_symbol.w:9:13 | 9 | let x = 2 + y; | ^ Unknown symbol \\"y\\" -error: Base class \\"unresolved\\" is not a class +error: Unable to resolve type \\"B\\" --> ../../../examples/tests/invalid/unknown_symbol.w:28:17 | 28 | class A extends B { - | ^ Base class \\"unresolved\\" is not a class + | ^ Unable to resolve type \\"B\\" -error: Unknown symbol \\"unknown\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:32:1 +error: Base class \\"unresolved\\" is not a class + --> ../../../examples/tests/invalid/unknown_symbol.w:28:17 | -32 | unknown = 1; - | ^^^^^^^ Unknown symbol \\"unknown\\" +28 | class A extends B { + | ^ Base class \\"unresolved\\" is not a class error: Unknown symbol \\"unknown\\" diff --git a/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md index 3f56acad94f..c22b9b38af1 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/custom_obj_id.w_compile_tf-aws.md @@ -83,11 +83,6 @@ class $Root extends $stdlib.std.Resource { } super._registerBind(host, ops); } - static _registerTypeBind(host, ops) { - if (ops.includes("$inflight_init")) { - } - super._registerTypeBind(host, ops); - } } const foo1 = new Foo(this,"Foo"); const bar2 = new Foo(this,"bar2"); From 78226b5d020b744ddeea1e2ca2907ded1c225c0f Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 17:08:21 +0300 Subject: [PATCH 10/20] oops --- libs/wingsdk/API.md | 3887 ------------------------------------------- 1 file changed, 3887 deletions(-) delete mode 100644 libs/wingsdk/API.md diff --git a/libs/wingsdk/API.md b/libs/wingsdk/API.md deleted file mode 100644 index 3f7ec4d317e..00000000000 --- a/libs/wingsdk/API.md +++ /dev/null @@ -1,3887 +0,0 @@ -# API Reference - -## Resources - -### Bucket - -**Inflight client:** [@winglang/sdk.cloud.IBucketClient](#@winglang/sdk.cloud.IBucketClient) - -Represents a cloud object store. - -#### Initializers - -```wing -bring cloud; - -new cloud.Bucket(props?: BucketProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | BucketProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* BucketProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_object | Add a file to the bucket that is uploaded when the app is deployed. | - ---- - -##### `add_object` - -```wing -add_object(key: str, body: str): void -``` - -Add a file to the bucket that is uploaded when the app is deployed. - -TODO: In the future this will support uploading any `Blob` type or -referencing a file from the local filesystem. - -###### `key`Required - -- *Type:* str - ---- - -###### `body`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### BucketBase - -Functionality shared between all `Bucket` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.BucketBase(props: BucketProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | BucketProps | *No description.* | - ---- - -##### `props`Required - -- *Type:* BucketProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_object | Add a file to the bucket that is uploaded when the app is deployed. | - ---- - -##### `add_object` - -```wing -add_object(key: str, body: str): void -``` - -Add a file to the bucket that is uploaded when the app is deployed. - -TODO: In the future this will support uploading any `Blob` type or -referencing a file from the local filesystem. - -###### `key`Required - -- *Type:* str - ---- - -###### `body`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### Counter - -**Inflight client:** [@winglang/sdk.cloud.ICounterClient](#@winglang/sdk.cloud.ICounterClient) - -Represents a distributed atomic counter. - -#### Initializers - -```wing -bring cloud; - -new cloud.Counter(props?: CounterProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | CounterProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* CounterProps - ---- - - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| initial | num | The initial value of the counter. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `initial`Required - -```wing -initial: num; -``` - -- *Type:* num - -The initial value of the counter. - ---- - - -### CounterBase - -Functionality shared between all `Counter` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.CounterBase(props?: CounterProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | CounterProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* CounterProps - ---- - - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| initial | num | The initial value of the counter. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `initial`Required - -```wing -initial: num; -``` - -- *Type:* num - -The initial value of the counter. - ---- - - -### Function - -**Inflight client:** [@winglang/sdk.cloud.IFunctionClient](#@winglang/sdk.cloud.IFunctionClient) - -Represents a function. - -#### Initializers - -```wing -bring cloud; - -new cloud.Function(inflight: ~Inflight, props?: FunctionProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| inflight | Inflight | *No description.* | -| props | FunctionProps | *No description.* | - ---- - -##### `inflight`Required - -- *Type:* Inflight - ---- - -##### `props`Optional - -- *Type:* FunctionProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_environment | Add an environment variable to the function. | - ---- - -##### `add_environment` - -```wing -add_environment(_key: str, _value: str): void -``` - -Add an environment variable to the function. - -###### `_key`Required - -- *Type:* str - ---- - -###### `_value`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| env | MutMap<str> | Returns the set of environment variables for this function. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `env`Required - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> - -Returns the set of environment variables for this function. - ---- - - -### FunctionBase - -- *Implements:* IInflightHost - -Functionality shared between all `Function` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.FunctionBase(inflight: ~Inflight, props: FunctionProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| inflight | Inflight | *No description.* | -| props | FunctionProps | *No description.* | - ---- - -##### `inflight`Required - -- *Type:* Inflight - ---- - -##### `props`Required - -- *Type:* FunctionProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| add_environment | Add an environment variable to the function. | - ---- - -##### `add_environment` - -```wing -add_environment(name: str, value: str): void -``` - -Add an environment variable to the function. - -###### `name`Required - -- *Type:* str - ---- - -###### `value`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | -| env | MutMap<str> | Returns the set of environment variables for this function. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - -##### `env`Required - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> - -Returns the set of environment variables for this function. - ---- - - -### JsonFile - -Represents a text file that should be synthesized in the app's outdir. - -#### Initializers - -```wing -bring fs; - -new fs.JsonFile(file_path: str, props: JsonFileProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| file_path | str | *No description.* | -| props | JsonFileProps | *No description.* | - ---- - -##### `file_path`Required - -- *Type:* str - ---- - -##### `props`Required - -- *Type:* JsonFileProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| save | Render the contents of the file and save it to the user's file system. | - ---- - -##### `save` - -```wing -save(outdir: str): void -``` - -Render the contents of the file and save it to the user's file system. - -###### `outdir`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| file_path | str | The file's relative path to the output directory. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `file_path`Required - -```wing -file_path: str; -``` - -- *Type:* str - -The file's relative path to the output directory. - ---- - - -### Logger - -**Inflight client:** [@winglang/sdk.cloud.ILoggerClient](#@winglang/sdk.cloud.ILoggerClient) - -A cloud logging facility. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| print | Logs a message (preflight). | - ---- - -##### `print` - -```wing -print(message: str): void -``` - -Logs a message (preflight). - -###### `message`Required - -- *Type:* str - -The message to log. - ---- - -#### Static Functions - -| **Name** | **Description** | -| --- | --- | -| register | Create a logger and register it to the given scope. | - ---- - -##### `register` - -```wing -bring cloud; - -cloud.Logger.register() -``` - -Create a logger and register it to the given scope. - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### LoggerBase - -Functionality shared between all `Logger` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.LoggerBase() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| print | Logs a message (preflight). | - ---- - -##### `print` - -```wing -print(message: str): void -``` - -Logs a message (preflight). - -###### `message`Required - -- *Type:* str - -The message to log. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### Queue - -**Inflight client:** [@winglang/sdk.cloud.IQueueClient](#@winglang/sdk.cloud.IQueueClient) - -Represents a queue. - -#### Initializers - -```wing -bring cloud; - -new cloud.Queue(props?: QueueProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | QueueProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* QueueProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Create a function to consume messages from this queue. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function -``` - -Create a function to consume messages from this queue. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* QueueOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### QueueBase - -Functionality shared between all `Queue` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.QueueBase(props?: QueueProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | QueueProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* QueueProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Create a function to consume messages from this queue. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: QueueOnMessageProps): Function -``` - -Create a function to consume messages from this queue. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* QueueOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### Schedule - -**Inflight client:** [@winglang/sdk.cloud.IScheduleClient](#@winglang/sdk.cloud.IScheduleClient) - -Represents a schedule. - -#### Initializers - -```wing -bring cloud; - -new cloud.Schedule(props?: ScheduleProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | ScheduleProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* ScheduleProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_tick | Create a function that runs when receiving the scheduled event. | - ---- - -##### `on_tick` - -```wing -on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function -``` - -Create a function that runs when receiving the scheduled event. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* ScheduleOnTickProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### ScheduleBase - -Functionality shared between all `Schedule` implementations. - -#### Initializers - -```wing -bring cloud; - -new cloud.ScheduleBase(props?: ScheduleProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | ScheduleProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* ScheduleProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_tick | Create a function that runs when receiving the scheduled event. | - ---- - -##### `on_tick` - -```wing -on_tick(inflight: ~Inflight, props?: ScheduleOnTickProps): Function -``` - -Create a function that runs when receiving the scheduled event. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* ScheduleOnTickProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### TextFile - -Represents a text file that should be synthesized in the app's outdir. - -#### Initializers - -```wing -bring fs; - -new fs.TextFile(file_path: str, props?: TextFileProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| file_path | str | *No description.* | -| props | TextFileProps | *No description.* | - ---- - -##### `file_path`Required - -- *Type:* str - ---- - -##### `props`Optional - -- *Type:* TextFileProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| save | Render the contents of the file and save it to the user's file system. | -| add_line | Append a line to the text file's contents. | - ---- - -##### `save` - -```wing -save(outdir: str): void -``` - -Render the contents of the file and save it to the user's file system. - -###### `outdir`Required - -- *Type:* str - ---- - -##### `add_line` - -```wing -add_line(line: str): void -``` - -Append a line to the text file's contents. - -###### `line`Required - -- *Type:* str - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| file_path | str | The file's relative path to the output directory. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `file_path`Required - -```wing -file_path: str; -``` - -- *Type:* str - -The file's relative path to the output directory. - ---- - - -### Topic - -**Inflight client:** [@winglang/sdk.cloud.ITopicClient](#@winglang/sdk.cloud.ITopicClient) - -Represents a topic. - -#### Initializers - -```wing -bring cloud; - -new cloud.Topic(props?: TopicProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | TopicProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* TopicProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Run an inflight whenever an message is published to the topic. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function -``` - -Run an inflight whenever an message is published to the topic. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* TopicOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -### TopicBase - -Topic base class. - -#### Initializers - -```wing -bring cloud; - -new cloud.TopicBase(props?: TopicProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| props | TopicProps | *No description.* | - ---- - -##### `props`Optional - -- *Type:* TopicProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| on_message | Run an inflight whenever an message is published to the topic. | - ---- - -##### `on_message` - -```wing -on_message(inflight: ~Inflight, props?: TopicOnMessageProps): Function -``` - -Run an inflight whenever an message is published to the topic. - -###### `inflight`Required - -- *Type:* Inflight - ---- - -###### `props`Optional - -- *Type:* TopicOnMessageProps - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | -| stateful | bool | Whether a resource is stateful, i.e. it stores information that is not defined by your application. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -##### `stateful`Required - -```wing -stateful: bool; -``` - -- *Type:* bool - -Whether a resource is stateful, i.e. it stores information that is not defined by your application. - -A non-stateful resource does not remember information about past -transactions or events, and can typically be replaced by a cloud provider -with a fresh copy without any consequences. - ---- - - -## Structs - -### BucketDeleteOptions - -Interface for delete method inside `Bucket`. - -#### Initializer - -```wing -bring cloud; - -let bucket_delete_options = cloud.BucketDeleteOptions{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| must_exist | bool | Check failures on the method and retrieve errors if any. | - ---- - -##### `must_exist`Optional - -```wing -must_exist: bool; -``` - -- *Type:* bool -- *Default:* false - -Check failures on the method and retrieve errors if any. - ---- - -### BucketProps - -Properties for `Bucket`. - -#### Initializer - -```wing -bring cloud; - -let bucket_props = cloud.BucketProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| public | bool | Whether the bucket's objects should be publicly accessible. | - ---- - -##### `public`Optional - -```wing -public: bool; -``` - -- *Type:* bool -- *Default:* false - -Whether the bucket's objects should be publicly accessible. - ---- - -### CounterProps - -Properties for `Counter`. - -#### Initializer - -```wing -bring cloud; - -let counter_props = cloud.CounterProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| initial | num | The initial value of the counter. | - ---- - -##### `initial`Optional - -```wing -initial: num; -``` - -- *Type:* num -- *Default:* 0 - -The initial value of the counter. - ---- - -### FunctionProps - -Properties for `Function`. - -This is the type users see when constructing a cloud.Function instance. - -#### Initializer - -```wing -bring cloud; - -let function_props = cloud.FunctionProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| env | MutMap<str> | Environment variables to pass to the function. | -| memory | num | The amount of memory to allocate to the function, in MB. | -| timeout | Duration | The maximum amount of time the function can run. | - ---- - -##### `env`Optional - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> -- *Default:* No environment variables. - -Environment variables to pass to the function. - ---- - -##### `memory`Optional - -```wing -memory: num; -``` - -- *Type:* num -- *Default:* 128 - -The amount of memory to allocate to the function, in MB. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* 1m - -The maximum amount of time the function can run. - ---- - -### JsonFileProps - -Props for `JsonFile`. - -#### Initializer - -```wing -bring fs; - -let json_file_props = fs.JsonFileProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| obj | any | The object that will be serialized into the file during synthesis. | - ---- - -##### `obj`Required - -```wing -obj: any; -``` - -- *Type:* any - -The object that will be serialized into the file during synthesis. - ---- - -### QueueOnMessageProps - -Options for Queue.onMessage. - -#### Initializer - -```wing -bring cloud; - -let queue_on_message_props = cloud.QueueOnMessageProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| env | MutMap<str> | Environment variables to pass to the function. | -| memory | num | The amount of memory to allocate to the function, in MB. | -| timeout | Duration | The maximum amount of time the function can run. | -| batch_size | num | The maximum number of messages to send to subscribers at once. | - ---- - -##### `env`Optional - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> -- *Default:* No environment variables. - -Environment variables to pass to the function. - ---- - -##### `memory`Optional - -```wing -memory: num; -``` - -- *Type:* num -- *Default:* 128 - -The amount of memory to allocate to the function, in MB. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* 1m - -The maximum amount of time the function can run. - ---- - -##### `batch_size`Optional - -```wing -batch_size: num; -``` - -- *Type:* num -- *Default:* 1 - -The maximum number of messages to send to subscribers at once. - ---- - -### QueueProps - -Properties for `Queue`. - -#### Initializer - -```wing -bring cloud; - -let queue_props = cloud.QueueProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| initial_messages | MutArray<str> | Initialize the queue with a set of messages. | -| timeout | Duration | How long a queue's consumers have to process a message. | - ---- - -##### `initial_messages`Optional - -```wing -initial_messages: MutArray; -``` - -- *Type:* MutArray<str> -- *Default:* [] - -Initialize the queue with a set of messages. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* Duration.fromSeconds(10) - -How long a queue's consumers have to process a message. - ---- - -### ScheduleOnTickProps - -Options for Schedule.onTick. - -#### Initializer - -```wing -bring cloud; - -let schedule_on_tick_props = cloud.ScheduleOnTickProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| env | MutMap<str> | Environment variables to pass to the function. | -| memory | num | The amount of memory to allocate to the function, in MB. | -| timeout | Duration | The maximum amount of time the function can run. | - ---- - -##### `env`Optional - -```wing -env: MutMap; -``` - -- *Type:* MutMap<str> -- *Default:* No environment variables. - -Environment variables to pass to the function. - ---- - -##### `memory`Optional - -```wing -memory: num; -``` - -- *Type:* num -- *Default:* 128 - -The amount of memory to allocate to the function, in MB. - ---- - -##### `timeout`Optional - -```wing -timeout: Duration; -``` - -- *Type:* Duration -- *Default:* 1m - -The maximum amount of time the function can run. - ---- - -### ScheduleProps - -Properties for `Schedule`. - -#### Initializer - -```wing -bring cloud; - -let schedule_props = cloud.ScheduleProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| cron | str | Trigger events according to a cron schedule using the UNIX cron format. | -| rate | Duration | Trigger events at a periodic rate. | - ---- - -##### `cron`Optional - -```wing -cron: str; -``` - -- *Type:* str -- *Default:* undefined - -Trigger events according to a cron schedule using the UNIX cron format. - -[minute] [hour] [day of month] [month] [day of week] - ---- - -*Example* - -```wing -"0/1 * ? * *" -``` - - -##### `rate`Optional - -```wing -rate: Duration; -``` - -- *Type:* Duration -- *Default:* undefined - -Trigger events at a periodic rate. - ---- - -*Example* - -```wing -1m -``` - - -### TextFileProps - -Props for `TextFile`. - -#### Initializer - -```wing -bring fs; - -let text_file_props = fs.TextFileProps{ ... } -``` - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| lines | MutArray<str> | The lines of text that will be serialized into the file during synthesis. | - ---- - -##### `lines`Optional - -```wing -lines: MutArray; -``` - -- *Type:* MutArray<str> -- *Default:* [] - -The lines of text that will be serialized into the file during synthesis. - -They will be joined with newline characters. - ---- - -### TopicOnMessageProps - -Options for `Topic.onMessage`. - -#### Initializer - -```wing -bring cloud; - -let topic_on_message_props = cloud.TopicOnMessageProps{ ... } -``` - - -### TopicProps - -Properties for `Topic`. - -#### Initializer - -```wing -bring cloud; - -let topic_props = cloud.TopicProps{ ... } -``` - - -## Classes - -### CounterClientBase - -- *Implements:* ICounterClient - -Functionality shared between all `CounterClient` implementations regardless of the target. - -#### Initializers - -```wing -bring cloud; - -new cloud.CounterClientBase() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| dec | Decrement the counter, returning the previous value. | -| inc | Increments the counter atomically by a certain amount and returns the previous value. | -| peek | Get the current value of the counter. | -| reset | Reset a counter to a given value. | - ---- - -##### `dec` - -```wing -dec(amount?: num): num -``` - -Decrement the counter, returning the previous value. - -###### `amount`Optional - -- *Type:* num - ---- - -##### `inc` - -```wing -inc(amount?: num): num -``` - -Increments the counter atomically by a certain amount and returns the previous value. - -###### `amount`Optional - -- *Type:* num - ---- - -##### `peek` - -```wing -peek(): num -``` - -Get the current value of the counter. - -Using this API may introduce race conditions since the value can change between -the time it is read and the time it is used in your code. - -##### `reset` - -```wing -reset(value?: num): void -``` - -Reset a counter to a given value. - -###### `value`Optional - -- *Type:* num - ---- - - - - -### Duration - -Represents a length of time. - - -#### Static Functions - -| **Name** | **Description** | -| --- | --- | -| from_hours | Create a Duration representing an amount of hours. | -| from_minutes | Create a Duration representing an amount of minutes. | -| from_seconds | Create a Duration representing an amount of seconds. | - ---- - -##### `from_hours` - -```wing -bring std; - -std.Duration.from_hours(amount: num) -``` - -Create a Duration representing an amount of hours. - -###### `amount`Required - -- *Type:* num - -the amount of Hours the `Duration` will represent. - ---- - -##### `from_minutes` - -```wing -bring std; - -std.Duration.from_minutes(amount: num) -``` - -Create a Duration representing an amount of minutes. - -###### `amount`Required - -- *Type:* num - -the amount of Minutes the `Duration` will represent. - ---- - -##### `from_seconds` - -```wing -bring std; - -std.Duration.from_seconds(amount: num) -``` - -Create a Duration representing an amount of seconds. - -###### `amount`Required - -- *Type:* num - -the amount of Seconds the `Duration` will represent. - ---- - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| hours | num | Return the total number of hours in this Duration. | -| minutes | num | Return the total number of minutes in this Duration. | -| seconds | num | Return the total number of seconds in this Duration. | - ---- - -##### `hours`Required - -```wing -hours: num; -``` - -- *Type:* num - -Return the total number of hours in this Duration. - ---- - -##### `minutes`Required - -```wing -minutes: num; -``` - -- *Type:* num - -Return the total number of minutes in this Duration. - ---- - -##### `seconds`Required - -```wing -seconds: num; -``` - -- *Type:* num - -Return the total number of seconds in this Duration. - ---- - - -### ImmutableArray - -Immutable Array. - -#### Initializers - -```wing -bring std; - -new std.ImmutableArray() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| at | Get the value at the given index. | -| copy | Create an immutable shallow copy of this array. | -| copy_mut | Create a mutable shallow copy of this array. | - ---- - -##### `at` - -```wing -at(index: num): T1 -``` - -Get the value at the given index. - -###### `index`Required - -- *Type:* num - -index of the value to get. - ---- - -##### `copy` - -```wing -copy(): ImmutableArray -``` - -Create an immutable shallow copy of this array. - -##### `copy_mut` - -```wing -copy_mut(): MutableArray -``` - -Create a mutable shallow copy of this array. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| length | num | The length of the array. | - ---- - -##### `length`Required - -```wing -length: num; -``` - -- *Type:* num - -The length of the array. - ---- - - -### ImmutableMap - -Immutable Map. - -#### Initializers - -```wing -bring std; - -new std.ImmutableMap() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this map. | -| copy_mut | Create a mutable shallow copy of this map. | -| get | Returns a specified element from the map. | -| has | Returns a boolean indicating whether an element with the specified key exists or not. | -| size | Returns the number of elements in the map. | - ---- - -##### `copy` - -```wing -copy(): ImmutableMap -``` - -Create an immutable shallow copy of this map. - -##### `copy_mut` - -```wing -copy_mut(): MutableMap -``` - -Create a mutable shallow copy of this map. - -##### `get` - -```wing -get(key: str): T1 -``` - -Returns a specified element from the map. - -If the value that is associated to the provided key is an object, then you will get a reference -to that object and any change made to that object will effectively modify it inside the map. - -###### `key`Required - -- *Type:* str - -The key of the element to return. - ---- - -##### `has` - -```wing -has(key: str): bool -``` - -Returns a boolean indicating whether an element with the specified key exists or not. - -###### `key`Required - -- *Type:* str - -The key of the element to test for presence. - ---- - -##### `size` - -```wing -size(): num -``` - -Returns the number of elements in the map. - -TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 - - - - -### ImmutableSet - -Immutable Set. - -#### Initializers - -```wing -bring std; - -new std.ImmutableSet() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this set. | -| copy_mut | Create a mutable shallow copy of this set. | -| has | Returns a boolean indicating whether an element with the specified value exists in the set. | - ---- - -##### `copy` - -```wing -copy(): ImmutableSet -``` - -Create an immutable shallow copy of this set. - -##### `copy_mut` - -```wing -copy_mut(): MutableSet -``` - -Create a mutable shallow copy of this set. - -##### `has` - -```wing -has(value: T1): bool -``` - -Returns a boolean indicating whether an element with the specified value exists in the set. - -###### `value`Required - -- *Type:* T1 - -The value to test for presence in the Set object. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| size | num | The length of the set. | - ---- - -##### `size`Required - -```wing -size: num; -``` - -- *Type:* num - -The length of the set. - ---- - - -### MutableArray - -Mutable Array. - -#### Initializers - -```wing -bring std; - -new std.MutableArray() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| at | Get the value at the given index. | -| copy | Create an immutable shallow copy of this array. | -| copy_mut | Create a mutable shallow copy of this array. | -| pop | Remove value from end of array. | -| push | Add value to end of array. | - ---- - -##### `at` - -```wing -at(index: num): T1 -``` - -Get the value at the given index. - -###### `index`Required - -- *Type:* num - -index of the value to get. - ---- - -##### `copy` - -```wing -copy(): ImmutableArray -``` - -Create an immutable shallow copy of this array. - -##### `copy_mut` - -```wing -copy_mut(): MutableArray -``` - -Create a mutable shallow copy of this array. - -##### `pop` - -```wing -pop(): T1 -``` - -Remove value from end of array. - -##### `push` - -```wing -push(value: T1): void -``` - -Add value to end of array. - -###### `value`Required - -- *Type:* T1 - -value to add. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| length | num | The length of the array. | - ---- - -##### `length`Required - -```wing -length: num; -``` - -- *Type:* num - -The length of the array. - ---- - - -### MutableMap - -Mutable Map. - -#### Initializers - -```wing -bring std; - -new std.MutableMap() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this map. | -| copy_mut | Create a mutable shallow copy of this map. | -| get | Returns a specified element from the map. | -| has | Returns a boolean indicating whether an element with the specified key exists or not. | -| size | Returns the number of elements in the map. | -| clear | Removes all elements. | -| delete | Removes the specified element from a map. | -| set | Adds or updates an entry in a Map object with a specified key and a value. | - ---- - -##### `copy` - -```wing -copy(): ImmutableMap -``` - -Create an immutable shallow copy of this map. - -##### `copy_mut` - -```wing -copy_mut(): MutableMap -``` - -Create a mutable shallow copy of this map. - -##### `get` - -```wing -get(key: str): T1 -``` - -Returns a specified element from the map. - -If the value that is associated to the provided key is an object, then you will get a reference -to that object and any change made to that object will effectively modify it inside the map. - -###### `key`Required - -- *Type:* str - -The key of the element to return. - ---- - -##### `has` - -```wing -has(key: str): bool -``` - -Returns a boolean indicating whether an element with the specified key exists or not. - -###### `key`Required - -- *Type:* str - -The key of the element to test for presence. - ---- - -##### `size` - -```wing -size(): num -``` - -Returns the number of elements in the map. - -TODO: For now this has to be a method rather than a getter as macros only work on methods https://github.com/winglang/wing/issues/1658 - -##### `clear` - -```wing -clear(): void -``` - -Removes all elements. - -##### `delete` - -```wing -delete(key: str): bool -``` - -Removes the specified element from a map. - -###### `key`Required - -- *Type:* str - -The key. - ---- - -##### `set` - -```wing -set(key: str, value: T1): void -``` - -Adds or updates an entry in a Map object with a specified key and a value. - -TODO: revisit this macro after we support indexed args https://github.com/winglang/wing/issues/1659 - -###### `key`Required - -- *Type:* str - -The key of the element to add. - ---- - -###### `value`Required - -- *Type:* T1 - -The value of the element to add. - ---- - - - - -### MutableSet - -Mutable Set. - -#### Initializers - -```wing -bring std; - -new std.MutableSet() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| copy | Create an immutable shallow copy of this set. | -| copy_mut | Create a mutable shallow copy of this set. | -| has | Returns a boolean indicating whether an element with the specified value exists in the set. | -| add | Add value to set. | -| clear | The clear() method removes all elements from a set. | -| delete | Removes a specified value from a set, if it is in the set. | - ---- - -##### `copy` - -```wing -copy(): ImmutableSet -``` - -Create an immutable shallow copy of this set. - -##### `copy_mut` - -```wing -copy_mut(): MutableSet -``` - -Create a mutable shallow copy of this set. - -##### `has` - -```wing -has(value: T1): bool -``` - -Returns a boolean indicating whether an element with the specified value exists in the set. - -###### `value`Required - -- *Type:* T1 - -The value to test for presence in the Set object. - ---- - -##### `add` - -```wing -add(value: T1): MutableSet -``` - -Add value to set. - -###### `value`Required - -- *Type:* T1 - -value to add. - ---- - -##### `clear` - -```wing -clear(): void -``` - -The clear() method removes all elements from a set. - -##### `delete` - -```wing -delete(value: T1): bool -``` - -Removes a specified value from a set, if it is in the set. - -###### `value`Required - -- *Type:* T1 - -The value to remove from the set. - ---- - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| size | num | The length of the set. | - ---- - -##### `size`Required - -```wing -size: num; -``` - -- *Type:* num - -The length of the set. - ---- - - -### String - -String. - -#### Initializers - -```wing -bring std; - -new std.String() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| at | Returns the character at the specified index. | -| concat | Combines the text of two (or more) strings and returns a new string. | -| contains | Checks if string includes substring. | -| ends | Does this string end with the given searchString? | -| index_of | Returns the index of the first occurrence of searchString found. | -| lowercase | Returns this string in lower case. | -| split | Splits string by separator. | -| starts | Does this string start with the given searchString? | -| substring | Returns a string between indexStart, indexEnd. | -| trim | Removes white spaces from start and end of this string. | -| uppercase | Returns this string in upper case. | - ---- - -##### `at` - -```wing -at(index: num): str -``` - -Returns the character at the specified index. - -###### `index`Required - -- *Type:* num - -position of the character. - ---- - -##### `concat` - -```wing -concat(str_n: str): str -``` - -Combines the text of two (or more) strings and returns a new string. - -###### `str_n`Required - -- *Type:* str - -one or more strings to concatenate to this string. - ---- - -##### `contains` - -```wing -contains(search_string: str): bool -``` - -Checks if string includes substring. - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `ends` - -```wing -ends(search_string: str): bool -``` - -Does this string end with the given searchString? - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `index_of` - -```wing -index_of(search_string: str): num -``` - -Returns the index of the first occurrence of searchString found. - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `lowercase` - -```wing -lowercase(): str -``` - -Returns this string in lower case. - -##### `split` - -```wing -split(separator: str): MutArray -``` - -Splits string by separator. - -###### `separator`Required - -- *Type:* str - -separator to split by. - ---- - -##### `starts` - -```wing -starts(search_string: str): bool -``` - -Does this string start with the given searchString? - -###### `search_string`Required - -- *Type:* str - -substring to search for. - ---- - -##### `substring` - -```wing -substring(index_start: num, index_end?: num): str -``` - -Returns a string between indexStart, indexEnd. - -###### `index_start`Required - -- *Type:* num - -index of the character we slice at. - ---- - -###### `index_end`Optional - -- *Type:* num - -optional - index of the character we end slicing at. - ---- - -##### `trim` - -```wing -trim(): str -``` - -Removes white spaces from start and end of this string. - -##### `uppercase` - -```wing -uppercase(): str -``` - -Returns this string in upper case. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| length | num | The length of the string. | - ---- - -##### `length`Required - -```wing -length: num; -``` - -- *Type:* num - -The length of the string. - ---- - - -### T1 - -Generic type argument. - -This type is replaced at compile time. - -#### Initializers - -```wing -bring std; - -new std.T1() -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | - ---- - - - - - -## Protocols - -### IBucketClient - -- *Implemented By:* IBucketClient - -Inflight interface for `Bucket`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| delete | Delete an existing object using a key from the bucket. | -| get | Retrieve an object from the bucket. | -| list | Retrieve existing objects keys from the bucket. | -| put | Put an object in the bucket. | - ---- - -##### `delete` - -```wing -delete(key: str, opts?: BucketDeleteOptions): void -``` - -**Inflight client:** [true](#true) - -Delete an existing object using a key from the bucket. - -###### `key`Required - -- *Type:* str - -Key of the object. - ---- - -###### `opts`Optional - -- *Type:* BucketDeleteOptions - -Options available for delete an item from a bucket. - ---- - -##### `get` - -```wing -get(key: str): str -``` - -**Inflight client:** [true](#true) - -Retrieve an object from the bucket. - -###### `key`Required - -- *Type:* str - -Key of the object. - ---- - -##### `list` - -```wing -list(prefix?: str): MutArray -``` - -**Inflight client:** [true](#true) - -Retrieve existing objects keys from the bucket. - -###### `prefix`Optional - -- *Type:* str - -Limits the response to keys that begin with the specified prefix. - ---- - -##### `put` - -```wing -put(key: str, body: str): void -``` - -**Inflight client:** [true](#true) - -Put an object in the bucket. - -###### `key`Required - -- *Type:* str - -Key of the object. - ---- - -###### `body`Required - -- *Type:* str - -Content of the object we want to store into the bucket. - ---- - - -### ICounterClient - -- *Implemented By:* CounterClientBase, ICounterClient - -Inflight interface for `Counter`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| dec | Decrement the counter, returning the previous value. | -| inc | Increments the counter atomically by a certain amount and returns the previous value. | -| peek | Get the current value of the counter. | -| reset | Reset a counter to a given value. | - ---- - -##### `dec` - -```wing -dec(amount?: num): num -``` - -**Inflight client:** [true](#true) - -Decrement the counter, returning the previous value. - -###### `amount`Optional - -- *Type:* num - -amount to decrement (default is 1). - ---- - -##### `inc` - -```wing -inc(amount?: num): num -``` - -**Inflight client:** [true](#true) - -Increments the counter atomically by a certain amount and returns the previous value. - -###### `amount`Optional - -- *Type:* num - -amount to increment (default is 1). - ---- - -##### `peek` - -```wing -peek(): num -``` - -**Inflight client:** [true](#true) - -Get the current value of the counter. - -Using this API may introduce race conditions since the value can change between -the time it is read and the time it is used in your code. - -##### `reset` - -```wing -reset(value?: num): void -``` - -**Inflight client:** [true](#true) - -Reset a counter to a given value. - -###### `value`Optional - -- *Type:* num - -value to reset (default is 0). - ---- - - -### IFunctionClient - -- *Implemented By:* IFunctionClient - -Inflight interface for `Function`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| invoke | Invoke the function asynchronously with a given payload. | - ---- - -##### `invoke` - -```wing -invoke(payload: str): str -``` - -**Inflight client:** [true](#true) - -Invoke the function asynchronously with a given payload. - -###### `payload`Required - -- *Type:* str - ---- - - -### IFunctionHandler - -- *Extends:* IResource - -- *Implemented By:* IFunctionHandler - -**Inflight client:** [wingsdk.cloud.IFunctionHandlerClient](#wingsdk.cloud.IFunctionHandlerClient) - -Represents a resource with an inflight "handle" method that can be used to create a `cloud.Function`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### IFunctionHandlerClient - -- *Implemented By:* IFunctionHandlerClient - -Inflight client for `IFunctionHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Entrypoint function that will be called when the cloud function is invoked. | - ---- - -##### `handle` - -```wing -handle(event: str): void -``` - -**Inflight client:** [true](#true) - -Entrypoint function that will be called when the cloud function is invoked. - -###### `event`Required - -- *Type:* str - ---- - - -### ILoggerClient - -- *Implemented By:* ILoggerClient - -Inflight interface for `Logger`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| print | Logs a message. The log will be associated with whichever resource is running the inflight code. | - ---- - -##### `print` - -```wing -print(message: str): void -``` - -**Inflight client:** [true](#true) - -Logs a message. The log will be associated with whichever resource is running the inflight code. - -NOTICE: this is not an async function because it is wrapped by `console.log()`. - -###### `message`Required - -- *Type:* str - -The message to print. - ---- - - -### IQueueClient - -- *Implemented By:* IQueueClient - -Inflight interface for `Queue`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| approx_size | Retrieve the approximate number of messages in the queue. | -| purge | Purge all of the messages in the queue. | -| push | Push a message to the queue. | - ---- - -##### `approx_size` - -```wing -approx_size(): num -``` - -**Inflight client:** [true](#true) - -Retrieve the approximate number of messages in the queue. - -##### `purge` - -```wing -purge(): void -``` - -**Inflight client:** [true](#true) - -Purge all of the messages in the queue. - -##### `push` - -```wing -push(message: str): void -``` - -**Inflight client:** [true](#true) - -Push a message to the queue. - -###### `message`Required - -- *Type:* str - -Payload to send to the queue. - ---- - - -### IQueueOnMessageHandler - -- *Extends:* IResource - -- *Implemented By:* IQueueOnMessageHandler - -**Inflight client:** [wingsdk.cloud.IQueueOnMessageHandlerClient](#wingsdk.cloud.IQueueOnMessageHandlerClient) - -Represents a resource with an inflight "handle" method that can be passed to `Queue.on_message`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### IQueueOnMessageHandlerClient - -- *Implemented By:* IQueueOnMessageHandlerClient - -Inflight client for `IQueueOnMessageHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Function that will be called when a message is received from the queue. | - ---- - -##### `handle` - -```wing -handle(message: str): void -``` - -**Inflight client:** [true](#true) - -Function that will be called when a message is received from the queue. - -###### `message`Required - -- *Type:* str - ---- - - -### IScheduleOnTickHandler - -- *Extends:* IResource - -- *Implemented By:* IScheduleOnTickHandler - -**Inflight client:** [wingsdk.cloud.IScheduleOnTickHandlerClient](#wingsdk.cloud.IScheduleOnTickHandlerClient) - -Represents a resource with an inflight "handle" method that can be passed to `Schedule.on_tick`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### IScheduleOnTickHandlerClient - -- *Implemented By:* IScheduleOnTickHandlerClient - -Inflight client for `IScheduleOnTickHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Function that will be called when a message is received from the schedule. | - ---- - -##### `handle` - -```wing -handle(): void -``` - -**Inflight client:** [true](#true) - -Function that will be called when a message is received from the schedule. - - -### ITopicClient - -- *Implemented By:* ITopicClient - -Inflight interface for `Topic`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| publish | Publish message to topic. | - ---- - -##### `publish` - -```wing -publish(message: str): void -``` - -**Inflight client:** [true](#true) - -Publish message to topic. - -###### `message`Required - -- *Type:* str - -Payload to publish to Topic. - ---- - - -### ITopicOnMessageHandler - -- *Extends:* IResource - -- *Implemented By:* ITopicOnMessageHandler - -**Inflight client:** [wingsdk.cloud.ITopicOnMessageHandlerClient](#wingsdk.cloud.ITopicOnMessageHandlerClient) - -Represents a resource with an inflight "handle" method that can be passed to `Topic.on_message`. - - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| display | Display | Information on how to display a resource in the UI. | - ---- - -##### `node`Required - -```wing -node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `display`Required - -```wing -display: Display; -``` - -- *Type:* Display - -Information on how to display a resource in the UI. - ---- - -### ITopicOnMessageHandlerClient - -- *Implemented By:* ITopicOnMessageHandlerClient - -Inflight client for `ITopicOnMessageHandler`. - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| handle | Function that will be called when a message is received from the topic. | - ---- - -##### `handle` - -```wing -handle(event: str): void -``` - -**Inflight client:** [true](#true) - -Function that will be called when a message is received from the topic. - -###### `event`Required - -- *Type:* str - ---- - - From 899bbaab0c4eb72c260180626494ed01cad708fc Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 17:18:36 +0300 Subject: [PATCH 11/20] add test `inflight_reassign` and fix errors --- examples/tests/invalid/inflight_reassign.w | 10 ++++++++++ libs/wingc/src/type_check.rs | 9 ++++----- 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 examples/tests/invalid/inflight_reassign.w diff --git a/examples/tests/invalid/inflight_reassign.w b/examples/tests/invalid/inflight_reassign.w new file mode 100644 index 00000000000..a38e40a40d8 --- /dev/null +++ b/examples/tests/invalid/inflight_reassign.w @@ -0,0 +1,10 @@ +let var xvar = "hello"; +let ylet = 123; + +inflight () => { + xvar = "hi"; +//^^^^ Variable cannot be reassigned from inflight + + ylet = 456; +//^^^^ Variable is not reassignable +}; \ No newline at end of file diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 64277589390..3f28be1d506 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -2435,12 +2435,11 @@ impl<'a> TypeChecker<'a> { if let ExprKind::Reference(r) = &variable.kind { let (var, _) = self.resolve_reference(&r, env); - if var_phase == Phase::Preflight && env.phase == Phase::Inflight { + + if !var_type.is_unresolved() && !var.reassignable { + self.spanned_error(variable, "Variable is not reassignable".to_string()); + } else if var_phase == Phase::Preflight && env.phase == Phase::Inflight { self.spanned_error(stmt, "Variable cannot be reassigned from inflight".to_string()); - } else { - if !var_type.is_unresolved() && !var.reassignable { - self.spanned_error(stmt, "Variable is not reassignable".to_string()); - } } } From 4cae383c3698a42e31db1169bac122ee2549b484 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 17:22:00 +0300 Subject: [PATCH 12/20] update snaps --- tools/hangar/__snapshots__/invalid.ts.snap | 34 ++++++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index d13469760af..91c4e07bfef 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -765,6 +765,28 @@ exports[`inflight_class_interface_structural_typing.w 1`] = ` +Tests 1 failed (1) +Test Files 1 failed (1) +Duration " +`; + +exports[`inflight_reassign.w 1`] = ` +"error: Variable cannot be reassigned from inflight + --> ../../../examples/tests/invalid/inflight_reassign.w:5:3 + | +5 | xvar = \\"hi\\"; + | ^^^^^^^^^^^^ Variable cannot be reassigned from inflight + + +error: Variable is not reassignable + --> ../../../examples/tests/invalid/inflight_reassign.w:8:3 + | +8 | ylet = 456; + | ^^^^ Variable is not reassignable + + + + Tests 1 failed (1) Test Files 1 failed (1) Duration " @@ -1260,7 +1282,7 @@ error: Variable is not reassignable --> ../../../examples/tests/invalid/optionals.w:46:3 | 46 | hi = \\"bye\\"; - | ^^^^^^^^^^^ Variable is not reassignable + | ^^ Variable is not reassignable @@ -1343,35 +1365,35 @@ exports[`reassign_to_nonreassignable.w 1`] = ` --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:3:1 | 3 | x = x + 1; - | ^^^^^^^^^^ Variable is not reassignable + | ^ Variable is not reassignable error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:28:5 | 28 | this.f = this.f + 1; - | ^^^^^^^^^^^^^^^^^^^^ Variable is not reassignable + | ^^^^^^ Variable is not reassignable error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:5 | 30 | this.innerR.inner = 2; - | ^^^^^^^^^^^^^^^^^^^^^^ Variable is not reassignable + | ^^^^^^^^^^^^^^^^^ Variable is not reassignable error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:35:5 | 35 | this.inflightF = this.inflightF + 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Variable is not reassignable + | ^^^^^^^^^^^^^^ Variable is not reassignable error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:42:3 | 42 | arg = 0; - | ^^^^^^^^ Variable is not reassignable + | ^^^ Variable is not reassignable From 06dee2f81da2fdbcd84080847b72880b8a54aae0 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 30 Jun 2023 14:47:28 +0000 Subject: [PATCH 13/20] chore: self mutation Signed-off-by: monada-bot[bot] --- libs/wingc/src/type_check.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 3f28be1d506..7be9034f6b9 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3697,7 +3697,7 @@ impl<'a> TypeChecker<'a> { name: Symbol::global(udt.full_path_str()), type_: t, reassignable: false, - phase: phase.clone(), + phase: phase, kind: VariableKind::Type, }, phase, @@ -3848,7 +3848,7 @@ impl<'a> TypeChecker<'a> { property, ), Type::Struct(ref s) => self.get_property_from_class_like(s, property), - _ => self.spanned_error_with_var(property, format!("Property not found")).0, + _ => self.spanned_error_with_var(property, "Property not found".to_string()).0, } } @@ -4079,14 +4079,14 @@ where pub fn resolve_udt_from_expr(expr: &Expr) -> Result<&UserDefinedType, TypeError> { let ExprKind::Reference(ref r) = expr.kind else { return Err(TypeError { - message: format!("Expected expression to be a reference"), + message: "Expected expression to be a reference".to_string(), span: expr.span.clone(), }); }; let Reference::TypeReference(udt) = r else { return Err(TypeError { - message: format!("Expected reference to be a reference to a type"), + message: "Expected reference to be a reference to a type".to_string(), span: expr.span.clone(), }); }; From af789dca8eb539a7229fad3b4351a7cecfdfb024 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 30 Jun 2023 15:10:00 +0000 Subject: [PATCH 14/20] chore: self mutation Signed-off-by: monada-bot[bot] --- libs/wingc/src/type_check.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 7be9034f6b9..b97f7ecf6dc 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3848,7 +3848,11 @@ impl<'a> TypeChecker<'a> { property, ), Type::Struct(ref s) => self.get_property_from_class_like(s, property), - _ => self.spanned_error_with_var(property, "Property not found".to_string()).0, + _ => { + self + .spanned_error_with_var(property, "Property not found".to_string()) + .0 + } } } From 96cc4b8166cc38d905f3943c3da458863dbf13b6 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 21:11:15 +0300 Subject: [PATCH 15/20] Update libs/wingc/src/type_check.rs Co-authored-by: Chris Rybicki --- libs/wingc/src/type_check.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index b97f7ecf6dc..9d3450e6b75 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3333,7 +3333,6 @@ impl<'a> TypeChecker<'a> { reassignable, phase: flight, kind, - .. }) => { // Replace type params in function signatures if let Some(sig) = v.as_function_sig() { From db3bafcf1e6a97b3c25f1d1e2d44515a02cf5b71 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 21:11:34 +0300 Subject: [PATCH 16/20] Update libs/wingc/src/type_check.rs Co-authored-by: Chris Rybicki --- libs/wingc/src/type_check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 9d3450e6b75..049af6d0cef 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -1168,7 +1168,7 @@ impl Types { self.resource_base_type.unwrap() } - /// Stores the type of a given expression node. + /// Stores the type and phase of a given expression node. pub fn assign_type_to_expr(&mut self, expr: &Expr, type_: TypeRef, phase: Phase) { let expr_idx = expr.id; if self.type_for_expr.len() <= expr_idx { From 7113d6f081431579427588d64628987c0abf9a35 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 21:55:52 +0300 Subject: [PATCH 17/20] fix diagnostics of base classes --- examples/tests/invalid/class.w | 4 ++-- libs/wingc/src/ast.rs | 6 ++---- libs/wingc/src/type_check.rs | 14 ++++++++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/examples/tests/invalid/class.w b/examples/tests/invalid/class.w index 7ebad6ef0e6..38771f3acd7 100644 --- a/examples/tests/invalid/class.w +++ b/examples/tests/invalid/class.w @@ -72,11 +72,11 @@ class C7 extends x { struct S1 {} class C8 extends S1 { - //^^ Preflight class C8's parent is not a class + //^^ Expected "S1" to be a class } class C11 extends C11 { - //^^^ Class cannot extend itself + //^^^ Unknown symbol "C11" } class Student { diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index a528f25dc45..2334fb3092c 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -618,12 +618,10 @@ pub enum Reference { property: Symbol, optional_accessor: bool, }, + /// A reference to a type (e.g. `std.Json` or `MyResource` or `aws.s3.Bucket`) TypeReference(UserDefinedType), /// A reference to a member inside a type: `MyType.x` or `MyEnum.A` - TypeMember { - typeobject: Box, - property: Symbol, - }, + TypeMember { typeobject: Box, property: Symbol }, } impl Display for Reference { diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 049af6d0cef..9f48c604c7f 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -1322,7 +1322,6 @@ impl<'a> TypeChecker<'a> { self.validate_type_in(exp_type, &self.types.stringables(), interpolated_expr); } }); - // TODO: do we need to determine the phase based on the inner expressions? (self.types.string(), Phase::Independent) } Literal::Number(_) => (self.types.number(), Phase::Independent), @@ -3681,8 +3680,10 @@ impl<'a> TypeChecker<'a> { } } Reference::TypeReference(udt) => { - let Ok(t) = self.resolve_user_defined_type(udt, env, self.statement_idx) else { - return self.spanned_error_with_var(udt, format!("Unable to resolve type \"{}\"", udt)); + let result = self.resolve_user_defined_type(udt, env, self.statement_idx); + let t = match result { + Err(e) => return self.spanned_error_with_var(udt, e.message), + Ok(t) => t, }; let phase = if let Some(c) = t.as_class() { @@ -3919,6 +3920,11 @@ impl<'a> TypeChecker<'a> { let (parent_type, _) = self.type_check_exp(&parent_expr, env); + // bail out if we could not resolve the parent type + if parent_type.is_unresolved() { + return (None, None); + } + // Safety: we return from the function above so parent_udt cannot be None let parent_udt = resolve_udt_from_expr(parent_expr).unwrap(); @@ -3942,7 +3948,7 @@ impl<'a> TypeChecker<'a> { } } else { report_diagnostic(Diagnostic { - message: format!("Base class \"{}\" is not a class", parent_type), + message: format!("Expected \"{}\" to be a class", parent_udt), span: Some(parent_expr.span.clone()), }); (None, None) From db6718e265dcdf9cab13890a60d4311c2c57489e Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 21:59:23 +0300 Subject: [PATCH 18/20] restore enum test and update snaps --- examples/tests/invalid/enums.w | 2 +- tools/hangar/__snapshots__/invalid.ts.snap | 71 ++++++---------------- 2 files changed, 19 insertions(+), 54 deletions(-) diff --git a/examples/tests/invalid/enums.w b/examples/tests/invalid/enums.w index 1ad4331794e..d7ea9571c19 100644 --- a/examples/tests/invalid/enums.w +++ b/examples/tests/invalid/enums.w @@ -2,7 +2,7 @@ enum SomeEnum { ONE, TWO, THREE } -// let four = SomeEnum.FOUR; +let four = SomeEnum.FOUR; // ERR ^^^^ Enum "SomeEnum" does not contain value "FOUR" let two = SomeEnum.TWO.TWO; diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index b657b481a3e..008845729f0 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -1,11 +1,11 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`access_hidden_namespace.w 1`] = ` -"error: Unable to resolve type \\"core.NodeJsCode\\" +"error: Unknown symbol \\"core\\" --> ../../../examples/tests/invalid/access_hidden_namespace.w:7:5 | 7 | new core.NodeJsCode(\\"/tmp/test.txt\\"); // This should fail even though \`fs.TextFile\` extends \`core.FileBase\` because we didn't bring in \`core\` explicitly. - | ^^^^^^^^^^^^^^^ Unable to resolve type \\"core.NodeJsCode\\" + | ^^^^^^^^^^^^^^^ Unknown symbol \\"core\\" @@ -294,39 +294,25 @@ error: Preflight field \\"y\\" is not initialized | ^ Preflight field \\"y\\" is not initialized -error: Unable to resolve type \\"x\\" +error: Expected \\"x\\" to be a type but it's a variable --> ../../../examples/tests/invalid/class.w:68:18 | 68 | class C7 extends x { - | ^ Unable to resolve type \\"x\\" + | ^ Expected \\"x\\" to be a type but it's a variable -error: Base class \\"unresolved\\" is not a class - --> ../../../examples/tests/invalid/class.w:68:18 - | -68 | class C7 extends x { - | ^ Base class \\"unresolved\\" is not a class - - -error: Base class \\"S1\\" is not a class +error: Expected \\"S1\\" to be a class --> ../../../examples/tests/invalid/class.w:74:18 | 74 | class C8 extends S1 { - | ^^ Base class \\"S1\\" is not a class + | ^^ Expected \\"S1\\" to be a class -error: Unable to resolve type \\"C11\\" +error: Unknown symbol \\"C11\\" --> ../../../examples/tests/invalid/class.w:78:19 | 78 | class C11 extends C11 { - | ^^^ Unable to resolve type \\"C11\\" - - -error: Class cannot extend itself - --> ../../../examples/tests/invalid/class.w:78:19 - | -78 | class C11 extends C11 { - | ^^^ Class cannot extend itself + | ^^^ Unknown symbol \\"C11\\" error: Expected type to be \\"num\\", but got \\"str\\" instead @@ -1578,18 +1564,11 @@ exports[`sorted_errors_no_span.w 1`] = ` | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead -error: Unable to resolve type \\"b\\" +error: Expected \\"b\\" to be a type but it's a variable --> ../../../examples/tests/invalid/sorted_errors_no_span.w:3:26 | 3 | inflight class c extends b {} - | ^ Unable to resolve type \\"b\\" - - -error: Base class \\"unresolved\\" is not a class - --> ../../../examples/tests/invalid/sorted_errors_no_span.w:3:26 - | -3 | inflight class c extends b {} - | ^ Base class \\"unresolved\\" is not a class + | ^ Expected \\"b\\" to be a type but it's a variable error: Expected type to be \\"num\\", but got \\"str\\" instead @@ -1599,18 +1578,11 @@ error: Expected type to be \\"num\\", but got \\"str\\" instead | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead -error: Unable to resolve type \\"b\\" - --> ../../../examples/tests/invalid/sorted_errors_no_span.w:5:26 - | -5 | inflight class e extends b {} - | ^ Unable to resolve type \\"b\\" - - -error: Base class \\"unresolved\\" is not a class +error: Expected \\"b\\" to be a type but it's a variable --> ../../../examples/tests/invalid/sorted_errors_no_span.w:5:26 | 5 | inflight class e extends b {} - | ^ Base class \\"unresolved\\" is not a class + | ^ Expected \\"b\\" to be a type but it's a variable @@ -1928,18 +1900,18 @@ Duration " `; exports[`unknown_symbol.w 1`] = ` -"error: Unable to resolve type \\"clod.Bucket\\" +"error: Unknown symbol \\"clod\\" --> ../../../examples/tests/invalid/unknown_symbol.w:3:18 | 3 | let bucket = new clod.Bucket(); - | ^^^^^^^^^^^ Unable to resolve type \\"clod.Bucket\\" + | ^^^^^^^^^^^ Unknown symbol \\"clod\\" -error: Unable to resolve type \\"cloudy.Funktion\\" +error: Unknown symbol \\"cloudy\\" --> ../../../examples/tests/invalid/unknown_symbol.w:6:17 | 6 | let funky = new cloudy.Funktion(inflight () => { }); - | ^^^^^^^^^^^^^^^ Unable to resolve type \\"cloudy.Funktion\\" + | ^^^^^^^^^^^^^^^ Unknown symbol \\"cloudy\\" error: Unknown symbol \\"y\\" @@ -1949,18 +1921,11 @@ error: Unknown symbol \\"y\\" | ^ Unknown symbol \\"y\\" -error: Unable to resolve type \\"B\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:28:17 - | -28 | class A extends B { - | ^ Unable to resolve type \\"B\\" - - -error: Base class \\"unresolved\\" is not a class +error: Unknown symbol \\"B\\" --> ../../../examples/tests/invalid/unknown_symbol.w:28:17 | 28 | class A extends B { - | ^ Base class \\"unresolved\\" is not a class + | ^ Unknown symbol \\"B\\" error: Unknown symbol \\"unknown\\" From 7d9a7d224097344cd8f653711b945b37478dacbf Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 30 Jun 2023 22:24:29 +0300 Subject: [PATCH 19/20] fix parser --- libs/wingc/src/parser.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index d49fbb1ccac..81ad87b5082 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -1018,7 +1018,7 @@ impl<'s> Parser<'s> { if last_child.kind() == "." { // even though we're missing a field, we can still parse the rest of the type - let _ = self.add_error::<()>("Expected namespaced type", &last_child); + self.add_error("Expected namespaced type", &last_child); } let mut cursor = type_node.walk(); @@ -1036,7 +1036,7 @@ impl<'s> Parser<'s> { "mutable_container_type" | "immutable_container_type" => { let container_type = self.node_text(&type_node.child_by_field_name("collection_type").unwrap()); match container_type { - "ERROR" => self.add_error("Expected builtin container type", type_node)?, + "ERROR" => self.with_error("Expected builtin container type", type_node)?, builtin => { let udt = UserDefinedType { root: Symbol::global(WINGSDK_STD_MODULE), @@ -1050,7 +1050,7 @@ impl<'s> Parser<'s> { } } } - other => self.add_error(format!("Expected class. Found {}", other), type_node), + other => self.with_error(format!("Expected class. Found {}", other), type_node), } } From 5b91ea5dc8f2359a7149b8b53d3a50fce2d13bf6 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 30 Jun 2023 19:52:31 +0000 Subject: [PATCH 20/20] chore: self mutation Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 82c393061f4..aba7b702922 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -542,7 +542,14 @@ Duration " `; exports[`enums.w 1`] = ` -"error: Property not found +"error: Enum \\"SomeEnum\\" does not contain value \\"FOUR\\" + --> ../../../examples/tests/invalid/enums.w:5:21 + | +5 | let four = SomeEnum.FOUR; + | ^^^^ Enum \\"SomeEnum\\" does not contain value \\"FOUR\\" + + +error: Property not found --> ../../../examples/tests/invalid/enums.w:8:24 | 8 | let two = SomeEnum.TWO.TWO;