Skip to content

[purs ide] Add a new namespace filter #2792

Description

@kritzcreek

This is a new feature for purs ide which is suitable as a first contribution. In this issue I've written down why we'd want to add a namespace filter and how you could go about implementing it. A good point to get started is to read the CONTRIBUTING.md file in the root of this repository. If you want to pick this as your first contribution to purs ide I'd be happy to answer any questions or help you if you run into problems. Just ask here in the issue or on IRC at #purescript where I'm usually available during the European day.

Motivation

The idea is that we'd like to be able to specify to which namespaces purs ide should limit the results of a query. Here are some future features this would enable in editors:

  • Split the type of command into type of or kind of, to let the user decide which of the two he wanted, in cases where type and constructor name overlap. With the new filter in place, type of would only allow declarations in the value namespace and the kind of command would limit its query results to the type namespace.
  • An editor could determine that the user is editing a specific syntax construct and limit the completions to the correct namespace. For example, if we determined (eg. with a regex) that the user is editing an instance head we know that we only need to allow completions from the type or kind namespace.
  • Allowing the editors to specify that they only want to import a type constructor, if it was determined that the to-be-imported identifier was at the type level. Right now, for example for newtypes which expose their constructor, it's impossible to only import the type.

Implementation

purs ide provides completions and type information through a set of commands. Through a JSON protocol editors can query the server. These queries are built up from a list of filters and an optional matcher. As the issue title already says, implementing this feature requires that we add a new filter. To do so we'll need to take two main steps:

  1. Implementing the filtering logic
  2. Parsing the new filter as JSON

Implementing the filtering logic

We'll need to implement a new function namespaceFilter :: NonEmpty IdeNamespace -> Filter, where the NonEmpty type is from Data.List.NonEmpty. It should be located in the Language.PureScript.Ide.Filter module, where all the other purs ide filters live. Inside this filter we'll need to only keep the declarations that live in the correct namespace.

For example, if we were filtering with IdeNSValue :| [IdeNSType] as the argument to namespaceFilter we'd need to remove all the IdeKindDecl declarations from the filtered modules. One thing to note here, is that the filters are also supposed to remove modules that contain no more declarations after the filter has been applied.

We'll want to add a couple of tests to tests/Language/PureScript/Ide/FilterSpec.hs to make sure our implementation does what we expect it to (I encourage you to write the tests first, but that's not for everyone and totally up to you).

After we have implemented the functionality we want our filter to have, it's time to wire everything up with the rest of purs ide.

Parsing the new filter

If you take a look at the psc-ide/PROTOCOL.md file, which documents the protocol purs ide speaks up to this point, and check out the Filter section you'll see that all the filters share some commonalities. They all have a top-level filter field, which contains the filter's name and a params field which contains the filters parameters. I'd suggest using a non-empty Array of Strings for the parameters to this filter. An example JSON encoded filter could look like:

{
  "filter": "namespace",
  "params": 
    {
      "namespaces": ["value", "type", "kind"]
    }
}

We'll then need to add another case to the FromJSON instance for Filter inside Language.PureScript.Ide.Filter. Once that instance is implemented and works correctly, we should be able to write queries that filter declarations by namespace!

Playing with it

Trying it out should look a little something like this:

mkdir test-project
cd test-project
pulp init
pulp build
purs ide server --log-level debug

# In a second terminal:

echo '{"command": "load"}' | purs ide client
echo '{"command": "complete", "params": {"filters": [{"filter": "namespace", "params": {"namespaces": ["kind"]}}]}}' | purs ide client

Which should return the Effect kind from Control.Monad.Eff.

Activity

  1. added this to the Approved milestone on Mar 28, 2017
  2. changed the title [-][purs ide] Add namespace filters[/-] [+][purs ide] Add namespace filter[/+] on May 10, 2017
  3. changed the title [-][purs ide] Add namespace filter[/-] [+][purs ide] Add a new namespace filter[/+] on May 10, 2017
  4. stefanholzmueller commented on May 11, 2017

    @stefanholzmueller
    Contributor

    I'll give it a try. Thanks for the nice description! Very newbie-friendy :)

  5. kritzcreek commented on May 11, 2017

    @kritzcreek
    MemberAuthor

    @stefanholzmueller Hopefully in the future I'll have better documentation for purs ide so that I can keep the issue descriptions a little shorter ;) Please don't hesitate to ask if you're running into problems or want to talk about the implementation.

  6. stefanholzmueller commented on May 11, 2017

    @stefanholzmueller
    Contributor

    Thanks, I'll do that if I get stuck. I already have two failing tests. :D The actual filtering logic seems to be a bit more complicated...

  7. stefanholzmueller commented on May 14, 2017

    @stefanholzmueller
    Contributor

    @sectore I see you are working on the same issue? maybe we should collaborate? have a look at my PR :)

  8. sectore commented on May 14, 2017

    @sectore
    Contributor

    @stefanholzmueller Oh, I thought that there is no progress on this issue anymore. Sorry about this! Sure, it would be nice if we can collaborate - my PR is already there (#2892) as well.

  9. stefanholzmueller commented on May 14, 2017

    @stefanholzmueller
    Contributor

    @sectore Alright, let's merge both our approaches as suggested by kRITZCREEK. We can meet on Slack or IRC tomorrow if you want to chat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions