luttje / luttje/glua-api-snippets

Plugin. WIP (DEFINE_BASECLASS, sent classes, NetworkVar, AccessorFunc)

Open
#74 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
45
Forks
10
PR merge metrics
No merged PRs in 30d

Description

Goal

We need a plugin that implements some game specific behavior of Lua things, like Set/Get generation, auto class naming/detection.

OnSetText implementation

An example of a simple plugin that

  1. Expands preprocessor macro DEFINE_BASECLASS.
  2. Automatically classifies scripted ents by folder/filename and solves "duplicate field" inside the sent file.
---@class gmod_hands: ENT
local ENT = {}

... original file code with ENT usage

However, I don't want to use it in this form, because it's working with text, and it's reached the edge of its possibilities. For example, you can see that the first character of sent file is displayed in green, because I am injecting a fake class there.

Implementing a NetworkVar and AccessorFunc already seems impossible with a text.

---@class diff
---@field start integer # The number of bytes at the beginning of the replacement
---@field finish integer # The number of bytes at the end of the replacement
---@field text string # What to replace

local scopeFolders = {
	{ "EFFECT", "effects" },
	{ "SWEP",   "weapons" },
	{ "ENT",    "entities" }
}

---@param uri string
---@return string?, string?
local function GetScopedClass(uri)
	for _, scope in ipairs(scopeFolders) do
		-- gamemode based uri:
		-- .../gamemodes/my_gamemode/entities/entities/ent_class_name/any.lua
		-- .../gamemodes/my_gamemode/entities/entities/ent_class_name.lua
		local class = uri:match("%Wentities/" .. scope[2] .. "/([^/]+)/?[^/]*%.lua$")
		if not class then
			-- addon or root based uri:
			-- .../addons/my_addon/lua/entities/ent_class_name/any.lua
			-- .../addons/my_addon/lua/entities/ent_class_name.lua
			class = uri:match("%Wlua/" .. scope[2] .. "/([^/]+)/?[^/]*%.lua$")
		end
		if class then
			return scope[1], class
		end
	end
end

---@param uri string # The uri of file
---@param text string # The content of file
---@return diff[]?
function OnSetText(uri, text)
	---@type diff[]
	local diffs = {}

	-- Detect "scripted" scope by folder and localize its global table to @class annotation.
	local scope, class = GetScopedClass(uri)
	if scope then
		diffs[#diffs + 1] = {
			start = 1,
			finish = 1,
			text = ([[
---@class %s: %s
local %s = {}

%s]]):format(class, scope, scope, text:sub(1, 1))
		}
	end

	-- Replace preprocessor keyword DEFINE_BASECLASS.
	for start, finish, b, c in text:gmatch("()DEFINE_BASECLASS()") do
		diffs[#diffs + 1] = {
			---@cast start integer
			start = start,
			finish = finish - 1,
			text = "local BaseClass = baseclass.Get",
		}
	end

	if #diffs == 0 then
		return nil
	end

	return diffs
end

Completed features

  • Expands preprocessor macro DEFINE_BASECLASS.
  • Automatically classifies scopes of scripted ents (ENT, SWEP, EFFECT) by folder/filename. This is necessary step to add any methods to the class, and also solves "duplicate field" inside the sent file.
  • It needs to be rewritten to OnTransformAst/VM.OnCompileFunctionParam.
  • How to distribute a plugin with an addon?
  • Implement NetworkVar/NetworkVarElement. It only works in sent file inside of ENT:SetupDataTables for self:NetworkVar(...) and self.NetworkVar(self, ...) for stack defined arguments, not localized one.
    Doesn't support BaseClass.SetupDataTables(self).

Refs

Plugin samples

OnSetText
https://github.com/goldenstein64/lualogging-definitions/blob/13aabcde86b98c3bd3d2cacc0121f288496db045/plugin.lua
https://github.com/goldenstein64/pl-definitions/blob/54bf99b9d6394f6e9bab0fb2029ecf908db9a8cc/plugin.lua
https://github.com/serg3295/nodeMCU-emmylua/blob/232b42845e2f7a32ef8837417b409f5db666ecdf/plugin.lua
https://github.com/RavenfieldCommunity/RavenscriptIDEA/blob/7525a2eb431d27199e8c17aeceb872b1d559c4aa/plugin.lua
https://github.com/ProjectTH/fivem-lls-addon/blob/c93a8d64d0b541feda6b09b86961a7d62db2ee6d/plugin.lua

ResolveRequire
https://github.com/Periapsises/Starfall-LLS/blob/de36268b6218dca73b492176e8ef013b31bf3d6c/plugin.lua

OnCompileFunctionParam, ResolveRequire
https://github.com/Wild-W/smbx2-lunalua-luacats/blob/417401f1e6ade91809067bb2afac84f90109ab08/plugin.lua

OnTransformAst
https://github.com/LuaCATS/dontstarve/blob/42a8810744bb00266d733f9ed84b56b91fe74e94/plugin/dontstave.lua
https://github.com/DeadlyBossMods/LuaLS-Config/blob/main/Plugin/Mod-Class-Plugin.lua

Custom diagnostics:
https://github.com/LuaLS/lua-language-server/discussions/2511
https://github.com/DeadlyBossMods/LuaLS-Config/blob/main/Plugin/Event-Diagnostic.lua

TODO

  • Implement AccessorFunc.
  • Localize Set/Get class to self: ent_myent instead of self: Entity?
  • Lookup ents.Find* functions for existing classes instead of T|Entity (cannot cast ent_notdefined|Entity to Entity).
  • PANEL table auto classification by derma.DefineControl, vgui.Register.
  • Maybe hook.Add/hook.Call/hook.Run.
  • Research support for BaseClass.SetupDataTables(self)
  • Performance check.

I haven't had time for further research yet 😪

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing plugin.lua implementation and the documented OnTransformAst and VM.OnCompileFunctionParam entry points. Define a single scope from the TODO list, such as AccessorFunc, PANEL classification, or BaseClass.SetupDataTables support; the issue names no test file or run command for verifying completion.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.