An open API service indexing awesome lists of open source software.

https://github.com/wavejumper/boonmee

A Clojure language server (WIP)
https://github.com/wavejumper/boonmee

Last synced: about 1 year ago
JSON representation

A Clojure language server (WIP)

Awesome Lists containing this project

README

          

![Clojure CI](https://github.com/wavejumper/boonmee/workflows/Clojure%20CI/badge.svg?branch=master)
![Release](https://github.com/wavejumper/boonmee/workflows/Release/badge.svg?branch=master)
[![Clojars Project](https://img.shields.io/clojars/v/wavejumper/boonmee.svg)](https://clojars.org/wavejumper/boonmee)

# boonmee

boonmee is a language server for Clojure that focuses on features relating to host interop.

It is an attempt to bring first-class 'intellisense' to ClojureScript projects.

Goals:

* For now, focus on interop - there are other great tools that lint Clojure code already ([clj-kondo](https://github.com/borkdude/clj-kondo), [joker](https://github.com/candid82/joker) etc)
* Tooling-agnostic - you should be able to integrate boonmee into any IDE/editor tool
* All analysis should be static, and side-effect free (eg, does not evaluate any code)

Right now boonmee only works on ClojureScript code (my personal frustration), but there are plans to target the JVM as well.

You can read [this](https://tscrowley.dev/#/posts/2020-20-07-boonmee) blog post about boonmee and its implementation details.

## Why

The biggest strength of Clojure is the fact that it is a hosted language.

Every Clojure codebase I have worked on leverages a host library at its core.

And yet, most linting/editor tools (outside of Cursive for the JVM) consider the host language as an afterthought.

## Features

### Editor functionality:

- [x] Quickinfo ([@jsdoc](https://jsdoc.app/) documentation, type signature, fn metadata etc)
- [x] Code completions (require, fn calls)
- [x] Code navigation (jump to definition)

### Linting (WIP):

- [ ] Warn on deprecated methods (via @jsdoc convention)
- [ ] Warn on undefined es6 method call
- [ ] Incorrect arity on es6 method call
- [ ] Basic type-checking

## Installation

Download a binary from the [releases](https://github.com/wavejumper/boonmee/releases) page.

Binaries get built via [GitHub Actions](https://github.com/wavejumper/boonmee/actions)

Refer to the [CI job](https://github.com/wavejumper/boonmee/blob/master/.github/workflows/release.yml) on how to compile boonmee as a native image from source.

## Dependencies

boonmee requires [NodeJS](https://nodejs.org/en/), and the TypeScript standalone server (`tsserver`):

```
npm install -g typescript
```

By default, boonmee will use the `tsserver` found on your `$PATH`. However, you can also specify a custom path:

```
./boonmee --tsserver=/path/to/tsserver
````

## Usage

Interaction with boonmee happens via stdio:

`./boonmee`

Refer to the [Example RPC](#example-rpc) section for some examples of client requests.

If you would like to use boonmee directly from a Clojure project, bring in the following dependency:

```clojure
[wavejumper/boonmee "0.1.0-alpha2"]
```

```clojure
(require '[boonmee.client.clojure :as boonmee])
(require '[clojure.core.async :as async])

(def client (boonmee/client {}))

(async/put! (:req-ch client) {}) ;; Make a request
(async/ number",
"documentation": "",
"tags": []
},
"interop": {
"fragments": [
"midiToFreq"
],
"sym": "Midi",
"isGlobal": false,
"usage": "method",
"prevLocation": [
7,
1
],
"nextLocation": [
7,
18
]
},
"requestId": "12345"
}
```

### Definitions

#### Request

```javascript
{
"command": "definition",
"type": "request",
"requestId": "12345",
"arguments": {
"file": "/path/to/core/core.cljs",
"projectRoot": "/path/to/project/root",
"line": 7,
"offset": 10
}
}
```

#### Response

```javascript
{
"command": "definition",
"data": {
"contextEnd": {
"line": 69,
"offset": 35
},
"contextStart": {
"line": 69,
"offset": 5
},
"end": {
"line": 69,
"offset": 15
},
"file": "/path/to/tonal/node_modules/@tonaljs/midi/dist/index.d.ts",
"start": {
"line": 69,
"offset": 5
}
},
"interop": {
"fragments": [
"midiToFreq"
],
"isGlobal": false,
"nextLocation": [
7,
18
],
"prevLocation": [
7,
1
],
"sym": "Midi",
"usage": "method"
},
"requestId": "12345",
"success": true,
"type": "response"
}
```