Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(compiler): cannot use fromJson on jsii imported struct #4040

Merged
merged 47 commits into from
Sep 8, 2023

Conversation

hasanaburayyan
Copy link
Contributor

@hasanaburayyan hasanaburayyan commented Sep 1, 2023

Summary

So this is actually quite a substantial refactor to how we generate jsonschemas for structs. Previously anytime we encountered a user defined wing struct we generated a json schema file with a schema and fromJson methods. However this meant that we were not created schema files for structs defined outside of the wing code (I.E. JSII imported). With the new changes I am taking a lazy creation approach where we only generate schemas for structs if there are references that would require the schema to exist.

This change also no longer generates a separate file for the schema, instead it creates an instance of a stdlib.std.StructSchema using the jsonschema inline.

The other big change is the removal of the require statements and defs from schemas that were dependent on other schemas. As in take for example this Wing struct:

struct A {
  val: num;
}

struct B {
  data: str;
}

struct C extends A {
  b: B;
}

The struct schema for C used to look like this:

{
        id: "/C",
        type: "object",
        properties: {
          ...require("./A.Struct.js")().jsonSchema().properties,
          b: { "$ref": "#/$defs/B" },
        },
        required: [
          "b",
          ...require("./A.Struct.js")().jsonSchema().required,
        ],
        $defs: {
          "B": { type: "object", "properties": require("./B.Struct.js")().jsonSchema().properties },
          ...require("./A.Struct.js")().jsonSchema().$defs,
        }
      }

Now it looks like this:

{
        id: "/C",
        type: "object",
        properties: {
          b: {
            type: "object",
            properties: {
              data: { type: "string" },
            },
            required: [
              "data",
            ]
          },
          val: { type: "number" },
        },
        required: [
          "b",
          "val",
        ]
      }

Implementation Notes

  1. Lazy creation of schemas, only emit struct schema files if there exists a reference to the struct type in the code.
  2. Schemas no longer consist of require statements for dependent schemas. As in the schemas are now fully self contained.
  3. Pre-Jsification parse of the ast to emit struct files for referenced schemas.

Closes: #3943
Closes: #3790

Checklist

  • Title matches Winglang's style guide
  • Description explains motivation and solution
  • Tests added (always)
  • Docs updated (only required for features)
  • 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.

@hasanaburayyan
Copy link
Contributor Author

hasanaburayyan commented Sep 1, 2023

@MarkMcCulloh @Chriscbr @yoav-steinberg Still have a bug to squash with 2 namespaces that have the same struct def (i.e. A.SomeStuct and B.SomeStruct) will cause collisions. But wanted to get some thoughts on these changes. The description has some notes about the big ideas with these changes. If you get a chance to review, please rip it apart 😁

I could not see a way around building a visitor and emitting structs defs before jsification phase. Its a pretty lightweight visitor.

Im planning to address the namespace issue tomorrow.

@monadabot
Copy link
Contributor

monadabot commented Sep 1, 2023

Console preview environment is available at https://wing-console-pr-4040.fly.dev 🚀

Updated (UTC): 2023-09-08 14:57

@monadabot monadabot added the ⚠️ pr/review-mutation PR has been mutated and will not auto-merge. Clear this label if the changes look good! label Sep 1, 2023
examples/tests/valid/struct_from_json.w Show resolved Hide resolved
libs/wingc/src/struct_schema.rs Show resolved Hide resolved
libs/wingc/src/jsify.rs Outdated Show resolved Hide resolved
libs/wingc/src/jsify.rs Outdated Show resolved Hide resolved
@hasanaburayyan hasanaburayyan force-pushed the hasan/jsii-struct-conversion branch 2 times, most recently from 17c5788 to 43f0b28 Compare September 2, 2023 18:50
@hasanaburayyan hasanaburayyan marked this pull request as ready for review September 2, 2023 19:30
@hasanaburayyan hasanaburayyan requested a review from a team as a code owner September 2, 2023 19:30
@hasanaburayyan
Copy link
Contributor Author

ironed out the namespaces bugs, and did some cleanups should be ready for review now

libs/wingc/src/files.rs Outdated Show resolved Hide resolved
libs/wingc/src/jsify.rs Outdated Show resolved Hide resolved
libs/wingc/src/jsify.rs Outdated Show resolved Hide resolved
libs/wingc/src/lib.rs Outdated Show resolved Hide resolved
libs/wingc/src/struct_schema.rs Outdated Show resolved Hide resolved
libs/wingc/src/struct_schema.rs Show resolved Hide resolved
@hasanaburayyan
Copy link
Contributor Author

hasanaburayyan commented Sep 4, 2023

@yoav-steinberg @Chriscbr Okay so I got in a groove today and might have gone crazy but I just did a refactor on this code. Please let me know your thoughts.

Summary:
I no longer need to emit schema files, rather now Its creating an instance of stdlib.std.StructSchema from the jsonschema objects.

I.E. The following wing code:

struct Foo {
  val: num;
  val2: str;
}

Foo.fromJson({val: 10, val2: "10"});

Just emits this into the prefilight.js

const Foo = $stdlib.std.Struct._createStructSchema({id:"/Foo",type:"object",properties:{val:{type:"number"},val2:{type:"string"},},required:["val","val2",]});

What I like about this is I no longer have to worry about file names and require calls. Also gets rid of a lot of boiler plate.

Also I added the implementation for being able to call .schema() on a struct as such:

struct Foo {
  val: num;
  val2: str;
}

let schema = Foo.schema();
schema.validate({val: 10, val2: "10"});
log(schema.asStr());

docs/docs/04-standard-library/02-std/api-reference.md Outdated Show resolved Hide resolved
docs/docs/04-standard-library/02-std/api-reference.md Outdated Show resolved Hide resolved
docs/docs/04-standard-library/02-std/api-reference.md Outdated Show resolved Hide resolved
docs/docs/04-standard-library/02-std/api-reference.md Outdated Show resolved Hide resolved
libs/wingc/src/struct_schema.rs Show resolved Hide resolved
libs/wingc/src/jsify.rs Outdated Show resolved Hide resolved
libs/wingc/src/jsify.rs Show resolved Hide resolved
examples/tests/valid/struct_from_json.w Show resolved Hide resolved
libs/wingc/src/jsify.rs Show resolved Hide resolved
libs/wingc/src/jsify.rs Show resolved Hide resolved
@Chriscbr
Copy link
Contributor

Chriscbr commented Sep 5, 2023

@hasanaburayyan Looks much better! The inlining solution sounds good to me as well

Copy link
Contributor

@yoav-steinberg yoav-steinberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this. Added a minor comment.
Didn't do an in depth review thought, this time. Hopefully good enough.

libs/wingc/src/struct_schema.rs Show resolved Hide resolved
@hasanaburayyan hasanaburayyan removed the ⚠️ pr/review-mutation PR has been mutated and will not auto-merge. Clear this label if the changes look good! label Sep 7, 2023
@mergify
Copy link
Contributor

mergify bot commented Sep 8, 2023

Thanks for contributing, @hasanaburayyan! This PR will now be added to the merge queue, or immediately merged if hasan/jsii-struct-conversion is up-to-date with main and the queue is empty.

@mergify
Copy link
Contributor

mergify bot commented Sep 8, 2023

Thanks for contributing, @hasanaburayyan! This PR will now be added to the merge queue, or immediately merged if hasan/jsii-struct-conversion is up-to-date with main and the queue is empty.

@mergify mergify bot merged commit a8e0ecb into main Sep 8, 2023
22 checks passed
@mergify mergify bot deleted the hasan/jsii-struct-conversion branch September 8, 2023 15:15
@monadabot
Copy link
Contributor

Congrats! 🚀 This was released in Wing 0.29.9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants