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
  • 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

  • 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.

  • Cannot detect types from child module tied to & when requiring parent module

    Cannot detect types from child module tied to & when requiring parent module

    Context

    I have a module labelled Utils that stores many helper functions I like to use, I also have a Types child module internally required and set to Utils.Types.

    Problem

    Typically, "type modules" would work as predicted where types pertaining to Utils.Types (when set as a variable, i.e. local Types = Utils.Types) would evaluate accordingly - Roblox LSP abides by this as a reference. The module is instead perceived as an empty table shown below:

    local Types: {|  |}
    

    Typehints used also raise the following error:

    TypeError: Unknown type 'Types.Array' Luau [1001]
    

    Reproduction

    Here's an example package if you'd rather skip the setup.

    Create 2 modules - a type module and a parent module that requires then sets the type module to a property within itself (e.g. { Types = require(...) }). Create a script that requires the parent module and attempt to use the types stored within it, you should run into the same problems as described.

    Sorry for the loopy name and post by the way, couldn't think of a better way to put my point across. Feel free to change the name to something more coherent or make suggestions.

  • Use ClassName for instance type name

    Use ClassName for instance type name

    I generated a single rbxm for workspace using remodel, then I added it to my project json file like this:

        "Workspace": {
          "$path": "src/Workspace.rbxm"
        }
    

    When I hover over the variable, I expect to see its type as BasePart. Instead it just shows the name of the instance. image

  • Workspace diagnostics do not respect ignore globs

    Workspace diagnostics do not respect ignore globs

    Seems that when workspace diagnostics are enabled they don't respect ignore globs. I've had this happen when initially opening a workspace in VSCode, and then sometimes periodically thereafter. A workaround for now is to just open the file that has the diagnostics and close it again.

  • Cannot intelligently infer type of re-defined parameters with default values

    Cannot intelligently infer type of re-defined parameters with default values

    Upon defining a parameter with an optional type, re-declaring the parameter causes the following error(?) to be raised:

    local iterations: number?
    TypeError: Type 'number?' could not be converted into 'number' Luau(1000)
    

    I would assume this is an internal error raised by the extension, regardless it's to be expected that the inferred type becomes number after re-defining the parameter as it then becomes impossible for it to be nil.

    Minimal reproduction code snippet:

    local function count(iterations: number?)
        iterations = iterations or 10  -- type remains "number?"
    
        for i = 1, iterations do  -- error raised here
            print(i)
        end
    end
    

    Type-casting the parameter upon usage and forcing the type to number silences the error despite the odd approach:

    for i = 1, iterations::number do
        print(i)
    end
    

    If there are any mistakes made/lacking information, do let me know and I will make edits accordingly.

  • Cannot require PlayerScripts in local player

    Cannot require PlayerScripts in local player

    TypeError: Unknown require: game/Players/LocalPlayer/PlayerScripts/PurchaseClient
    

    We should map game/Players/LocalPlayer/PlayerScripts to StarterPlayerScripts (and similar for StarterGear, StarterGui etc.)

  • Add option to customize enabled FFlags

    Add option to customize enabled FFlags

    Blindly enabling all FFlags can result in unintended Luau errors that aren't reproducible in Roblox Studio. Is there possibly a way to match the currently enabled flags for Roblox, and also provide customization (e.g. toggling a specific flag)?

  • Types not being exported from modules along a FindFirstAncestor path

    Types not being exported from modules along a FindFirstAncestor path

    I have a types.lua file at the root of my project that simply exports types and returns an empty table.

    The following using a relative path works just fine:

    local types = require(script.Parent.Parent.Parent.types)
    
    export type Node = {
    	name: string,
    	children: { Node },
    	icon: string?,
    	instance: Instance?,
    	storybook: types.Storybook,
    }
    

    However, the following does not work for types:

    local flipbook = script:FindFirstAncestor("flipbook")
    local types = require(flipbook.types)
    
    export type Node = {
    	name: string,
    	children: { Node },
    	icon: string?,
    	instance: Instance?,
    	storybook: types.Storybook, -- <-- This is highlighted as an error
    }
    

    Note that FindFirstAncestor paths do work for non-type members. Seems to be just types that aren't getting picked up

  • FindFirstAncestor does not properly resolve children

    FindFirstAncestor does not properly resolve children

    I have the following project:

    {
      "name": "flipbook",
      "tree": {
        "Packages": {
          "$path": "Packages"
        },
        "$path": "src"
      }
    }
    

    And in a module under src/ I am trying to include the following:

    local flipbook = script:FindFirstAncestor("flipbook")
    

    The flipbook variable is typed as Instance, which tells me that luau-lsp is at least doing some work, but attempting to index flipbook for any of its child modules comes up empty.

    I'm unsure if this is a misconfiguration on my part, or if luau-lsp just doesn't support this yet

    For further context, you can view the source code for the repo here

  • Required modules' types do not update

    Required modules' types do not update

    If you require a module that returns a function, for example, and change the return to a table, other scripts that require that module will still have the old function type. The script that is requiring the module has to be open while the module gets updated for this to happen.

    Closing the module and/or the script that requires it does not fix the issue.

    How to reproduce:

    1. rojo init
    2. Paste following code into src/server/init.server.lua:
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    
    local Hello = require(ReplicatedStorage.Common.Hello)
    
    Hello()
    
    1. Keep the server script open
    2. Paste following code into src/shared/Hello.lua:
    return {
    	hello = function() end,
    }
    
    1. Change the last line in src/server/init.server.lua: Hello.hello()
    2. Error appears on that line: TypeError: Type '() -> ()' does not have key 'hello'
  • Errors when loading non-Roblox workspace

    Errors when loading non-Roblox workspace

    I see the following two errors when opening a workspace that is vanilla Luau: image

    I have disabled both of the settings mentioned in the readme:

    image image

    Interestingly I see these errors when I double-click to open a file in the workspace, not when the workspace is first opened.

  • ToStringNamedFunction does not correctly resolve table name

    ToStringNamedFunction does not correctly resolve table name

    local Account = {}
    
    function Account.New()
        local self = setmetatable({}, Account)
        self.Balance = 10
    
        return self
    end
    
    function Account:Deposit(Amount: number)
        self.Balance += Amount
    end
    
    local a: Account = Account.New()
    
    a:Deposit(10)
    

    Hovering over a:Deposit(10) gives function a:Deposit(self: ..., Amount: number): (), when it should ideally give function Account:Deposit(self: ..., Amount: number):()

  • LSP does not recover from invalid UTF-8

    LSP does not recover from invalid UTF-8

    Accidentally typing or pasting a symbol such as these:

    §

    Will emit the following message:

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

    When the symbol is removed, the message does not go away like it does in studio. Worth noting is that the error message in studio is slightly different:

    SyntaxError: Expected identifier when parsing expression, got unicode character U+...

  • 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.

  • Register extra definition files depending on file

    Register extra definition files depending on file

    It would be good to be able to register extra definitions, e.g. testez.d.lua.

    We should put this in configuration and make it so it maps globs to extra definitions

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

Jun 19, 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

Jun 16, 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

May 29, 2022
Simple String_View implementation for C programming language.

Simple String_View implementation for C programming language.

May 14, 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

Jun 10, 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.

Jun 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

Jun 9, 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

Dec 26, 2021
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

Jun 19, 2022