Preserve autocomplete while breaking into submodules

I have a big module that contains useful functions / values for many scripts to use. I want to break this in to submodules, then require them in a way similar to:

for _, module in script:GetChildren() do 
	for name, value in require(module) do 
		mainModule[name] = value
	end
end

This way, all the functions and values can still be returned in one table. However, the autocomplete does not work when doing this. Is there any way to break into submodules while preserving autocomplete?

This question was asked previously here, but not answered.

Not sure if this will work, but try explicitly declaring the required modules in the main module’s table instead of using a for loop.

local mainModule = {
	sub1 = require(script.sub1),
	sub2 = require(script.sub2),
}
return mainModule

The problem is this is slightly different. I imagine it would work. But, then I cannot just directly index from the main module. So, instead this would be mainModule.submodule.func(), where i want mainModule.func().

Hi, I’m the original poster.

The only way I could think of solving this is to generate a bunch of headers and pass it to the modules.

In this example, I put the function headers in a block of code that won’t execute at all in runtime but would be picked up by the editor. The header block is generated at runtime once all modules have loaded into it.

	local AGENT = {}

	if not RECOMPILE_FUNC_HEADERS then
		function AGENT:AutoTurn() : nil end
		function AGENT:Avoid() : nil end
		function AGENT:BindResetFunction() : nil end
		function AGENT:CheckTarget() : nil end
		...
		function AGENT:TurnTo() : nil end
		function AGENT:UpdateTarget() : nil end
		function AGENT:UpdateTargetSightline() : nil end
		function AGENT:VerifyPather() : nil end
		function AGENT:Wander() : nil end
	end

	if RECOMPILE_FUNC_HEADERS then
		local list = {}
		for i,v in pairs(AGENT) do
			if type(v) == "function" and not internalFuncNames[i] then
				table.insert(list, string.format("function AGENT:%s() : nil end", i))
			end
		end
		table.sort(list)
		
		for _,e in pairs(list) do
			print(e)
		end
	end

	return AGENT

You can also take advantage of export type and pass the data structure around for the auto complete to work with.

export type LoadedModule = {
	ModuleA: {
		FunctionA1: (string) -> (boolean),
		FunctionA2: (string) -> (nil),
	},
	ModuleB: {
		FunctionB1: (string) -> (boolean),
		FunctionB2: (string) -> (nil),
		FunctionB3: (LoadedModule, number, number) -> (nil),
	},
}

local mainModule: LoadedModule = {}
for _, module in script:GetChildren() do 
	for name, value in require(module) do 
		mainModule[name] = value
	end
end

return mainModule

Again, you need to manually put in the function names, the parameters and their types, and the output.

All of this work is very tedious, but it works. You can automate it if you write a plugin to scan the lines of code and generate new header code based on that, but no one’s done it yet. I haven’t felt the need to do that yet since in most applications I only needed to look at 1-2 scripts within the module set to get stuff working.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.