forked from qt-creator/qt-creator
On macOS, files in Contents/PlugIns/ need to be codesigned individually. Since Lua plugins are not really binaries, per Apple's documentation that is to be avoided (and we currently only sign executables there). Just move Lua plugins generally to the resources directory, like we do for other scripts like the debugger Python scripts, and load them from there. Change-Id: Idabd6b7c0c7c6e842b1752488cb7073f00e7be49 Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
197 lines
5.0 KiB
Lua
197 lines
5.0 KiB
Lua
-- Copyright (C) 2024 The Qt Company Ltd.
|
|
-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
local LSP = require('LSP')
|
|
local mm = require('MessageManager')
|
|
local Utils = require('Utils')
|
|
local Process = require('Process')
|
|
local S = require('Settings')
|
|
local Gui = require('Gui')
|
|
local a = require('async')
|
|
local fetch = require('Fetch').fetch
|
|
local Install = require('Install')
|
|
|
|
Settings = {}
|
|
|
|
local function createCommand()
|
|
local cmd = { Settings.binary.expandedValue:nativePath() }
|
|
return cmd
|
|
end
|
|
|
|
local function filter(tbl, callback)
|
|
for i = #tbl, 1, -1 do
|
|
if not callback(tbl[i]) then
|
|
table.remove(tbl, i)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function installOrUpdateServer()
|
|
local data = a.wait(fetch({
|
|
url = "https://qtccache.qt.io/RustLanguageServer/LatestReleases",
|
|
convertToTable = true,
|
|
}))
|
|
|
|
if type(data) == "table" and #data > 1 then
|
|
local r = data[1]
|
|
if r.prerelease then
|
|
r = data[2]
|
|
end
|
|
local lspPkgInfo = Install.packageInfo("rust-analyzer")
|
|
if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then
|
|
local osTr = { mac = "apple-darwin", windows = "pc-windows-msvc", linux = "unknown-linux-gnu" }
|
|
local archTr = { unknown = "", x86 = "", x86_64 = "x86_64", itanium = "", arm = "", arm64 = "aarch64" }
|
|
local extTr = { mac = "gz", windows = "zip", linux = "gz" }
|
|
local os = osTr[Utils.HostOsInfo.os]
|
|
local arch = archTr[Utils.HostOsInfo.architecture]
|
|
local ext = extTr[Utils.HostOsInfo.os]
|
|
|
|
local expectedFileName = "rust-analyzer-" .. arch .. "-" .. os .. "." .. ext
|
|
|
|
filter(r.assets, function(asset)
|
|
return string.find(asset.name, expectedFileName, 1, true) == 1
|
|
end)
|
|
|
|
if #r.assets == 0 then
|
|
print("No assets found for this platform")
|
|
return
|
|
end
|
|
local res, err = a.wait(Install.install(
|
|
"Do you want to install the rust-analyzer?", {
|
|
name = "rust-analyzer",
|
|
url = r.assets[1].browser_download_url,
|
|
version = r.tag_name
|
|
}))
|
|
|
|
if not res then
|
|
mm.writeFlashing("Failed to install rust-analyzer: " .. err)
|
|
return
|
|
end
|
|
|
|
lspPkgInfo = Install.packageInfo("rust-analyzer")
|
|
print("Installed:", lspPkgInfo.name, "version:", lspPkgInfo.version, "at", lspPkgInfo.path)
|
|
end
|
|
|
|
local binary = "rust-analyzer"
|
|
if Utils.HostOsInfo.isWindowsHost() then
|
|
binary = "rust-analyzer.exe"
|
|
end
|
|
|
|
Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary))
|
|
Settings:apply()
|
|
return
|
|
end
|
|
|
|
if type(data) == "string" then
|
|
print("Failed to fetch:", data)
|
|
else
|
|
print("No rust-analyzer release found.")
|
|
end
|
|
end
|
|
IsTryingToInstall = false
|
|
|
|
local function setupClient()
|
|
Client = LSP.Client.create({
|
|
name = 'Rust Language Server',
|
|
cmd = createCommand,
|
|
transport = 'stdio',
|
|
languageFilter = {
|
|
patterns = { '*.rs' },
|
|
mimeTypes = { 'text/rust' }
|
|
},
|
|
settings = Settings,
|
|
startBehavior = "RequiresProject",
|
|
onStartFailed = function()
|
|
a.sync(function()
|
|
if IsTryingToInstall == true then
|
|
return
|
|
end
|
|
IsTryingToInstall = true
|
|
installOrUpdateServer()
|
|
IsTryingToInstall = false
|
|
end)()
|
|
end
|
|
})
|
|
end
|
|
|
|
local function using(tbl)
|
|
local result = _G
|
|
for k, v in pairs(tbl) do result[k] = v end
|
|
return result
|
|
end
|
|
local function layoutSettings()
|
|
--- "using namespace Gui"
|
|
local _ENV = using(Gui)
|
|
|
|
local layout = Form {
|
|
Settings.binary, br,
|
|
Row {
|
|
PushButton {
|
|
text = "Try to install Rust language server",
|
|
onClicked = function() a.sync(installOrUpdateServer)() end,
|
|
br,
|
|
},
|
|
st
|
|
}
|
|
}
|
|
|
|
return layout
|
|
end
|
|
|
|
local function binaryFromPkg()
|
|
local lspPkgInfo = Install.packageInfo("rust-analyzer")
|
|
if lspPkgInfo then
|
|
local binary = "rust-analyzer"
|
|
if Utils.HostOsInfo.isWindowsHost() then
|
|
binary = "rust-analyzer.exe"
|
|
end
|
|
local binaryPath = lspPkgInfo.path:resolvePath(binary)
|
|
if binaryPath:isExecutableFile() == true then
|
|
return binaryPath
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
local function findBinary()
|
|
local binary = binaryFromPkg()
|
|
if binary then
|
|
return binary
|
|
end
|
|
|
|
-- Search for the binary in the PATH
|
|
local serverPath = Utils.FilePath.fromUserInput("rust-analyzer")
|
|
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
|
|
if absolute:isExecutableFile() == true then
|
|
return absolute
|
|
end
|
|
return serverPath
|
|
end
|
|
local function setupAspect()
|
|
---@class Settings: AspectContainer
|
|
Settings = S.AspectContainer.create({
|
|
autoApply = false,
|
|
layouter = layoutSettings,
|
|
});
|
|
|
|
Settings.binary = S.FilePathAspect.create({
|
|
settingsKey = "Rustls.Binary",
|
|
displayName = "Binary",
|
|
labelText = "Binary:",
|
|
toolTip = "The path to the rust analyzer binary.",
|
|
expectedKind = S.Kind.ExistingCommand,
|
|
defaultPath = findBinary(),
|
|
})
|
|
|
|
return Settings
|
|
end
|
|
|
|
local function setup(parameters)
|
|
setupAspect()
|
|
setupClient()
|
|
end
|
|
|
|
return {
|
|
setup = function() a.sync(setup)() end,
|
|
}
|