Script Analysis API for Plugins

Currently on Roblox, it’s far too difficult to analyse the contents of scripts from a plugin.

There are many developer tools in the wider industry which typically depend on static analysis, such as linters, code formatters, transpilers and various further kinds of debugging tools. While I appreciate the effort to try and build all of this right into Roblox Studio, this will never be able to cover the specialist applications of these tools.

For disparate and niche use cases, there should be a way for plugins to statically analyse scripts using Luau’s existing lexing and parsing tools. The inputs to our plugins that deal with source code should not be strings - instead, they should be structures that can be easily consumed, traversed, modified and compared by machines.


A representative, yet horrible, real world example


Here’s a specific real-world example to solidify the concept - I’m going to write a plugin that automatically detects Fusion components in module scripts and lists them in a UI. You don’t need to know Fusion - I’ll provide simplified definitions of what you need to know.

Fusion components are not a special object or construct. Instead, they are a coding convention. They are plain Lua functions, which take in a table and return an Instance. In other words, we’re looking for functions with this type definition:

type Component = ( {[string]: any} ) -> Instance

In our plugin, we’ll define a function that we call with any module scripts we find. We want this function to return the names of every component found in the file:

local function getComponentNamesFrom(module: ModuleScript): {string}
    -- TODO: implement this
end

How do we implement this? There’s a lot of steps involved:

  • Get the source code from the module
  • Divide up the source code into small units, such as keywords, strings, numbers, comments, identifiers etc. (‘lexing’ the source code)
  • Analyse how the units fit together into larger Lua structures, such as function definitions, statements, for-loops etc. (‘parsing’ the units)
  • Figure out how variables, values and type definitions move around the program; where they come into and go out of scope, etc.
  • Infer types of variables, functions, etc. by tracing where their values come from and what types those values take on. (in addition to other stuff, like type narrowing)
  • Identify functions with the Component type signature, using everything we’ve learned so far
  • Compile the function names into a list, and return the list.

We’ve essentially re-implemented Luau’s entire static analysis stack for a really trivial task! What’s even worse is that, even if we got all of this right, Luau is an ever-developing language, and our code will break the moment new syntax or behaviour is introduced. It becomes an endless treadmill of keeping up to date on top of an already-monumental upfront implementation cost.

This is where this feature request comes into play. If plugins had access to some kind of script analysis API, we could offload almost all of that language parsing and analysis work to the Luau tools which already exist and are actively used by Roblox’s tools. The new series of steps would be much simpler and far more robust:

  • Get the source code from the module
  • Use the Script Analysis API to process the source code into an easy-to-analyse structure of some kind
  • Identify functions with the Component type signature within that structure
  • Compile the function names into a list, and return the list.

This is far more reasonable to do, and serves as a perfect example of why such an API is necessary for the development of any kind of scripting-oriented plugin, beyond the basic infrastructure of editing a text string. This is the reason Roblox has almost no good intelligent script-oriented plugins right now, and it’s holding developers back.

The modern development workflow demands good analysis tools as table stakes. It’s time Roblox made this possible on their platform without reimplementing an entire scripting language by hand.

35 Likes

It would be so cool to access the backend luau-analyze tool that Roblox uses to run this.

It would also be cool to “inject” autocompletes into the autocomplete tool, as someone who relies on a functional driven engine…

function main(self, scriptAPI)
  scriptAPI. [Services]
             [Networking]
end

I have to export a types module with the engine to just get these niceties, but it would still be so much better to just have a plugin do it for me using the analyser tool.

Even in general usecases, it would be so useful to have this, to, for example, colour code in code blocks inside a plugin’s UI.

4 Likes