Skip to content

Commit

Permalink
fix(compiler): cant call fromJson on imported structs (#3944)
Browse files Browse the repository at this point in the history
Closes: #3792

Now supports calling fromJson on structs that were brought from other wing files

example: 
file_1.w
```js
struct Person {
	name: str;
}
```

file_2.w
```js
bring "./file1.w" as f1;

let j = { name: "cool" };
f1.Person.fromJson(j);
```

## Checklist

- [x] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/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 [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
hasanaburayyan authored Aug 24, 2023
1 parent f0480cd commit bd45fd5
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 8 deletions.
14 changes: 13 additions & 1 deletion examples/tests/valid/struct_from_json.w
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,16 @@ test "lifting a student" {
assert(studentInflight1.dob.month == 10);
assert(studentInflight1.dob.day == 10);
assert(studentInflight1.dob.year == 2005);
}
}

// bring structs from other files
bring "./subdir/structs.w" as externalStructs;

let jj1 = {
data: {
val: 10
}
};

let externalBar = externalStructs.MyOtherStruct.fromJson(jj1);
assert(externalBar.data.val == 10);
7 changes: 7 additions & 0 deletions examples/tests/valid/subdir/structs.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
struct MyStruct {
val: num;
}

struct MyOtherStruct {
data: MyStruct;
}
10 changes: 6 additions & 4 deletions libs/wingc/src/jsify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,9 @@ impl<'a> JSifier<'a> {
ExprKind::Reference(Reference::InstanceMember { object, .. }) => {
self.jsify_expression(&object, ctx)
},
ExprKind::Reference(Reference::TypeMember { .. }) => {
expr_string.clone().split(".").next().unwrap_or("").to_string()
ExprKind::Reference(Reference::TypeMember { property, .. }) => {
// remove the property name from the expression string
expr_string.split(".").filter(|s| s != &property.name).join(".")
},
_ => expr_string,
}
Expand Down Expand Up @@ -1556,8 +1557,9 @@ fn get_public_symbols(scope: &Scope) -> Vec<Symbol> {
}
// interfaces are bringable, but there's nothing to emit
StmtKind::Interface(_) => {}
// structs are bringable, but there's nothing to emit
StmtKind::Struct { .. } => {}
StmtKind::Struct { name, .. } => {
symbols.push(name.clone());
}
StmtKind::Enum { name, .. } => {
symbols.push(name.clone());
}
Expand Down
2 changes: 0 additions & 2 deletions libs/wingc/src/type_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4593,8 +4593,6 @@ impl<'a> TypeChecker<'a> {
}
}
}
let lookup = env.lookup(&s.name, None);
let type_ = lookup.unwrap().as_type().unwrap();

let new_class = self.hydrate_class_type_arguments(env, WINGSDK_STRUCT, vec![type_]);
let v = self.get_property_from_class_like(new_class.as_class().unwrap(), property, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ module.exports = function({ $stdlib }) {
})({})
;
const Point = require("./Point.Struct.js")($stdlib.std.Struct, $stdlib.core.NodeJsCode.fromInline);
return { Util, Store, Color };
return { Util, Store, Color, Point };
};

```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,67 @@ module.exports = function(stdStruct, fromInline) {

```

## MyOtherStruct.Struct.js
```js
module.exports = function(stdStruct, fromInline) {
class MyOtherStruct {
static jsonSchema() {
return {
id: "/MyOtherStruct",
type: "object",
properties: {
data: { "$ref": "#/$defs/MyStruct" },
},
required: [
"data",
],
$defs: {
"MyStruct": { type: "object", "properties": require("./MyStruct.Struct.js")().jsonSchema().properties },
}
}
}
static fromJson(obj) {
return stdStruct._validate(obj, this.jsonSchema())
}
static _toInflightType(context) {
return fromInline(`require("./MyOtherStruct.Struct.js")(${ context._lift(stdStruct) })`);
}
}
return MyOtherStruct;
};

```

## MyStruct.Struct.js
```js
module.exports = function(stdStruct, fromInline) {
class MyStruct {
static jsonSchema() {
return {
id: "/MyStruct",
type: "object",
properties: {
val: { type: "number" },
},
required: [
"val",
],
$defs: {
}
}
}
static fromJson(obj) {
return stdStruct._validate(obj, this.jsonSchema())
}
static _toInflightType(context) {
return fromInline(`require("./MyStruct.Struct.js")(${ context._lift(stdStruct) })`);
}
}
return MyStruct;
};

```

## Person.Struct.js
```js
module.exports = function(stdStruct, fromInline) {
Expand Down Expand Up @@ -561,6 +622,7 @@ const $stdlib = require('@winglang/sdk');
const $outdir = process.env.WING_SYNTH_DIR ?? ".";
const $wing_is_test = process.env.WING_IS_TEST === "true";
const std = $stdlib.std;
const externalStructs = require("./preflight.structs-1.js")({ $stdlib });
class $Root extends $stdlib.std.Resource {
constructor(scope, id) {
super(scope, id);
Expand Down Expand Up @@ -731,10 +793,24 @@ class $Root extends $stdlib.std.Resource {
}
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:flight school student :)",new $Closure1(this,"$Closure1"));
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:lifting a student",new $Closure2(this,"$Closure2"));
const jj1 = ({"data": ({"val": 10})});
const externalBar = (externalStructs.MyOtherStruct.fromJson(jj1));
{((cond) => {if (!cond) throw new Error("assertion failed: externalBar.data.val == 10")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(externalBar.data.val,10)))};
}
}
const $App = $stdlib.core.App.for(process.env.WING_TARGET);
new $App({ outdir: $outdir, name: "struct_from_json", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth();

```
## preflight.structs-1.js
```js
module.exports = function({ $stdlib }) {
const std = $stdlib.std;
const MyStruct = require("./MyStruct.Struct.js")($stdlib.std.Struct, $stdlib.core.NodeJsCode.fromInline);
const MyOtherStruct = require("./MyOtherStruct.Struct.js")($stdlib.std.Struct, $stdlib.core.NodeJsCode.fromInline);
return { MyStruct, MyOtherStruct };
};

```

0 comments on commit bd45fd5

Please sign in to comment.