marcoroth / stimulus-parser

Statically analyze Stimulus controllers in your project.
https://hotwire.io/ecosystem/tooling/stimulus-parser
MIT License
34 stars 7 forks source link

Invalid Stimulus Controller with multiple layouts/js files #136

Open jaryl opened 4 months ago

jaryl commented 4 months ago

I have two view layouts in my rails app, application and backend, which require a different set of stimulus controllers. I've created the necessary js files for it to include, and have set up my folder structure as such (simplified):

Screenshot 2024-06-03 at 10 47 24 AM

The actual codebase works, it loads the controllers and I can connect them as such. However, the LSP is flagging my data-[controller] attributes as invalid controllers, and the quick fix suggests I put my controllers in an extraneous controllers folder, as such:

Screenshot 2024-06-03 at 10 44 44 AM

How does Stimulus LSP infer which folders to look for controllers, the fact that it's suggesting two potential solutions indicates it does pick up my two configurations. I think that the extra "controllers" folder it requires may be a bug, or if there is a configuration option to change the folders where it thinks controllers should be, I'm not seeing it.

marcoroth commented 4 months ago

Hey @jaryl, thank you for reporting this issue!

As of right now, there is no configuration to configure the LSP/Stimulus Parser on where to look for controllers. The idea is that it should be able to figure it out by itself so you don't have to deal with configs.

In this case it's recognizing the two "controller roots", but is somehow still struggling to properly deal with it. I think the issue might be that you have the "application files" inside of your app/javascript/controllers/ folder, but I'll check if we can handle that somehow.

Where are your controllers? Are they all located in app/javascript/controllers/? And if so, are there also controllers being registered on both Stimulus applications?

Would you mind sharing these files:

Just so we can create a minimal setup and write an integration test for it, like the ones we have here: https://github.com/marcoroth/stimulus-parser/tree/main/test/fixtures

Thank you!

marcoroth commented 4 months ago

I opened a pull request with a failing test https://github.com/marcoroth/stimulus-parser/pull/137 for this

jaryl commented 4 months ago

Thanks for the quick turnaround on this @marcoroth ❤️

Both application.js is exactly the same stock file:

import { Application } from "@hotwired/stimulus"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus   = application

export { application }

And the only difference between the index.js files will be the load path:

import { application } from "./application"

import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers/application", application)

For the other file:

// ...
eagerLoadControllersFrom("controllers/backend", application)

Where are your controllers? Are they all located in app/javascript/controllers/? And if so, are there also controllers being registered on both Stimulus applications?

I put my controllers in:

If I do have controllers I need in both, I expect to create a app/javascript/controllers/common/ folder, and load that via eagerLoadControllersFrom as well, but I have not done that yet, as this is a relatively new app.

marcoroth commented 4 months ago

Thanks for the feedback, @jaryl! This helps!

Am I right to assume that your controllers for the application are in app/javascript/controllers/application/ and the controllers for the backend are in app/javascript/controllers/backend/?

jaryl commented 4 months ago

Yes you are right! I updated the above comment with more deets.

marcoroth commented 4 months ago

Awesome, thanks! I'll check what I can do!

I think detecting the controllers/applications should be straightforward, but I'm not sure how we would figure out which "Stimulus application" is applicable for which view file.

Do you also have a clear separation/any pattern for the view files?

jaryl commented 4 months ago

In the layout files, I include the precompiled js as such:

<%= javascript_importmap_tags "application" %> for application.html.erb <%= javascript_importmap_tags "backend" %> for backend.html.erb

Loosely speaking, all the "backend" view templates will reside in the backend namespace, but the "application" ones will just be where we expect them to be.

I see how this can be tricky to make any concrete determination where the controllers should be in a non-fragile way, especially if the design in my case is to isolate "application" and "backend" as two stimulus apps, which may not be how other codebases are structured.

If anything I also expect the parser to work in a more general, non-surprising manner, which could be as straight forward as supporting all detected controllers wherever they may be.

Of course, it'd be awesome to see how some logic could be introduced to help with isloation based on folder structure; other apps I've worked on include separation into rails engines, so the challenge is finding something that works in different configurations.