Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Move React ppx from compiler repo, add tests #124

Merged
merged 9 commits into from
Sep 26, 2020

Conversation

jchavarri
Copy link
Contributor

@jchavarri jchavarri commented Aug 30, 2020

I find myself wanting to contribute to React ppx but always end up giving up because of the lack of infrastructure. By moving the file here, we can leverage the testing infrastructure and keeping it more in sync with the parser.

If this makes sense and gets merged, I will update the compiler repo to read from new file.

Hopefully this change makes sense as well from organizational perspective, as the React ppx is a syntax transformation.

Summary of changes:

Thanks to these changes, I already found 2 bugs:

  • Comments at the top of the file are placed in the wrong position
  • <Foo.bar /> elements are not supported by new parser

@IwanKaramazow
Copy link
Contributor

@jchavarri This is great! Will take a look at your PR. Long term we want to merge the jsx ppx with the parser itself, i.e. do the syntax transform in the parser.

@jchavarri
Copy link
Contributor Author

Thanks for the responsiveness @IwanKaramazow! Much appreciated :)

Long term we want to merge the jsx ppx with the parser itself.

I realized while working on this that there is no need to have it as a separate step now. It makes sense to do so, although maybe in mid-long term? e.g. 6-12 months. I mention that because I guess that merging the ppx with the parser would potentially break conversion between code in Reason and ReScript syntaxes? 🤔 Which is really useful while this transitions happens.

Also, I don't know if it's possible, but it'd be great to keep it as a separate module, so that tools like https://jchavarri.github.io/ppx-explorer/ that rely on a PPX-like API can keep updates with upstream easily, e.g here.

@chenglou
Copy link
Member

Hey Javier! It's been a while
We're gonna pause this specifically, because the React PPX might change in the future (cc @rickyvetter). Switching version without breakage would require a big syntax-level switch, which would need some consideration.

@jchavarri
Copy link
Contributor Author

@chenglou hey! long time indeed :)

Could you elaborate, please? This PR doesn't change the ppx semantics, and it does not contain any breaking changes in the ppx code. All changes in Reactjs_jsx_ppx module are purely cosmetic (formatting, add reanalyze @raise attributes etc).

If there is some breaking change planned for the future for the ppx, this PR should actually help @rickyvetter and any other authors build and release that change, because once there are more tests, we will know exactly what cases are breaking after the change.

In other words, if this PR gets merged, nobody should notice anything, except the ppx maintainers and contributors, who would get a quality of life improvement thanks to the ppx now being part of the testing infrastructure in this repo.

@jchavarri
Copy link
Contributor Author

Oh, I think I see what you mean. If PPX lives in compiler repo, then it's easy to configure bsconfig flags like it was done with jsx2 and 3. 😞 I didn't think of that.

Maybe the parser could offer a way to switch between syntaxes per file with an attribute, like Reason parser is doing: https://github.com/facebook/reason/pull/2605/files#diff-2f961a549953a72af3a11bb3b36ecc49R4975.

This would be helpful not only for ppx of course, but any breaking syntax change.

@jchavarri
Copy link
Contributor Author

@chenglou I thought more about this. Because syntax is consumed as a git submodule inside compiler repo, nothing would prevent having 2 ppx modules with 2 different versions, and then adding any bsconfig configuration in compiler repo like it's been done in the past. From the compiler perspective, nothing changes either after this change, except it has to read the ppx file from another location. I'm curious to know what @bobzhang thinks as well.

@bobzhang
Copy link
Member

@jchavarri Ricky (@rickyvetter) owns the module.
There's a concern since we still need support the reason syntax, so if we spins off the jsx ppx, how would it affect the old reason syntax

@jchavarri
Copy link
Contributor Author

@bobzhang There should be no impact in old Reason syntax. From the compiler perspective, this PR can be considered for all effects and purposes like moving a file from one folder to another.

@bobzhang
Copy link
Member

bobzhang commented Aug 31, 2020 via email

@jchavarri
Copy link
Contributor Author

jchavarri commented Aug 31, 2020

I created a draft PR to show how minimal the impact downstream for the compiler is: rescript-lang/rescript#4660. Hopefully that and the comments above help unblock the PR 🙏

@rickyvetter
Copy link

I think this move could make maintaining quite a bit cleaner but I want to clarify setup. In the near future we need to make a series of major breaking changes to the ppx and need to ship both versions to the compiler so that folks can update their ppx version independently of their compiler version. Would you propose just exposing both versions as different modules here and then doing the switch logic in the compiler based on config?

@jchavarri
Copy link
Contributor Author

Hey @rickyvetter ! 👋

Would you propose just exposing both versions as different modules here and then doing the switch logic in the compiler based on config?

Yes, exactly. The companion PR in the compiler repo shows how the ppx module is available just like before (see ppx_entry module). I only had to change the linking order so that napkin.cmxa lib (this repo) is linked before the syntax.cmxa lib (that contains the ppx entry in compiler), which depends on it.

If there is a new version of the ppx, there can be another module added next to the one in this PR. Keeping these modules close to the testing infra might be beneficial too to guarantee the migration is smooth, and new tests can also be added from user reports. It seems the compiler still keeps the ppx version handling from bsconfig option.

The only thing that will change from previous setup is that every time there is a fix or update in the ppx, the compiler repo will have to sync the submodule version, while before the file could be just directly updated in-repo. I hope this is not a deal breaker.

Maybe I'm missing something :) Please let me know if there's anything else that I'm not accounting for 👍

@rickyvetter
Copy link

Gotcha. Seems like a win to me. @chenglou you seemed hesitant at first - okay with this plan?

@jchavarri
Copy link
Contributor Author

updated the PR with the following:

  • merge the changes from master
  • add flag -ppx to the main rescript.exe binary (as discussed with @IwanKaramazow offline)
  • remove ppx-related stuff from multiprinter (as jsx ppx seems very unrelated to printing really)
  • skip roundtrip tests for specs that have ppx defined
  • added some test externalWithCustomName that was failing before but now passes, I guess some recent change fixed it.

lmk what you think :)

Copy link
Contributor

@IwanKaramazow IwanKaramazow left a comment

Choose a reason for hiding this comment

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

Left a couple of questions, what do you think?

@@ -243,8 +251,12 @@ module CliArgProcessor = struct
else exit 1
end
else
let parsetree = match ppx with
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we keep this a string and match on the string for now? Does this extra conversion give us something in the end?

Makefile Outdated
@@ -49,6 +50,8 @@ lib/rescript.exe: $(CLI_FILES)

build-native: lib/refmt.exe lib/rescript.exe depend

build-ppx: src/reactjs_jsx_ppx.cmx
Copy link
Contributor

Choose a reason for hiding this comment

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

why does the ppx need a separate build-ppx rule? If it's a part "API_FILES", is this sufficient?

src/res_cli.ml Outdated
@@ -178,6 +179,7 @@ end = struct
let origin = ref ""
let interface = ref false
let report = ref "pretty"
let ppx = ref "none"
Copy link
Contributor

Choose a reason for hiding this comment

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

can we default this to the empty string ""?

src/res_cli.ml Outdated
@@ -227,6 +230,11 @@ module CliArgProcessor = struct
| _ -> false
in

let ppx = match ppx with
Copy link
Contributor

Choose a reason for hiding this comment

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

See comment down, this conversion doesn't add that much value?

tests/runner.js Outdated
@@ -204,15 +202,16 @@ let makeReproducibleFilename = (txt) => {
})
};

global.runPrinter = (dirname) => {
global.runPrinter = (dirname, ppx = "none") => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make this the empty string or just keep it undefined as default value?

tests/runner.js Outdated
@@ -226,7 +225,7 @@ Make sure the test input is syntactically valid.`;
expect(result).toMatchSnapshot();
}

if (process.env.ROUNDTRIP_TEST) {
if (process.env.ROUNDTRIP_TEST && ppx === "none") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a comment here on why we don't run ppx'es in the roundtrip tests?

@@ -0,0 +1,101 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should make a separate folder for ppx tests: tests/ppx/...? What do you think?

with
| Failure txt ->
prerr_string txt;
prerr_newline();
exit 1
| _ -> exit 1
[@@raises exit]
[@@raises Invalid_argument, exit]
Copy link
Contributor

Choose a reason for hiding this comment

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

What raises Invalid_argument?

Copy link
Contributor Author

@jchavarri jchavarri Sep 22, 2020

Choose a reason for hiding this comment

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

The existing react ppx uses that exception to note cases with unexpected situations. I can count at least 19 different places, e.g.

raise
(Invalid_argument
"Key cannot be accessed inside of a component. Don't worry - you can always key a component from its \
parent!")

@jchavarri
Copy link
Contributor Author

@IwanKaramazow I think I tackled all the comments, let me know if there's anything missing :)

Copy link
Contributor

@IwanKaramazow IwanKaramazow left a comment

Choose a reason for hiding this comment

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

@jchavarri Looking good, thank you for all the work.

@IwanKaramazow IwanKaramazow merged commit 9d2be71 into rescript-lang:master Sep 26, 2020
@jchavarri jchavarri deleted the react-ppx branch September 26, 2020 10:12
@bobzhang
Copy link
Member

This is not finished since the removal of jsx ppx is not done in the compiler.

After some thoughts, I think this may make your test workflow more difficult, @rickyvetter , since now you make changes to the ppx, you need update the syntax submodule to test your new changes

@IwanKaramazow
Copy link
Contributor

@bobzhang I'll take care of it.

@jchavarri
Copy link
Contributor Author

@bobzhang I had created a companion PR in rescript-lang/rescript#4660 that included the compiler changes. I didn't continue working on this because @chenglou mentioned on DM a few days after this PR was merged that the move to the PPX to the parser might be rethought / retracted because of the new jsx transform.

@IwanKaramazow
Copy link
Contributor

Let's sync up on this first.

@jchavarri
Copy link
Contributor Author

jchavarri commented Oct 23, 2020

I talked to @IwanKaramazow and these are the steps to take before this is finished:

  1. Update syntax repo so that Reactjs_jsx_ppx becomes Reactjs_jsx_ppx_v3 again, as it will be useful later on, when new JSX ppx versions will be added.
  2. Update Adapt ninja config to use react ppx from upstream syntax submodule rescript#4660 with master and latest syntax, and make sure everything compiles.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants