Benjamin-Dobell / IntelliJ-Luanalysis

Type-safe Lua IDE — IntelliJ IDEA plugin
Apache License 2.0
155 stars 22 forks source link

Smart cast expressions #63

Open pouwelsjochem opened 3 years ago

pouwelsjochem commented 3 years ago

Environment

name version
IDEA version IC2020.3
Luanalysis version 1.2.2
OS MacOS Big Sur

What are the steps to reproduce this issue?

This is not really an issue, more like a stretch goal / idea. Making an issue so the idea is documented.

As of now, the usage of nil-able types are not really encouraged because everything has to be casted to --[[---@not nil]]. It would be nice if expressions would be able to detect certain conditions and automatically do the cast / type removal on params and variables. Such as Kotlin's smart casts.

Such as regular if statements looking for non nil objects:

---@param _paramTable nil|{a:number, b:fun()}
local function testSmartNil(_paramTable)
    local a = _paramTable and _paramTable.a -- currently gives an error and disabled autoComplete on _paramTable
    if _paramTable then
         _paramTable.b()-- currently gives an error and disabled autoComplete on _paramTable
    else
         -- here it could show only the type 'nil'
    end
end

Usage of the type() function. And maybe even let the user define their own cast functions as well?

---@param _numberOrStringParam string|number
local function testSmartType(_numberOrStringParam)
    if type(_numberOrStringParam) == "string" then
        string.upper(_numberOrStringParam) -- currently gives an error string.upper doesn't accept number | string
    else
        math.random(_numberOrStringParam) -- currently gives an error math.random doesn't accept number | string
    end
end

Or maybe the ability to use annotations on conditions, probably not doable with variables though since we'd need the reference to its name

---@param _param string|MyObject
local function testSmartCast(_param)
     if isMyObject(_param) then ---@cast _numberOrStringParam MyObject
         wantsMyObject(_param)
     end

     local variable = getMyObjectOrItsSubclass()
     if isSubclassOfMyObject(variable) then ---@cast variable MySubclass
         wantsSubclass(variable)
     end
end
Benjamin-Dobell commented 3 years ago

There's an issue for nil #4.

However, seems as you've mentioned types as well, it's worth keeping this open. You can probably remove the stuff about nil specifically and just reference #4 though.