• Stars
    star
    145
  • Rank 246,145 (Top 5 %)
  • Language
    Kotlin
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Type-safe Lua IDE Plugin for IntelliJ IDEA

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

More Repositories

1

Heimdall

Heimdall is a cross-platform open-source tool suite used to flash firmware (aka ROMs) onto Samsung Galaxy devices.
C++
2,291
star
2

nvidia-update

Install nVidia drivers on macOS the easy way.
Shell
1,284
star
3

react-native-markdown-view

MarkdownView for React Native
JavaScript
190
star
4

VelocityViewPager

Custom Android ViewPager with support for flinging/velocity based scrolling.
Java
80
star
5

s3tc-dxt-decompression

S3TC DXT1/DXT5 texture decompression routines.
C++
44
star
6

luabundle

A library for bundling several Lua files into a single file.
TypeScript
34
star
7

luabundler

CLI tool for bundling several Lua files into a single file.
TypeScript
27
star
8

humble-bundle-key-redeemer

Bulk redemption/activation of Humble Bundle Steam keys.
Ruby
25
star
9

ge_tts

Lua
21
star
10

kogan-tv-gpl

C
20
star
11

Fookoff

Prevent OS X apps stealing focus.
Objective-C
19
star
12

GERazerKit

Unofficial SDK for Razer hardware on macOS.
C
16
star
13

tts-types

Tabletop Simulator EmmyLua types.
Lua
8
star
14

docker-tts

Dockerized Tabletop Simulator
ASP.NET
8
star
15

react-native-android-slidingtabstrip

React Native sliding tab strip implementation for Android.
Java
5
star
16

react-native-android-drawables

React Native support for custom Android Drawables
Java
3
star
17

LuanalysisTypesDemo

Demo of the advanced type functionality added to my EmmyLua fork.
Lua
3
star
18

libopenddl

Several parsers & composers for OpenDDL in different programming languages.
Java
3
star
19

RazerBuildLight

OS X app to turn Razer Chroma accessories into a build light for Github projects
Objective-C
2
star
20

ReactNativeNotificationsExample

Integration of react-native-notifications with the Android Overhaul and iOS Firebase integration.
Objective-C
2
star
21

ge_tts_demo

ge_tts (Tabletop Simulator) demonstration project.
Lua
2
star
22

libpit--Java-

Java library for reading/writing Samsung PIT files, a part of the Heimdall project.
Java
2
star
23

Samsung-Read-Only-FSR

Samsung Flex Sector Remapper (Read-Only)
C
2
star
24

react-native-android-toolbar-badge

React Native support for displaying badges in ToolbarAndroid
Java
2
star
25

SteamKitIntegrationTests

Integration tests for SteamKit
C#
2
star
26

shc

shc creates a stripped binary executable version a shell script.
C
2
star
27

steam-redeem

Steam (in particular Humble Bundle) key redemption extension for Chrome.
JavaScript
2
star
28

pdbtomdb

CLI program to convert C# debug symbols from PDB to MDB (Mono).
C#
1
star
29

pymdown-toc-ext

Python-Markdown Table of Contents (Extended) Extension
Python
1
star
30

react-native-tabular-grid-markdown-view

react-native-tabular-grid fork to be used with react-native-markdown-view
JavaScript
1
star