IntelliJ-Luanalysis
IntelliJ-Luanalysis copied to clipboard
Improved class declaration/creation/instanciation support
Environment
name | version |
---|---|
IDEA version | IDEA 2020.1 |
Luanalysis version | 1.0.1 |
OS | Linux |
This is somewhat linked to an item I suggested here: https://github.com/EmmyLua/IntelliJ-EmmyLua/issues/26 :
Custom class constructor hint support (maybe @constructor?). The class system I'm using is like: function MyClass:new(arg1, arg2...) (not init) called implicitely by the MyClass table __call, so it'd be helpful if local test = MyClass("hello", 42) would be recognized as calling the constructor, thus proposing parameters autocompletion etc.
Right now, I have to declare my classes this way, which is absurdly redundant:
Would there be a way to simplify this? I'm open to suggestions :)
What I had in mind (but it probably needs more brainstorming) is that whenever declaring a class with @class
, the plugin should automatically/internally declare the callable overload corresponding to the constructor (whose name is set in the plugin preferences already), returning (an instance of) that class. Maybe make this behavior a setting, though, not everyone has the same class system...
In addition, it would be nice to have my Class
function being able to be annotated as a function that returns a callable table (in my case, as said above, it will call the :new
method), but I don't know how I can do that, so far what I have tried didn't work. Is that actually something doable yet?
Thanks!
Rather than doing this auto-magically, I'd prefer a more explicit approach e.g.
---@class ServiceDefinition
---@overload ServiceDefinition:new
That way the one project can mix and match instantiation schemes, and if you're publishing a library, people can just use your library as is without needing to change Luanalysis preferences.
This actually touches a little bit on https://github.com/Benjamin-Dobell/IntelliJ-Luanalysis/issues/5... Will comment more there.
At this point, having a per-project setting/config file setting this kind of thing would make more sense than boosting each (!) @class annotation with another new line that will extremely likely be the same for all classes of said project.
That file would provide override over the IDE settings. What do you think?
That said, this setting in the file could also be itself overridden by an inline annotation like you described, yes, this would always have the last word.
(sorry for the double comment, I cleaned that up, the first one got posted too early...)
Any news ? :)
I'm asking because I'm still facing difficulties getting everything to work correctly for some more "complex" annotations:
(ignore that dummy
Class
function, that's just for the sake of this screenshot)
As you can see here, for some reason the tmp
variable isn't typed as a MyClass
, even though everything else seems OK:
- the private fields are correctly typed if I ctrl-hover them in any class method. (thanks to the first part of the MyClass
@type
annotation) - the constructor is correctly recognized (thanks to the second part of the MyClass
@type
annotation)
BTW, I did try the following, but that didn't solve it completely (to be clear: it made the return value typed correctly, but the constructor parameters became unknown because MyClass
doesn't have the alternate function type that provided the info anymore)
---@class MyClass
---@overload fun(id:number, name:string, options:table<string,any>|nil):MyClass
Is this a bug somehow, or am I missing something? Or is it something that's known to be non-working right now and that would be handled later (with something like what you mentioned in the earlier comments)
Thanks!
Edit : I found a way to make it work, but unfortunately the actual Lua code changes, and that's a no-no: I guess the following is the only way to "dual-type" a class correctly.
---@class MyClass
---@overload fun(id:number, name:string, options:table<string,any>|nil):MyClass
---@field private id number
---@field private name string
---@field private options table<string,any>
local MyClass
---@type MyClass | fun(id:number, name:string, options:table<string,any>|nil):MyClass
local MyClass = Class()
[...]