feat: support non identifier classnames#309
Conversation
|
96d2d6f to
3e6cbfb
Compare
|
Great work! This is a big change. I'll review it carefully. It may take some time. |
|
FYI: CSS Modules Kit has flaky tests (#301). Even if your implementation is correct, CI may fail. |
|
Looking back at the code, I noticed there was unnecessary code and deleted it 🙏 |
|
@apple-yagi I've made some changes to the main branch—could you please merge or rebase the main branch?
|
It certainly looks like a bit of complex code. I'll think deeply about whether there's a way to replace it with simpler code. |
81f5cfb to
76ca2ba
Compare
76ca2ba to
1340313
Compare
|
@mizdra I believe all functions are now working correctly after fixing the bug in rename. |
…#309 This is the issue fixed in mizdra#317.
| return result; | ||
| } | ||
|
|
||
| export function getDefinitionAndBoundSpan( |
There was a problem hiding this comment.
Honestly, I still don't understand what this function is trying to do. Is it doing something that contributes to supporting non-identifier classnames?
There was a problem hiding this comment.
When type definitions are made into string literals, tsserver cannot return definitions (it might be a bug in some tool, but I don't know). Therefore, I am manually mapping the definitions(I had Codex write the code).
There was a problem hiding this comment.
Hmm, shouldn't we investigate that bug first? If it's a dependency bug and fixable, fixing it is the best approach.
If the dependency bug is difficult to fix or would take a long time to resolve, I think implementing a workaround to bypass it is worthwhile. Otherwise, I'd prefer to avoid implementing a complex workaround.
I'll investigate this bug. At this stage, I suspect it's a bug in tsserver or Volar.js.
There was a problem hiding this comment.
Yes, I agree.
While organizing the discussion, I thought of another implementation method, so I'll create a new Pull Request and commit step by step. When defining types with string literals, I feel that single quotes are also recognized as part of the type. That might be a specification of tsserver (I briefly read the tsserver implementation but couldn't quite understand it).
With that in mind, I'll try implementing it using tsserver.
There was a problem hiding this comment.
Sharing progress.
- I also opened a PR to support non-js identifier tokens.
- [PoC] Support non js identifier token #322
- Unlike @apple-yagi's PR, this one addresses several edge cases.
- Currently, this PR also breaks definitions and references results.
- While implementing the above Pull Request, I found and fixed several bugs. I also performed some refactoring.
- Since the main branch was updated, @apple-yagi's PR is now in conflict. Sorry about that!
- Investigating the issue where definitions and references results break in the following repository:
- https://github.com/mizdra/typescript-volar-span-comparison
- Currently, I believe we need to create an issue in Volar.js and submit a patch. I plan to do that later :)
There was a problem hiding this comment.
Thank you for sharing! The findings in https://github.com/mizdra/typescript-volar-span-comparison are very clear, and I was able to understand what's happening. Great work!
There was a problem hiding this comment.
@apple-yagi I investigated Volar.js's behavior further. It appears Volar.js intentionally does not support overlapping mapping ranges.
While we could submit a feature request, it's uncertain whether it would be accepted. Therefore, implementing a workaround in CSS Modules Kit seems the best approach.
I considered several workarounds, but I think the fourth solution in the link below, "Using multiple mapping objects" is the best approach.
I implemented it in #330. It passes all test cases. I plan to merge this.
...By the way, after creating #330, I noticed that #320 also adopted same solution! I should have reviewed the pull request sooner 🙇 Did the Codex come up with that solution too? If so, that's amazing.
There was a problem hiding this comment.
Even before using Codex, I had an intuitive feeling that double-mapping would work (I later realized that whether quotes are included or not changes when using "go to definition" and "rename symbol" functions: https://github.com/microsoft/TypeScript/blob/022800b0472ecfb8d94ce10e2b51cf01acede27/src/services/rename.ts#L219-L228).
Conversely, in this PR, Codex suggested that it would be better to stop double-mapping midway, so I accepted it. I made the wrong choice...
I apologize if I confused you, mizdra-san, but I'm glad the feature was implemented! Thank you very much!
There was a problem hiding this comment.
I knew Volar.js was behaving strangely, but I couldn't figure out the specific cause until I read mizdra's report, which helped me understand it. I never thought there would be issues similar to ours, so I didn't even bother looking for them 😅
There was a problem hiding this comment.
That's amazing intuition! I struggled to come up with that idea myself.
Anyway, I'm glad we got the feature implemented. Thanks for building the PoC!
There was a problem hiding this comment.
I refactored dts-generator.ts to avoid breaking the code (1340313...12f5b4b). Additionally, I fixed the regression (c4dbe5b). As a result, it seems adding new mappings is no longer necessary.
By the way, you explained the following in #309 (comment):
As an implementation issue, the logic has become complex because we needed to manage mappings doubly
What does "managing mappings doubly" mean? Does it mean one more element is added to the mapping array? Looking at the changes in dts-generator.ts, it doesn't appear that any additional elements are being added to the mapping array.
There was a problem hiding this comment.
@mizdra Sorry, Initially, when I submitted the PR, I thought that both quoted and unquoted mappings were necessary for string literals like styles['a-1'], because tsserver returns spans including quotes
css-modules-kit/packages/core/src/dts-generator.ts
Lines 262 to 275 in 96d2d6f
However, I realized that go-to-definition works even without double mapping because getDefinitionAndBoundSpan normalizes def.name and replaces it with the CSS location (https://github.com/apple-yagi/css-modules-kit/blob/c4dbe5b554281a3501ec0cb6544cbc62875e6ba6/packages/ts-plugin/src/language-service/feature/definition-and-bound-span.ts#L110-L132). Therefore, I removed it.
There was a problem hiding this comment.
Incidentally, performing double mapping allows tsserver's getDefinitionAndBoundSpan to work partially correctly. For example, jumps for styles.a_1; or styles['a-1']; work correctly (this was my original idea). However, bugs occur with duplicate class names like styles.a_2, @import, @value ... from '...';, and symbol renaming, making the implementation increasingly complex.
Background
At a social gathering after a certain study session held in Fukuoka the other day, the topic of css-modules-kit came up. At that time, I heard that css-modules-kit does not allow kebab-case, so I couldn't use it. I investigated whether it was not allowed, and found that it was, so I submitted a PR.
Description
I have modified it to generate type definitions using string literals, referring to #177. This allows defining classnames that are not JS identifiers.
Since namedExports can only use JS identifiers, this will only support defaultExports.
As an implementation issue, the logic has become complex because we needed to manage mappings doubly (one for definition jumps and one for renaming) (this change caused various bugs).
While I believe this feature addition is good for the further adoption of css-modules-kit, I also want to avoid making the code so complex that it becomes unmaintainable in the long run. I would like to respect mizdra's opinion on this 🙏
Related issues
#176
AI Assistance
This PR was written with assistance from Codex (ChatGPT).