Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
Showing results for 
Search instead for 
Did you mean: 
Developer Advocate
Developer Advocate
This is a searchable description of the content of a live stream recording, specifically "Episode 7 - Digging into the language server protocol, cds-lsp and Vim" in the "Hands-on SAP dev with qmacro" series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the "Catch the replays" section of the series blog post.

This episode, titled "Digging into the language server protocol, cds-lsp and Vim", was streamed live on Wed 27 Feb 2019 and is approximately one hour in length. The stream recording is available on YouTube.

Below is a brief synopsis, and links to specific highlights - use these links to jump directly to particular places of interest in the recording, based on 'hh:mm:ss' style timestamps.

Brief synopsis

One of the things we looked at briefly in the previous episode was the language server protocol (LSP) implementation for the CDS language, in the VS Code extension. In this midweek episode we explore getting a Vim LSP client working and connected to the cds-lsp server.

00:00:22: Talking about the occasional midweek slot, compared with the regular Friday slot. Remember - Friday is the regular slot and we sometimes do other slots too midweek.

00:03:08: Showing the Google Calendar that I maintain for the live stream episodes, to which you can subscribe and get notifications of upcoming episodes. More info here:

00:04:05: Starting at the SAP Development Tools page for cloud topics, looking at the details of what's on offer with the "CDS Language Support for Visual Studio Code" extension.

00:04:50: Looking inside the extension download, by renaming the file, changing the extension vsix to tgz because the extension file is actually a gzipped tarball. Now we can unpack it into a temporary folder to have a look around.

00:06:00: We see that there are two Node.js modules in the @Sap namespace - cds-compiler and cds-lsp.

00:06:40: Noting the differences between versions of these two modules in the VSIX extension and those in the latest released version of @Sap/cds a few days previously.

00:07:50: Starting up VS Code to examine the extension as installed, including a quick look at the Changelog.

00:08:45: Noting that I've taken a slightly more recent version of the @Sap/cds-lsp module for the purposes of this episode, as we need a slightly newer version than the one that's in the 1.0.36 release of the extension, which is 1.4.24. The extension is about to be updated (at the time of the live stream) with a new version of the cds-compiler and cds-lsp modules.

00:09:42: Examining the details of what the extension offers, to see what sort of language server features we should be looking for (noting that syntax highlighting doesn't come from the cds-lsp package, but from the syntaxes files in the extension, taking a look at a snippet of the configuration for 'Association to many').

00:12:15: Having a look at the Language Server Protocol homepage to understand what it is and does.

00:13:34: Having a quick look at the things we should be able to achieve when we wire up a language client in Vim with the language server from @Sap/cds-lsp via the Language Server Protocol (LSP), via a really simple CAP project with a service.cds and model.cds file: error highlighting, go-to-definition, find-references (and jumping to those references).

00:18:00: Looking at my .vim folder, noting the packages including the 'languageclient' and 'fzf' packages which we looked at in episode 1 and which is a dependency of the 'languageclient' package.

00:19:00: The language client we are using for Vim is LanguageClient-neovim which also works with regular Vim (as well as NeoVim). We look at a list of features the client supports, a quick start guide and some install documentation (I've already got this and 'fzf' installed).

00:20:20: Loading up model.cds in Vim, noting that it initially looks very boring, no syntax highlighting or any error notifications.

00:21:00: Starting to modify our Vim configuration to connect up the language client to the @Sap/cds-lsp-based language server and looking inside the server package to find the server.js entrypoint.

00:23:00: Simply starting node out/src/server.js does nothing much at all, but supplying the --stdio option causes the language server to start listening.

00:23:30: Quick chat with my neighbour on whose drive I've parked my car temporarily. Oops!

00:24:00: Understanding how to invoke the language server from the client, by looking at the sample configuration in the "Configure this plugin" section of the language client install guide.

00:25:50: Going to the language client package directory (./vim/bundle/languageclient), where I've already unpacked the @Sap/cds-lsp package (noting that I have the old 1.4.24 version as well as the newer 2.0.1 version which we'll be using).

00:26:50: Opening my Vim config file (in .vimrc) and adding some initial configuration thus:
set runtimepath+=~/.vim/bundle/languageclient

autocmd BufRead,BufNewFile *.cds setfiletype cds

set hidden
let g:LanguageClient_serverCommands = {
\ 'cds': [expand('~/.vim/bundle/languageclient/startcdslsp')]
\ }

00:31:09: Creating a startcdslsp in the same directory, that looks like this:


node "${HOME}/.vim/bundle/languageclient/cds-lsp-${VERSION}/out/src/server.js" --stdio

This is what we need to start up the language server so that the language client can connect to it and start using its services.

00:32:25: Discussing a question about opening VS Code from a Docker container to edit files within it.

00:33:25: All the configuration we see in this episode is in my dotvim repository.

00:34:15: Opening up the simple CAP project in Vim to see what happens now we have this basic configuration in place. Will anything happen? Yes! We see a message from the language client package:

"[LC] Project root: /Users/i347491/local/projects/livestream/capm/lsp"

That's all, so far though. I restored my saved configuration as I suspected I'd entered something incorrectly, and we then get the error highlighting!

00:36:34: On removing the 'e' from 'entity' to cause an error, we see an 'error' symbol (an 'x') in the gutter on the left hand side, along with the error description at the bottom: "[Error][syntax-mismatched-token]Mismatched identifier, expecting ...". Success!

The restored configuration also included this to ensure the gutter is shown:
set signcolumn=yes

00:38:05: Investigating more features, such as "go-to-definition" via the LanguageClient#textDocument_definition() command, which for now we call manually with :call, and also the "find-references" feature via the LanguageClient#textDocument_references() command, which shows references in a window that pops up at the bottom - using fzf for selection. Note that jumping to references also works across different files, as we saw here.

00:40:20: Back in the Vim config, mapping some keypresses as shortcuts for these commands:
nnoremap <silent> gd :call LanguageClient#textDocument_definition()<CR>
nnoremap <silent> fr :call LanguageClient#textDocument_references()<CR>

This makes using the "go-to-definition" and "find-references" features much quicker and more comfortable.

00:42:15: Starting to turn our attention to syntax highlighting, which is done separately from the language server facilities, taking some hints from the Syntax Highlighting chapter of Learn Vimscript the Hard Way. We also use the resource Creating your own syntax files.

We end up with this, in .vim/syntax/cds.vim:
if exists("b:current_syntax")

let b:current_syntax = "cds"

syntax keyword cdsKeyword entity namespace key to on
syntax keyword cdsType Integer String Association to Decimal Boolean
highlight link cdsKeyword Keyword
highlight link cdsType Constant