EmmyLua / IntelliJ-EmmyLua

Lua IDE/Debugger Plugin for IntelliJ IDEA
https://emmylua.github.io
Apache License 2.0
1.75k stars 292 forks source link

[Feature requset] Multiple inheritance in `@class` annotation or add new `@mixin` annotation #588

Open alek13 opened 3 months ago

alek13 commented 3 months ago

Lua is very flexible and allows you to do anything.

Sometimes we need something like multiple inheritance or rather mixins. When several functionality is mixed into the resulting class/table when “designing” the class programmatically.

Example

For example, something like: We have some base "mixer", that can mix different mixins to itself

-- /base_classes/Form/Base.lua

--- @class base_classes.Form.Mixin      @just interface for mixins
--- @field mix_to fun(base_class:base_classes.Form.Base)

--- @class base_classes.Form.Base
local BaseForm  = {
  -- ...
}

--- @param mixin base_classes.Form.Mixin
function BaseForm:mix(mixin)
    mixin.mix_to(self)
end

Then we have some Factory for “designing” the new class programmatically:

-- /base_classes/Form.lua
require('base_classes.Form.Base')

--- Form Class Factory class.
--- This class constructs for you a base form class.
---
--- @class base_classes.Form
--- @field for_node    fun(self:self):self  mixes `base_classes.Form.Mixin.ForNode` into your class
--- @field for_entity  fun(self:self):self  mixes `base_classes.Form.Mixin.ForEntity` into your class
--- @field ...
--- @field ...
local Form = {
    --- @param self  self
    --- @param mixin string
    __index = function(self, mixin)
        if not table.has_key(self.mixins) then
            return self[mixin]
        end

        return function()
            self.now_constructing = self.now_constructing or setmetatable({}, { __index = BaseForm })
            if not self.now_constructing then
                self.now_constructing:mix(ForNode)
            end
        end
    end
}

And we have several mixins for different purposes:

-- /base_classes/Form/Mixin/ForNode.lua

--- @class base_classes.Form.Mixin.ForNode: base_classes.Form.Mixin
--- @field for_node_any_var string
--- @field for_node_any_fun fun(self:base_classes.Form.Base)
--- @field for_node_...
--- @field for_node_...
local ForNode = {}

--- @static
--- @param base_class base_classes.Form.Base
function ForNode.mix_to(base_class)
    base_class.for_node_any_var = 'any_value'
    base_class.for_node_any_fun = function(self, some_var)
        -- ....
    end
    -- ...
end
-- /base_classes/Form/Mixin/ForEntity.lua

--- @class base_classes.Form.Mixin.ForEntity: base_classes.Form.Mixin
--- @field for_entity_...
--- @field for_entity_...
--- @field for_entity_...
local ForEntity = {}
-- ...
-- /base_classes/Form/Mixin/Personal.lua
-- ...
-- /base_classes/Form/Mixin/Shared.lua
-- ...
-- /base_classes/Form/Mixin/WithTabs.lua
-- ...
-- /base_classes/Form/Mixin/WithPlayerInventory.lua
-- ...

and so on....


So, then we can "construct"/design our own class like this:

-- /some_module/src/SomeForm.lua

local SomeForm = base_classes.Form:personal():for_node():with_tabs()

-- ...

Feature request

So.... It would be very useful, if we could specify from which mixins the class consists of. For example like this:

-- /some_module/src/SomeForm.lua

--- @class some_module.src.SomeForm: base_classes.Form.Base
--- @mixin base_classes.Form.Mixin.Personal
--- @mixin base_classes.Form.Mixin.ForNode
--- @mixin base_classes.Form.Mixin.WithTabs
local SomeForm = base_classes.Form :personal() :for_node() :with_tabs()

-- ...

or just like multiple inheritance:

-- /some_module/src/SomeForm.lua

--- @class some_module.src.SomeForm: base_classes.Form.Base, base_classes.Form.Mixin.Personal, base_classes.Form.Mixin.ForNode, base_classes.Form.Mixin.WithTabs
local SomeForm = base_classes.Form :personal() :for_node() :with_tabs()

-- ...

Related issues

CppCXY commented 3 months ago

vscode emmylua supports multiple inheritance

CppCXY commented 3 months ago

You can also use vscodeemmylua's language server directly in intellij by installing LSP4IJ. VSCode-EmmyLua supports many advanced features and its performance far exceeds IntelliJ-EmmyLua. I will try to make IntelliJ-EmmyLua use the analysis backend of VSCode-EmmyLua.

alek13 commented 3 months ago

@CppCXY , thanx for suggestion. Is there any chance, that it will be added to this plugin ?

CppCXY commented 2 months ago

maybe you can try my plugin: https://plugins.jetbrains.com/plugin/25076-emmylua2/edit/versions/stable/584455