- changed status to open
Override Detection Fails with Mixins in Class Inheritance
The IDE correctly identifies overridden properties and methods in a child class when inheriting from a base class. However, as soon as a mixin is introduced alongside class inheritance, the override detection stops working. This makes it harder to determine if a child class properly overrides properties or methods from either the mixin or the base class.
Expected Behavior: The IDE should display overridden methods and properties consistently, regardless of whether the class inherits from a base class, uses a mixin, or both.
Actual Behavior: The IDE fails to detect overridden properties and methods when a mixin is applied alongside a base class.
Environment:
- IDE version: IntelliJ IDEA 2024.2.4 (Ultimate Edition)
- Illuminated Cloud Version 2.3.3.8
- Operating system: Mac OS Sequoia 15.1.1 (24B91)
Comments (12)
-
repo owner -
repo owner Actually I think I figured it out. If all goes well, I’ll be committing a fix for the next build shortly.
-
reporter Nice! After looking into this more, I noticed that the TypeScript plugin in IntelliJ detects overrides for base class functions or properties even when a mixin is applied. It will be great for IlluminatedCloud to have this same behavior. IntelliJ doesn't currently seem to detect when mixin properties or functions are overridden, although I think it should. Having that functionality in IlluminatedCloud will definitely make working with mixins much easier.
Looking forward to seeing the fix in action—thanks again for the quick turnaround!
Attaching my test below.
-
repo owner - changed status to resolved
Delivered in 2.3.4.0.
-
reporter I am not seeing it working, if you notice when I add a mixin the icons showing that something is being overridden are not showing up as soon as I add the mixin. Should I open a new issue or this can be reopen?
-
repo owner To be clear about what was fixed in this build, it was specifically
NavigationMixin
and not anything more general than that.If you’re seeing other issues with mixin behavior in JavaScript, let’s try to see whether it’s something IC-specific or more general to the JetBrains IDE’s JavaScript/TypeScript support. If you create a non-IC project and apply the same mixin pattern, does it work properly or not? If not, you’ll likely need to log a bug with JetBrains. If it works outside of IC and the exact same pattern does not work in an IC project, please provide a standalone reproducible example so I can take a look at what the difference might be.
-
reporter yeah here’s an example of a Typescript Project. After applying a Mixin to an inherited class I can still see that the icon showing that the greet method from the Base Class is being overridden.
-
repo owner And that exact same code doesn’t work the same way in IC? Can you provide it as text instead of as an image?
-
reporter Sure, here’s same exact code for both Typescript and LWC.
Typescript:
type Constructor<T = {}> = new (...args: any[]) => T; function LoggerMixin<T extends Constructor>(Base: T) { return class extends Base { log(message: string): void { console.log(`[LOG]: ${message}`); } }; } class BaseClass { prop = 1; greet() { console.log("Hello from BaseClass!"); } } class EnhancedClass extends LoggerMixin(BaseClass) { prop = 2; log(message: string) { console.log(`[EnhancedClass LOG]: ${message}`); } greet(): void { this.log("Hello from EnhancedClass!"); } doSomething(): void { this.log("Doing something..."); } } const instance = new EnhancedClass(); instance.greet(); instance.doSomething();
LWC:
import { LightningElement } from "lwc"; class BaseClass extends LightningElement { prop = 1; greet() { console.log("Hello from BaseClass!"); } } function LoggerMixin (Base) { return class extends Base { log(message) { console.log(`[LOG]: ${message}`); } } } export default class EnhancedClass extends LoggerMixin(BaseClass) { prop = 2; log(message) { console.log(`[EnhancedClass LOG]: ${message}`); } greet() { this.log("Hello from EnhancedClass!"); } doSomething() { this.log("Doing something..."); } }
the expectations is that the greet method shows the overridden icon like in Typescript
-
repo owner Thanks. I’m not sure I asked the question quite correctly. Let me try again. If you create a 100% pure JavaScript project – nothing to do with Illuminated Cloud – and try to implement this exact same mixin pattern in JavaScript – not TypeScript – do you see the same behavior as if you did the exact same thing in a JavaScript-based LWC component in an Illuminated Cloud project?
When I take the LWC JavaScript version of your code and strip the LWC-specific aspects out of it:
function LoggerMixin (Base) { return class extends Base { log(message) { console.log(`[LOG]: ${message}`); } } } class BaseClass { prop = 1; greet() { console.log("Hello from BaseClass!"); } } class EnhancedClass extends LoggerMixin(BaseClass) { prop = 2; log(message) { console.log(`[EnhancedClass LOG]: ${message}`); } greet() { this.log("Hello from EnhancedClass!"); } doSomething() { this.log("Doing something..."); } } const instance = new EnhancedClass(); instance.greet(); instance.doSomething();
and then I execute that script, I see that overrides are being properly processed:
node issue2694.js [EnhancedClass LOG]: Hello from EnhancedClass! [EnhancedClass LOG]: Doing something...
but I don’t see the JetBrains IDE adding override gutter annotations for the overridden methods.
If I comment out the override of
greet()
inEnhancedClass
and execute the script again, I can confirm proper inheritance/polymorphic behavior:node issue2694.js Hello from BaseClass! [EnhancedClass LOG]: Doing something...
Unless I’m misunderstanding the issue, I think what you’re seeing probably needs to be reported to JetBrains, no? Apologies if I’m still misunderstanding the problem.
-
reporter You are completely right, I didn’t expect to see a difference when using a Javacript Project but it isn’t showing gutter icons for the overridden functions. Thanks for all the help!, I’ll report it to Jetbrains.
-
repo owner Okay…whew! I was thinking I was missing something pretty fundamental there. Yeah, just distill the general reproducible example – no IC2/LWC specific stuff – and log a bug with them.
- Log in to comment
This one is more tricky than the other I just resolved. At least one of the following is causing this issue:
NavigationMixin
inlwc-standard.d.ts
isn't correct for how a mixin should be declared to trigger proper inhertance behavior. This is quite possible as I'm far from a TypeScript expert. Any advice you have on changes that might help there are welcomed.I think I need to rule out the first case before logging a bug with JetBrains on the second. I need to be fully confident that the way the mixin is declared should imply an inheritance relationship with the mixin parameter type and it's not properly working.