IntelliJ-Luanalysis icon indicating copy to clipboard operation
IntelliJ-Luanalysis copied to clipboard

Improved class declaration/creation/instanciation support

Open adriweb opened this issue 3 years ago • 3 comments

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:

image

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!

adriweb avatar Jul 15 '20 00:07 adriweb

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.

Benjamin-Dobell avatar Jul 15 '20 06:07 Benjamin-Dobell

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.

adriweb avatar Jul 15 '20 11:07 adriweb

(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:

image (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()

[...]

adriweb avatar Nov 17 '20 03:11 adriweb