GithubHelp home page GithubHelp logo

elm-tooling / elm-language-server-haskell Goto Github PK

View Code? Open in Web Editor NEW
52.0 15.0 5.0 50 KB

Elm language server written in haskell (archived). Use https://github.com/elm-tooling/elm-language-server instead.

License: BSD 3-Clause "New" or "Revised" License

Haskell 100.00%

elm-language-server-haskell's Introduction

elm-language-server-haskell (archived)

NOTE: The repository elm-language-server is actively maintained. This repository is currently not maintained.


First attempt to write a language server for Elm.

See https://microsoft.github.io/language-server-protocol/specification for a description of the protocol.

Features

  • Diagnostics

If you want to work on more, please reach out and create an issue, before you start working on it.

Conceptual workings of the language server

The editor should start one language server for each Elm project (there may be multiple). rootPath should be set to the location of the elm.json file.

  • On the initialize notification, the language server will copy all files in the project to a temporary directory. This is so that we can handle open files by saving them there. It will then compile all files in the project, to get diagnostics. It will then send diagnostics for all files to the editor.
  • When a file is changed in the editor, we change it in our copy, and recompile everything to get new diagnostics.

Libraries used

  • haskell-lsp
  • json-rpc-server
  • elm-compiler-library (which is a version of elm-compiler)

Notes

  • Code formatted using hlint

Building

Clone the repository and its subrepositories:

  • git clone https://github.com/elm-tooling/elm-language-server
  • git submodule update --init --recursive Install ghc and dependencies. You need to have stack installed
  • stack setup
  • stack install

Contributing

elm-language-server-haskell's People

Contributors

andys8 avatar matheus23 avatar norpan avatar razzeee avatar ringods avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elm-language-server-haskell's Issues

no handler for ...

when it starts it just fails with error

[LC] [Error] haskell-lsp:no handler for. Object (fromList [("jsonrpc",String "2.0"),("params",Object (fromList [("textDocument",Object (fromList [("languageId",String "elm"),("text",String "m odule HTTP exposing (main)\n\nimport Browser\nimport Html exposing (Html, div)\nimport Http\n\n\ntype alias Model =\n    { txt : String }\n\n\ntype Msg\n    = Get\n    | Got (Result Http.Erro r String)\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    --{{{\n    case msg of\n        Get ->\n            ( model, Cmd.none )\n\n        Got m ->\n            ca se m of\n                Ok s ->\n                    ( { model | txt = s }, Cmd.none )\n\n                Err _ ->\n                    ( model, Cmd.none )\n\n\n\n--}}}\n\n\ninit : () -> ( M odel, Cmd Msg )\ninit _ =\n    ( Model \"\", Cmd.none )\n\n\nview : Model -> Html Msg\nview model =\n    div [] []\n\n\nsubscriptions : Model -> Sub msg\nsubscriptions model =\n    Sub.none\n \n\nmain =\n    Browser.element { init = init, view = view, update = update, subscriptions = subscriptions }\n"),("uri",String "file:///home/nikos/projects/elm_interface/src/HTTP.elm"),("vers ion",Number 0.0)]))])),("method",String "textDocument/didOpen")])

Transfer ownership of @norpan repo instead of forking

I noticed that this repo in the elm-tooling organization is forked from @norpan. Would it be possible to transfer the ownership of the @norpan repo to this organization? I bumped into similar cases with other projects too. When searching github for code or issues, I experienced the original (outdated) repository popping up in the search results along with the the organization fork. For users, this could be confusing.

Therefor, I would like to ask for a few more cycles in the setup:

  • merge all changed code back to the @norpan origin.
  • disable CI of this fork
  • delete this forked repo
  • transfer the ownership of the @norpan repo to this organization
  • re-enable CI of the transferred repo.

Advantage of ownership transfer is that any web links to the @norpan repo will be redirected to the organization now. Only drawback is that you loose the issues from this existing fork. But I guess better now than later.

Feature: Go to defintion

Feature

Based on the selection the user should be able to jump to the file to the position where the selection is defined. This can be in a dependency or the codebase of the application.

Gathering information

Elm Compiler

Interfaces are defined in Elm.Interface.

type Interfaces =
  Map.Map ModuleName.Canonical Interface

data Interface =
  Interface
    { _types   :: Map.Map N.Name Can.Annotation
    , _unions  :: Map.Map N.Name Union
    , _aliases :: Map.Map N.Name Alias
    , _binops  :: Map.Map N.Name Binop
    }

https://github.com/matheus23/elm-compiler-library/blob/502c59df4ac3df6578f99d3eb789d3eb96e3b5a0/compiler/src/Elm/Interface.hs#L34-L48

Stuff.Verify.verify emits Summary and is already used. Defined in Elm.Project.Summary.

data Summary =
  Summary
    { _root :: FilePath
    , _project :: Project
    , _exposed :: ExposedModules
    , _ifaces :: Module.Interfaces
    , _depsGraph :: DepsGraph
    }


type ExposedModules =
  Map.Map Module.Raw [Package]


type DepsGraph =
  Map.Map Name ( Version, [Name] )

https://github.com/matheus23/elm-compiler-library/blob/502c59df4ac3df6578f99d3eb789d3eb96e3b5a0/builder/src/Elm/Project/Summary.hs#L27-L42

File.Find.find can return the path of the file on disk, given Summary, Origin and Module.Raw.

data Asset
  = Local FilePath
  | Kernel FilePath (Maybe FilePath)
  | Foreign Pkg.Package
  | ForeignKernel

find :: Summary.Summary -> E.Origin -> Module.Raw -> Task.Task_ E.Problem Asset
find (Summary.Summary root project exposed _ _) origin name =
  do  here <- liftIO Dir.getCurrentDirectory
      let toRoot dir = FP.makeRelative here (root </> dir)
      case project of
        Project.App info ->
          do  let srcDirs = map toRoot (Project._app_source_dirs info)
              findElm project srcDirs exposed origin name

        Project.Pkg _ ->
          if N.startsWith "Elm.Kernel." name then
            if Project.isPlatformPackage project then
              findKernel (toRoot "src") exposed origin name
            else
              Task.throw $ E.ModuleNameReservedForKernel origin name

          else
            findElm project [ toRoot "src" ] exposed origin name

https://github.com/matheus23/elm-compiler-library/blob/502c59df4ac3df6578f99d3eb789d3eb96e3b5a0/builder/src/File/Find.hs#L30-L58

Language Server Protocol

Called "Goto Type Definition Request".

Request:
method: ‘textDocument/definition’
params: TextDocumentPositionParams

Response:
result: Location | Location[] | null

https://microsoft.github.io/language-server-protocol/specification#textDocument_definition

Related: Goto Type Definition Request, Goto Implementation Request

Haskell LSP

type DefinitionRequest = 
  RequestMessage ClientMethod TextDocumentPositionParams LocationResponseParams

type DefinitionResponse = 
  ResponseMessage LocationResponseParams

https://hackage.haskell.org/package/haskell-lsp-types-0.8.0.1/docs/Language-Haskell-LSP-Types.html#t:DefinitionRequest

Comparison

intellij-elm

The klazuka/intellij-elm (elm plugin for IntelliJ in Kotlin) has the go to source feature.
https://github.com/klazuka/intellij-elm/blob/master/src/main/kotlin/org/elm/ide/navigation/ElmGoToSymbolContributor.kt

Feature: Code Action should use elm proposal for replacement

Elm compiler error messages have proposals how to replace e.g. a typo.

Module build failed: Error: Compiler process exited with error Compilation failed
-- NAMING ERROR - path/Main.elm

Cannot find variable `flag`

53|             flag |> Env.config |> initialModel
                ^^^^
Maybe you want one of the following?

    flags
    flip
    Basics.flip
    Debug.log

Detected errors in 1 module.

This information can be used to give code actions: https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction

This is currently worked on in: https://github.com/elm-tooling/elm-language-server/tree/code-action

Getting Started (not working / help wanted)

Sorry - rookie question.

I am using elm-language-server with kakoune-lsp.

I downloaded and installed elm-language-server using stack.

And nothing happens afterwards. It just stays like this.

