forked from qt-creator/qt-creator
LanguageClient: Automate setup of rust-analyzer
Change-Id: I6f97840ec55675219071d4a9644b8cba7f70f24e Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -122,3 +122,4 @@ add_subdirectory(qtapplicationmanager)
|
||||
add_subdirectory(luatests)
|
||||
add_subdirectory(tellajoke)
|
||||
add_subdirectory(lualsp)
|
||||
add_subdirectory(rustls)
|
||||
|
4
src/plugins/rustls/CMakeLists.txt
Normal file
4
src/plugins/rustls/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
add_qtc_lua_plugin(rustls
|
||||
SOURCES rustls/rustls.lua
|
||||
rustls/init.lua
|
||||
)
|
176
src/plugins/rustls/rustls/init.lua
Normal file
176
src/plugins/rustls/rustls/init.lua
Normal file
@@ -0,0 +1,176 @@
|
||||
-- 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 Layout = require('Layout')
|
||||
local a = require('async')
|
||||
local fetch = require('Fetch').fetch
|
||||
|
||||
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://api.github.com/repos/rust-lang/rust-analyzer/releases?per_page=2",
|
||||
convertToTable = true,
|
||||
headers = {
|
||||
Accept = "application/vnd.github.v3+json",
|
||||
["X-GitHub-Api-Version"] = "2022-11-28"
|
||||
}
|
||||
}))
|
||||
|
||||
if type(data) == "table" and #data > 1 then
|
||||
local r = data[1]
|
||||
if r.prerelease then
|
||||
r = data[2]
|
||||
end
|
||||
Install = require('Install')
|
||||
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.defaultPath = 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 Layout"
|
||||
local _ENV = using(Layout)
|
||||
|
||||
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 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 = Utils.FilePath.fromUserInput("rust-analyzer"),
|
||||
})
|
||||
-- Search for the binary in the PATH
|
||||
local serverPath = Settings.binary.defaultPath
|
||||
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
|
||||
if absolute:isExecutableFile() == true then
|
||||
Settings.binary.defaultPath = absolute
|
||||
end
|
||||
|
||||
return Settings
|
||||
end
|
||||
|
||||
local function setup(parameters)
|
||||
setupAspect()
|
||||
setupClient()
|
||||
end
|
||||
|
||||
return {
|
||||
setup = function() a.sync(setup)() end,
|
||||
}
|
24
src/plugins/rustls/rustls/rustls.lua
Normal file
24
src/plugins/rustls/rustls/rustls.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Copyright (C) 2024 The Qt Company Ltd.
|
||||
-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
return {
|
||||
Name = "RustLanguageServer",
|
||||
Version = "1.0.0",
|
||||
CompatVersion = "1.0.0",
|
||||
Vendor = "The Qt Company",
|
||||
Category = "Language Client",
|
||||
Description = "The Rust Language Server",
|
||||
Experimental = false,
|
||||
DisabledByDefault = false,
|
||||
LongDescription = [[
|
||||
This plugin provides the Rust Language Server.
|
||||
It will try to install it if it is not found.
|
||||
]],
|
||||
Dependencies = {
|
||||
{ Name = "Core", Version = "13.0.82", Required = true },
|
||||
{ Name = "Lua", Version = "13.0.82", Required = true },
|
||||
{ Name = "LuaLanguageClient", Version = "13.0.82", Required = true }
|
||||
},
|
||||
setup = function()
|
||||
require 'init'.setup()
|
||||
end,
|
||||
} --[[@as QtcPlugin]]
|
Reference in New Issue
Block a user