Commit Graph

49 Commits

Author SHA1 Message Date
Simon Jakobi
8d3c4e4250 Allow megaparsec-8 (#1582)
This also officially removes support for megaparsec-6.5 – the
build had been broken before though.
2019-12-03 03:28:06 +00:00
Frederik Ramcke
d7cd30d2ce Use foldl' over foldl everywhere (#1564)
* Use foldl' over foldl

As suggested by @sjakobi. Germans banding together in the fight against
laziness!

* Add missing foldl' imports

* Ups, forgot one!
2019-11-23 16:28:13 +00:00
Gabriel Gonzalez
5f15c860b3 List dependencies in "post-order" (#1539)
* List dependencies in "post-order"

Related to https://github.com/dhall-lang/dhall-lang/issues/823

This lists dependencies starting from the leaves and concluding with the root
import, same as how `nix-store --query --requisites` does

Example output:

```bash
$ dhall resolve --no-cache --transitive-dependencies <<< 'https://prelude.dhall-lang.org/package.dhall'
https://prelude.dhall-lang.org/Bool/and
https://prelude.dhall-lang.org/Bool/build
https://prelude.dhall-lang.org/Bool/even
https://prelude.dhall-lang.org/Bool/fold
https://prelude.dhall-lang.org/Bool/not
https://prelude.dhall-lang.org/Bool/odd
https://prelude.dhall-lang.org/Bool/or
https://prelude.dhall-lang.org/Bool/show
https://prelude.dhall-lang.org/Bool/package.dhall
https://prelude.dhall-lang.org/Double/show
https://prelude.dhall-lang.org/Double/package.dhall
https://prelude.dhall-lang.org/Function/compose
https://prelude.dhall-lang.org/Function/package.dhall
https://prelude.dhall-lang.org/Integer/show
https://prelude.dhall-lang.org/Integer/toDouble
https://prelude.dhall-lang.org/Integer/package.dhall
https://prelude.dhall-lang.org/List/all
https://prelude.dhall-lang.org/List/any
https://prelude.dhall-lang.org/List/build
https://prelude.dhall-lang.org/List/concat
https://prelude.dhall-lang.org/List/concatMap
https://prelude.dhall-lang.org/List/default
https://prelude.dhall-lang.org/List/empty
https://prelude.dhall-lang.org/List/filter
https://prelude.dhall-lang.org/List/fold
https://prelude.dhall-lang.org/List/generate
https://prelude.dhall-lang.org/List/head
https://prelude.dhall-lang.org/List/indexed
https://prelude.dhall-lang.org/List/iterate
https://prelude.dhall-lang.org/List/last
https://prelude.dhall-lang.org/List/length
https://prelude.dhall-lang.org/List/map
https://prelude.dhall-lang.org/List/null
https://prelude.dhall-lang.org/List/partition
https://prelude.dhall-lang.org/List/replicate
https://prelude.dhall-lang.org/List/reverse
https://prelude.dhall-lang.org/List/shifted
https://prelude.dhall-lang.org/List/unzip
https://prelude.dhall-lang.org/List/package.dhall
https://prelude.dhall-lang.org/Location/Type
https://prelude.dhall-lang.org/Location/package.dhall
https://prelude.dhall-lang.org/Map/Type
https://prelude.dhall-lang.org/Map/Entry
https://prelude.dhall-lang.org/Map/empty
https://prelude.dhall-lang.org/Map/keyText
https://prelude.dhall-lang.org/Map/keyValue
https://prelude.dhall-lang.org/Map/keys
https://prelude.dhall-lang.org/Map/map
https://prelude.dhall-lang.org/Map/values
https://prelude.dhall-lang.org/Map/package.dhall
https://prelude.dhall-lang.org/Monoid
https://prelude.dhall-lang.org/Natural/build
https://prelude.dhall-lang.org/Natural/enumerate
https://prelude.dhall-lang.org/Natural/even
https://prelude.dhall-lang.org/Natural/fold
https://prelude.dhall-lang.org/Natural/isZero
https://prelude.dhall-lang.org/Natural/odd
https://prelude.dhall-lang.org/Natural/product
https://prelude.dhall-lang.org/Natural/sum
https://prelude.dhall-lang.org/Natural/show
https://prelude.dhall-lang.org/Natural/toDouble
https://prelude.dhall-lang.org/Natural/toInteger
https://prelude.dhall-lang.org/Natural/lessThanEqual
https://prelude.dhall-lang.org/Natural/greaterThanEqual
https://prelude.dhall-lang.org/Natural/lessThan
https://prelude.dhall-lang.org/Natural/equal
https://prelude.dhall-lang.org/Natural/greaterThan
https://prelude.dhall-lang.org/Natural/min
https://prelude.dhall-lang.org/Natural/max
https://prelude.dhall-lang.org/Optional/map
https://prelude.dhall-lang.org/Natural/listMin
https://prelude.dhall-lang.org/Natural/listMax
https://prelude.dhall-lang.org/Natural/sort
https://prelude.dhall-lang.org/Natural/subtract
https://prelude.dhall-lang.org/Natural/package.dhall
https://prelude.dhall-lang.org/Optional/all
https://prelude.dhall-lang.org/Optional/any
https://prelude.dhall-lang.org/Optional/build
https://prelude.dhall-lang.org/Optional/concat
https://prelude.dhall-lang.org/Optional/default
https://prelude.dhall-lang.org/Optional/filter
https://prelude.dhall-lang.org/Optional/fold
https://prelude.dhall-lang.org/Optional/head
https://prelude.dhall-lang.org/Optional/last
https://prelude.dhall-lang.org/Optional/length
https://prelude.dhall-lang.org/Optional/null
https://prelude.dhall-lang.org/Optional/toList
https://prelude.dhall-lang.org/Optional/unzip
https://prelude.dhall-lang.org/Optional/package.dhall
https://prelude.dhall-lang.org/JSON/Type
https://prelude.dhall-lang.org/JSON/Nesting
https://prelude.dhall-lang.org/JSON/Tagged
https://prelude.dhall-lang.org/JSON/keyText
https://prelude.dhall-lang.org/JSON/keyValue
https://prelude.dhall-lang.org/JSON/string
https://prelude.dhall-lang.org/JSON/number
https://prelude.dhall-lang.org/JSON/object
https://prelude.dhall-lang.org/JSON/array
https://prelude.dhall-lang.org/JSON/bool
https://prelude.dhall-lang.org/JSON/null
https://prelude.dhall-lang.org/Text/concatMapSep
https://prelude.dhall-lang.org/JSON/render
https://prelude.dhall-lang.org/JSON/package.dhall
https://prelude.dhall-lang.org/Text/concat
https://prelude.dhall-lang.org/Text/concatMap
https://prelude.dhall-lang.org/Text/concatSep
https://prelude.dhall-lang.org/Text/default
https://prelude.dhall-lang.org/Text/defaultMap
https://prelude.dhall-lang.org/Text/show
https://prelude.dhall-lang.org/Text/package.dhall
https://prelude.dhall-lang.org/XML/Type
https://prelude.dhall-lang.org/XML/attribute
https://prelude.dhall-lang.org/XML/render
https://prelude.dhall-lang.org/XML/element
https://prelude.dhall-lang.org/XML/leaf
https://prelude.dhall-lang.org/XML/text
https://prelude.dhall-lang.org/XML/emptyAttributes
https://prelude.dhall-lang.org/XML/package.dhall
https://prelude.dhall-lang.org/package.dhall
```

* Document order in `dhall resolve --help` output

... as suggested by @sjakobi

* Fix dhall-lsp-server build
2019-11-21 16:20:48 +00:00
Frederik Ramcke
619788f795 dhall-lsp-server: Fix hovering in presence of nested lets (#1537)
* Fix hacked-together parsers

Back when we changed the linter to preserve let comments we made
whitespace parsing explicit (previously combinators swallowed any
trailing whitespace), but we forgot to update the hacked-together
parsers used by the LSP server. As a result, various convenience
features broke, but that's easy enough to fix.

* Fix 'annotate lets' and 'type on hover' features

Both features only work as intended if as much of the Dhall code as
possible is wrapped in Note annotations, since we use that to figure out
where the user was pointing. Since the removal of explicit multi-lets in
the syntax the parser no longer wraps immediately nested lets (i.e.
multilets) in Notes, which means we need to split them manually (like we
used to).

* Fix hovering test

Now the behaviour expected by the test matches what we would want in
reality.
2019-11-20 17:02:06 +00:00
Simon Jakobi
dedd5e0ea6
Strip trailing whitespace (#1422)
This raises the lower bound on prettyprinter to 1.5.1 since
`removeTrailingWhitespace` is buggy in earlier versions.

This jailbreaks hnix, which isn't compatible with prettyprinter-1.5.1 yet.

Fixes #183, #1400, #1525. 

Co-authored-by: Gabriel Gonzalez <Gabriel439@gmail.com>
2019-11-14 14:43:35 +01:00
Frederik Ramcke
12ca71f0c7 dhall-lsp-server: Add option to only use ASCII when formatting and linting (#1533)
* Add config support

The config so far consists of a single `asciiOnly` flag (whose intended
behaviour is not yet implemented).

* Implement 'ascii-only' option when formatting and linting

This commit adds functionality to the 'asciiOnly' flag, i.e. when turned
on we don't output fancy non-ascii characters. Needs a recent version of
the client to function -- the version on the marketplace does not relay
configuration data to the server yet!
2019-11-14 05:08:05 +00:00
Simon Jakobi
e931451a2b Format more text literals as multi-line strings (#1508)
This causes text literals to be formatted as multi-line strings
whenever they contain at least one newline and at least one non-newline
character. "Spacers" like `"\n\n"` continue be formatted as single-line
strings. If the heuristic turns out to be too eager to choose a
multi-line layout, we can refine it later.

This partially addresses #1496.

Also

* update some variable names

* use 80-column "smart" layout consistently
2019-11-04 03:31:49 +00:00
Simon Jakobi
7eec31d1d7 Parse whitespace more precisely (#1483)
This is preparatory work for #1454.

This also fixes some cases where dhall would previously accept
malformatted inputs.

The changes to dhall-lsp-server are mostly untested. See #1510.

Co-authored-by: Gabriel Gonzalez <Gabriel439@gmail.com>
2019-11-03 19:42:58 +00:00
Gabriel Gonzalez
b843cae5d2
Improve encoding/decoding speed (#1500)
... by not going through a `Term` intermediate

This gives a ~28% performance in decoding improvement, which means that
cache looks are not faster.

Here are the new decoding benchmarks before and after this change:

Before:

```
benchmarked Issue #108/Binary
time                 266.5 μs   (265.7 μs .. 267.4 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 266.3 μs   (265.6 μs .. 267.1 μs)
std dev              2.418 μs   (1.891 μs .. 3.436 μs)

benchmarking Kubernetes/Binary ... took 36.94 s, total 56 iterations
benchmarked Kubernetes/Binary
time                 641.3 ms   (623.0 ms .. 655.4 ms)
                     0.999 R²   (0.997 R² .. 1.000 R²)
mean                 679.7 ms   (665.5 ms .. 702.6 ms)
std dev              29.48 ms   (14.15 ms .. 39.05 ms)
```

After:

```
benchmarked Issue #108/Binary
time                 282.2 μs   (279.6 μs .. 284.7 μs)
                     1.000 R²   (0.999 R² .. 1.000 R²)
mean                 281.9 μs   (280.7 μs .. 287.7 μs)
std dev              7.089 μs   (2.550 μs .. 15.44 μs)
variance introduced by outliers: 11% (moderately inflated)

benchmarking Kubernetes/Binary ... took 27.57 s, total 56 iterations
benchmarked Kubernetes/Binary
time                 499.1 ms   (488.1 ms .. 506.6 ms)
                     0.999 R²   (0.998 R² .. 1.000 R²)
mean                 498.9 ms   (494.4 ms .. 503.9 ms)
std dev              8.539 ms   (6.236 ms .. 12.56 ms)
```

There's a slight performance regression for the decoding microbenchmark, but
in practice my testing on real examples matches performance improvements seen
in the larger benchmark based on an example cache product from
`dhall-kubernetes`.

Note that is a breaking change because:

* There is no longer a `FromTerm` nor `ToTerm` class.  Now we use the
  `Serialise` class and `{encode,decode}Expression` now work on `ByteString`s
  instead of `Term`s

* I further narrowed the types of several encoding/decoding utilites to expect a
  `Void` for the first type parameter of `Expr`

* This is a regression with respect to stripping 55799 CBOR tags, mainly
  because properly handling the tags at every possible point in the syntax tree
  would considerably complicate the code
2019-10-31 20:05:22 -07:00
Gabriel Gonzalez
5c26dace8b Improve parsing error messages (#1443)
* Improve parsing error messages

The main changes are:

* Don't quote expected tokens in the error message (to avoid visual clutter)
* Consolidate expected tokens into simpler categories (e.g. "operator" or
  "literal") instead of listing them all

For example, this would be an error message before this change:

```
$ dhall <<< '1 + [1'
dhall:
Error: Invalid input

(stdin):2:1:
  |
2 | <empty line>
  | ^
unexpected end of input
expecting "!=", "&&", "++", "->", "//", "//\\", "/\", "==", "===", "merge", "toMap", "||", "→", "∧", "≡", "⩓", "⫽", '#', '(', '*', '+', ',', '.', ':', '?', ']', built-in expression, double infinity, double literal, import, integer literal, label, list literal, natural literal, record type or literal, text literal, union type, or whitespace
```

... and this would be an error message after this change:

```
$ dhall <<< '1 + [1'
dhall:
Error: Invalid input

(stdin):1:4:
  |
1 | 1 + [1
  |    ^^^^
unexpected " [1<newline>"
expecting (, import, keyword, label, or literal
```

* Fix test failures

* Fix warnings
2019-10-27 03:34:33 +00:00
Basile Henry
69b228454e Test that dhall format is idempotent (#1427) 2019-10-22 19:45:08 +02:00
Sergei Dolgov
ad443cd685 Fix dhall-lsp-server to be "-Wall clean" (#1446) (#1449) 2019-10-21 12:54:00 +00:00
Gabriel Gonzalez
17fb0e3c46
100% haddock coverage (#1416)
This updates the `dhall` package to have 100% haddock coverage and
also updates CI to enforce this going forward.

This also includes a change to deprecate the `X` type synonym, which
I noticed along the way
2019-10-13 22:22:39 -07:00
Gabriel Gonzalez
96921f03ab
Fix dhall format to preserve let comments (#1273)
Related to https://github.com/dhall-lang/dhall-haskell/issues/145

Note that this also refactors `Let` to use `Binding` in order
to avoid having to duplicate `Src`-related fields in two
places.
2019-09-04 23:41:44 -05:00
Simon Jakobi
350b54c43e Lint: Don't remove asserts wrapped in lambdas or other expressions (#1269)
Also reuse the core linting logic in dhall-lsp-server
2019-09-01 18:09:28 +00:00
Simon Jakobi
72fd2ac983
Treat multi-lets as syntactic sugar (#1242)
Closes #1185.

This mostly reverts "Add support for multi-`let` (#675)" /
8a5bfaa3b9.

Also:

* Add fields for Src
  This is useful for to make 'Note's less noisy during debugging:

      first srcText expr
2019-08-31 18:31:24 +02:00
Frederik Ramcke
b997d43efd Fix type-on-hover over non-dependent function types (#1233)
Previously, hovering over any part of a non-dependent function type like
`Bool -> Bool` would result in the type of the domain being displayed
(`Bool` in this example). The correct type is `Type`.

This bug resulted from the fact that we
expected all functions types to be syntactically of the form
`forall (b : Bool) -> Bool`, disregarding the simpler syntax for the
non-dependent function space (which desugars to
`forall (_ : Bool) -> Bool`).
2019-08-20 02:00:18 +00:00
Frederik Ramcke
6ce01a0eda dhall-lsp-server: Remove superfluous language extensions (#1232)
* Remove superfluous language extensions

* Remove use of ScopedTypeVariables

In order to make the code more accessible it makes sense to refrain from
using ScopedTypeVariables, which we only used in two places.

* Remove use of LambdaCase extension
2019-08-20 01:35:07 +00:00
Frederik Ramcke
8c3db821db Correctly handle dependent types in dhall-lsp-server (#1216)
* Correctly handle dependent types in dhall-lsp-server

Removes the "fast path" when typechecking `let`s whose bound expression
has a small type. This optimisation is no longer legal in the presence
of dependent types (as introduced in #1164).

* Fix bad merge

* Remove redundant import
2019-08-12 13:27:41 +00:00
Frederik Ramcke
4c1736b154 Improve rendering of types when annotating lets (#1222)
Previously the annotated type would have too many line-breaks, e.g. when
the result of annotating
  let id = \(A : Type) -> \(a : A) -> a
was
  let id :   ∀ ( A
  : Type
  )
  → ∀ ( a
  : A
  )
  → A = \(A : Type) -> \(a : A) -> a
while it should be
  let id : ∀(A : Type) → ∀(a : A) → A = \(A : Type) -> \(a : A) -> a
2019-08-08 15:16:07 +00:00
Frederik Ramcke
6609270fe4 Only underline link in import (#1217)
This restricts the clickable link part of an import to just the actual
link; previously we also underline hash and headers if those were
present.

Now:
./Bool/package.dhall sha256:7ee950e7c2142be5923f76d00263e536b71d96cb9c190d7743c1679501ddeb0a
~~~~~~~~~~~~~~~~~~~~

Previously:
./Bool/package.dhall sha256:7ee950e7c2142be5923f76d00263e536b71d96cb9c190d7743c1679501ddeb0a
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-08-08 13:42:49 +00:00
Frederik Ramcke
5f3b05a8f2 dhall-lsp-server: Implement completion support (#1190)
* Implement completion support

Completes the following:
- environment variables
- local imports
- identifiers in scope (as well as built-ins)
- record projections
- union constructors

* Add support for general dependent types

Removes the non-dependent let path. Needed since #1164 added support for
general dependent types.

* Remove unused import

* Use monad instance to cast between `Expr Src _`

As suggested by @Gabriel439: Use `typeOf (do _ <- expr; holeExpr)`
instead of `fmap undefined expr`. In the absence of `Embed` constructors
(in this case `Import`s) the two are equivalent.

* Simplify completeFromContext

Caught by @Gabriel439

* Remove debug code

* Add 1s timeout to listDirectory call

As pointed out by @Gabriel439, listDirectory can be a potentially
expensive operation. Adding a timeout should improve the user
experience.

* Fix unclean merge
2019-08-07 14:11:59 +00:00
Frederik Ramcke
523861a92c dhall-lsp-server: Upgrade to haskell-lsp 0.15 (#1203)
* Clean up dhall-lsp-server.cabal

Removes unused dependencies.

* Upgrade to haskell-lsp-0.15.0.0

The stackage LTS version is still 0.8.2 so we need to add this as an
'extra-dep'.

* Display type information as plaintext rather than markdown

* Fix nix build

* Update nix haskell-lsp-types
2019-08-07 11:40:43 +00:00
Ollie Charles
4a93c255db Remove Dhall.X and replace with Data.Void (#1172)
* Remove Dhall.X and replace with Data.Void

This commit removes the Dhall.X module and the Dhall.X.X type,
preferring the use of Data.Void.Void. As I'm sure a lot of people are
actually using X, I've added a type-alias type X = Void. However,
pattern matching on X would be a breaking change.

Fixes #1120.

* Restore unsafeCoerce

* Fix regression

* Unused

* Reorganise exports

* Fix dhall-nix

* Another fix

* Fix Dhall.LSP.Backend.Typing

* Fix dhall-bash
2019-08-05 13:00:59 +00:00
Gabriel Gonzalez
a81c75fc5b Remove most uses of StandardVersion from the API (#1169)
* Remove most uses of `StandardVersion` from the API

We no longer support multiple versions of the standard, except for
supporting old integrity checks, so this change removes all inessential
uses of `StandardVersion` from the API and command-line interface.

* Fix `dhall-lsp-server` build
2019-07-31 01:49:53 +00:00
Frederik Ramcke
4faf25bbbe Load imports recursively (#1128)
* Load imports recursively

This is the big change that enables us to implement 'semi-semantic'
caching.

* Use `throwM` instead of `liftIO . throwIO`

* Fix build with __GHCJS__

* Fix exceptions in Dhall.Import

* Fix dhall-lsp-server

* Revert exception behaviour on typecheck errors

This is one for a separate pull request!

* Make sure loadImportFresh returns alpha-normal expression

As caught by @Gabriel439, `loadImportFresh` violated the invariant that
`ImportSemantics` should be alpha-beta-normal. This fix also means that
we don't have to alpha-normalise again in `loadImportWithSemanticCache`.

* Remove old comment

* Fix regression test for issue 216

Turns out the test was testing the wrong thing, because it was
pretty-printing an import. This worked previously because when importing
uncached expressions we would not alpha-normalise them.

* Restore `dhall freeze` bevhaviour

Newly frozen imports should also be present in the cache.
2019-07-23 16:11:33 +00:00
Frederik Ramcke
7e9728f0e9 dhall-lsp-server: Freezing imports (#1123)
* Implement dhall.freezeImport and dhall.freezeAllImports

* Remove old (broken) test suite

* Rename `relativePosition` to `subtractPosition`

as suggested by @Gabriel439

* Add doctest for `subtractPosition`

as suggested by @Gabriel439

* Simplify getImportHashPosition

As spotted by @Gabriel439

* Use `forM` instead of `mapM` for prettier code

As suggested by @Gabriel439
2019-07-19 17:24:11 +00:00
Frederik Ramcke
d5d0224bc3 Preparing Dhall.Import for "Semi-semantic" caching (#1113)
* Fix misleading comment

* Add `Chained` type to capture fully chained imports

Until now we used `Import` two mean two different things:
- The syntactic construct; e.g. `./a.dhall` corresponds to the following
  AST:
  ```
  Embed
    (Import
      (ImportHashed Nothing (Local Here (Directory ["."]) "a.dhall"))
      Code)
  ```

- The physical location the import is pointing to, computed by
'chaining' the syntactical import with the the 'physical' parent import.
For example the syntactic import `./a.dhall` might actually refer to the
remote file `http://host/directory/a.dhall`.

This commit adds a `Chained` newtype on top of `Import` to make this
distinction explicit at type level.

* Use `HTTPHeaders` alias for binary headers

I claim that `HTTPHeaders` is more readable and informative than the
unfolded type `(CI ByteString, ByteString)`.

* Typecheck and normalise http headers earlier

Previously we would typecheck and normalise http headers in
`exprFromImport`, i.e. while loading the import. This commit adds the
invariant that any headers in 'Chained' imports are already typechecked
and normalised, and moves this step into `loadWith` accordingly.

This causes a subtle difference in behaviour when importing remote files
with headers `as Location`: previously, nonsensical expressions like
`http://a using 0 0 as Location` were valid, while they would now cause
a type error.

* Fix dhall-lsp-server

* Fix Dhall.Import API regarding `Chained` imports

Do not expose the `Chained` constructor; we don't want external code
breaking our invariants! Also further clarifies the comment describing
the `Chained` type.

* Fix dhall-lsp-server

Since we are no longer able to construct `Chained` imports directly we
need to export a few additional helper functions from Dhall.Import.
Furthermore, since VSCode (and presumably the other editors out there
implementing the LSP protocol) does not support opening remote files
anyway we can get rid of some complications by dropping support for
remote files entirely on the back-end.

* Generalise decodeExpression, fixes TODO

* Fix tests

* Fix benchmarks

* Remove Travis cache for `~/.local/bin`

* Fix copy-pasted comment

Thanks to @Gabriel439 for spotting this!

* Add clarifying comment to `toHeaders`
2019-07-17 15:20:48 +00:00
Frederik Ramcke
33ebf7ee71 dhall-lsp-server: Turn imports into clickable links (#1121)
* Expose `localToPath` in Dhall.Import

Also modifies `localToPath` to return a relative path if the input was
relative, rather than resolving relative paths by appending the current
directory.

* Turn imports into clickable links

This implements a handler for 'Document Link' requests. As a result,
imports are now clickable!

* Recover original behaviour
2019-07-17 08:54:56 +00:00
Mario
8aa2ac3ce9 Implementation of toMap (#1041)
... as standardized in https://github.com/dhall-lang/dhall-lang/pull/610
2019-07-15 08:28:29 -07:00
Frederik Ramcke
8ae7b603fe
dhall-lsp-server: Fix cache to correctly invalidate transitive dependencies (#1069)
* Move "Dot" import graph generation to Dhall.Main

Previously `Dhall.Import` would generate the import graph in "dot"
format while resolving imports. This change simplifies `Dhall.Import` to
only keep track of the adjacency list representing the import graph,
moving the logic for generating "dot" files to Dhall.Main.

This change will allow us to implement proper cache invalidation for
`dhall-lsp-server`.

* Correctly invalidate transitive dependencies

Fixes dhall-lsp-server`s caching behaviour to correctly invalidate
cached imports that (possibly indirectly) depend on the changed file.

Example:

Suppose we have the following three files:
{- In A.dhall -} 2 : ./B.dhall
{- In B.dhall -} ./C.dhall
{- In C.dhall -} Natural

Previously, changing C.dhall to `Text` would not cause `A.dhall` to stop
type-checking, since the old version of `B.dhall` (which evaluated to
`Natural`) would still have been in the cache. This change fixes that
behaviour.

* Make edges of import graph self-documenting

As suggested by @Gabriel439

* Don't cache expressions manually

After computing the diagnostics for a given file we added its normal
form to the cache, but forgot to add its dependencies to the dependency
graph. This bug points out that keeping the import graph consistent
manually is probably not a good idea. With this commit we never mess
with the import cache manually; this means that files are only cached
once they are depended upon by some other file, potentially causing us
to duplicate work (but no more than once).

* Fix left-overs from previous commit
2019-07-08 10:55:15 +00:00
Frederik Ramcke
2cd4ed948f dhall-lsp-server: Improve type-on-hover behaviour over binders (#1062)
* Improve type-on-hover behaviour over binders

Dhall's parser does not generate `Src` annotations for the names in
binders, which means that it's not quite as straight-forward to check
whether the user meant to hover over it and see its type as one would
hope. As a result, the current "naive" implementation sometimes behaves
slightly unintuitively and returns the type of the entire expression,
rather than the type of the bound variable. E.g.
  let x = 2 in "text"
      ~
would result in the type `Text` being displayed, rather than `Natural`
as one would expect. Since the language server also marks the expression
whose type is being displayed, the behaviour isn't quite that bad in
practice (we aren't falsely led to believe that `x` has type `Text`).

This change recovers the `Src` information describing the bound variable
names and handles those cases in a way that should be more in line with
the expectations of the user.

* Fix exprAt not handling multi-lets correctly

* Fix merge left-overs
2019-07-06 23:17:52 +00:00
Frederik Ramcke
53e1967754
dhall-lsp-server: Normalize types before displaying them to the user (#1060)
* Normalize types before displaying them to the user

Previously, the type displayed when hovering over the arrow in a lambda
(or forall) binder would not always be normal, e.g.
  \(n : {Left = Natural, Right = Natural}.Left) -> n + n
                                                ~
would result in
  forall (n : {Left = Natural, Right = Natural}.Left) -> Natural
being displayed.

The (expected) normal type would be:
  forall (n : Natural) -> Natural

This fix normalises types before displaying them to the user (fixes both
the type-on-hover and annotate-let behaviour).

* Move normalisation from typeAt' to typeAt

This way we only have to worry about it one place, rather than  in each
clause of `typeAt'`.
2019-07-05 03:58:44 +00:00
Frederik Ramcke
3a120d277f
Change rangeFromDhall to exclude trailing whitespace (#1046)
This gets rid of the separate `santiseRange` utility function that we
used to exclude trailing whitespace from source code ranges. As a result
of this change, we no longer have to carry around the original source
code everywhere to be able to santise ranges after the fact.
2019-07-03 09:25:24 +00:00
Frederik Ramcke
41161aa390
dhall-lsp-server: Implement caching (#1040)
* Rewriting Dhall.LSP.Backend.Dhall: Implement new API

The old "backend" consisted of a random collection of ways to invoke
Dhall:
- runDhall :: FilePath -> Text -> IO (Expr Src X)
- runDhallSafe :: FilePath -> Text -> IO (Maybe (Expr Src X))
- loadDhallExprSafe :: FilePath -> Text -> IO (Maybe (Expr Src X))

The new backend exposes a slightly more though-out API. This also lays
the foundation for performance improvements in the dhall lsp server via
caching.

* Reorder code in Dhall.LSP.Backend.Dhall

* Remove unused constructor

* Rewrite and document Backend.Formatting

* Refactor Dhall.LSP.Backend.Linting

* Refactor Dhall.LSP.Backend.ToJSON

* Adapt Diagnostics backend to the new Dhall API

* Remove old Dhall backend API

* Implement caching; revamp LSP frontend

This commit implements caching of Dhall expressions: we only need to
fetch, typecheck and normalise each import once per session, unless they
change! This means that `dhall-lsp-server` is now viable for non-trivial
Dhall projects, for example probing around in `dhall-nethack` everything
feels near-instantaneous once the imports have been resolved.

This implementation currently has a bug: we don't invalidate imports
transitively, i.e. if A.dhall loads B.dhall and B.dhall changes we do
not discard the cached version of A.dhall. This should be reasonably
easy to fix given some time with Dhall's import graph. Furthermore,
there is some cleaning up left to do:
  - Fix warnings
  - Reorganise things in a less ad-hoc way
  - Make the code a bit prettier

* Fix caching of errors

* Use `bimap` instead of `first` and `second`

* Re-export `Dhall.lint` rather than aliasing

Rids us of some boilderplate

* Use MVar instead of TVar for server state

The main benefit is that we get to use `modifyMVar_` which does updating
of the shared state for us (and gracefully handles any uncaught
exceptions).

* Don't invalidate hashed imports

Fixes a misinterpretation on my end of the correct behaviour regarding
the caching of imports. Quoting @Gabriel439:

> A hashed import is valid indefinitely once it is successfully
> resolved, even when the underlying import later becomes broken. That's
> why missing sha256:… works so long as the cache has that import cached
> (and this behavior is part of the standard).

* Cleanup Dhall.LSP.Backend.Dhall a little bit

* Add note about fixing cache invalidation

* Use TemplateHaskell to generate state lenses

* Make types of `typeAt` and `annotateLet` more expressive

Both assume the input to be well-typed; by using `WellTyped` rather than
`Expr Src X` as the type of their input we can make this explicit.

This change exposed a bug (also fixed in this commit) in the
type-on-hover functionality: we run `typeAt` only if the input was
well-typed _the last time we checked it_ (which was at the last save);
this means that if the code changed without being written to disk we
would happily try to normalise (in `typeAt`) non-well-typed code...

* Fix type of typecheck

Typecheck returned the well-typed _type_ of a given expression, while I
was assuming it would certify the input to be well-typed. Silly indeed.

* Remove `checkDhall` from Dhall.Backend.Diagnostics

Removes the left-over stub from the change to the new Dhall backend.

* Update comments and remove TODO note

* Remove superfluous parentheses

* Simplify MonadState code via lens combinators

* Use `guard` instead of matching on True

* Remove more superfluous parentheses
2019-07-01 17:30:32 +00:00
Frederik Ramcke
8d4aa0320e dhall-lsp-server: Correctly handle dependent lets (#1018)
While I do believe the previous version to be correct as well, this
certainly makes it easier to reason about it.
2019-06-22 09:35:52 -07:00
Frederik Ramcke
dc5f70011d dhall-lsp-server: (new feature) annotate lets (#1014) 2019-06-20 09:37:59 -07:00
Frederik Ramcke
66833cbfa5
dhall-lsp-server: Type on hover (#1008)
* Type on Hover 1/2: Backend

Adds a function typeAt that, given an annotated expression and a text
position finds the type of the subexpression at that position.

* Type on Hover 2/2: Frontend

Exposes the new type-on-hover functionality as part of the hover
handler.

* Simplify explainDiagnosis

As suggested by @Gabriel439

* Simplify `inside`

Adressing @Gabriel439's comment.

* Simplify typeAt' by assuming well-typedness

* Simply srcAt

Use choice operator `<|>` instead of case distinction
2019-06-17 10:37:38 +00:00
Frederik Ramcke
bed87530b5 dhall-lsp-server: Towards implementing a "convert to JSON" command (#1005)
At the moment the VSCode plugin contains a hacked-together prototype of
a dhall-to-json (and -to-yaml) preview feature. We should ultimately
move that kind of functionality to dhall-lsp-server to 1) minimise the
amount of VSCode specific code and 2) avoid having to work with and fix
bugs in typescript code ;)

This commit takes us most of the way there; what is missing is the
ability to create files (via a WorkspaceEditRequest), which is not yet
implemented by haskell-lsp-types. I will wait with exposing the
corresponding command (and removing the existing preview code) in
vscode-dhall-lsp-server until this is fixed upstream.
2019-06-13 07:23:48 -07:00
Frederik Ramcke
af4ccc9db9 dhall-lsp-server: Implement linter diagnostics and "Lint and Format" command (#1003)
* Refactor Dhall.LSP.Backend.Formatting

Exposes `formatExpr :: Text -> Expr a Import -> Text` that can be reused
in the lintAndFormat command.

* Implement linting backend in Dhall.LSP.Backend.Linting

Exposes `suggest :: Eq a => Expr Src a -> [Suggestion]` and
`lintAndFormatDocument :: Text -> Either ParseError Text`.

* Fix unusedBindings

* Implement linter diagnostics

* Improve linting diagnostic ranges

In VSCode we now mark the "let" following a superfluous "in".
  let a = 0 in let b = a in b
               ~
Previously we got
  let a = 0 in let b = a in b
  ~
which was slightly confusing

* Implement executeCommand handler for "Lint and Format"

This exposes the command "dhall.server.lint", which should be called
from the vscode plugin to lint and format the current dhall file. Needs
a correspondingly patched vscode-dhall-lsp-server (branch lint).
2019-06-11 08:10:16 -07:00
Frederik Ramcke
05f4d5cd1e dhall-lsp-server: Use LSP VFS rather than disk IO (#994)
* Remove dummy LSP handlers

* Publish diagnostics directly

So far we were using haskell-lsp's diagnostics infrastructure.
haskell-lsp is geared towards plugin-based language servers like
haskell-ide-engine, which means that their approach to handling
diagnostics (on a per-plugin basis) doesn't really fit our use-case.
This commit changes our diagnostics implementation to send
protocol-level messages directly, rather than going through haskell-lsp.

* Refactor diagnostics handler

Reduce clutter and clean up Dhall.LSP.Handlers.Diagnostics a bit.

* Remove unused import

* Don't flush diagnostics on file close

The LSP protocol does not expect (or require) us to flush diagnostics at
any point. This change doesn't have any user-visible impact (since we
recompute diagnostics on file open anyway).

* Use LSP VFS instead of disk IO

Rather than reading the files from disk each time, we now simply query
haskell-lsp's "virtual file system". This also allows us to check code
before it has been saved (though we do not implement this).
2019-06-07 20:48:42 -07:00
Frederik Ramcke
dfee2fbbca
Simplify dhall-lsp-server and reorganise its modules (#992)
* Clean up dhall-lsp-server's Main.hs

Also adds haddock comments.

* Remove TODO comment

The comment talks about adding a mechanism for protocol-level logging to
dhall-lsp-server. Since the VSCode LSP implementation has this feature
already baked in on the client side, we don't have to implement it
ourselves.

* Simplify dhall-lsp-server's infrastructure

So far we had a system where we set up the LSP message handlers to relay
messages to a separate dispatcher thread via a shared channel. Since our
language server is at the same time designed in a completely synchronous
manner, this complication turns out to be unnecessary.

* Remove sample code

* Fix unused variable warning

* Reorganise dhall-lsp-server's module hierarchy

Prefixes all modules with "Dhall.LSP.".

Previously:
  Backend.Dhall.
               .Diagnostics
               .Formatting
  LSP.
     .Handlers
     .Handlers.
              .Diagnostics
              .DocumentFormatting
              .Server

Now:
  Dhall.LSP.
           .Backend.
                   .Diagnostics
                   .Formatting
           .Handlers
           .Handlers.
                    .Diagnostics
                    .DocumentFormatting
           .Server

* Make dhall-lsp-server tests compile again

They still fail though!
2019-06-07 07:47:07 +00:00
Javier Neira
00f7478759 Fix compiling of dhall-lsp test (#990)
* Avoid clash between Backend.Dhall.Diagnostics.Range and Language.Haskell.LSP.Types.Range

* Ignore .cache dirs created by tests

* Fix rest of compile errors and warnings
2019-06-05 16:40:09 -07:00
Frederik Ramcke
49d29d685f
dhall-lsp-server: Rework diagnostics backend + detailed error messages on hover (#982)
* Refactor Diagnostics backend

This commits refactors Backend.Dhall.Diagnostics, cleaning things up and
adding comments along the way. We also lose Backend.Dhall.DhallErrors.

The user-facing result is a step backwards, as we revert to using Dhall's
Show instances to print errors, which gives us error messages that don't
fit the LSP use case very well at the moment. In the future
we should change Dhall's error printing API (the Show instances) to make
them more generally useful (in particular for the LSP use case), thus
saving us from having to duplicate code (as was previously did, when
dhall-lsp-server was not yet part of the upstream project).

* Proof of concept: Provide detailed error messages

This proof of concept provides detailed explanations on hovering over type
errors. Currently this is done by injecting the explanation directly into
the hover text, which 1. conflicts with the short error messages, which
are still being displayed at the same time and 2. is not particularly
readable, since the explanations are meant to be rendered at least 80
characters wide.

For future work I am planning to instead only add an "explain" link to the
hover window, which when clicked opens the explanation in a separate
window (inspired by how the haskell ide engine presents documentation
links). This will require a small amount of client-side logic.

* Explain error messages via VSCode Command URIs

The first proof of concept simply spit out the explanations as hover text;
in order to make the feature a bit more useful, we now encode the
explanation text into a VSCode command URI (that still needs to be
implemented client-side), so that upon hovering over an error the user is
presented with a clickable "Explain error message" link.

The feature is still in the prototype stage!

* Use custom URI scheme instead of command URIs

Use URIs of the form "dhall-explain:?text" to present detailed
explanations on hovering. Previously we used command URIs, which are
specific to VSCode.

Needs a correspondingly patched vscode-lsp-server to handle the
"dhall-explain" URI scheme.

* Fix handling of relative imports in diagnostics

In refactoring the diagnostics backend I forgot to initialise the settings
passed to the Dhall type-checker, which are needed to properly resolve
relative imports. An easy fix for a silly mistake ;)

* Remove outdated TODO comment

* Make GHC stricter when building dhall-lsp-server

Add -Wall and -fwarn-incomplete-uni-patterns to the GHC options when
building dhall-lsp-server. This brings it in line with the rest of
dhall-haskell.

* Fix warnings when building dhall-lsp-server

* Fix review comments

Fixes Gabriel's PR comments. Note that I leave a proper fix to
DhallException for the future (I want to work on something else for a bit
;)).

* Use underscores to pacify warnings
2019-06-04 16:48:06 +00:00
Frederik Ramcke
7ba33437e2 Fix LSP diagnostics to trailing whitespace (#974)
* dhall-lsp-server: Revert from Relude to standard Prelude

The code so far used Relude in place of the standard Prelude. Reverting
back to the standard Prelude brings dhall-lsp-server in line with the
rest of the dhall-haskell family, while also reducing the barrier to
contribution.

This change causes a number of additional explicit imports; creating a
"Library" module to gather the common imports could perhaps solve both
problems, i.e. reducing overhead while not having to resort to a custom
prelude. (This is left for a future refactoring.)

*  dhall-lsp-server: Exclude trailing whitespace in diagnostics

Dhall's current parser includes trailing whitespace in source range
annotations. Until now, we simply passed these "loose" ranges on to the
LSP client when generating diagnostic messages; this behaviour is fixed
in the present commit.

Previously (assuming funcTion is misspelled):
 funcTion argument
 ~~~~~~~~~

Now:
  funcTion argument
  ~~~~~~~~

* Refactor lines' to return NonEmpty list

Thanks to Gabriel for pointing this out! Since "lines'" always returns at
least a singleton list containing the empty line we can reflect this in
its type; this allows us to get rid of a test for non-emptiness in
"offsetToPosition".
2019-05-29 14:38:02 -07:00
Gabriel Gonzalez
2a78ac06b7
Define expression equality as CBOR equality (#866)
... as standardized in https://github.com/dhall-lang/dhall-lang/pull/426

This adds two new `ToTerm`/`FromTerm` classes in order to minimize
code disruption.  The main disruption is due to renaming the old
`encode`/`decode` to `encodeExpression`/`decodeExpression`
2019-03-27 18:26:02 -07:00
PanAeon
e6be5c050e
LSP. Fix import errors location. Minor clean-up. Add tests for backend/diagnostics. (#868) 2019-03-26 13:20:25 +00:00
PanAeon
21f9e951cc
[LSP] add basic formatting (#844) 2019-03-08 14:24:54 +00:00
PanAeon
f2f4fc2979 Add dhall-lsp-server (#843) 2019-03-06 21:41:38 -08:00