diff --git a/agents/ls-clang/pom.xml b/agents/ls-clang/pom.xml new file mode 100644 index 0000000000..d22dd2291d --- /dev/null +++ b/agents/ls-clang/pom.xml @@ -0,0 +1,23 @@ + + + + 4.0.0 + + che-agents-parent + org.eclipse.che + 6.1.0-SNAPSHOT + + ls-clang-agent + Language Server Clang Agent + diff --git a/agents/ls-clang/src/main/resources/installers/1.0.0/org.eclipse.che.ls.clang.json b/agents/ls-clang/src/main/resources/installers/1.0.0/org.eclipse.che.ls.clang.json new file mode 100644 index 0000000000..0cbe6283df --- /dev/null +++ b/agents/ls-clang/src/main/resources/installers/1.0.0/org.eclipse.che.ls.clang.json @@ -0,0 +1,8 @@ +{ + "id": "org.eclipse.che.ls.clangd", + "version": "1.0.0", + "name": "Clangd language server", + "description": "Clangd intellisense for C/C++ projects.", + "dependencies": [], + "properties": {} + } diff --git a/agents/ls-clang/src/main/resources/installers/1.0.0/org.eclipse.che.ls.clang.script.sh b/agents/ls-clang/src/main/resources/installers/1.0.0/org.eclipse.che.ls.clang.script.sh new file mode 100644 index 0000000000..0a5e517b57 --- /dev/null +++ b/agents/ls-clang/src/main/resources/installers/1.0.0/org.eclipse.che.ls.clang.script.sh @@ -0,0 +1,172 @@ +# +# Copyright (c) 2012-2018 Red Hat, Inc. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Red Hat, Inc. - initial API and implementation +# + +is_current_user_root() { + test "$(id -u)" = 0 +} + +is_current_user_sudoer() { + sudo -n true > /dev/null 2>&1 +} + +set_sudo_command() { + if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi +} + +set_sudo_command +unset PACKAGES +command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; } +command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; } +command -v wget >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" wget"; } + +CHE_DIR=$HOME/che +LS_DIR=${CHE_DIR}/ls-clangd +LS_LAUNCHER=${LS_DIR}/launch.sh +CLANGD_VERSION=6.0 +CLANGD_BINARY=clangd-${CLANGD_VERSION} + +if [ -f /etc/centos-release ]; then + FILE="/etc/centos-release" + LINUX_TYPE=$(cat $FILE | awk '{print $1}') + elif [ -f /etc/redhat-release ]; then + FILE="/etc/redhat-release" + LINUX_TYPE=$(cat $FILE | cut -c 1-8) + else + FILE="/etc/os-release" + LINUX_TYPE=$(cat $FILE | grep ^ID= | tr '[:upper:]' '[:lower:]') + LINUX_VERSION=$(cat $FILE | grep ^VERSION_ID=) +fi + +MACHINE_TYPE=$(uname -m) + +mkdir -p ${CHE_DIR} +mkdir -p ${LS_DIR} + +######################### +#### Install packages ### +######################### +# +# Red Hat Enterprise Linux 7 +############################ +if echo ${LINUX_TYPE} | grep -qi "rhel"; then + test "${PACKAGES}" = "" || { + ${SUDO} yum install ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + echo "LLVM / Clang ${CLANGD_VERSION} not supported on Red Hat Enterprise Linux 7."; + exit 1; + } + +# Red Hat Enterprise Linux 6 +############################ +elif echo ${LINUX_TYPE} | grep -qi "Red Hat"; then + test "${PACKAGES}" = "" || { + ${SUDO} yum install ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + echo "LLVM / Clang ${CLANGD_VERSION} not supported on Red Hat Enterprise Linux 6."; + exit 1; + } + + +# Ubuntu 14.04 16.04 / Linux Mint 17 +#################################### +elif echo ${LINUX_TYPE} | grep -qi "ubuntu"; then + test "${PACKAGES}" = "" || { + ${SUDO} apt-get update; + ${SUDO} apt-get -y install ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + { + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -; + # Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 + ${SUDO} apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-${CLANGD_VERSION} main"; + }; + + ${SUDO} apt-get update; + ${SUDO} apt-get install -y clang-tools-${CLANGD_VERSION}; + ${SUDO} ln -s /usr/bin/clangd-${CLANGD_VERSION} /usr/bin/clangd + } + + +# Debian 8 +########## +elif echo ${LINUX_TYPE} | grep -qi "debian"; then + test "${PACKAGES}" = "" || { + ${SUDO} apt-get update; + ${SUDO} apt-get -y install ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + { + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -; + # Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 + ${SUDO} apt-add-repository "deb http://apt.llvm.org/jessie/ llvm-toolchain-jessie-${CLANGD_VERSION} main"; + }; + + ${SUDO} apt-get update; + ${SUDO} apt-get install -y clang-tools-${CLANGD_VERSION}; + ${SUDO} ln -s /usr/bin/clangd-${CLANGD_VERSION} /usr/bin/clangd + } + +## Fedora 23 +############ +elif echo ${LINUX_TYPE} | grep -qi "fedora"; then + test "${PACKAGES}" = "" || { + ${SUDO} dnf -y install ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + echo "LLVM / Clang ${CLANGD_VERSION} not supported on Fedora 23."; + exit 1; + } + +## CentOS 7.1 & Oracle Linux 7.1 +################################ +elif echo ${LINUX_TYPE} | grep -qi "centos"; then + test "${PACKAGES}" = "" || { + ${SUDO} yum -y install ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + echo "LLVM / Clang ${CLANGD_VERSION} not supported on CentOS."; + exit 1; + } + +## openSUSE 13.2 +################ +elif echo ${LINUX_TYPE} | grep -qi "opensuse"; then + test "${PACKAGES}" = "" || { + ${SUDO} zypper install -y ${PACKAGES}; + } + + command -v ${CLANGD_BINARY} >/dev/null 2>&1 || { + echo "LLVM / Clang ${CLANGD_VERSION} not supported on OpenSUSE 13.2."; + exit 1; + } + +else + >&2 echo "Unrecognized Linux Type" + >&2 cat $FILE + exit 1 +fi + + +######################### +### Install Clangd LS ### +######################### + +touch ${LS_LAUNCHER} +chmod +x ${LS_LAUNCHER} +echo "tee -a /home/user/clangd-input.log | clangd -disable-symbolication -pretty -resource-dir=/usr/include/ -enable-snippets | tee -a /home/user/clangd-output.log" > ${LS_LAUNCHER} diff --git a/agents/pom.xml b/agents/pom.xml index 1fb3e32f11..5f9b6beafb 100644 --- a/agents/pom.xml +++ b/agents/pom.xml @@ -39,5 +39,6 @@ test-ls ls-yaml ls-camel + ls-clang diff --git a/assembly/assembly-wsagent-war/pom.xml b/assembly/assembly-wsagent-war/pom.xml index 9fad61aed3..303275d2c9 100644 --- a/assembly/assembly-wsagent-war/pom.xml +++ b/assembly/assembly-wsagent-war/pom.xml @@ -39,6 +39,10 @@ org.eclipse.che.plugin che-plugin-camel-server + + org.eclipse.che.plugin + che-plugin-clangd-lang-server + org.eclipse.che.plugin che-plugin-composer-server diff --git a/assembly/assembly-wsmaster-war/pom.xml b/assembly/assembly-wsmaster-war/pom.xml index f7bcbcb9ac..c908477d46 100644 --- a/assembly/assembly-wsmaster-war/pom.xml +++ b/assembly/assembly-wsmaster-war/pom.xml @@ -88,6 +88,10 @@ org.eclipse.che ls-camel-agent + + org.eclipse.che + ls-clang-agent + org.eclipse.che ls-csharp-agent diff --git a/plugins/plugin-clangd/che-plugin-clangd-lang-server/pom.xml b/plugins/plugin-clangd/che-plugin-clangd-lang-server/pom.xml new file mode 100644 index 0000000000..a3547bc83a --- /dev/null +++ b/plugins/plugin-clangd/che-plugin-clangd-lang-server/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + che-plugin-clangd-parent + org.eclipse.che.plugin + 6.1.0-SNAPSHOT + + che-plugin-clangd-lang-server + Che Plugin :: ClangD C/C++ :: Extension Server + + false + + + + com.google.inject + guice + + + com.google.inject.extensions + guice-multibindings + + + org.eclipse.che.core + che-core-api-languageserver + + + org.eclipse.che.core + che-core-api-languageserver-shared + + + org.eclipse.che.core + che-core-api-project + + + org.eclipse.che.core + che-core-commons-inject + + + org.eclipse.che.plugin + che-plugin-cpp-lang-server + + + org.eclipse.lsp4j + org.eclipse.lsp4j + + + org.eclipse.lsp4j + org.eclipse.lsp4j.jsonrpc + + + org.slf4j + slf4j-api + + + diff --git a/plugins/plugin-clangd/che-plugin-clangd-lang-server/src/main/java/org/eclipse/plugin/clangd/inject/ClangModule.java b/plugins/plugin-clangd/che-plugin-clangd-lang-server/src/main/java/org/eclipse/plugin/clangd/inject/ClangModule.java new file mode 100644 index 0000000000..0698a35143 --- /dev/null +++ b/plugins/plugin-clangd/che-plugin-clangd-lang-server/src/main/java/org/eclipse/plugin/clangd/inject/ClangModule.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.plugin.clangd.inject; + +import static java.util.Arrays.asList; + +import com.google.inject.AbstractModule; +import com.google.inject.multibindings.Multibinder; +import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncher; +import org.eclipse.che.api.languageserver.shared.model.LanguageDescription; +import org.eclipse.che.api.project.server.type.ProjectTypeDef; +import org.eclipse.che.inject.DynaModule; +import org.eclipse.che.plugin.cpp.projecttype.CProjectType; +import org.eclipse.che.plugin.cpp.projecttype.CppProjectType; +import org.eclipse.plugin.clangd.languageserver.ClangDLanguageServerLauncher; + +/** @author Alexander Andrienko */ +/** @author Hanno Kolvenbach */ +@DynaModule +public class ClangModule extends AbstractModule { + public static final String LANGUAGE_ID = "clangd"; + private static final String[] EXTENSIONS = + new String[] { + "c", "h", "cpp", "hpp", "cc", "hh", "hxx", "cxx", "C", "H", "CPP", "HPP", "CC", "HH", "CXX", + "HXX" + }; + private static final String MIME_TYPE = "text/x-cpp"; + + @Override + protected void configure() { + Multibinder projectTypeMultibinder = + Multibinder.newSetBinder(binder(), ProjectTypeDef.class); + + projectTypeMultibinder.addBinding().to(CProjectType.class); + projectTypeMultibinder.addBinding().to(CppProjectType.class); + + Multibinder.newSetBinder(binder(), LanguageServerLauncher.class) + .addBinding() + .to(ClangDLanguageServerLauncher.class); + + LanguageDescription description = new LanguageDescription(); + description.setFileExtensions(asList(EXTENSIONS)); + description.setLanguageId(LANGUAGE_ID); + description.setMimeType(MIME_TYPE); + + Multibinder.newSetBinder(binder(), LanguageDescription.class) + .addBinding() + .toInstance(description); + } +} diff --git a/plugins/plugin-clangd/che-plugin-clangd-lang-server/src/main/java/org/eclipse/plugin/clangd/languageserver/ClangDLanguageServerLauncher.java b/plugins/plugin-clangd/che-plugin-clangd-lang-server/src/main/java/org/eclipse/plugin/clangd/languageserver/ClangDLanguageServerLauncher.java new file mode 100644 index 0000000000..c6a4219f27 --- /dev/null +++ b/plugins/plugin-clangd/che-plugin-clangd-lang-server/src/main/java/org/eclipse/plugin/clangd/languageserver/ClangDLanguageServerLauncher.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.plugin.clangd.languageserver; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import org.eclipse.che.api.languageserver.exception.LanguageServerException; +import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncher; +import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncherTemplate; +import org.eclipse.che.api.languageserver.registry.DocumentFilter; +import org.eclipse.che.api.languageserver.registry.LanguageServerDescription; +import org.eclipse.che.api.languageserver.registry.ServerInitializerObserver; +import org.eclipse.che.api.languageserver.service.LanguageServiceUtils; +import org.eclipse.lsp4j.ServerCapabilities; +import org.eclipse.lsp4j.jsonrpc.Launcher; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.LanguageServer; +import org.eclipse.plugin.clangd.inject.ClangModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** @author Alexander Andrienko */ +/** @author Hanno Kolvenbach */ +@Singleton +public class ClangDLanguageServerLauncher extends LanguageServerLauncherTemplate + implements ServerInitializerObserver { + + private static final LanguageServerDescription DESCRIPTION = createServerDescription(); + private static final String REGEX = ".*\\.(c|h|cc|hh|cpp|hpp|cxx|hxx|C|H|CC|HH|CPP|HPP|CXX|HXX)"; + private final Path launchScript; + + private static final Logger LOG = LoggerFactory.getLogger(ClangDLanguageServerLauncher.class); + + @Inject + public ClangDLanguageServerLauncher() { + launchScript = Paths.get(System.getenv("HOME"), "che/ls-clangd/launch.sh"); + } + + @Override + public boolean isAbleToLaunch() { + return Files.exists(launchScript); + } + + @Override + protected LanguageServer connectToLanguageServer( + Process languageServerProcess, LanguageClient client) throws LanguageServerException { + Launcher launcher = + Launcher.createLauncher( + client, + LanguageServer.class, + languageServerProcess.getInputStream(), + languageServerProcess.getOutputStream()); + launcher.startListening(); + return launcher.getRemoteProxy(); + } + + protected Process startLanguageServerProcess(String projectPath) throws LanguageServerException { + + ProcessBuilder processBuilder = new ProcessBuilder(); + + processBuilder.directory(new File(LanguageServiceUtils.removeUriScheme(projectPath))); + processBuilder.command(launchScript.toString()).inheritIO(); + processBuilder.redirectInput(ProcessBuilder.Redirect.PIPE); + + processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE); + try { + return processBuilder.start(); + } catch (IOException e) { + throw new LanguageServerException("Can't start ClangD language server", e); + } + } + + @Override + public void onServerInitialized( + LanguageServerLauncher launcher, + LanguageServer server, + ServerCapabilities capabilities, + String projectPath) { + LOG.debug(projectPath); + LOG.debug("clangd language server initialized"); + } + + @Override + public LanguageServerDescription getDescription() { + return DESCRIPTION; + } + + private static LanguageServerDescription createServerDescription() { + LanguageServerDescription description = + new LanguageServerDescription( + "org.eclipse.che.plugin.clangd.languageserver", + null, + Arrays.asList(new DocumentFilter(ClangModule.LANGUAGE_ID, REGEX, null))); + return description; + } +} diff --git a/plugins/plugin-clangd/pom.xml b/plugins/plugin-clangd/pom.xml new file mode 100644 index 0000000000..22dec1a81d --- /dev/null +++ b/plugins/plugin-clangd/pom.xml @@ -0,0 +1,39 @@ + + + + 4.0.0 + + che-plugin-parent + org.eclipse.che.plugin + 6.1.0-SNAPSHOT + ../pom.xml + + che-plugin-clangd-parent + pom + Che Plugin :: Clangd :: Parent + + che-plugin-clangd-lang-server + + + + + + org.eclipse.che.core + che-core-api-dto-maven-plugin + ${project.version} + + + + + diff --git a/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/editor/codeassist/CompletionItemBasedCompletionProposal.java b/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/editor/codeassist/CompletionItemBasedCompletionProposal.java index ff2a70ed37..cc1ec293be 100644 --- a/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/editor/codeassist/CompletionItemBasedCompletionProposal.java +++ b/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/editor/codeassist/CompletionItemBasedCompletionProposal.java @@ -232,7 +232,7 @@ public class CompletionItemBasedCompletionProposal implements CompletionProposal new TextEdit( newRange( cursorPosition.getLine(), - cursorPosition.getCharacter() - offset, + cursorPosition.getCharacter() - currentWord.length(), cursorPosition.getLine(), cursorPosition.getCharacter()), completionItem.getInsertText())); diff --git a/plugins/pom.xml b/plugins/pom.xml index dc802733fd..d5601c2d0b 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -59,5 +59,6 @@ plugin-pullrequest-parent plugin-yaml plugin-camel + plugin-clangd diff --git a/pom.xml b/pom.xml index 727bf5dd2d..ca2f61b6b0 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,11 @@ ls-camel-agent ${che.version} + + org.eclipse.che + ls-clang-agent + ${che.version} + org.eclipse.che ls-csharp-agent @@ -1028,6 +1033,11 @@ che-plugin-camel-server ${che.version} + + org.eclipse.che.plugin + che-plugin-clangd-lang-server + ${che.version} + org.eclipse.che.plugin che-plugin-composer-ide