diff --git a/package.json b/package.json index b699a88..e40e49a 100644 --- a/package.json +++ b/package.json @@ -256,6 +256,11 @@ "default": true, "description": "If false, do not update Luau-LSP and Selene configurations unless the Force Language Update is done" }, + "slVscodeEdit.syntax.useGitHubDefinitions": { + "type": "boolean", + "default": true, + "description": "Fetch LSL definition files from GitHub instead of the Second Life viewer" + }, "slVscodeEdit.ui.statusTimeoutSeconds": { "type": "number", "default": 3, diff --git a/src/interfaces/configinterface.ts b/src/interfaces/configinterface.ts index afea4b6..7293d29 100644 --- a/src/interfaces/configinterface.ts +++ b/src/interfaces/configinterface.ts @@ -30,6 +30,7 @@ export enum ConfigKey { PreprocessorConstantsInSLua = 'preprocessor.constantsInSLua', PreprocessorLSLSwitchStatements = 'preprocessor.lsl.switchStatements', LastSyntaxID = 'syntax.lastID', + UseGitHubDefinitions = 'syntax.useGitHubDefinitions', AskIfViewerScriptMismatchesMaster = 'sync.askIfViewerScriptMismatchesMaster', CompareHashBeforeSync = 'sync.compareHashBeforeSync', KeepViewerFileOpen = 'sync.keepViewerFileOpen', diff --git a/src/shared/languagerepository.ts b/src/shared/languagerepository.ts index 1861a4d..53a381b 100644 --- a/src/shared/languagerepository.ts +++ b/src/shared/languagerepository.ts @@ -10,6 +10,8 @@ import { LSLKeywords } from "./lslkeywords"; import { LuaTypeDefinitions } from "./luadefsinterface"; import { sortObjectKeysRecursive } from '../utils'; +const GitHubRawBase = "https://raw.githubusercontent.com/secondlife/lsl-definitions/main/generated"; + export interface LanguageInfo { id: string; lsl?: LSLKeywords; @@ -156,6 +158,21 @@ export class LanguageRepository { } } + public async fetchFromGitHub(filename: string): Promise { + const url = `${GitHubRawBase}/${filename}`; + try { + const response = await fetch(url); + if (!response.ok) { + console.warn(`GitHub fetch failed for ${filename}: HTTP ${response.status}`); + return null; + } + return await response.text(); + } catch (error) { + console.error(`Error fetching ${filename} from GitHub:`, error); + return null; + } + } + private async requestLanguageSyntax(socket: JSONRPCInterface, kind: string): Promise { const params = { kind }; try { diff --git a/src/shared/languageservice.ts b/src/shared/languageservice.ts index 7430e53..567d2a8 100644 --- a/src/shared/languageservice.ts +++ b/src/shared/languageservice.ts @@ -112,10 +112,20 @@ export class LanguageService implements DisposableLike { force?: boolean, syntaxCacheSupported?: boolean, ): Promise { + // Try GitHub first if enabled (most reliable, no viewer dependency) + if (this.host.config.getConfig(ConfigKey.UseGitHubDefinitions, true)) { + const githubOk = await this.configureSyntaxFromGitHub(syntaxId); + if (githubOk) { + return true; + } + } + + // Fallback to viewer cache if available if (syntaxCacheSupported && socket) { return await this.configureSyntaxFromViewerCache(syntaxId, socket); } + // Last resort: fetch from viewer and generate locally const syntax = await this.repository.getSyntax(syntaxId, { force, socket, @@ -146,6 +156,30 @@ export class LanguageService implements DisposableLike { return true; } + private async configureSyntaxFromGitHub(syntaxId: string): Promise { + const selene = new SelenePlugin(this.host); + const seleneYml = await this.repository.fetchFromGitHub("secondlife_selene.yml"); + if (typeof seleneYml === "string") { + await selene.configureFromViewerCache(syntaxId, seleneYml); + } else { + console.warn("github_fetch: secondlife_selene.yml missing or invalid, skipping Selene configuration"); + } + + const luauLSP = new LuaLSPPlugin(this.host); + const dLuau = await this.repository.fetchFromGitHub("secondlife.d.luau"); + const docs = await this.repository.fetchFromGitHub("secondlife.docs.json"); + if (typeof dLuau === "string" && typeof docs === "string") { + await luauLSP.configureFromViewerCache(syntaxId, dLuau, docs); + } else { + console.warn("github_fetch: secondlife.d.luau or secondlife.docs.json missing or invalid, skipping Luau-LSP configuration"); + return false; + } + + this.languageVersion = syntaxId; + await ConfigService.getInstance().setConfig(ConfigKey.LastSyntaxID, syntaxId, { target: "global" }); + return true; + } + private async configureSyntaxFromViewerCache( syntaxId: string, socket: JSONRPCInterface,