Language Server Implementation for Luau

Luau Language Server

An implementation of a language server for the Luau programming language.

Getting Started

Install the extension from the marketplace: https://marketplace.visualstudio.com/items?itemName=JohnnyMorganz.luau-lsp

The extension will automatically populate the latest API types and documentation.

To resolve your instance tree and provide module resolution, the language server uses Rojo sourcemaps. The language server will automatically create a sourcemap.json in your workspace root on startup and whenever files are added/created/renamed.

It does this by running the rojo sourcemap command, hence Rojo 7.1.0+ must be available to execute in your workspace root. It is recommend to .gitignore the sourcemap.json file. In future, the language server will generate the file internally.

By default we generate a sourcemap for a default.project.json project file. The name can be changed in extension settings, as well as whether non-script instances are included in the sourcemap (included by default). Autogeneration of sourcemaps can also be toggled completely on/off in settings - the server will instead just listen to manual changes to sourcemap.json files.

Design Goals

The initial goal is to develop a language server supporting all common LSP functions. Module resolution and typing will initially revolve around Rojo.

The idea is to ensure module resolution is customisable, allowing the server to later be easily extended to support other environments where Luau may be used. We could also potentially take it a step forward, allowing the server to be used on an Lua 5.1 codebase through a translation layer (such as type comments through EmmyLua), allowing the language server to support general purpose Lua development powered by the Luau type inference engine.

If you use Luau in a different environment and are interested in using the language server, please get in touch!

Supported Features

  • Rojo Files Resolution
  • API Type Definitions
  • Diagnostics (incl. type errors)
  • Autocompletion
  • Hover
  • Signature Help
  • Go To Definition
  • Go To Type Definition
  • Find References
  • Document Highlight
  • Document Link
  • Document Symbol
  • Color Provider
  • Rename
  • Folding Range
  • Selection Range
  • Call Hierarchy
  • Type Hierarchy
  • Semantic Tokens
  • Inlay Hints
  • Workspace Symbols

The following are extra features defined in the LSP specification, but most likely do not apply to Luau or are not necessary. They can be investigated at a later time:

  • Go To Declaration (do not apply)
  • Go To Implementation (do not apply)
  • Code Actions (not necessary - could potentially add "fixers" for lints)
  • Code Lens (not necessary)
  • Inline Value (applies for debuggers only)
  • Moniker
  • Formatting (see stylua)

Build From Source

mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --target luau-lsp --config Release
Owner
A CS Student interested in tooling, game development, and cyber security
null
Comments
  • Support Studio plugin to infer instance hierarchy

    Support Studio plugin to infer instance hierarchy

    Luau-lsp does not recognize required modules defined in rbxms. However, the instance of the ModuleScript is still recognized by luau-lsp. I expect requires of ModuleScripts defined in .rbxms to work with luau-lsp, but I get type errors instead, shown below.

    I have two reasons for keeping certain modules inside the .rbxl. The first reason is that I do not want to see several hundred modules from Roblox in my VSCode project. The second reason is to easily allow non-coders in my team create projects to edit particular module scripts without Rojo overwriting their work.

    Here is an example project already setup with rbxm files: lsp_bug.zip The included .rbxl shows that the code is valid and works with Rojo.

    image

  • Types a and Player cannot be compared because they do not have the same metatable

    Types a and Player cannot be compared because they do not have the same metatable

    No warnings occur in Studio.

    --!strict
    local event = game:GetService("ReplicatedStorage"):FindFirstChild("RemoteEvent")
    assert(event:IsA("RemoteEvent"), "") -- LSP does now recognize `event` as a `RemoteEvent`.
    
    -- Won't warn if `player` is typed explicitly, but `Player` type is inferred anyway.
    event.OnServerEvent:Connect(function(player, target: Player)
    	print(player == target) -- Warning.
    end)
    
    local working_event: RemoteEvent = game:GetService("ReplicatedStorage"):FindFirstChild("RemoteEvent")
    working_event.OnServerEvent:Connect(function(player, target: Player)
    	print(player == target) -- No warning.
    end)
    
    TypeError: Types a and Player cannot be compared with == because they do not have the same metatable
    
  • `Instance:FindFirstChild()` and `Instance:FindFirstAncestor()` can't always be compared with `nil`

    `Instance:FindFirstChild()` and `Instance:FindFirstAncestor()` can't always be compared with `nil`

    --!strict
    local model = Instance.new("Model")
    assert(model:FindFirstChild("does_not_exist") ~= nil) -- This warns.
    assert(workspace:FindFirstChild("does_not_exist") ~= nil) -- This is fine.
    
    TypeError: Types Instance and nil cannot be compared with ~= because they do not have the same metatable
    
  • Instance.GetChildren returns

    Instance.GetChildren returns "Objects"

    Instead of returning an array of Instances, luau-lsp says workspace:GetChildren() returns Objects. This happens for any other instance as well. image

    This is what Roblox Studio shows for workspace:GetChildren() image

  • UTF-8 error within globalTypes.d.lua causes invalid typechecking

    UTF-8 error within globalTypes.d.lua causes invalid typechecking

    Freshly installed this extension with no conflicting extensions (eg. RobloxLSP), getting a strange error that causes substantial typechecking inaccuracy and general bugs

    Failed to read definitions file c:/Users/Snowdust/AppData/Roaming/Code/User/globalStorage/johnnymorganz.luau-lsp/globalTypes.d.lua. Extended types will not be provided

    image

    SyntaxError: Expected identifier when parsing expression, got invalid UTF-8 sequence

    image

  • Path for luau-lsp.types.definitionFiles doesn't work on Windows

    Path for luau-lsp.types.definitionFiles doesn't work on Windows

    I'm successfully using luau-lsp.types.definitionFiles on macOS to define my own types with an absolute path to a definition file. Unfortunately I can't get the same definitions to work on Windows though. On reload, luau-lsp simply says the definitions file does not exist.

    I'm pretty sure I've tried all combinations and permutations of forward slashes, backward slashes, double slashes, double quotes, etc. I've also tried both using the VSCode Settings UI and editing the json manually.

    I'm also sure the file exists at the path I'm providing! Not sure what else it could be.

  • Diagnostics do not cleared for ignored files

    Diagnostics do not cleared for ignored files

    I would like Luau-LSP to copy Roblox Studio's "Type Inference Modes" behavior documented here: https://luau-lang.org/typecheck#type-inference-modes

    This makes it easier to use other people's code that also uses these annotations without finding and changing ignore globs in vscode. I think this feature should be an optional setting in vscode to respect type inference modes annotation.

  • TypeError: Key not found in class 'LuaSourceContainer'

    TypeError: Key not found in class 'LuaSourceContainer'

    Problem

    Indexing the script keyword when attempting to reference children, i.e. script.Foo, is met with the error of title.

    Replication

    Index the script keyword with an unknown property name, which should resolve to the instance it references.

    Workaround

    Replacing indexing with FindFirstChild method calls silences the error, yet creates strange looking code (maybe biased) with redundant code practice/method misuse. Be aware that module type inference fails if requiring what's returned.

  • Make more generic for non-Roblox use cases

    Make more generic for non-Roblox use cases

    I'm using Luau outside of Roblox. My top problems with this (in terms of LSP-related issues) are:

    1. Type checking with require. The require that Luau gives us doesn't work outside Roblox. Until this is fixed in Luau, I'm using a custom require. It takes a string that is a script name without its file extension. Sadly this breaks exported types because luau-analyze doesn't know what to do. Since it may take a while for require to be fixed, some interim solution for this would be great.
    2. Built-in types. There's no way to inform luau-analyze of my own built-in types (e.g. types I define in C++). zeus mentioned we can modify luau-analyze itself, or in the future there may also be type definition files. But I need a solution in the meantime. :)
    3. OO types. There's no documentation for how to type-annotate OO code. I believe it's doable by casting in the right places. I know it'll be fixed one day with the Records feature. But again, in the meantime I just need something that works.
    4. Dependencies. Some way to use luau-lsp without installing anything extra like Rojo.
    5. Other editors. Ideally some way to get language features outside of just VS Code as well. The Sublime extension zeux showed looked great if it could just address the above issues.

    I know some of these may not make sense to solve in luau-lsp, and maybe in some cases I'm just missing something, but thought I'd share in case anyone has suggestions and/or it's helpful to others.

  • Missing children

    Missing children

    When indexing a player, IntelliSense is missing Player.PlayerGui along with some other instances listed below.

    • Children of StarterGui -> Player.PlayerGui
    • Children of StarterPack -> Player.Backpack
    • Children of StarterPlayerScripts -> Player.PlayerScripts
    • StarterPlayer.StarterCharacter -> Player.Character

    The current workaround for this bug is to manually add these instances into your project.json file.

  • `game` does not contain its children

    `game` does not contain its children

    print(game.ReplicatedStorage) reports the error: TypeError: Key 'ReplicatedStorage' not found in class 'DataModel'

    It's considered good practice to use game:GetService() instead but it can be confusing when this doesn't work.

  • Improve Completion ordering

    Improve Completion ordering

    Right now, we apply no ordering in completion lists, so it is purely alphabetical.

    There are cases where we could improve this:

    • foo: should complete methods before properties (and vice versa for foo.)
    • We should highlight completion items which have the correct type first
    • Autocompleting services should go after variables defined locally
    • "Arbitrary enforcements": eg., FindFirstChild showing first when you use :F on an Instance

    AutocompleteEntry gives us a few things we can use to do this:

    • wrongIndexType (determines method vs property)
    • typeCorrect

    In terms of implementation, the protocol doesn't give us much to work with. There is a property sortText which we can use to enforce sorting. We should compute some sort of ranking on the server side and apply sorting.

  • Improved rename support

    Improved rename support

    A few examples of where renaming can be improved:

    -- Renaming both "tab" and "key" in any of these locations
    local tab = {
    	key = "foo",
    }
    
    tab.key = "bar"
    
    -- Renaming "foo" or "bar" in any of these
    local foo = 1
    
    local function bar()
    	foo = 2
    end
    

    It would also be cool to be able to rename types!

  • Type complexity + `LuauTarjanChildLimit` causes `*error-type*` for resolved requires

    Type complexity + `LuauTarjanChildLimit` causes `*error-type*` for resolved requires

    local module = require(script:FindFirstChild("module"))
    
    local module = {}
    
    function module.execute(player: Player) end -- Won't occur with `player: Instance`.
    
    return module
    

    While I can jump to the module from the require line, module gets typed to *error-type*. This does not occur with "Fflags Enable By Default" off. I don't think this occurred five days ago.

    I haven't yet been able to replicate this in a new project.

C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting

ccls ccls, which originates from cquery, is a C/C++/Objective-C language server. code completion (with both signature help and snippets) definition/re

Oct 2, 2022
A concatenative functional language to be used as a sidekick for the mlatu language

gerku _, | | __ _, ___ ,_ __ | | __ _, _, /\___ / _` | / _ \| '__)| |

Jan 14, 2022
exp2swift translator which translates STEP schema files described in ISO 10303-11 STEP EXPRESS language to the Swift programing language.

STEPswiftcode/ exp2swift exp2swift translator which translates STEP schema files described in ISO 10303-11 STEP EXPRESS language to the Swift programi

Jan 3, 2022
StarkScript - or the Stark programming language - is a compiled C-based programming language that aims to offer the same usability as that of JavaScript's and TypeScript's

StarkScript StarkScript - or the Stark programming language - is a compiled C-based programming language that aims to offer the same usability as that

May 10, 2022
The Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.

Wren is a small, fast, class-based concurrent scripting language Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a fami

Oct 1, 2022
C implementation of the Monkey programming language.
C implementation of the Monkey programming language.

Development of this interpreter continues here: dannyvankooten/pepper-lang C implementation of the Monkey programming language. Bytecode compiler and

Aug 30, 2022
Simple String_View implementation for C programming language.

Simple String_View implementation for C programming language.

Sep 22, 2022
A C++ implementation of the Forth programming language

onward A C++ implementation of the Forth programming language Build # Clone repository git clone https://github.com/tetsuo-cpp/onward.git cd onward/

Mar 6, 2022
In DFS-BFS Implementation In One Program Using Switch Case I am Using an Simple And Efficient Code of DFS-BFS Implementation.
In DFS-BFS Implementation In One Program Using Switch Case I am Using an Simple And Efficient Code of DFS-BFS Implementation.

DFS-BFS Implementation-In-One-Program-Using-Switch-Case-in-C Keywords : Depth First Search(DFS), Breadth First Search(BFS) In Depth First Search(DFS),

Nov 17, 2021
Web Server based on the Raspberry Pico using an ESP8266 with AT firmware for WiFi
Web Server based on the Raspberry Pico using an ESP8266 with AT firmware for WiFi

PicoWebServer This program runs on a Raspberry Pico RP2040 to provide a web server when connected to an Espressif ESP8266. This allows the Pico to be

Sep 1, 2022
OpenTibiaBR - Canary Project is a free and open-source MMORPG server emulator written in C++.
OpenTibiaBR - Canary Project is a free and open-source MMORPG server emulator written in C++.

OpenTibiaBR - Canary Project is a free and open-source MMORPG server emulator written in C++. It is a fork of the OTServBR-Global project. To connect to the server and to take a stable experience, you can use our own client or tibia client and if you want to edit something, check our customized tools.

Sep 22, 2022
Crashser - open source dump/crash server for different programming languages

Crashser - open source dump/crash server for different programming languages (used for crash analysis in various applications). This library is crossplatfrom (now only Windows, Linux, OSX) implementation C++ client for Crasher dump/crash server.

Oct 24, 2021
The Cycle: Frontier server emulation

Prospect Also known as "The Cycle: Frontier". This repository is just something I work on when bored, do not expect much at this stage. Features Conne

Sep 20, 2022
Remastered MW3 Server Freezer for the 1.4:382 version of the game (client)

MW3ServerFreezer Remastered MW3 Server Freezer for the 1.4:382 version of the game (client). Disclaimer This software has been created purely for the

Jul 5, 2022
OneFlow Backend For Triton Inference Server

Triton Inference Server OneFlow Backend

Jan 6, 2022
Passive scriptable LED server for Raspberry Pi

Passive LED server Scriptable LED server that you can just keep running all the time on a Raspberry Pi. Requirements Raspberry Pi 4 or newer (older mi

Dec 1, 2021
Plex media server local privilige escalation poc - CVE-2021-42835

Local Privilege PlEXcalasion - CVE-2021-42835 Plex Media Server for Windows prior to version 1.25.0.5282, vulnerable to Time Of Check Time Of Use (TOC

May 24, 2022
The main repository for the Darkflame Universe Server Emulator project.
The main repository for the Darkflame Universe Server Emulator project.

Darkflame Universe Introduction Darkflame Universe (DLU) is a server emulator for LEGO® Universe. Development started in 2013 and has gone through mul

Sep 24, 2022