From 453ed5cb8eef4d864fff397089632928a08a3120 Mon Sep 17 00:00:00 2001 From: TaylorsRus Date: Wed, 13 Nov 2024 20:06:39 +0000 Subject: [PATCH 1/3] Plugin settings now save, minor code refactor --- plugin/src/DefaultSettings.lua | 20 --- plugin/src/init.server.lua | 306 ++++++++++++++++----------------- 2 files changed, 151 insertions(+), 175 deletions(-) delete mode 100644 plugin/src/DefaultSettings.lua diff --git a/plugin/src/DefaultSettings.lua b/plugin/src/DefaultSettings.lua deleted file mode 100644 index 3c529804..00000000 --- a/plugin/src/DefaultSettings.lua +++ /dev/null @@ -1,20 +0,0 @@ -return { - port = 3667, - startAutomatically = false, - include = { - game:GetService("Workspace"), - game:GetService("Players"), - game:GetService("Lighting"), - game:GetService("ReplicatedFirst"), - game:GetService("ReplicatedStorage"), - game:GetService("ServerScriptService"), - game:GetService("ServerStorage"), - game:GetService("StarterGui"), - game:GetService("StarterPack"), - game:GetService("StarterPlayer"), - game:GetService("SoundService"), - game:GetService("Chat"), - game:GetService("LocalizationService"), - game:GetService("TestService"), - }, -} diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 5ba98c87..12cfd00c 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -1,83 +1,49 @@ ---!strict +--!nocheck local HttpService = game:GetService("HttpService") -assert(plugin, "This code must run inside of a plugin") +local RunService = game:GetService("RunService") +local ScriptEditorService = game:GetService("ScriptEditorService") +local TestService = game:GetService("TestService") -if game:GetService("RunService"):IsRunning() then +local IsRunning = RunService:IsRunning() +if IsRunning then return end +assert(plugin, "This code must run inside of a plugin") -local toolbar = plugin:CreateToolbar("Luau") - -local ConnectButton = toolbar:CreateButton( - "Luau Language Server Setup", - "Toggle Menu", - "rbxassetid://11115506617", - "Luau Language Server" -) :: PluginToolbarButton - -local SettingsButton = - toolbar:CreateButton("Settings", "Open Settings", "rbxassetid://13997395868") :: PluginToolbarButton - ---#region Settings - -local AnalyticsService = game:GetService("AnalyticsService") - -local Settings = nil :: any - -local SettingsModule = AnalyticsService:FindFirstChild("LuauLSP_Settings") :: ModuleScript -if not SettingsModule then - SettingsModule = (script :: any).DefaultSettings:Clone() - assert(SettingsModule, "Luau Typechecking") - SettingsModule.Name = "LuauLSP_Settings" - SettingsModule.Parent = AnalyticsService -end -assert(SettingsModule, "failed to create settings module") - -local function LoadSettings() - local result, parseError: any = loadstring(SettingsModule.Source) - if result == nil then - warn("[Luau Language Server] Could not load settings: " .. parseError) - Settings = nil - return - end - assert(result, "") - local _, err = pcall(function() - Settings = result() - end) - if err then - warn(err) - end - if type(Settings) ~= "table" then - Settings = nil - warn("[Luau Language Server] Could not load settings: invalid settings") - elseif type(Settings.port) ~= "number" then - Settings = nil - warn("[Luau Language Server] Could not load settings: invalid port") - elseif type(Settings.startAutomatically) ~= "boolean" then - Settings = nil - warn("[Luau Language Server] Could not load settings: invalid startAutomatically value") - elseif type(Settings.include) ~= "table" then - Settings = nil - warn("[Luau Language Server] Could not load settings: invalid include list") - end -end - -LoadSettings() - ---#endregion - ---#region Connect - -local ConnectAction = plugin:CreatePluginAction( - "Luau Language Server Connect", - "Connect", - "Connects to Luau Language Server", - "rbxassetid://11115506617", - true -) +local SETTINGS_MODULE_NAME = "LuauLSP_Settings" +local DEFAULT_SOURCE = [[ +return { + --// Should be unique to Rojo port (different). + Port = 3667, + + --// Decides whether or not the companion plugin automatically starts listening on studio launch. + StartAutomatically = false, + + --// Setting to true will enable verbose error messages and warns. Currently does nothing. + DebugMode = false, + + --// List of instances who's descendants will be encoded and sent to VS Code. + Include = { + game:GetService("Workspace"), + game:GetService("Players"), + game:GetService("Lighting"), + game:GetService("ReplicatedFirst"), + game:GetService("ReplicatedStorage"), + game:GetService("ServerScriptService"), + game:GetService("ServerStorage"), + game:GetService("StarterGui"), + game:GetService("StarterPack"), + game:GetService("StarterPlayer"), + game:GetService("SoundService"), + game:GetService("Chat"), + game:GetService("LocalizationService"), + game:GetService("TestService"), + }, +} +]] -local connected = Instance.new("BoolValue") -local connections = {} +local Connections: { RBXScriptConnection } = {} +local Connected = false type EncodedInstance = { Name: string, @@ -85,138 +51,168 @@ type EncodedInstance = { Children: { EncodedInstance }, } -local wasConnected -SettingsButton.Click:Connect(function() - plugin:OpenScript(SettingsModule) - wasConnected = connected.Value -end) +local Toolbar = plugin:CreateToolbar("Luau LSP Test") +local ConnectAction = + plugin:CreatePluginAction("Luau LSP Connect", "Connect", "Connects to Luau LSP", "rbxassetid://11115506617", true) +local ConnectButton = Toolbar:CreateButton("Luau LSP Setup", "Toggle Menu", "rbxassetid://11115506617", "Luau LSP") +local SettingsButton = Toolbar:CreateButton("Settings", "Open Settings", "rbxassetid://13997395868") + +local function GetAndValidateSettingsModule() + local SettingsModule = ( + TestService:FindFirstChild(SETTINGS_MODULE_NAME) or Instance.new("ModuleScript") + ) :: ModuleScript + local SettingsModuleSource = ScriptEditorService:GetEditorSource(SettingsModule) + if SettingsModuleSource == "" or SettingsModuleSource == nil then + ScriptEditorService:UpdateSourceAsync(SettingsModule, function() + return DEFAULT_SOURCE + end) + warn("[Luau LSP] Could not load settings: Unable to find saved settings, reverting to default settings.") + end -local function filterServices(child: Instance): boolean - return not not table.find(Settings.include, child) + --// No loss in not running a check here since Luau runs an internal validation for set + SettingsModule.Name = SETTINGS_MODULE_NAME + SettingsModule.Parent = TestService + + local Settings = require(SettingsModule) + if typeof(Settings) ~= "table" then + error("[Luau LSP] Could not load settings: Settings module does not return a table.") + elseif typeof(Settings.Port) ~= "number" then + error("[Luau LSP] Could not load settings: Port is not a number.") + elseif type(Settings.StartAutomatically) ~= "boolean" then + error("[Luau LSP] Could not load settings: StartAutomatically is not a boolean.") + elseif type(Settings.Include) ~= "table" then + error("[Luau LSP] Could not load settings: Include list is not a table.") + end + + return SettingsModule end -local function encodeInstance(instance: Instance, childFilter: ((Instance) -> boolean)?): EncodedInstance - local encoded = {} - encoded.Name = instance.Name - encoded.ClassName = instance.ClassName - encoded.Children = {} +local SettingsModule = GetAndValidateSettingsModule() +local Settings = require(SettingsModule) - for _, child in instance:GetChildren() do - if childFilter and not childFilter(child) then +local function FilterServices(Child: Instance): boolean + return not not table.find(Settings.Include, Child) +end + +local function EncodeInstance(Instance: Instance, ChildFilter: (Instance) -> boolean?): EncodedInstance + local Encoded = {} + Encoded.Name = Instance.Name + Encoded.ClassName = Instance.ClassName + Encoded.Children = {} + + for _, Child in Instance:GetChildren() do + if ChildFilter and not ChildFilter(Child) then continue end - table.insert(encoded.Children, encodeInstance(child)) + table.insert(Encoded.Children, EncodeInstance(Child)) end - return encoded + return Encoded end -local function cleanup() - for _, connection in pairs(connections) do - connection:Disconnect() +local function CleanUpConnections() + local WasConnected = Connected + for _, Connection in Connections do + Connection:Disconnect() + end + Connected = false + ConnectButton.Icon = "rbxassetid://11115506617" + + if WasConnected then + warn("[Luau LSP] No longer sending DataModel information.") end - connected.Value = false end -local function sendFullDMInfo(isSilent) - local tree = encodeInstance(game, filterServices) +local function SendDataModelInfo() + local Tree = EncodeInstance(game, FilterServices) - local success, result = pcall(HttpService.RequestAsync, HttpService, { + local Success, Result = pcall(HttpService.RequestAsync, HttpService, { Method = "POST" :: "POST", - Url = string.format("http://localhost:%s/full", Settings.port), + Url = string.format("http://localhost:%s/full", tostring(Settings.Port)), Headers = { ["Content-Type"] = "application/json", }, Body = HttpService:JSONEncode({ - tree = tree, + tree = Tree, }), Compress = Enum.HttpCompression.Gzip, }) - if not success then - warn(`[Luau Language Server] Connecting to server failed: {result}`) - cleanup() - elseif not result.Success then - warn(`[Luau Language Server] Sending full DM info failed: {result.StatusCode}: {result.Body}`) - cleanup() + if not Success then + warn(`[Luau LSP] Connecting to server failed: {Result}`) + CleanUpConnections() + elseif not Result.Success then + warn(`[Luau LSP] Sending DataModel info failed: {Result.StatusCode}: {Result.Body}`) + CleanUpConnections() else - connected.Value = true - if not isSilent then - print(`[Luau Language Server] Successfully sent full DataModel info`) - end + Connected = true + ConnectButton.Icon = "rbxassetid://11116536087" + warn("[Luau LSP] Now sending DataModel information.") end end -local function watchChanges(isSilent) - local sendTask: thread? - if connected.Value or Settings == nil then - if not isSilent then - warn("[Luau Language Server] Connecting to server failed: invalid settings") - end +local function WatchChanges() + local SendTask: thread? + if Connected or Settings == nil then + warn("[Luau LSP] Connecting to server failed: Already connected, or settings non-existent.") return end - cleanup() + CleanUpConnections() - local function deferSend() - if sendTask then - task.cancel(sendTask) + local function DeferSend() + if SendTask then + task.cancel(SendTask) end - sendTask = task.delay(0.5, function() - sendFullDMInfo(isSilent) - sendTask = nil + SendTask = task.delay(0.5, function() + SendDataModelInfo() + SendTask = nil end) end -- TODO: we should only send delta info if possible - local function descendantChanged(instance: Instance) - for _, service in Settings.include do - if instance:IsDescendantOf(service) then - deferSend() + local function DescendantChanged(Instance: Instance) + for _, Service in Settings.Include do + if Instance:IsDescendantOf(Service) then + DeferSend() return end end end - table.insert(connections, game.DescendantAdded:Connect(descendantChanged)) - table.insert(connections, game.DescendantRemoving:Connect(descendantChanged)) - sendFullDMInfo(isSilent) + table.insert(Connections, game.DescendantAdded:Connect(DescendantChanged)) + table.insert(Connections, game.DescendantRemoving:Connect(DescendantChanged)) + SendDataModelInfo() end -function connectServer(isSilent: boolean?) - if connected.Value then - if not isSilent then - print("[Luau Language Server] Disconnecting from DataModel changes") - end - cleanup() +function ToggleServerConnection() + if Connected then + CleanUpConnections() else - if not isSilent then - print("[Luau Language Server] Connecting to server") - end - watchChanges(isSilent) + WatchChanges() end end -ConnectButton.Click:Connect(connectServer) +ConnectButton.Click:Connect(ToggleServerConnection) +ConnectAction.Triggered:Connect(ToggleServerConnection) -ConnectAction.Triggered:Connect(connectServer) - -connected.Changed:Connect(function() - ConnectButton.Icon = if connected.Value then "rbxassetid://11116536087" else "rbxassetid://11115506617" +SettingsButton.Click:Connect(function() + plugin:OpenScript(SettingsModule) end) -if Settings and Settings.startAutomatically then - connectServer() -end - -SettingsModule.Changed:Connect(function() - if connected.Value then - cleanup() +SettingsModule:GetPropertyChangedSignal("Source"):Connect(function() + local WasConnected = Connected + if Connected then + CleanUpConnections() end - LoadSettings() - if wasConnected then - connectServer(true) -- Silent mode + SettingsModule = GetAndValidateSettingsModule() + Settings = require(SettingsModule) + + if WasConnected then + ToggleServerConnection() end end) ---#endregion +if Settings and Settings.StartAutomatically then + ToggleServerConnection() +end From 96c56976b1e0698563700c2c1985693da066ae46 Mon Sep 17 00:00:00 2001 From: TaylorsRus Date: Wed, 11 Dec 2024 14:28:21 +0000 Subject: [PATCH 2/3] Rewrote plugin script, Settings now save, groundworks laid for a bit more functionality --- plugin/src/init.server.lua | 130 +++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 35 deletions(-) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 12cfd00c..997dcf6a 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -1,4 +1,3 @@ ---!nocheck local HttpService = game:GetService("HttpService") local RunService = game:GetService("RunService") local ScriptEditorService = game:GetService("ScriptEditorService") @@ -10,7 +9,14 @@ if IsRunning then end assert(plugin, "This code must run inside of a plugin") -local SETTINGS_MODULE_NAME = "LuauLSP_Settings" +local SETTINGS_MODULE_NAME = "LuauLanguageServer_Settings" + +--// List of classes who's data will not be updated, due to lag more often then not. +local CLASSES_EXCEPTION_LIST = { + "Camera", --(CFrame) + "Player", --(CloudEditCameraCoordinateFrame) +} + local DEFAULT_SOURCE = [[ return { --// Should be unique to Rojo port (different). @@ -39,8 +45,7 @@ return { game:GetService("LocalizationService"), game:GetService("TestService"), }, -} -]] +}]] local Connections: { RBXScriptConnection } = {} local Connected = false @@ -48,25 +53,49 @@ local Connected = false type EncodedInstance = { Name: string, ClassName: string, - Children: { EncodedInstance }, + Children: { EncodedInstance? }, } -local Toolbar = plugin:CreateToolbar("Luau LSP Test") -local ConnectAction = - plugin:CreatePluginAction("Luau LSP Connect", "Connect", "Connects to Luau LSP", "rbxassetid://11115506617", true) -local ConnectButton = Toolbar:CreateButton("Luau LSP Setup", "Toggle Menu", "rbxassetid://11115506617", "Luau LSP") +local Toolbar = plugin:CreateToolbar("Luau Language Server Test") +local ConnectAction = plugin:CreatePluginAction( + "Luau Language Server Connect", + "Connect", + "Connects to Luau Language Server", + "rbxassetid://11115506617", + true +) +local ConnectButton = Toolbar:CreateButton( + "Luau Language Server Setup", + "Toggle Menu", + "rbxassetid://11115506617", + "Luau Language Server" +) local SettingsButton = Toolbar:CreateButton("Settings", "Open Settings", "rbxassetid://13997395868") +local DefaultSettingsModule = Instance.new("ModuleScript") +DefaultSettingsModule.Name = SETTINGS_MODULE_NAME +ScriptEditorService:UpdateSourceAsync(DefaultSettingsModule, function() + return DEFAULT_SOURCE +end) +local DefaultSettings: { + Port: number, + StartAutomatically: boolean, + DebugMode: boolean, + Include: boolean, +} = + require(DefaultSettingsModule) +--// Was just much easier to create a permanent reference for the default settings config + local function GetAndValidateSettingsModule() local SettingsModule = ( TestService:FindFirstChild(SETTINGS_MODULE_NAME) or Instance.new("ModuleScript") ) :: ModuleScript local SettingsModuleSource = ScriptEditorService:GetEditorSource(SettingsModule) if SettingsModuleSource == "" or SettingsModuleSource == nil then - ScriptEditorService:UpdateSourceAsync(SettingsModule, function() - return DEFAULT_SOURCE - end) - warn("[Luau LSP] Could not load settings: Unable to find saved settings, reverting to default settings.") + SettingsModule = DefaultSettingsModule:Clone() + warn( + "[Luau Language Server] Could not load settings: Unable to find saved settings, reverting to default settings." + ) end --// No loss in not running a check here since Luau runs an internal validation for set @@ -75,13 +104,25 @@ local function GetAndValidateSettingsModule() local Settings = require(SettingsModule) if typeof(Settings) ~= "table" then - error("[Luau LSP] Could not load settings: Settings module does not return a table.") + warn( + "[Luau Language Server] Could not load settings: Settings module does not return a table. Defaulting to default settings." + ) + SettingsModule = DefaultSettingsModule:Clone() elseif typeof(Settings.Port) ~= "number" then - error("[Luau LSP] Could not load settings: Port is not a number.") + warn( + `[Luau Language Server] Could not load settings: Port is not a number. Defaulting to {DefaultSettings.Port}.` + ) + Settings.Port = DefaultSettings.Port elseif type(Settings.StartAutomatically) ~= "boolean" then - error("[Luau LSP] Could not load settings: StartAutomatically is not a boolean.") + warn( + `[Luau Language Server] Could not load settings: StartAutomatically is not a boolean. Defaulting to {DefaultSettings.Port}.` + ) + Settings.StartAutomatically = DefaultSettings.StartAutomatically elseif type(Settings.Include) ~= "table" then - error("[Luau LSP] Could not load settings: Include list is not a table.") + warn( + `[Luau Language Server] Could not load settings: Include list is not a table. Defaulting to {DefaultSettings.Include}}.` + ) + Settings.Include = DefaultSettings.Include end return SettingsModule @@ -94,10 +135,10 @@ local function FilterServices(Child: Instance): boolean return not not table.find(Settings.Include, Child) end -local function EncodeInstance(Instance: Instance, ChildFilter: (Instance) -> boolean?): EncodedInstance +local function EncodeInstance(Instance: Instance, ChildFilter: ((Instance) -> boolean)?): EncodedInstance local Encoded = {} - Encoded.Name = Instance.Name - Encoded.ClassName = Instance.ClassName + Encoded.Name = Instance.Name or "EmptyName" + Encoded.ClassName = Instance.ClassName or "EmptyClassName" Encoded.Children = {} for _, Child in Instance:GetChildren() do @@ -120,7 +161,7 @@ local function CleanUpConnections() ConnectButton.Icon = "rbxassetid://11115506617" if WasConnected then - warn("[Luau LSP] No longer sending DataModel information.") + warn("[Luau Language Server] No longer sending DataModel information.") end end @@ -136,31 +177,32 @@ local function SendDataModelInfo() Body = HttpService:JSONEncode({ tree = Tree, }), + Compress = Enum.HttpCompression.Gzip, }) if not Success then - warn(`[Luau LSP] Connecting to server failed: {Result}`) + warn(`[Luau Language Server] Connecting to server failed: {Result}`) CleanUpConnections() elseif not Result.Success then - warn(`[Luau LSP] Sending DataModel info failed: {Result.StatusCode}: {Result.Body}`) + warn(`[Luau Language Server] Sending DataModel info failed: {Result.StatusCode}: {Result.Body}`) CleanUpConnections() else Connected = true ConnectButton.Icon = "rbxassetid://11116536087" - warn("[Luau LSP] Now sending DataModel information.") + warn("[Luau Language Server] Now sending DataModel information.") end end local function WatchChanges() local SendTask: thread? if Connected or Settings == nil then - warn("[Luau LSP] Connecting to server failed: Already connected, or settings non-existent.") + warn("[Luau Language Server] Connecting to server failed: Already connected, or settings non-existent.") return end CleanUpConnections() - local function DeferSend() + local function DeferSendDataModelInfo() if SendTask then task.cancel(SendTask) end @@ -170,18 +212,36 @@ local function WatchChanges() end) end - -- TODO: we should only send delta info if possible - local function DescendantChanged(Instance: Instance) - for _, Service in Settings.Include do - if Instance:IsDescendantOf(Service) then - DeferSend() - return + for _, Service: Instance in Settings.Include do + table.insert( + Connections, + Service.DescendantAdded:Connect(function(Descendant: Instance) + if table.find(CLASSES_EXCEPTION_LIST, Descendant.ClassName) ~= nil then + return + end + --print(`[Luau Language Server] {Descendant.Name} added to {Service.ClassName}`) + table.insert( + Connections, + Descendant.Changed:Connect(function(Property: string) + --print(`[Luau Language Server] {Property} changed on {Descendant.Name}`) Re enable for Verbose of some sort + DeferSendDataModelInfo() + end) + ) + end) + ) + for _, Descendant in Service:GetDescendants() do + if table.find(CLASSES_EXCEPTION_LIST, Descendant.ClassName) ~= nil then + continue end + table.insert( + Connections, + Descendant.Changed:Connect(function(Property: string) + print(`{Property} changed on {Descendant.Name}`) + DeferSendDataModelInfo() + end) + ) end end - - table.insert(Connections, game.DescendantAdded:Connect(DescendantChanged)) - table.insert(Connections, game.DescendantRemoving:Connect(DescendantChanged)) SendDataModelInfo() end From 6771182fddb3109040e9c97a4c9dc5b1fd9f6f54 Mon Sep 17 00:00:00 2001 From: TaylorsRus Date: Fri, 13 Dec 2024 20:12:52 +0000 Subject: [PATCH 3/3] further modifications to fit review, debug mode added --- plugin/src/init.server.lua | 125 ++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 57 deletions(-) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 997dcf6a..e1497ca7 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -1,3 +1,4 @@ +--!strict local HttpService = game:GetService("HttpService") local RunService = game:GetService("RunService") local ScriptEditorService = game:GetService("ScriptEditorService") @@ -11,12 +12,6 @@ assert(plugin, "This code must run inside of a plugin") local SETTINGS_MODULE_NAME = "LuauLanguageServer_Settings" ---// List of classes who's data will not be updated, due to lag more often then not. -local CLASSES_EXCEPTION_LIST = { - "Camera", --(CFrame) - "Player", --(CloudEditCameraCoordinateFrame) -} - local DEFAULT_SOURCE = [[ return { --// Should be unique to Rojo port (different). @@ -56,7 +51,7 @@ type EncodedInstance = { Children: { EncodedInstance? }, } -local Toolbar = plugin:CreateToolbar("Luau Language Server Test") +local Toolbar = plugin:CreateToolbar("Luau Language Server") local ConnectAction = plugin:CreatePluginAction( "Luau Language Server Connect", "Connect", @@ -83,7 +78,7 @@ local DefaultSettings: { DebugMode: boolean, Include: boolean, } = - require(DefaultSettingsModule) + require(DefaultSettingsModule) :: any --// Was just much easier to create a permanent reference for the default settings config local function GetAndValidateSettingsModule() @@ -102,7 +97,8 @@ local function GetAndValidateSettingsModule() SettingsModule.Name = SETTINGS_MODULE_NAME SettingsModule.Parent = TestService - local Settings = require(SettingsModule) + local Settings = require(SettingsModule) :: any + print(Settings) if typeof(Settings) ~= "table" then warn( "[Luau Language Server] Could not load settings: Settings module does not return a table. Defaulting to default settings." @@ -129,7 +125,7 @@ local function GetAndValidateSettingsModule() end local SettingsModule = GetAndValidateSettingsModule() -local Settings = require(SettingsModule) +local Settings = require(SettingsModule) :: any local function FilterServices(Child: Instance): boolean return not not table.find(Settings.Include, Child) @@ -152,20 +148,15 @@ local function EncodeInstance(Instance: Instance, ChildFilter: ((Instance) -> bo return Encoded end -local function CleanUpConnections() - local WasConnected = Connected +local function CleanUp() for _, Connection in Connections do Connection:Disconnect() end Connected = false ConnectButton.Icon = "rbxassetid://11115506617" - - if WasConnected then - warn("[Luau Language Server] No longer sending DataModel information.") - end end -local function SendDataModelInfo() +local function SendDataModelInfo(InternalUpdate: boolean?) local Tree = EncodeInstance(game, FilterServices) local Success, Result = pcall(HttpService.RequestAsync, HttpService, { @@ -183,73 +174,88 @@ local function SendDataModelInfo() if not Success then warn(`[Luau Language Server] Connecting to server failed: {Result}`) - CleanUpConnections() + CleanUp() elseif not Result.Success then warn(`[Luau Language Server] Sending DataModel info failed: {Result.StatusCode}: {Result.Body}`) - CleanUpConnections() + CleanUp() else + if not InternalUpdate then + warn("[Luau Language Server] Connected to server.") + end Connected = true ConnectButton.Icon = "rbxassetid://11116536087" - warn("[Luau Language Server] Now sending DataModel information.") end end -local function WatchChanges() +local function WatchChanges(InternalUpdate: boolean?) local SendTask: thread? if Connected or Settings == nil then - warn("[Luau Language Server] Connecting to server failed: Already connected, or settings non-existent.") + warn("[Luau Language Server] Connecting to server failed: Already connected, or settings are blank.") return end - CleanUpConnections() + CleanUp() local function DeferSendDataModelInfo() if SendTask then task.cancel(SendTask) end SendTask = task.delay(0.5, function() - SendDataModelInfo() + SendDataModelInfo(true) SendTask = nil end) end + local function SetupListeners(Instance: Instance) + local NameChangedConnection: RBXScriptConnection = nil + NameChangedConnection = Instance:GetPropertyChangedSignal("Name"):Connect(function() + print(Settings.DebugMode) + if Settings.DebugMode then + print(`[Luau Language Server] Name changed on {Instance.Name}`) + end + DeferSendDataModelInfo() + end) + table.insert(Connections, NameChangedConnection) + + local ParentChangedConnection: RBXScriptConnection = nil + ParentChangedConnection = Instance:GetPropertyChangedSignal("Parent"):Connect(function() + if Instance.Parent == nil and Settings.DebugMode then + print(`[Luau Language Server] {Instance.Name} deleted from DataModel.`) + end + + ParentChangedConnection:Disconnect() + NameChangedConnection:Disconnect() + DeferSendDataModelInfo() + end) + end + for _, Service: Instance in Settings.Include do - table.insert( - Connections, - Service.DescendantAdded:Connect(function(Descendant: Instance) - if table.find(CLASSES_EXCEPTION_LIST, Descendant.ClassName) ~= nil then - return - end - --print(`[Luau Language Server] {Descendant.Name} added to {Service.ClassName}`) - table.insert( - Connections, - Descendant.Changed:Connect(function(Property: string) - --print(`[Luau Language Server] {Property} changed on {Descendant.Name}`) Re enable for Verbose of some sort - DeferSendDataModelInfo() - end) - ) - end) - ) - for _, Descendant in Service:GetDescendants() do - if table.find(CLASSES_EXCEPTION_LIST, Descendant.ClassName) ~= nil then - continue + Service.DescendantAdded:Connect(function(Descendant: Instance) + if Settings.DebugMode then + print(`[Luau Language Server] {Descendant.Name} parented to {Descendant.Parent}`) end - table.insert( - Connections, - Descendant.Changed:Connect(function(Property: string) - print(`{Property} changed on {Descendant.Name}`) - DeferSendDataModelInfo() - end) - ) + SetupListeners(Descendant) + end) + + for _, Descendant in Service:GetDescendants() do + SetupListeners(Descendant) end end - SendDataModelInfo() + SendDataModelInfo(InternalUpdate) end -function ToggleServerConnection() +function ToggleServerConnection(InternalUpdate: boolean?) + SettingsModule = GetAndValidateSettingsModule() + Settings = require(SettingsModule) :: any + if Connected then - CleanUpConnections() + if not InternalUpdate then + warn("[Luau Language Server] Disconnected from server.") + elseif InternalUpdate and Settings.DebugMode then + warn("[Luau Language Server] Disconnected from server (internally).") + end + CleanUp() else - WatchChanges() + WatchChanges(InternalUpdate) end end @@ -263,16 +269,21 @@ end) SettingsModule:GetPropertyChangedSignal("Source"):Connect(function() local WasConnected = Connected if Connected then - CleanUpConnections() + CleanUp() end SettingsModule = GetAndValidateSettingsModule() - Settings = require(SettingsModule) + Settings = require(SettingsModule) :: any + print(Settings) if WasConnected then - ToggleServerConnection() + if Settings.DebugMode then + warn("[Luau Language Server] No longer sending DataModel information.") + end + ToggleServerConnection(true) end end) if Settings and Settings.StartAutomatically then + warn("[Luau Language Server] Companion plugin automatically connecting.") ToggleServerConnection() end