Code Monkey home page Code Monkey logo

intellij-luanalysis's Introduction

Luanalysis (an EmmyLua fork) for IntelliJ IDEA Build Sponsors

Editor Features

Find usages

find_usages

Rename

rename

Parameter hints

param_hints param_hints_cfg

Go to symbol

go_to_symbol

Go to class

go_to_class

Quick Documentation (Ctrl + Q)

quick_documentation

Method separators

method_separators_cfg method_separators

Method override line marker

method_override_line_marker

Installation

The latest release is available for download within IntelliJ or from the Jetbrains Plugin website.

Static Analysis Features

Luanalysis is derived from EmmyLua and supports all the basic editing and refactoring functionality provided by EmmyLua.

Beyond basic Lua editing capabilities, Luanalysis supports a significant amount of additional functionality necessary to statically type advanced codebases.

*Note*: Features are roughly listed in the order they were implemented, by no means order of importance.

Demo Project

A great way to see what’s possible in terms of static typing is to checkout the Luanalysis demo project.

EmmyDoc Block Comments

image

Type casts

In addition to defining new types, the @type tag can now be also used to cast the result of a Lua expression.

This is most useful with the newly added support for EmmyDoc block comments as we can easily specify inline type casts:

image

Improved variance detection

EmmyLua attempts to determine if a type is assignable to another type simply by checking if the former is a "subtype" of latter, however proper type variance of complex types is not implemented. For example, functions may be covariant or contravariant of other function types, depending on parameters and return value types:

image

EmmyLua does not report the above error.

Additionally, union variance detection has been fixed:

image

As above, the current release of EmmyLua does not catch this error.

Binding of EmmyDoc to lambdas in assignments

i.e. Type checking now works inside function "lambdas" assigned to a variable with an EmmyDoc definition.

image

Table type checking improvements

Various improvements, for example EmmyDoc "arrays" are now assignable to compatible table types e.g.

image

The current EmmyLua release will report an error here even though this is sound.

Generic inference fixes

The current EmmyLua release is unable to infer generics correctly in several situations and thus reports type errors where no error exists, and also misses errors where errors should exist e.g.

Type errors are now errors by default

By default, type safety errors are now reported as errors instead of warnings. This is made feasible by three things:

  1. Many improvements in the ability to specify complex types

  2. Type safety bug fixes

  3. Casting

Casting in particular means that if a user is doing something the type system deems unsafe, but they know at runtime will be fine, they can just add a cast to signify this and the error will go away.

Generic parameter use within a class

image

Shadowing of a generic parameter is forbidden and an error reports:

image

self is a real type

Improved type checking for self, for example self can be assigned to a variable that matches the parent type of a method. However, that parent type cannot be assigned to self, as the class may be sub-classed (in which case self refers to a more specific type).

image

Type checking of immediately assigned variable declarations

image

Current EmmyLua release will allow this invalid assignment.

Fixed a bug where the type inference cache was being used in the presence of an index

When a function returns multiple values, the current EmmyLua release will infer values and put them in the cache. This is inaccurate as generic types analysis may result in the same generic parameter being resolved differently based on the value being assigned, thus the cache cannot be used in this circumstance. Presently this results in both missing errors, and additional inaccurate errors, depending on the assignment.

Added support for @shape

A shape can be defined similarly to a class, except that contravariance is determined by compatibility of the members not the inheritance hierarchy.

This is most useful when working with "structures" (e.g. JSON) rather than OOP classes.

image

What makes shapes particularly useful is that they support generics and inheritance (at definition time, not assignment) just like classes:

Even better, type inspections are not just reported on incompatible `table`s as whole, but rather the inspections know how to traverse table literals and provide detailed annotations of incompatibilities between two shapes e.g.

image

Generic Aliases

Aliases can now take generic parameters, just like a class or shape.

image

Improved vararg syntax

Function types can now use …​: T as an alternative to vararg T:

image

Variadic return values

We now support variadic return values:

image

Internally, TyTuple has been replaced with TyMultipleResults to reflect the fact that this construct is not fixed size. Additionally, multiple results are now properly handled in more locations.

Standard library type improvements

Various improvements to typings of Lua built-ins taking advantage of variadic return values etc.

Support for indexed fields

We can now type all properties of tables, not just string constants. Given that Luanalysis also adds support for primitive literal types we can use this a lot of different ways e.g.

image

Here we have regular string identifier fields, number literal fields [1], [2] and [3] and a [boolean] field. That last one is really powerful, because it’s not a constant, it’s a real type.

We can type custom data structures e.g.

---@class Dictionary<K, V>
---@field [K] V

This will work correctly for any K and everything will be statically type checked as you’d expect.

There’s also syntax for table types, it works for table literals and anonymous classes (i.e. tables that aren’t explicitly typed):

image

Partially typed functions

We now support fun types with optional parameter lists and optional return values i.e. fun: boolean and fun(arg: boolean). fun (with neither specified) also works for posterity but is functionally equivalent to the existing function type.

Partially typed functions are extremely useful for implementing callback and handler patterns. For example, it’s quite common to have an extensible event system where each event has unique arguments, but the handler must return true to indicate the event was handled:

image

Callable types

This is another really useful feature. We can now properly indicate that an object is callable (i.e. is a table whose metatable has a __call method).

image

This is done by using the existing @overload EmmyDoc keyword, and works similarly i.e. we can specify many overloads and type checking and completion will work as you’d expect:

image

Strongly typed tuples

Tuples can be implemented as shapes with number literal indexes:

image

or as aliases of table literal types:

image

As can be seen above, when a tuple is compatible with an array, it can be assigned to one, but not vice versa.

Type lists

The @type annotation supports a list of types. This can be used when declaring variables:

image

or for casting multiple results returned by an expression (e.g. function call):

image

@not type casts

A @not type cast eliminates types from a union. It’s useful in a variety of circumstances, the most straight-forward of which is eliminating nil:

image

Like @type, is also supports type lists for casting multiple return values of a function, and can itself eliminate unions:

image

When you simply want to eliminate types from a union, it’s generally safer to use @not cast than a @type cast because a @type cast essentially disables all type checking for the assignment, where as @not cast just excludes certain types.

@type annotations on return statements

Return statements now accept type annotations, which are type-safe way of typing the return value of anonymous lambdas.

image

Unlike a type cast, these are type-safe:

image

Recursive alias resolution

Alias types are now lazily resolved, which allows us to type recursive data structures. For example, JSON:

image

Casting to/from variadic type lists

A functions API may return an unknown number of results. However, when calling these functions, you tend to know how many results you expect back.

A variadic return value can be cast to a concrete type list by @not casting away nil:

image

One variadic type may also be cast to another:

image

Support for optional parameters

We now support optional parameters in both short and long-form function type definitions e.g.

image

Importantly, optional is not short-hand for nil | type.

image

You cannot provide nil unless the optional parameter type itself include nil as part of a union in its type definition. This is desirable for correctness purposes when implementing functions in Lua, say for example if the implementation makes use of [select('#', …​)](https://www.lua.org/manual/5.3/manual.html#pdf-select). However, beyond that, Lua is regularly used as a scripting language, binding Lua function calls to implementations in other languages that have support for overloads etc. where the number and type of arguments are important.

Inspections that prevent incorrect optional parameter order have also been implemented:

image

Building from Source

Build the plugin with:

./gradlew build

For more details about the Jetbrains Platform SDK please refer to the official documentation.

The resultant plugin .zip will end up in the directory ./build/distributions/.

Installation from Source

To install the .zip you built, you’ll need to go to IntelliJ’s…

Preferences -> Plugins -> Settings Cog Icon -> Install Plugin from Disk...

image

Select the .zip, and then when prompted, restart IntelliJ.

Developed By

Luanalysis by: Benjamin Dobell

EmmyLua by: @tangzx 阿唐

Contributors

Please refer to Github for a complete list of contributors.

Sponsors

Thank you to Luanalysis' sponsors and supporters who help ensure the continued development of Luanalysis.

Sponsors

Sponsor Sponsor Sponsor Sponsor Sponsor Sponsor

Supporters

Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter Supporter

intellij-luanalysis's People

Contributors

beenlong avatar benjamin-dobell avatar christopher-st avatar cslei avatar dauch avatar fangfang1984 avatar github-actions[bot] avatar iam95a avatar ice1000 avatar jb574 avatar kkkiio avatar knoxfighter avatar liamyao avatar luchuanbaker avatar mheetu avatar mikatuo avatar mqualizz avatar muescha avatar omniraptorr avatar perryvw avatar pouwelsjochem avatar songtm avatar taigacon avatar tangzx avatar yanex avatar zj6882917 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

intellij-luanalysis's Issues

Stackoverflow while inferring types

Environment

name version
IDEA version 2020.2
Luanalysis version 1.0.3-IDEA201
OS MacOS 10.15.6

What are the steps to reproduce this issue?

Analyze the tableEqualty.lua found here
https://gist.github.com/dcorbin/2b783571732ebf3d38c4975581dfe822

What happens?

Stackoverflow

What were you expecting to happen?

Not an exception

Any logs, error output, etc?

Two stack traces included in the above GIST

Any other comments?

If you can detect the infinite loop and abort with more information, perhaps I can provide small reproducing sample.

[Feature request] Annotating function params with ... before last arg

Hi,

I was wondering if it would be possible to support annotating functions taking n variadic args then a known fixed type.

Basically I have this utility function, which unfortunately can't be perfectly annotated AFAIK:
(ignore the lack of @generic, that's another topic for now, but see the bottom)

--- Convert the function taking a callback into a function returning a promise.
--- The function to wrap must take a callback as last parameter.
--- The callback must take an error as first parameter, or nil if no error, and the result as second parameter.
function promisify(wrappedFn) ... end

What I tried and what would seem to be the optimal annotation but isn't supported (with ... or ...:any):

--- @param wrappedFn fun(..., cb:fun(nilOrErr:nil|string, result:any)) The function to wrap.
--- @return fun(...):Promise The function converted to return a promise.

What I ended up doing for now, which is the best I could find:

--- @param wrappedFn fun(arg:any, cb:fun(nilOrErr:nil|string, result:any)) The function to wrap.
--- @return fun(...):Promise The function converted to return a promise.

Thanks for the awesome work as usual!


Note that I also tried the following, which seemed like an appropriate usage of @generic, although that triggers errors in usages of that function, where T isn't matched to the actual usage I have for some reason. Maybe I should make another specific issue for that though.

--- @generic T
--- @param wrappedFn fun(arg:T, cb:fun(nilOrErr:nil|string, result:any)) The function to wrap.
--- @return fun(arg:T):Promise The function converted to return a promise.

Or even more optimally with that feature request implemented, although it's even more complex because all the variadic args may have different types... Ideally it would just "forward" the type from the wrapped function to the new one, but that sounds quite complex to annotate.

--- @generic ...anyT
--- @param wrappedFn fun(...:anyT, cb:fun(nilOrErr:nil|string, result:any)) The function to wrap.
--- @return fun(...:anyT):Promise The function converted to return a promise.

loadstring has invalid signature in the std libs annotations

Environment

name version
IDEA version 2020.3 (IC-203.5981.155)
Luanalysis version 1.2.1
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. Use local l, s = loadstring(str) (the important point being s as 2nd retval)

What happens?

Error on s local variable: Too many assignees, will be assigned nil.

What were you expecting to happen?

No such warning, the 2nd retval is actually valid in case of failure: returns nil plus the error message (see the load doc which loadstring refers to).

tonumber(e, base) should accept number as first parameter

Environment

name version
IDEA version 2020.3 (IC-203.5981.155)
Luanalysis version 1.2.1
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. tonumber(42)

What happens?

Error on param type.

What were you expecting to happen?

Not such errors

Any other comments?

---@param e string should probably be ---@param e string | number in the std annotations (same in the overload annotation).

IndexOutOfBoundsException in matchSignature from getParameterHints

On the latest release, on the latest 2020.2 IDEs:

I'll try to see if I can find a minimal code for repro, but that will be hard... hopefully the stack trace is enough

java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:458)
	at com.tang.intellij.lua.ty.TyKt.matchSignature(Ty.kt:321)
	at com.tang.intellij.lua.ty.TyKt.matchSignature$default(Ty.kt:228)
	at com.tang.intellij.lua.codeInsight.LuaParameterHintsProvider.getParameterHints(LuaParameterHintsProvider.kt:74)
	at com.intellij.codeInsight.hints.InlayParameterHintsProvider.getParameterHints(InlayParameterHintsProvider.java:29)
	at com.intellij.codeInsight.hints.ParameterHintsPass.process(ParameterHintsPass.java:74)
	at com.intellij.codeInsight.hints.ParameterHintsPass.lambda$doCollectInformation$0(ParameterHintsPass.java:66)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at com.intellij.codeInsight.hints.ParameterHintsPass.doCollectInformation(ParameterHintsPass.java:66)
	at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:54)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$1(PassExecutorService.java:399)
	at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1110)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:392)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:629)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:581)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:60)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:391)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:367)
	at com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:170)
	at com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:182)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:365)
	at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:181)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

Local variable type is not inferred from the constructor invocation if it is a table call

Environment

name version
IDEA version CLion 2020.3.1 Build #CL-203.6682.181
Luanalysis version 1.2.1-IDEA203
OS Windows 10 x64

Type safety flags are checked in the settings:

  • Unknown type (any) is indexable
  • Unknown type (any) is callable

What are the steps to reproduce this issue?

  1. open https://github.com/Benjamin-Dobell/LuanalysisTypesDemo/src/lambda_class.lua in IDE
  2. see local lambdaClass = LambdaClass(1)

What happens?

The lambdaClass local var type is shown as any.
The next example shows an unexpected error:

---@type number
local aNumber = lambdaClass.getNumber()
No such member 'getNumber' found on type 'any' 

What were you expecting to happen?

The lambdaClass local var type is shown as LambdaClass.

Any logs, error output, etc?

screenshot

Unable to extend `Std__` libraries

Environment

name version
IDEA version LATEST
Luanalysis version [1.2.2
OS MacOS

What are the steps to reproduce this issue?

math.additionalFunction = function()

end

What happens?

An error saying "No such member 'additionalFunction' found on type 'std__Math' " and seemingly no way to extend the math class with annotations.

math = math ---@class myMath : std__Math`

doesn't work

---@class myMath : std__Math

math = math ---@type myMath

also doesn't work

What were you expecting to happen?

The ability to extend the math class or any other standard library in some way.
math is now always seen as std__Math (by type infer and error inspection) and as far as I can see there's no way to change this

Incorrect error inspection when returning 'void' in a union type?

Environment

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

What are the steps to reproduce this issue?

Create an @param with a fun():void|number

---@param _function1 fun()
---@param _function2 fun():void
---@param _function3 fun():any|number
---@param _function4 fun():any
---@param _function5 fun():void|number ERROR
---@param _function6 fun():void|number|nil ERROR
---@param _function7 (fun():number)|(fun():any)
---@param _function8 (fun():number)|(fun():void)
local function optionalReturnValueTest(_function1, _function2, _function3, _function4, _function5, _function6, _function7, _function8)

end
optionalReturnValueTest(function()

end, function()

end, function()

end, function()

end, function()

end, function()

end, function()

end, function()

end)

What happens?

An error is indicated at all methods where void is used to indicate an optional number return value. When using any it doesn't give an error anymore, but its a very confusing way to indicate a function with an optional number return value.

The (fun():number)|(fun():void) sounds like the best alternative to me, so people reading this issue might consider that as well.

What were you expecting to happen?

No error when there's no return statement when using void|number as a return value.

void can't seem to be an alternative return type in function retval annotations

Environment

name version
IDEA version 2020.3.1 (IC-203.6682.168)
Luanalysis version 1.2.2 and also repro'd in latest master (now 5018fdb)
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

---@alias Handler fun(): (void | nil)

---@type Handler
local myFunc3 = function() end

---@type Handler
local myFunc4 = function() return nil end

What happens?

Error on the function definition:
Type mismatch. Required: 'fun(): nil' Found: 'fun(): void'

image

What were you expecting to happen?

For void to be able to be accepted as an alternative return type.

How to support the development?

This time, not a bug report or a feature request, but a question about the project: are you open to donations, or is there any "standard" way to support the project and its development/developer, if not financially? :)

Side-question: I see some commits still being done upstream (emmylua) - any plan to cherry-pick those (at least what's still doable of course)

Is it doable to add a UnlogicalComparisonInspector?

Environment

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

What are the steps to reproduce this issue?

Not really an issue, but more of an idea to discuss.

What happens?

When using the following code, no warning or error is given:

---@alias Direction "left"|"right"|"up"|"down"

local myDirection = math.random() > 0.5 and "right" or "left" ---@type Direction
if myDirection == "ight" then

end

What were you expecting to happen?

An Intellij inspection to turn on these types of errors, effectively creating enumerations with zero performance cost.

Support of types with dots in their name

I have a rather large codebase using EmmyLua annotations, and some types have dots (.) in them.
It seems IntelliJ-Luanalysis doesn't support that.

This is quite useful when adding annotations to third-party libs for instance.

Example with a Penlight function:

--- Return a list of all file names within an array which match a pattern.
--- Raise dir and mask must be strings
--- @param filenames table|pl.List An array containing file names.
--- @param pattern string A shell pattern.
--- @return pl.List List of matching file names.
function dir.filter(filenames, pattern) end

This fails with the first @param type since the dots isn't recognized as part of the type name. Same with the return type.

Add support for typing accessors/modifiers (getters/setters)

Lua's metatable and userdata functionality both provide mechanisms for a "property" accessor on a table/userdata to return a value of one type, whilst a different type may be accepted for assignment. We should provide a mechanism to type such "properties".

Additionally, some "fields" are read or write-only; perhaps these could be typed by simply marking a setter or getter type as void?

Class names with dots are not accepted

Environment

name version
IDEA version IU2020.1.3
Luanalysis version 1.0.1-IDEA201
OS Windows 10

What are the steps to reproduce this issue?

Define two classes with dots:

--- @class a.x

--- @class a.y

What happens?

I get Duplicate type found in the file: ... error, i.e. both classes are treated as one

What were you expecting to happen?

Classes are independent

Any other comments?

Works in EmmyLua

Bracketed-name fields shown as .null by docs

Environment

name version
IDEA version IdeaIU 2020.3
Luanalysis version 1.2.1-IDEA203
OS Win7

What are the steps to reproduce this issue?

  1. Create a class/shape with bracketed field names, e.g.:
    image
  2. With the sample shape above, try to index members (and assign to them) through an instance of the class/shape, through brackets or dot notation (if possible), then hover over the indexer (example in "What happens?" section)
  3. Additionally, type a. on a new line and look at the suggestions.

What happens?

2: Bracketed fields show as .null
image
H21AZvY
(Field m is correct when hovered, both by doing a.m and a["m"]: shows Test.m)

3: The bracketed fields aren't being suggested
image

What were you expecting to happen?

For 2, should show the field names normally: treating the n field as Test.n, and others as Test[1], Test[true], etc.
For 3, it should at least include n; better if it'd also suggest the non-string-name fields.

Any logs, error output, etc?

None

Any other comments?

Also, field description is placed too near to the left edge of the tooltip, don't know if it's normal.

Suggest/complete primitive indexed fields

Presently only named fields are suggested/completed.

For example:

---@class Vector
---@field x number
---@field y number
---@field [1] number
---@field [2] number

---@type Vector
local myVector

myVector.--<cursor here>

This will display a completion prompt that only includes the members x and y. However, it could also suggest [1] and [2] and upon completion delete the period.

Additionally, index expressions using brackets could similar be completed e.g.

myVector[--<cursor here>

If we're going to be completing all fields in brackets then we'll presumably want to prioritise primitive indexed fields over regular named fields and vice versa when completing fields after a period.

See #27 for initial report.

Considerations / Additional Thoughts

We're only going to be completing primitives, but what about aliases? e.g.

---@alias Color "Red" | "Blue"

---@class Palette
---@field [Color] number

---@type Palette
local palette

palette.--<cursor here>

Should we suggest "Red" and "Blue"?

We certainly can, however completion prompts ought to be very responsive, so minimising work is a good idea 😕

Shape inspections incorrectly occuring on type cast shapes

Environment

name version
IDEA version 2020.2
Luanalysis version 1.03
OS macOs 10.15.6

What are the steps to reproduce this issue?

  1. Run Inspect Code against his file:
---@alias VArgs std__Packed<any>

local result = --[[---@type std__Packed<any> ]] {n = 0}
local result = --[[---@type VArgs ]] {n = 0}

What happens?

The cast on the last line appears to have no effect, and and error is shown

What were you expecting to happen?

The aliased type should behave the same as the original

Limit type visibility

The mere presence of a type in a project should not expose that type to every file i.e. types should not be global.

Luanalysis should (recursively EDIT: Recursively pulling in is a bad idea, don't do that) pull in types when it sees a require. Additionally, we should provide some mechanism to allow consumers to avoid type name collisions.

e.g.

local Map = require("Map")
local LibraryMap = require("library/Map") ---@prefix Library

---@type Map
local myMap = Map()

---@type LibraryMap
local libraryMap = LibraryMap()

Just a hypothetical solution, other languages allow individual types to be renamed. The above is fairly low friction though.

Additionally, we may want to define types that we never export to consumers i.e. consider adding local types like:

---@local alias Builder fun(): void

Improve literal inspections for arrays whose element is a union of shapes

e.g.

---@shape StringThing
---@field tag "String"
---@field value string

---@shape NumberThing
---@field tag "Number"
---@field value number

---@type (StringThing | NumberThing)[]
local thing = {
    {
        tag = "Number",
        value = {}
    }
}

Currently this gives the inspection:

Screen Shot 2020-08-01 at 6 02 51 pm

It should drill down and indicate that value is invalid.

We don't have proper support for discriminated unions, so it won't be unreasonable to also see incompatibilities with StringThing (not just NumberThing). However, that'd still be a big improvement over the current behaviour.

Alternative way to add overloads

Environment

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

What happens?

As of now, function overloads always need to be added by using the @overload annotation. But this annotation requires you to copy&paste most of your signature.

What were you expecting to happen?

Most of my overloads are actually optional parameters, it would be nice if there was a way to indicate optional parameters in a different way so overloads are added automatically.

See below for several examples how I think the syntax could look like:

current situation

---@param _duration number
---@param _easing EasingFunction
---@param _delta boolean
---@param _properties table
---@optional _options table<string, number>
---@param _onComplete TransitionOnCompleteFunction
---@return TransitionHandle|nil
---@overload fun(_obj, _duration:number, _easing:EasingFunction, _delta:boolean, _properties:table<string, number>):TransitionHandle|nil
---@overload fun(_obj, _duration:number, _easing:EasingFunction, _delta:boolean, _properties:table<string, number>, _options:table):TransitionHandle|nil
---@overload fun(_obj, _duration:number, _easing:EasingFunction, _delta:boolean, _properties:table<string, number>, _onComplete:TransitionOnCompleteFunction):TransitionHandle|nil
---@overload fun(_obj, _duration:number, _easing:EasingFunction, _delta:boolean, _properties:table<string, number>, _options:table, _onComplete:TransitionOnCompleteFunction):TransitionHandle|nil
local function createToTransition(_obj, _duration, _easing, _delta, _properties, _options, _onComplete)

void type parameters

---@param _duration number
---@param _easing EasingFunction
---@param _delta boolean
---@param _properties table
---@param _options void|table<string, number>
---@param _onComplete void|TransitionOnCompleteFunction
---@return TransitionHandle|nil
local function createToTransition(_obj, _duration, _easing, _delta, _properties, _options, _onComplete) end

suffixed or prefixed parameters

---@param _duration number
---@param _easing EasingFunction
---@param _delta boolean
---@param _properties table
---@param _options table<string, number>?
---@param _onComplete TransitionOnCompleteFunction?
---@return TransitionHandle|nil
local function createToTransition(_obj, _duration, _easing, _delta, _properties, _options, _onComplete) end

@optionalparam annotation

---@param _duration number
---@param _easing EasingFunction
---@param _delta boolean
---@param _properties table
---@optionalparam _options table<string, number>?
---@optionalparam _onComplete TransitionOnCompleteFunction?
---@return TransitionHandle|nil
local function createToTransition(_obj, _duration, _easing, _delta, _properties, _options, _onComplete) end

basic Lua 5.4 support

Even if the plugin doesn't understand new 5.4 features, it would be helpful to at least ignore new syntax like local variable attributes (<const> and <close>).

collectgarbage has incomplete @overload annotations

Environment

name version
IDEA version 2020.3 (IC-203.5981.155)
Luanalysis version 1.2.1
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. Use collectgarbage("collect") for instance

What happens?

Errors about invalid/missing arguments.

What were you expecting to happen?

No errors.

This function is a bit more complex than what annotated, it's collectgarbage([opt [, arg]]), and all possible opt values (that vary with the different Lua versions) are known strings, so that's easily annotatable.

See the docs: 5.1, 5.2, 5.3, 5.4.

setmetatable has invalid signature in the std libs annotations

Environment

name version
IDEA version 2020.3 (IC-203.5981.155)
Luanalysis version 1.2.1
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. Use setmetatable(t, nil) (the important point being nil as 2nd parameter)

What happens?

Error Type mismatch. Required: 'table' Found: 'nil'

What were you expecting to happen?

No such warning, nil is actually valid:
If `metatable` is **nil**, removes the metatable of the given table.

Illegal primitive inheritance inspection

Defining a class/shape that inherits from a primitive type is forbidden.

For most primitive types that's reasonably obvious, however table<K, V> is also considered a primitive type, and that's certainly a lot less obvious. Should have an inspection that raises an error if this is attempted.

debug.getinfo has incomplete @overload annotations

Environment

name version
IDEA version 2020.3 (IC-203.5981.155)
Luanalysis version 1.2.1
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. Use local info = debug.getinfo(3, "S")

What happens?

Errors about type mismatchs.

What were you expecting to happen?

This function is a bit weird signature-wise, it's debug.getinfo([thread,] function [, what]), and f/function can be a number.
See the docs: 5.1, 5.2, 5.3, 5.4.

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: EmmyLua/IntelliJ-EmmyLua#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!

Add subclass field compatibility inspections

Currently Luanalysis allows the following unsafe code:

---@class HasStringThing
---@field thing string

---@class SubStringThing : HasStringThing
---@field thing boolean

---@type HasStringThing
local hasStringThing

---@type SubStringThing
local subStringThing

hasStringThing = subStringThing

---@type string
local uhOh = hasStringThing.thing

It should show an inspection for:

---@field thing boolean

Stating something like "boolean is not covariant of string".

Autocomplete doc and Search Everywhere results don't show proper containing table name

Environment

name version
IDEA version IdeaIU 2020.3
Luanalysis version 1.2.2-IDEA203
OS Win7

What are the steps to reproduce this issue?

  1. Create functions which are members of tables, where tables are: a defined local, a defined global, and an undefined global. For example:
local base = {}
defGlob = {}

function base.exec(a) end
function base.execN(a, n) end

function defGlob.exec(b) end
function defGlob.execN(b, n) end

function undefGlob.exec(x) end
function undefGlob.execN(x, n) end
  1. Bring up the Search Everywhere pane (double shift), and search for the functions' names (optionally in Symbols tab to filter out other items)
  2. Additionally type base. or defGlob. and see the documentation that pops out

What happens?

For functions that are contained within declared variables, docs and search results show table.exec, table.execN, etc. despite being in base or exec
For functions contained in undeclared variables, search results only show the function name itself without the undefGlob. prefix

image

image

What were you expecting to happen?

Autocomplete docs and search results should say base.exec, defGlob.execN, undefGlob.exec, etc.

Any logs, error output, etc?

None

Any other comments?

I feel that this issue only recently showed up for me, or I haven't noticed before. On the other hand, might this be intentional?

`or` operator, incorrect inferred type with varreturn

---@type fun(): number...
local varnum

---@type number
local aNumber

aNumber = varnum() or aNumber -- Problem here

Presently (version 1.2.0) shows problem:

Type mismatch. Required: 'number' Found: 'nil | number'

where as this is inaccurate, number should be inferred.

Unexpected errors in text_styling.lua in LuanalysisTypesDemo

Environment

name version
IDEA version CLion 2020.3.1 Build #CL-203.6682.181
Luanalysis version 1.2.1-IDEA203
OS Windows 10 x64

Type safety flags checked in the settings:

  • Unknown type (any) is indexable
  • Unknown type (any) is callable

What are the steps to reproduce this issue?

  1. open https://github.com/Benjamin-Dobell/LuanalysisTypesDemo/src/text_styling.lua in IDE

What happens?

I see errors that is not tagged with the "Expected error" comment like as in other error cases.

What were you expecting to happen?

No errors or the "Expected error" tags.

Any logs, error output, etc?

screenshot

  1. Type mismatch. Required: 'V[]' Found: 'any'
  2. No such indexer '[1]' found on type 'any'
  3. No such indexer '[string]' found on type 'table'
  4. No such member 'hi' found on type 'any'
  5. No such member 'blarg' found on type 'void'

Add operator type inspections

Operators (in particular arithmetic operators) should ensure their operands are covariant of number.

The following certainly shouldn't be allowed:

---@type boolean
local aBoolean = true + true -- Illegal

However, non-arithmetic operators should also be checked for compatibility e.g.

---@type number
local a = 1

---@type number
local length = #a -- Illegal

Issue

Hide the main signature of overloaded functions

This will be a breaking change, however, the main signature of a function is often very loosely typed, take the following example:

---@overload fun(a: string, b: number): void
---@overload fun(a: number): void
---@param a string | number
---@param b nil | number
function thing(a, b)
end

We want to call the function like:

thing("hi", 1)
-- or
thing(1)

However, the Luanalysis type system will also allow:

thing("hi", nil)

which is probably not what the implementer intended.

Thus, if we encounter a function with @overload, we should treat the main signature as internal, and only use it for type checking the function body, but not externally expose that signature to callers.

Length operator inspection

Length operator should only be used on tables, and definitely not nil. We should displays errors.

The length operator can be overloaded by the __len metamethod. Seems as we currently lack the means to document operator overloading, at present we should simply restrict to table and userdata (including classes/shapes).

It doesn't seem possible to add entries to _G directly

Environment

name version
IDEA version Intellij IDEA 2020.3.1 ; #IC-203.6682.168
Luanalysis version v1.2.2
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. Write _G.log = loggerInstance

What happens?

Error: No such member 'log' found on type '_G'

What were you expecting to happen?

No such error, and even more importantly, the variable recognized as a shared/global one in the project.

Multiple invalid warnings on some code

Environment

name version
IDEA version 2020.3 (IC-203.5981.155)
Luanalysis version 1.2.1
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

This code:

local utilities = {}

--- Split a string using pattern.
--- @overload fun(str:string):string[]
--- @param str string the string to split
--- @param pattern string pattern used to split. Default = "[^%s]+"
--- @return string[]
utilities.stringSplit = function(str, pattern)
  if type(str) ~= "string" then return {} end
  if type(pattern) ~= "string" or pattern:len() == 0 then
    pattern = "[^%s]+"
  end
  local parts = { __index = table.insert }
  setmetatable(parts, parts)
  str:gsub(pattern, parts)
  setmetatable(parts, nil)
  parts.__index = nil
  return parts
end

What happens?

  1. When hovering utilities.stringSplit:
    image
    Note that this disappears if I annotate utilities with ---@type table but I don't see why I'd need to do that though?

  2. When hovering parts.__index:
    image
    Why wouldn't I be able to set any field I want? Is it assuming a numeric table? It shouldn't considering it was created as a k-v table.

  3. I was unable to repro this in a standalone lua file, but I've seen it as part of my utilities.lua file when hovering parts in the return:
    image

What were you expecting to happen?

No such warnings, it's all supposed to be valid as far as I know.

@overload annotations don't seem to understand generic types

Environment

name version
IDEA version 2020.3.1 (IC-203.6682.168)
Luanalysis version 1.2.2
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

I was adding annotations for Penlight classes, and the following code sample doesn't seem to be working as expected

--- return the index (or key) of a value in a table using a comparison function.
--- @generic K, V
--- @overload fun(t:table<K,V>, cmp:fun(a:V, b:V):boolean):(K,boolean)
--- @param t table<K,V> @ A table
--- @param cmp fun(a:V, b:V):boolean @ A comparison function
--- @param arg any an optional second argument to the function
--- @return K,boolean
function tablex.find_if(t, cmp, arg) end

What happens?

Generic types K and V aren't recognized in @overload annotations.
image

What were you expecting to happen?

For them to be recognized.

string literal doesn't match string in multiple return value function annotation

Environment

name version
IDEA version 2020.3.1 (IC-203.6682.168)
Luanalysis version 1.2.2 and also repro'd in latest master (now 5018fdb)
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

---@alias Handler fun(asyncCb:fun(success:boolean)): nil | true | (false,string)

---@type Handler
local myFunc1 = function(asyncCb) local msg = "asdf" return false, msg end

---@type Handler
local myFunc2 = function(asyncCb) return false, "asdf" end

What happens?

Error on the "asdf" string literal return:
Type mismatch. Required: 'fun(asyncCb: fun(success: boolean)): ((false, string) | nil | true)' Found: 'fun(asyncCb: any): false, "asdf"'

image

Note that the issue is specific to the case of multiple return values. No problem if there's only one return value, "asdf" will match string.

What were you expecting to happen?

For "asdf" string to be treated as a string matching the annotation.

IJ Lockup with LuaAnalysis

Environment

name version
IDEA version IJ2020.2 (locally built)
Luanalysis version 1.1.0 (locally built)
OS macOS 10.15.6

What are the steps to reproduce this issue?

I was eating a file

What happens?

IJ locks up. I'm unable to type anything. I must forcibly kill the IJ process

What were you expecting to happen?

Editing should not lock up :)

Any logs, error output, etc?

I took a threadDump, and this was the only interesting thread:
"OurIconsCalculating Pool" prio=0 tid=0x0 nid=0x0 waiting on condition
java.lang.Thread.State: WAITING
on com.intellij.util.indexing.StorageGuard@22b5658c
at [email protected]/java.lang.Object.wait(Native Method)
at [email protected]/java.lang.Object.wait(Object.java:328)
at com.intellij.util.indexing.StorageGuard.doWait(StorageGuard.java:63)
at com.intellij.util.indexing.StorageGuard.enter(StorageGuard.java:53)
at com.intellij.util.indexing.StorageBufferingHandler.runUpdate(StorageBufferingHandler.java:15)
at com.intellij.util.indexing.FileBasedIndexImpl.runCleanupAction(FileBasedIndexImpl.java:1005)
at com.intellij.psi.stubs.StubIndexImpl.wipeProblematicFileIdsForParticularKeyAndStubIndex(StubIndexImpl.java:451)
at com.intellij.psi.stubs.StubIndexImpl.processElements(StubIndexImpl.java:433)
at com.intellij.psi.stubs.StubIndex.getElements(StubIndex.java:107)
at com.intellij.psi.stubs.StubIndex.getElements(StubIndex.java:95)
at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex.get(LuaClassMemberIndex.kt:37)
at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processKey(LuaClassMemberIndex.kt:45)
at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processClassKey(LuaClassMemberIndex.kt:52)
at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processMember(LuaClassMemberIndex.kt:89)
at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processMember$default(LuaClassMemberIndex.kt:88)
at com.tang.intellij.lua.psi.LuaPsiResolveUtilKt.multiResolve(LuaPsiResolveUtil.kt:115)
at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1$1.invoke(Expressions.kt:354)
at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1$1.invoke(Expressions.kt)
at com.tang.intellij.lua.search.SearchContext.withRecursionGuard(SearchContext.kt:202)
at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1.compute(Expressions.kt:353)
at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1.compute(Expressions.kt)
at com.intellij.openapi.util.RecursionManager$1.doPreventingRecursion(RecursionManager.java:117)
at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:75)
at com.tang.intellij.lua.ext.UtilsKt.recursionGuard(utils.kt:23)
at com.tang.intellij.lua.ext.UtilsKt.recursionGuard$default(utils.kt:22)
at com.tang.intellij.lua.ty.ExpressionsKt.infer(Expressions.kt:338)
at com.tang.intellij.lua.ty.ExpressionsKt.inferExprInner(Expressions.kt:104)
at com.tang.intellij.lua.ty.ExpressionsKt.inferExpr(Expressions.kt:64)
at com.tang.intellij.lua.ty.DeclarationsKt.inferInner(Declarations.kt:40)
at com.tang.intellij.lua.ty.LuaTypeInfer.inferType(LuaTypeInfer.kt:25)
at com.tang.intellij.lua.ext.ILuaTypeInfer$Companion.infer(ILuaTypeInfer.kt:33)
at com.tang.intellij.lua.search.SearchContext.inferAndCache(SearchContext.kt:228)
at com.tang.intellij.lua.search.SearchContext.access$inferAndCache(SearchContext.kt:35)
at com.tang.intellij.lua.search.SearchContext$Companion$infer$2.invoke(SearchContext.kt:63)
at com.tang.intellij.lua.search.SearchContext$Companion$infer$2.invoke(SearchContext.kt:37)
at com.tang.intellij.lua.search.SearchContext$Companion.with(SearchContext.kt:75)
at com.tang.intellij.lua.search.SearchContext$Companion.infer(SearchContext.kt:63)
at com.tang.intellij.lua.psi.LuaTypeGuessable.guessType(LuaTypeGuessable.java:30)
at com.tang.intellij.lua.psi.LuaPsiImplUtilKt$guessParentType$parentTy$1.compute(LuaPsiImplUtil.kt:148)
at com.tang.intellij.lua.psi.LuaPsiImplUtilKt$guessParentType$parentTy$1.compute(LuaPsiImplUtil.kt)
at com.intellij.openapi.util.RecursionManager$1.doPreventingRecursion(RecursionManager.java:117)
at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:75)
at com.tang.intellij.lua.ext.UtilsKt.recursionGuard(utils.kt:23)
at com.tang.intellij.lua.ext.UtilsKt.recursionGuard$default(utils.kt:22)
at com.tang.intellij.lua.psi.LuaPsiImplUtilKt.guessParentType(LuaPsiImplUtil.kt:147)
at com.tang.intellij.lua.psi.impl.LuaClassMethodDefImpl.guessParentType(LuaClassMethodDefImpl.java:65)
at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findOwnerClassGenericDef(LuaPsiTreeUtil.java:106)
at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findOwnerClassGenericDef(LuaPsiTreeUtil.java:142)
at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findGenericDef(LuaPsiTreeUtil.java:259)
at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findGenericDef(LuaPsiTreeUtil.java:273)
at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.resolveType(LuaDocPsiImplUtil.kt:59)
at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.getType(LuaDocPsiImplUtil.kt:325)
at com.tang.intellij.lua.comment.psi.impl.LuaDocGeneralTyImpl.getType(LuaDocGeneralTyImpl.java:38)
at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.getType(LuaDocPsiImplUtil.kt:165)
at com.tang.intellij.lua.comment.psi.impl.LuaDocTagReturnImpl.getType(LuaDocTagReturnImpl.java:51)
at com.tang.intellij.lua.stubs.LuaClassMethodType.createStub(LuaClassMethodStub.kt:65)
at com.tang.intellij.lua.stubs.LuaClassMethodType.createStub(LuaClassMethodStub.kt:34)
at com.intellij.psi.stubs.DefaultStubBuilder$StubBuildingWalkingVisitor.createStub(DefaultStubBuilder.java:85)
at com.intellij.psi.stubs.DefaultStubBuilder$StubBuildingWalkingVisitor.visitNode(DefaultStubBuilder.java:60)
at com.intellij.psi.stubs.DefaultStubBuilder$StubBuildingWalkingVisitor.buildStubTree(DefaultStubBuilder.java:55)
at com.intellij.psi.stubs.DefaultStubBuilder.buildStubTreeFor(DefaultStubBuilder.java:33)
at com.intellij.psi.stubs.DefaultStubBuilder.buildStubTree(DefaultStubBuilder.java:22)
at com.intellij.psi.stubs.StubTreeBuilder.buildStubTree(StubTreeBuilder.java:128)
at com.intellij.psi.stubs.StubUpdatingIndex$1.lambda$computeValue$0(StubUpdatingIndex.java:145)
at com.intellij.psi.stubs.StubUpdatingIndex$1$$Lambda$2798/0x0000000801dae840.compute(Unknown Source)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:894)
at com.intellij.openapi.application.ReadAction.compute(ReadAction.java:61)
at com.intellij.psi.stubs.StubUpdatingIndex$1.computeValue(StubUpdatingIndex.java:126)
at com.intellij.psi.stubs.StubUpdatingIndex$1.computeValue(StubUpdatingIndex.java:99)
at com.intellij.util.indexing.SingleEntryCompositeIndexer.computeValue(SingleEntryCompositeIndexer.java:27)
at com.intellij.util.indexing.SingleEntryIndexer.map(SingleEntryIndexer.java:28)
at com.intellij.util.indexing.SingleEntryIndexer.map(SingleEntryIndexer.java:17)
at com.intellij.util.indexing.impl.MapReduceIndex.mapByIndexer(MapReduceIndex.java:317)
at com.intellij.util.indexing.impl.MapReduceIndex.mapInput(MapReduceIndex.java:309)
at com.intellij.util.indexing.VfsAwareMapReduceIndex.mapInput(VfsAwareMapReduceIndex.java:150)
at com.intellij.util.indexing.VfsAwareMapReduceIndex.mapInput(VfsAwareMapReduceIndex.java:40)
at com.intellij.util.indexing.impl.MapReduceIndex.calculateUpdateData(MapReduceIndex.java:267)
at com.intellij.util.indexing.impl.MapReduceIndex.update(MapReduceIndex.java:239)
at com.intellij.util.indexing.FileBasedIndexImpl.lambda$indexUnsavedDocument$14(FileBasedIndexImpl.java:973)
at com.intellij.util.indexing.FileBasedIndexImpl$$Lambda$4033/0x0000000802aa7840.run(Unknown Source)
at com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl.freezeFileTypeTemporarilyIn(FileTypeManagerImpl.java:722)
at com.intellij.util.indexing.FileBasedIndexImpl.indexUnsavedDocument(FileBasedIndexImpl.java:942)
at com.intellij.util.indexing.RegisteredIndexes$DocumentUpdateTask.doProcess(RegisteredIndexes.java:197)
at com.intellij.util.indexing.RegisteredIndexes$DocumentUpdateTask.doProcess(RegisteredIndexes.java:188)
at com.intellij.util.indexing.UpdateTask.process(UpdateTask.java:77)
at com.intellij.util.indexing.UpdateTask.processAll(UpdateTask.java:46)
at com.intellij.util.indexing.FileBasedIndexImpl.lambda$indexUnsavedDocuments$13(FileBasedIndexImpl.java:901)
at com.intellij.util.indexing.FileBasedIndexImpl$$Lambda$4027/0x0000000802aa5040.compute(Unknown Source)
at com.intellij.util.indexing.StorageBufferingHandler.runUpdate(StorageBufferingHandler.java:30)
at com.intellij.util.indexing.FileBasedIndexImpl.indexUnsavedDocuments(FileBasedIndexImpl.java:901)
at com.intellij.util.indexing.FileBasedIndexImpl.ensureUpToDate(FileBasedIndexImpl.java:689)
at com.intellij.psi.stubs.StubIndexImpl.getContainingIds(StubIndexImpl.java:540)
at com.intellij.psi.stubs.StubIndexImpl.processElements(StubIndexImpl.java:396)
at com.intellij.psi.stubs.StubIndex.getElements(StubIndex.java:107)
at com.intellij.psi.stubs.StubIndex.getElements(StubIndex.java:95)
at org.jetbrains.kotlin.idea.stubindex.KotlinFileFacadeFqNameIndex.get(KotlinFileFacadeFqNameIndex.kt:19)
at org.jetbrains.kotlin.idea.caches.resolve.IDEKotlinAsJavaSupport$findFilesForFacade$1.invoke(IDEKotlinAsJavaSupport.kt:243)
at org.jetbrains.kotlin.idea.caches.resolve.IDEKotlinAsJavaSupport$findFilesForFacade$1.invoke(IDEKotlinAsJavaSupport.kt:40)
at org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt$sam$com_intellij_openapi_util_Computable$0.compute(ApplicationUtils.kt)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:880)
at org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt.runReadAction(ApplicationUtils.kt:28)
at org.jetbrains.kotlin.idea.caches.resolve.IDEKotlinAsJavaSupport.findFilesForFacade(IDEKotlinAsJavaSupport.kt:242)
at org.jetbrains.kotlin.idea.caches.resolve.IDEKotlinAsJavaSupport.getFacadeClasses(IDEKotlinAsJavaSupport.kt:171)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClasses(JavaElementFinder.kt:58)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClass(JavaElementFinder.kt:46)
at com.intellij.psi.impl.JavaPsiFacadeImpl.doFindClass(JavaPsiFacadeImpl.java:107)
at com.intellij.psi.impl.JavaPsiFacadeImpl.findClass(JavaPsiFacadeImpl.java:84)
at com.intellij.micronaut.MicronautUtils.hasMicronautLibrary(MicronautUtils.kt:62)
at com.intellij.micronaut.config.MnIconProvider.getIcon(MnIconProvider.kt:13)
at com.intellij.util.PsiIconUtil.getProvidersIcon(PsiIconUtil.java:17)
at com.intellij.ide.FileIconPatcherImpl.getIcon(FileIconPatcherImpl.java:37)
at com.intellij.util.IconUtil.getProvidersIcon(IconUtil.java:199)
at com.intellij.util.IconUtil.lambda$static$0(IconUtil.java:143)
at com.intellij.util.IconUtil$$Lambda$886/0x0000000800b6f440.fun(Unknown Source)
at com.intellij.ui.DeferredIconImpl.evaluate(DeferredIconImpl.java:268)
at com.intellij.ui.DeferredIconImpl.lambda$null$0(DeferredIconImpl.java:158)
at com.intellij.ui.DeferredIconImpl$$Lambda$863/0x0000000800afb840.run(Unknown Source)
at com.intellij.ui.IconDeferrerImpl.evaluateDeferred(IconDeferrerImpl.java:98)
at com.intellij.ui.DeferredIconImpl.lambda$null$1(DeferredIconImpl.java:158)
at com.intellij.ui.DeferredIconImpl$$Lambda$860/0x0000000800afe040.run(Unknown Source)
at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1106)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runInReadActionWithWriteActionPriority$0(ProgressIndicatorUtils.java:75)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils$$Lambda$861/0x0000000800afc840.run(Unknown Source)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runWithWriteActionPriority$1(ProgressIndicatorUtils.java:129)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils$$Lambda$862/0x0000000800afc040.run(Unknown Source)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:164)
at com.intellij.openapi.progress.impl.CoreProgressManager$$Lambda$406/0x0000000800511040.run(Unknown Source)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:625)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:570)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:61)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:151)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runWithWriteActionPriority(ProgressIndicatorUtils.java:118)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(ProgressIndicatorUtils.java:75)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(ProgressIndicatorUtils.java:96)
at com.intellij.ui.DeferredIconImpl.lambda$paintIcon$4(DeferredIconImpl.java:157)
at com.intellij.ui.DeferredIconImpl$$Lambda$858/0x0000000800affc40.run(Unknown Source)
at com.intellij.util.concurrency.BoundedTaskExecutor.doRun(BoundedTaskExecutor.java:222)
at com.intellij.util.concurrency.BoundedTaskExecutor.access$200(BoundedTaskExecutor.java:29)
at com.intellij.util.concurrency.BoundedTaskExecutor$1.execute(BoundedTaskExecutor.java:201)
at com.intellij.util.concurrency.BoundedTaskExecutor$1$$Lambda$431/0x000000080058f040.run(Unknown Source)
at com.intellij.util.ConcurrencyUtil.runUnderThreadName(ConcurrencyUtil.java:210)
at com.intellij.util.concurrency.BoundedTaskExecutor$1.run(BoundedTaskExecutor.java:190)
at [email protected]/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at [email protected]/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at [email protected]/java.lang.Thread.run(Thread.java:834)

Remove "assumed constructor" functionality (BREAKING CHANGE)

EmmyLua doesn't support callable types so it had a hack in place that meant if it detected a class being used as a function it'd assume it was a constructor.

e.g.

---@class SomeClass
local SomeClass = {}

---@type SomeClass
local someClass = SomeClass()

The assumption that calling a table returns an instance of that table's type may be incorrect, however even if it is correct, there's no known parameters to perform type checking against.

It's a breaking change, but I think the best course action is to outright remove the functionality. Users will instead be required to use Luanalysis' existing "Callable Types" functionality to define an overload on the class. Might be a bit of teething pain but I suspect users will find bugs they didn't know they had!

Is it possible to declare a @field overload?

Context: I have a class where some fields are methods only set after init (self.foobar = function(this, arg1, arg2) ... end).

I have no choice but to annotate those with @field below the @class annotation, for instance:
@field public foobar fun(self:MyClass, arg1:number, arg2:string):boolean

The issue is that arg2 is optional, and I can't seem to annotate that succesfully. If I do arg2:string|nil it expects a string or an explicit nil to be passed by the caller, and if I annotate with a whole alternative type to that function (like this: @field public foobar (fun(self:MyClass, arg1:number, arg2:string):boolean)|(fun(self:MyClass, arg1:number):boolean)), only one seems to be taken into account (the one with most args).

Thanks!

@deprecated doesn't actually do anything

Environment

name version
IDEA version 2020.3.1 (IC-203.6682.168)
Luanalysis version 1.2.1 (also tested on master as of Jan 11th)
OS Linux Ubuntu 20.10

What are the steps to reproduce this issue?

  1. Enable the Lua > Lua deprecation inspection if it isn't already
  2. Annotate a class or a function with @deprecated Use foobar instead (or without the words after the tag, it doesn't matter)
  3. Use said deprecated symbol anywhere

What happens?

Only the words written after @deprecated end up being shown in the documentation popup of a symbol (but not mentioning Deprecated), and no actual warning or visual representation (like strikethrough) on the usage of the deprecated symbol.

What were you expecting to happen?

The "standard" visual+warnings feedback when trying to use deprecated functions/classes, if this inspection is enabled.

Indexing field freezes the IDEA

Environment

name version
IDEA version IC2020.3
Luanalysis version 1.1.0-IDEA201
OS Windows 10

What are the steps to reproduce this issue?

  1. Open Player.def.lua in tts-types/tts
  2. Append this snippet of code to the end of the file
---@return string[]
function Player.getAvailableColors() end
  1. Create a new field after line 51 like this one
    ---@field [string]

What happens?

As soon as you type
---@field [s
IntelliJ IDEA freezes completely

Any logs, error output, etc?

java.lang.Exception
	at com.intellij.psi.stubs.StubTreeLoaderImpl.diagnoseLengthMismatch(StubTreeLoaderImpl.java:177)
	at com.intellij.psi.stubs.StubTreeLoaderImpl.checkLengthMatch(StubTreeLoaderImpl.java:143)
	at com.intellij.psi.stubs.StubTreeLoaderImpl.readFromVFile(StubTreeLoaderImpl.java:105)
	at com.intellij.psi.stubs.StubTreeLoader.stubTreeAndIndexDoNotMatch(StubTreeLoader.java:59)
	at com.intellij.psi.stubs.StubProcessingHelperBase.inconsistencyDetected(StubProcessingHelperBase.java:150)
	at com.intellij.psi.stubs.StubProcessingHelperBase.checkType(StubProcessingHelperBase.java:92)
	at com.intellij.psi.stubs.StubProcessingHelperBase.processStubsInFile(StubProcessingHelperBase.java:71)
	at com.intellij.psi.stubs.StubIndexImpl.lambda$processElements$2(StubIndexImpl.java:289)
	at com.intellij.psi.stubs.StubIndexImpl.processElements(StubIndexImpl.java:325)
	at com.intellij.psi.stubs.StubIndex.getElements(StubIndex.java:105)
	at com.intellij.psi.stubs.StubIndex.getElements(StubIndex.java:93)
	at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex.get(LuaClassMemberIndex.kt:37)
	at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processKey(LuaClassMemberIndex.kt:45)
	at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processClassKey(LuaClassMemberIndex.kt:52)
	at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processMember(LuaClassMemberIndex.kt:89)
	at com.tang.intellij.lua.stubs.index.LuaClassMemberIndex$Companion.processMember$default(LuaClassMemberIndex.kt:88)
	at com.tang.intellij.lua.psi.LuaPsiResolveUtilKt.multiResolve(LuaPsiResolveUtil.kt:115)
	at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1$1.invoke(Expressions.kt:354)
	at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1$1.invoke(Expressions.kt)
	at com.tang.intellij.lua.search.SearchContext.withRecursionGuard(SearchContext.kt:202)
	at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1.compute(Expressions.kt:353)
	at com.tang.intellij.lua.ty.ExpressionsKt$infer$set$1.compute(Expressions.kt)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:42)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:68)
	at com.tang.intellij.lua.ext.UtilsKt.recursionGuard(utils.kt:23)
	at com.tang.intellij.lua.ext.UtilsKt.recursionGuard$default(utils.kt:22)
	at com.tang.intellij.lua.ty.ExpressionsKt.infer(Expressions.kt:338)
	at com.tang.intellij.lua.ty.ExpressionsKt.inferExprInner(Expressions.kt:104)
	at com.tang.intellij.lua.ty.ExpressionsKt.inferExpr(Expressions.kt:64)
	at com.tang.intellij.lua.ty.DeclarationsKt.inferInner(Declarations.kt:40)
	at com.tang.intellij.lua.ty.LuaTypeInfer.inferType(LuaTypeInfer.kt:25)
	at com.tang.intellij.lua.ext.ILuaTypeInfer$Companion.infer(ILuaTypeInfer.kt:33)
	at com.tang.intellij.lua.search.SearchContext.inferAndCache(SearchContext.kt:228)
	at com.tang.intellij.lua.search.SearchContext.access$inferAndCache(SearchContext.kt:35)
	at com.tang.intellij.lua.search.SearchContext$Companion$infer$2.invoke(SearchContext.kt:63)
	at com.tang.intellij.lua.search.SearchContext$Companion$infer$2.invoke(SearchContext.kt:37)
	at com.tang.intellij.lua.search.SearchContext$Companion.with(SearchContext.kt:68)
	at com.tang.intellij.lua.search.SearchContext$Companion.infer(SearchContext.kt:63)
	at com.tang.intellij.lua.psi.LuaTypeGuessable.guessType(LuaTypeGuessable.java:30)
	at com.tang.intellij.lua.ty.ExpressionsKt.inferExpr(Expressions.kt:59)
	at com.tang.intellij.lua.ty.DeclarationsKt.inferInner(Declarations.kt:40)
	at com.tang.intellij.lua.ty.LuaTypeInfer.inferType(LuaTypeInfer.kt:25)
	at com.tang.intellij.lua.ext.ILuaTypeInfer$Companion.infer(ILuaTypeInfer.kt:33)
	at com.tang.intellij.lua.search.SearchContext.inferAndCache(SearchContext.kt:228)
	at com.tang.intellij.lua.search.SearchContext.access$inferAndCache(SearchContext.kt:35)
	at com.tang.intellij.lua.search.SearchContext$Companion$infer$2.invoke(SearchContext.kt:63)
	at com.tang.intellij.lua.search.SearchContext$Companion$infer$2.invoke(SearchContext.kt:37)
	at com.tang.intellij.lua.search.SearchContext$Companion.with(SearchContext.kt:75)
	at com.tang.intellij.lua.search.SearchContext$Companion.infer(SearchContext.kt:63)
	at com.tang.intellij.lua.psi.LuaTypeGuessable.guessType(LuaTypeGuessable.java:30)
	at com.tang.intellij.lua.psi.LuaPsiImplUtilKt$guessParentType$parentTy$1.compute(LuaPsiImplUtil.kt:148)
	at com.tang.intellij.lua.psi.LuaPsiImplUtilKt$guessParentType$parentTy$1.compute(LuaPsiImplUtil.kt)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:42)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:68)
	at com.tang.intellij.lua.ext.UtilsKt.recursionGuard(utils.kt:23)
	at com.tang.intellij.lua.ext.UtilsKt.recursionGuard$default(utils.kt:22)
	at com.tang.intellij.lua.psi.LuaPsiImplUtilKt.guessParentType(LuaPsiImplUtil.kt:147)
	at com.tang.intellij.lua.psi.impl.LuaClassMethodDefImpl.guessParentType(LuaClassMethodDefImpl.java:65)
	at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findOwnerClassGenericDef(LuaPsiTreeUtil.java:106)
	at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findOwnerClassGenericDef(LuaPsiTreeUtil.java:142)
	at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findGenericDef(LuaPsiTreeUtil.java:259)
	at com.tang.intellij.lua.psi.LuaPsiTreeUtil.findGenericDef(LuaPsiTreeUtil.java:273)
	at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.resolveType(LuaDocPsiImplUtil.kt:59)
	at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.getType(LuaDocPsiImplUtil.kt:325)
	at com.tang.intellij.lua.comment.psi.impl.LuaDocGeneralTyImpl.getType(LuaDocGeneralTyImpl.java:38)
	at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.getType(LuaDocPsiImplUtil.kt:320)
	at com.tang.intellij.lua.comment.psi.impl.LuaDocArrTyImpl.getType(LuaDocArrTyImpl.java:38)
	at com.tang.intellij.lua.comment.psi.LuaDocPsiImplUtilKt.getType(LuaDocPsiImplUtil.kt:165)
	at com.tang.intellij.lua.comment.psi.impl.LuaDocTagReturnImpl.getType(LuaDocTagReturnImpl.java:51)
	at com.tang.intellij.lua.stubs.LuaClassMethodType.createStub(LuaClassMethodStub.kt:65)
	at com.tang.intellij.lua.stubs.LuaClassMethodType.createStub(LuaClassMethodStub.kt:34)
	at com.intellij.psi.stubs.DefaultStubBuilder$StubBuildingWalkingVisitor.createStub(DefaultStubBuilder.java:85)
	at com.intellij.psi.stubs.DefaultStubBuilder$StubBuildingWalkingVisitor.visitNode(DefaultStubBuilder.java:60)
	at com.intellij.psi.stubs.DefaultStubBuilder$StubBuildingWalkingVisitor.buildStubTree(DefaultStubBuilder.java:55)
	at com.intellij.psi.stubs.DefaultStubBuilder.buildStubTreeFor(DefaultStubBuilder.java:33)
	at com.intellij.psi.stubs.DefaultStubBuilder.buildStubTree(DefaultStubBuilder.java:22)
	at com.intellij.psi.stubs.StubTreeBuilder.buildStubTree(StubTreeBuilder.java:122)
	at com.intellij.psi.stubs.StubUpdatingIndex$1.computeValue(StubUpdatingIndex.java:172)
	at com.intellij.psi.stubs.StubUpdatingIndex$1.computeValue(StubUpdatingIndex.java:150)
	at com.intellij.psi.stubs.StubUpdatingIndex$1.computeValue(StubUpdatingIndex.java:117)
	at com.intellij.util.indexing.SingleEntryIndexer.map(SingleEntryIndexer.java:30)
	at com.intellij.util.indexing.SingleEntryIndexer.map(SingleEntryIndexer.java:19)
	at com.intellij.util.indexing.impl.MapReduceIndex.mapByIndexer(MapReduceIndex.java:291)
	at com.intellij.util.indexing.impl.MapReduceIndex.mapInput(MapReduceIndex.java:283)
	at com.intellij.util.indexing.impl.storage.VfsAwareMapReduceIndex.mapInput(VfsAwareMapReduceIndex.java:168)
	at com.intellij.util.indexing.impl.storage.VfsAwareMapReduceIndex.mapInput(VfsAwareMapReduceIndex.java:46)
	at com.intellij.util.indexing.impl.MapReduceIndex.mapInputAndPrepareUpdate(MapReduceIndex.java:226)
	at com.intellij.psi.stubs.StubUpdatingIndex$MyIndex.mapInputAndPrepareUpdate(StubUpdatingIndex.java:444)
	at com.intellij.psi.stubs.StubUpdatingIndex$MyIndex.mapInputAndPrepareUpdate(StubUpdatingIndex.java:408)
	at com.intellij.util.indexing.FileBasedIndexImpl.lambda$indexUnsavedDocument$12(FileBasedIndexImpl.java:1023)
	at com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl.freezeFileTypeTemporarilyIn(FileTypeManagerImpl.java:555)
	at com.intellij.util.indexing.FileBasedIndexImpl.indexUnsavedDocument(FileBasedIndexImpl.java:995)
	at com.intellij.util.indexing.RegisteredIndexes$DocumentUpdateTask.doProcess(RegisteredIndexes.java:181)
	at com.intellij.util.indexing.RegisteredIndexes$DocumentUpdateTask.doProcess(RegisteredIndexes.java:172)
	at com.intellij.util.indexing.UpdateTask.process(UpdateTask.java:64)
	at com.intellij.util.indexing.UpdateTask.processAll(UpdateTask.java:33)
	at com.intellij.util.indexing.FileBasedIndexImpl.lambda$indexUnsavedDocuments$11(FileBasedIndexImpl.java:951)
	at com.intellij.util.indexing.StorageBufferingHandler.runUpdate(StorageBufferingHandler.java:33)
	at com.intellij.util.indexing.FileBasedIndexImpl.indexUnsavedDocuments(FileBasedIndexImpl.java:951)
	at com.intellij.util.indexing.FileBasedIndexImpl.ensureUpToDate(FileBasedIndexImpl.java:726)
	at com.intellij.psi.stubs.StubIndexImpl.getContainingIds(StubIndexImpl.java:463)
	at com.intellij.psi.stubs.StubIndexImpl.processElements(StubIndexImpl.java:296)
	at com.intellij.psi.stubs.StubIndex.processElements(StubIndex.java:49)
	at com.intellij.psi.stubs.StubIndex.get(StubIndex.java:39)
	at com.intellij.psi.stubs.AbstractStubIndex.get(AbstractStubIndex.java:22)
	at com.tang.intellij.lua.stubs.index.LuaClassIndex$Companion.process(LuaClassIndex.kt:60)
	at com.tang.intellij.lua.stubs.index.LuaClassIndex$Companion.find(LuaClassIndex.kt:52)
	at com.tang.intellij.lua.stubs.index.LuaClassIndex$Companion.find(LuaClassIndex.kt:47)
	at com.tang.intellij.lua.psi.search.LuaShortNamesManagerImpl.findClass(LuaShortNamesManagerImpl.kt:39)
	at com.tang.intellij.lua.psi.search.CompositeLuaShortNamesManager.findClass(CompositeLuaShortNamesManager.kt:42)
	at com.tang.intellij.lua.psi.search.LuaShortNamesManager.findType(LuaShortNamesManager.kt:70)
	at com.tang.intellij.lua.comment.reference.LuaClassNameReference.resolve(LuaClassNameReference.kt:49)
	at com.intellij.codeInsight.TargetElementUtilBase.getReferencedElement(TargetElementUtilBase.java:177)
	at com.intellij.codeInsight.TargetElementUtilBase.doGetReferenceOrReferencedElement(TargetElementUtilBase.java:165)
	at com.intellij.codeInsight.TargetElementUtilBase.getReferenceOrReferencedElement(TargetElementUtilBase.java:204)
	at com.intellij.codeInsight.TargetElementUtilBase.getReferencedElement(TargetElementUtilBase.java:248)
	at com.intellij.codeInsight.TargetElementUtilBase.doFindTargetElement(TargetElementUtilBase.java:227)
	at com.intellij.codeInsight.TargetElementUtilBase.findTargetElement(TargetElementUtilBase.java:295)
	at com.intellij.codeInsight.TargetElementUtil.findTargetElement(TargetElementUtil.java:147)
	at com.intellij.model.psi.impl.TargetsKt.fromTargetEvaluator(targets.kt:175)
	at com.intellij.model.psi.impl.TargetsKt.declarationsOrReferences(targets.kt:136)
	at com.intellij.model.psi.impl.TargetsKt.declaredReferencedData(targets.kt:43)
	at com.intellij.model.psi.impl.TargetsKt.targetSymbols(targets.kt:24)
	at com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass.getTargetSymbols(IdentifierHighlighterPass.java:233)
	at com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass.highlightReferencesAndDeclarations(IdentifierHighlighterPass.java:225)
	at com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass.doCollectInformation(IdentifierHighlighterPass.java:85)
	at com.intellij.codeInsight.highlighting.BackgroundHighlighter.lambda$updateHighlighted$1(BackgroundHighlighter.java:147)
	at com.intellij.codeInsight.highlighting.BackgroundHighlightingUtil.lambda$lookForInjectedFileInOtherThread$0(BackgroundHighlightingUtil.java:55)
	at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.insideReadAction(NonBlockingReadActionImpl.java:521)
	at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.lambda$attemptComputation$3(NonBlockingReadActionImpl.java:468)
	at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1137)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runInReadActionWithWriteActionPriority$0(ProgressIndicatorUtils.java:76)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runActionAndCancelBeforeWrite(ProgressIndicatorUtils.java:152)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runWithWriteActionPriority$1(ProgressIndicatorUtils.java:113)
	at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:59)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:178)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:658)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:610)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:65)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:165)
	at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:59)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runWithWriteActionPriority(ProgressIndicatorUtils.java:110)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(ProgressIndicatorUtils.java:76)
	at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.attemptComputation(NonBlockingReadActionImpl.java:486)
	at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.lambda$transferToBgThread$1(NonBlockingReadActionImpl.java:408)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:668)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:665)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:665)
	at java.base/java.lang.Thread.run(Thread.java:834)

Code completion for defined callbacks

The typescript plugin provides code completion for callback types, including filling in parameter names for the generated function. I really miss that functionality. Especially given the clunky HTTP API I'm dealing with, who's callback is:

EventHandler = function(table, code, data, errors, header) end

Screen Shot 2020-10-26 at 1 36 44 PM

Screen Shot 2020-10-26 at 1 36 03 PM

This is another item I'd be happy to help on, but I feel like there's a far greater learning curve for me to get there. My Java is rusty, and I don't know the Inellij API at all. I have spent a fair amount of time writing code transforms and know my way around the Javascript AST. I would guess the LUA one is not much different, so I probably could pick it up. If you do want my help, some pointers on where to start would be helpful.

Single line annotation to define function signature (@signature)

Environment

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

What happens?

Currently the only way to define a signature is with multiple annotations, like the @param & @return ones seen in this snippets.

---@param _parent DisplayGroup
---@param _filename string
---@param _baseDir BaseDir
---@param _width number
---@param _height number
---@return Image
---@overload fun(_filename:number, _width:number, _height:number):Image
---@overload fun(_filename:number, _baseDir:number, _width:number, _height:number):Image
---@overload fun(_imageSheet:ImageSheet, frameIndex:number, _width:number, _height:number):Image
---@overload fun(_parent:DisplayGroup, _imageSheet:ImageSheet, frameIndex:number, _width:number, _height:number):Image
function display.newImageRect(_parent, _filename, _baseDir, _width, _height) end
---@param _width number
---@param _height number
---@param _x number
---@param _y number
---@return Rect
function display.newRect(_width, _height, _x, _y) end

What were you expecting to happen?

There to be a way to define the signature without using this many lines. Like the @overload annotations below that. So it would look something like this:

---@signature fun(_parent:DisplayGroup, _filename:number, _baseDir:BaseDir, _width:number, _height:number):Image
---@overload fun(_filename:number, _width:number, _height:number):Image
---@overload fun(_filename:number, _baseDir:number, _width:number, _height:number):Image
---@overload fun(_imageSheet:ImageSheet, frameIndex:number, _width:number, _height:number):Image
---@overload fun(_parent:DisplayGroup, _imageSheet:ImageSheet, frameIndex:number, _width:number, _height:number):Image
function display.newImageRect(_parent, _filename, _baseDir, _width, _height) end
---@signature fun(_width:number, _height:number, _x:number, _y:number):Rect
function display.newRect(_width, _height, _x, _y) end

Any other comments?

Using @overload wouldn't work since it adds a additional signature. And the main signature would be all 'any' types

Nil tracking/checking

Environment

name version
IDEA version IDEA 2020.1
Luanalysis version 1.0.1
OS Linux

What are the steps to reproduce this issue?

  1. Make a local with type foo|nil (in my case, that's because the function's return is marked as so)
  2. Check for ~nil in a branch
  3. Use the local knowing it's not nil

image

What happens?

The local is still assumed to be potentially nil

What were you expecting to happen?

The local should be un-flagged as "potentially nil" interally

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.