Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with dot notation for require #874

Open
mhrf opened this issue Dec 23, 2024 · 2 comments
Open

Problem with dot notation for require #874

mhrf opened this issue Dec 23, 2024 · 2 comments

Comments

@mhrf
Copy link

mhrf commented Dec 23, 2024

Hello everyone,

I tried to look up for solution for luau-lsp to accept . (dot) notation but without any success. I am using "luau-lsp.platform.type": "standard".

This is required format in luau script in environment I am forced to use:

local components = require(engine.widgets.proto.components)

(engine.widgets.proto.components is filled in runtime using directory tree structure so file is in cfgpath/Scripts/widgets/proto/component.lua)

This is closest I managed to get:
local components = require("@engine/widgets/proto/components") using alias.

Is there any settings or way how for require to correctly resolve required script, is there simple way how to implement custom file resolver for require ?

Restrictions

  1. I cannot change require nor modify it in runtime to create wrapper that would do translation from

"@engine/widgets/proto/components" -> engine.widgets.proto.components and to call require on this global object

  1. At this moment I dont want to write preprocess script that would change given lua script, except if there is option to directly feed this into luau-lsp (without the need to change lua script on disk)

Thank you for your time

@JohnnyMorganz
Copy link
Owner

Hey, interesting to hear about usage in a different engine!

Unfortunately, there isn't a way right now to fully support custom require syntaxes like this, without modifying the C++ code to introduce a new platform with require resolver. Ideally this would be solved with either (1) standardised require-by-string semantics as you've tried with an alias (but this requires your engine to support it, as pointed out by your restrictions), or (2) support Luau-based plugins to configure require logic (but this requires a lot of implementation, covered in #595)

However, the example you give seems very similar to the way Roblox requires work, so you might be able to abuse some of that logic. You would need to set luau-lsp.platform.type to roblox and create a sourcemap.json file in the root of your workspace in the following style:

{
  "name": "Engine",
  "className": "DataModel",
  "children": [
    {
      "name": "widgets",
      "className": "Folder",
      "children": [
        {
          "name": "proto",
          "className": "Folder",
          "children": [
            {
              "name": "components",
              "className": "ModuleScript",
              "filePaths": ["cfgpath/Scripts/widgets/proto/components.lua"]
            }
          ]
        }
      ]
    }
  ]
}

Then, put declare engine: DataModel in a global definitions file would allow indexing (we are faking the game node here that is normally used in Roblox). You might need to edit the Roblox definitions file to prevent it from polluting your autocomplete.

Do you have more details / examples of the engine you are using this with? I'd be interested to see how we can support that better.

@mhrf
Copy link
Author

mhrf commented Jan 8, 2025

Hello Johny and Happy new year to you,

thank you for providing alternative solution I really appreciate it. I tried several combinations of sourcemap.json content and luau-lsp settings, but I was not able to achieve any progress. After import (local x = require(game.y.z) there was really no understanding of what was imported in the same way when it works with local components = require("@engine/widgets/grid") or local cross require("@game/hud/cross") where @engine and @GAMe are aliases and path goes relative to project root and then given variable really contains anything returned and autocomplete works.

in .luaurc I simply set following values:

"aliases": {
    "engine": "./scripts",
    "game": "./scripts/game"
}

So my current workaround is that at start of coding session I run custom program that takes all *.lua from git project A and creates copy of it into directory B with all lua files modified requires statements:

require(game.x.y") -> require("@game/x/y")

and then I open in VSCode this directory B, and on save of lua file ("Run on Save" from emeraldwalk extension) I run again for given file reverse conversion

require("@game/x/y") -> require(game.x.y) and save it to correct place in directory A, game is monitoring directory A so any change in lua scripts in directory A will reload scripts correctly.

Its a bit cumbersome, but the benefit of autocomplete for imports is worth it, I tried it without it and it was really pain, now everything works flawlessly.

Also you asked about what engine is this for - its project based on unreal engine, lua scripts are used to call exposed api functions from game itself, atm mostly related to scene & camera manipulation. Also UI is planned to be created this way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants