Need help with Elsa?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

emacs-elsa
494 Stars 22 Forks GNU General Public License v3.0 578 Commits 91 Opened issues

Description

Emacs Lisp Static Analyzer

Services available

!
?

Need anything else?

Contributors list

Elsa - Emacs Lisp Static Analyser Build Status

(Your favourite princess now in Emacs!)

Coverage Status Paypal logo Patreon

Elsa is a tool that analyses your code without loading or running it. It can track types and provide helpful hints when things don't match up before you even try to run the code.

Table of Contents

State of the project

We are currently in a very early ALPHA phase. API is somewhat stable but the type system and annotations are under constant development. Things might break at any point.

Non-exhaustive list of features

Here comes a non-exhaustive list of some more interesting features.

The error highlightings in the screenshots are provided by Elsa Flycheck extension.

Everything you see here actually works, this is not just for show!

Detect dead code

Detect suspicious branching logic

Find unreachable code in short-circuiting forms

Enforce style rules

Provide helpful tips for making code cleaner

Add custom rules for your own project with rulesets

Make formatting consistent

Look for suspicious code

Find references to free/unbound variables

Don't assign to free variables

Detect conditions which are always true or false

Make sure functions are passed enough arguments

Make sure functions are not passed too many arguments

Track types of expressions

Check types of arguments passed to functions for compatibility

How do I run it

Elsa can be run with makem.sh or with Cask.

makem.sh

Using

makem.sh
, simply run this command from the project root directory, which installs and runs Elsa in a temporary sandbox:
./makem.sh --sandbox lint-elsa

To use a non-temporary sandbox directory named

.sandbox
and avoid installing Elsa on each run:
  1. Initialize the sandbox:
    ./makem.sh -s.sandbox --install-deps --install-linters
    .
  2. Run Elsa:
    ./makem.sh -s.sandbox lint-elsa
    .

See

makem.sh
's documentation for more information.

Cask

[RECOMMENDED] Using packaged version

This method uses Cask and installs Elsa from MELPA.

  1. Add
    (depends-on "elsa")
    to
    Cask
    file of your project.
  2. Run
    cask install
    .
  3. cask exec elsa FILE-TO-ANALYSE [ANOTHER-FILE...]
    to analyse the file.

Using development version

To use the development version of Elsa, you can clone the repository and use the

cask link
feature to use the code from the clone.
  1. git clone https://github.com/emacs-elsa/Elsa.git
    somewhere to your computer.
  2. Add
    (depends-on "elsa")
    to
    Cask
    file of your project.
  3. Run
    cask link elsa 
    .
  4. cask exec elsa FILE-TO-ANALYSE [ANOTHER-FILE...]
    to analyse the file.

Flycheck integration

If you use flycheck you can use the flycheck-elsa package which integrates Elsa with Flycheck.

Configuration

By default Elsa core comes with very little built-in logic, only understanding the elisp special forms.

However, we ship a large number of extensions for popular packages such as

eieio
,
cl
,
dash
or even
elsa
itself.

You can configure Elsa by adding an

Elsafile.el
to your project. The
Elsafile.el
should be located next to the
Cask
file.

There are multiple ways to extend the capabilities of Elsa.

Analysis extension

One is by providing special analysis rules for more forms and functions where we can exploit the knowledge of how the function behaves to narrow the analysis down more.

For example, we can say that if the input of

not
is
t
, the return value is always
nil
. This encodes our domain knowledge in form of an analysis rule.

All the rules are added in form of extensions. Elsa has few core extensions for most common built-in functions such as list manipulation (

car
,
nth
...), predicates (
stringp
,
atomp
...), logical functions (
not
, ...) and so on. These are automatically loaded because the functions are so common virtually every project is going to use them.

Additional extensions are provided for popular external packages such as dash.el. To use them, add to your

Elsafile.el
the
register-extensions
form, like so
(register-extensions
 dash
 ;; more extensions here
 )

Rulesets

After analysis of the forms is done we have all the type information and the AST ready to be further processed by various checks and rules.

These can be (non-exhaustive list):

  • Stylistic, such as checking that a variable uses
    lisp-case
    for naming instead of
    snake_case
    .
  • Syntactic, such as checking we are not wrapping the else branch of
    if
    with a useless
    progn
    .
  • Semantic, such as checking that the condition of
    if
    does not always evaluate to
    non-nil
    (in which case the
    if
    form is useless).

Elsa provides some built-in rulesets and more can also be used by loading extensions.

To register a ruleset, add the following form to

Elsafile.el
(register-ruleset
 dead-code
 style
 ;; more rulesets here
 )

Type annotations

In Elisp users are not required to provide type annotations to their code. While at many places the types can be inferred there are places, especially in user-defined functions, where we can not guess the correct type (we can only infer what we see during runtime).

Read the type annotations documentation for more information on how to write your own types.

How can I contribute to this project

Open an issue if you want to work on something (not necessarily listed below in the roadmap) so we won't duplicate work. Or just give us feedback or helpful tips.

You can provide type definitions for built-in functions by extending

elsa-typed-builtin.el
. There is plenty to go. Some of the types necessary to express what we want might not exist or be supported yet, open an issue so we can discuss how to model things.

F.A.Q.

What's up with the logo?

See the discussion.

For developers

After calling

(require 'elsa-font-lock)
there is a function
elsa-setup-font-lock
which can be called from
emacs-lisp-mode-hook
to set up some additional font-locking for Elsa types.

How to write an extension for your-favourite-package

How to write a ruleset

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.