Liking cljdoc? Tell your friends :D

General Requirements

Guardrails (GR) is a free OSS project that is usable by any project/library, and Copilot is a commercial utility that leverages GR annotations to provide dynamic code analysis.

Seamless General Use

The library needs to satisfy the following constraints for general use:

  1. Libraries can use it without hurting their community.

  2. Free users of GR can upgrade to Copilot without making any source changes.

  3. GR and Copilot can be on classpath at the same time without ill effect. If you have a license, you get Copilot features automatically.

Therefore: Copilot uses GR as a dependency. The central function and spec macros defined in GR will either have to be extensible, or they will have to capture everything we need even though GR itself does not use it.

Since capture has space overhead, it will be off by default, and therefore will have zero overhead for GR users (it won’t even be a documented option in GR).

Actually, it might also be possible to simply have a :pro true option that causes GR >defn to simply re-emit a grp/>defn macro, which will only be available if they have Copilot. This is probably the best option: The core >defn macro is in GR, but the option simply causes >defn to re-emit a Copilot >defn.

Low Development Overhead

GR currently does checking at runtime. We will continue to support this mode of operation, but will be adding in static checking. When static checking is enabled it will capture the code and place it in a registry. This allows us to create an alternate build and runtime in which the static checks can run.

This means that the developer can use their normal REPL-driven development without any runtime checks in their normal REPL, and can run our static analysis on a separate thread (for clj or cljs) in order to keep their flow.

Optimized Checking

Copilot should be able to analyze the dependency graph and last change timestamps (combined with the hash of the function content) to understand what work can be skipped.

Targeted Checking

A developer should be able to indicate the primary interest (i.e. the function they are working on) so that messages unrelated to that function are muted. Such a mode would probably show the body of the function being coded, with any warnings/errors.

Generative Testing

It should be trivial to run generative tests on a function via the REPL or the Copilot GUI and see results.

Ideally there will be a generative testing section where generative tests on all known-pure functions are run any time that function’s hash changes (or the hash of anything in its deps tree).

Pluggable

The static analysis should have hooks that make it easy to add new checkers. The simplest of these could simply be passed the functions that have been determined to be stale. Some checks may need to re-run in a global way even if there were just local changes. For example, a check that looks for specific entries for multi-methods might need to run on any change.

Environment State

It will be necessary to reload namespaces in order to ensure we "unload" things that have been renamed or removed. It will also be necessary to figure out how to "uninstall" things that relate to protocols, mutlimethods, and other things that "capture" state in libraries (i.e. source not in the current project). Another example that is important is Clojure Spec’s registry, since a spec might be removed from code, the namespace reloaded, but the registry would still have it (and we rely on them).

Multimethods and protocols live in the namespace in which they are declared; therefore, reloading those namespaces should effectively clear those.

It’s probably true that we only care about augmented protocols and multimethods, so perhaps we use our own >defmulti and >defprotocol, and that will give us a clear hook into dealing with their internal state over time.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close