In my kak-lsp.toml I put

[language.elm]
filetypes = ["elm"]
roots = ["elm.json"]
command = "elm-language-server"

When I open an elm file and try to use lsp features like go to definition it does not do anything.

Now when I start the server I see

❯ elm-language-server  
2019-01-10 21:40:47.35797303 [ThreadId 11] - 




haskell-lsp:Starting up server ...

How can I make sure the server is at all operational and not stuck?

Any hot tips on how to get this to work?

Using the end users installed version of Elm for diagnostics?

Hey, first off I'm psyched that this project is being worked on! I had a question (or comment) about how this project decided to report diagnostics. If my understanding is correct, it looks like this project uses a library version fork of the Elm compiler and uses that to type check the user's code. This is pretty cool, but I'm not sure that it's the best way to do this. My reasons for thinking this are

  1. It seems like a lot of work to maintain a fork of of the Elm compiler. This is especially true if there ends up being something like an 0.19.1 to address a bug that is being discussed here. Additionally, it seems hard to eventually support both 0.19 and 0.20 down the line if this project uses a compiler fork.

  2. Elm includes a flag to get these syntax and type errors. If one runs elm make src/Main.elm, and the error something like

-- UNBOUND TYPE VARIABLE ----------------------------------------- src/Field.elm

The `Field` type uses an unbound type variable `error` in its definition:

44| type Field value
45|     = Field value Metadata (Status error)
                                       ^^^^^
You probably need to change the declaration to something like this:

    type Field value error = ...

Why? Well, imagine one `Field` where `error` is an Int and another where it is a
Bool. When we explicitly list the type variables, the type checker can see that
they are actually different types.

then one can run elm make src/Main.elm --report=json and the output will be

{
	"type": "compile-errors",
	"errors": [{
		"path": "src/Field.elm",
		"name": "Field",
		"problems": [{
			"title": "UNBOUND TYPE VARIABLE",
			"region": {
				"start": {
					"line": 44,
					"column": 1
				},
				"end": {
					"line": 45,
					"column": 42
				}
			},
			"message": ["The `Field` type uses an unbound type variable ", {
				"bold": false,
				"underline": false,
				"color": "yellow",
				"string": "`error`"
			}, " in its definition:\n\n44| type Field value\n45|     = Field value Metadata (Status error)\n                                       ", {
				"bold": false,
				"underline": false,
				"color": "red",
				"string": "^^^^^"
			}, "\nYou probably need to change the declaration to something like this:\n\n    type Field value ", {
				"bold": false,
				"underline": false,
				"color": "GREEN",
				"string": "error"
			}, " = ...\n\nWhy? Well, imagine one `Field` where `error` is an Int and another where it is a\nBool. When we explicitly list the type variables, the type checker can see that\nthey are actually different types."]
		}]
	}]
}

Then, one only has to parse the json to get the error and report it back to the user.

Because of the challenges of maintaining a fork and the fact the you can get compile errors from elm make, it seems to me that attempting to find the user installed version of Elm and getting diagnostics from that would be more effective. Other benefits of this approach are

  1. The language server could prefer local installations. If a user used 0.19 in one project and 0.20 installed in another (both installed in maybenode_modules), then the language server could report errors seamlessly in both. Additionally, it can always fallback to looking at a global installation.

  2. This project only has to maintain a fork of the elm parser, which is simpler than maintaining a fork of the compiler. I think it's fair to say that generally speaking the elm syntax doesn't change drastically between releases, so maintain a fork of just the compiler may end up being more straightforward.

I would also like to point out that this seems to be the approach taken by [elm-format] (https://github.com/avh4/elm-format), though their goal/use case is somewhat different.

And lastly, I have been working on my own implementation of an elm language server, and the approach I've outlined in this issue has worked well so far. It seems that collaborating on one project is more beneficial to the community though, which is why I'm writing this issue. If interested, this project can use that as a basis for the implementation.

Please let me know your thoughts on this, it's super possible that there are reasons for keeping a fork of the compiler that I haven't thought of! And I'm super down to work on this refactor if it's decided that this is the way to go.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.