From e93948228a69a5fc9aee954fa52a4ba72d072d68 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 17 Jan 2024 07:15:04 +0100 Subject: [PATCH] LanguageClient: Fix npm installs for newer npm versions We used the bin command line parameter for npm to get the path to the runnable cmd inside the install location, but it seems this command is missing for newer npm versions. Just check the default install location and fall back to parse the npm list output in order to find the language server path. Change-Id: Ie144b061552c4a26fa6d54b232cef308669f7dbd Reviewed-by: Artem Sokolovskii Reviewed-by: --- .../languageclient/languageclientutils.cpp | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 404f534cab6..eb292843428 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -551,22 +551,38 @@ void autoSetupLanguageServer(TextDocument *document) LanguageClientManager::instance()); auto handleInstall = [=](const bool success) { - if (success) { - Process process; - process.setCommand(CommandLine(npm, {"bin"})); - process.setWorkingDirectory(lsPath); - process.start(); - process.waitForFinished(); - const FilePath lspath = FilePath::fromUserInput( - process.stdOutLines().value(0)); - FilePath lsExecutable = lspath.pathAppended(languageServer); - if (HostOsInfo::isWindowsHost()) - lsExecutable = lsExecutable.stringAppended(".cmd"); - - if (lsExecutable.isExecutableFile()) - setupStdIOSettings(lsExecutable); - } install->deleteLater(); + if (!success) + return; + FilePath relativePath = FilePath::fromPathPart( + QString("node_modules/.bin/" + languageServer)); + if (HostOsInfo::isWindowsHost()) + relativePath = relativePath.withSuffix(".cmd"); + FilePath lsExecutable = lsPath.resolvePath(relativePath); + if (lsExecutable.isExecutableFile()) { + setupStdIOSettings(lsExecutable); + return; + } + Process process; + process.setCommand(CommandLine(npm, {"list", languageServer})); + process.setWorkingDirectory(lsPath); + process.start(); + process.waitForFinished(); + const QStringList output = process.stdOutLines(); + // we are expecting output in the form of: + // tst@ C:\tmp\tst + // `-- vscode-json-languageserver@1.3.4 + for (const QString &line : output) { + const qsizetype splitIndex = line.indexOf('@'); + if (splitIndex == -1) + continue; + lsExecutable = FilePath::fromUserInput(line.mid(splitIndex + 1).trimmed()) + .resolvePath(relativePath); + if (lsExecutable.isExecutableFile()) { + setupStdIOSettings(lsExecutable); + return; + } + } }; QObject::connect(install,