Canonical linter for Atom?


#1

I wanted to pose this question to the community to see what people think:

Should Atom have a canonical linter? Or a bit more extreme, should Atom have a linter as part of Atom core?

I’ve found myself wondering this after making use of some of the linter packages, mostly AtomLinter. Personally I love what AtomLinter’s trying to do, and they basically are the de facto canonical linter for Atom at this point. But, I have noticed that linting is quite slow, seemingly because the linter is being re-run from scratch on every change event, which leads to a somewhat sluggish writing user experience. It’s led me to wonder if there could be any advantages, speed or otherwise, to including a linter in Atom core. I think if there were one it should be just as user configurable (maybe even “off” by default) as the community package.

(FWIW, this is the approach Brackets took, providing a consistent core API so that the community can focus on just building the specific linters)

What do you think?


Canonical way to show errors in the editor
#2

TL;DR; Kinda. The concepts within AtomLinter should be split in two, for this to move into the core:

  1. Run these function(s) on save for files of these grammar(s)
  2. Display these messages, and allow interaction with them.

Read on for the explanation:


Generalizing the notion of linting a little: my package (go-plus) does many things when a file is saved, and then optionally displays messages to the user (e.g. info, warning, error) associated with each tool I run. These include things like:

  • gofmt / goimports / goreturns
  • golint
  • go vet
  • go build / go test (yes, we can compile on save in go because compilation times are wonderfully fast)

(Back to generalizing:) When you think about it, linting really is about:

  1. Call a function (which might invoke a tool)
  2. Display output to user in a formatted way

This necessitates having a pipeline of functions to run on save, and then having a consistent user experience for viewing the output, and optionally taking action (e.g. source, filename, line, column, message + gutter marker + optionally a highlight of the actual range associated with the issue).

AtomLinter addresses both items above by providing a common API for integration of functions to call on save, and by providing a panel for the display of output.

atom-message-panel also addresses the display output aspect, and I’ve integrated it into go-plus. omnisharp-atom has also provided an interesting implementation of a message panel, which - while it could be improved - more closely aligns with what I’d like to see (and @park9140 agrees).

So:

should Atom have a linter as part of Atom core?

No (but bear with me :smile:). It sure would be nice if the following were in the core:

  1. A registry of functions to run when files of a particular grammar are saved
  2. An API for publishing “messages” associated with tools that have been run
  • info / warning / error messages, with source, filename, line, column, message + gutter marker + click on error to go to the message’s location in an editor
  • tool output (i.e. stdout / stderr from running a tool) - this could also be used for build output, or to allow package authors to print informational text about their package
  • errors from atom itself (i.e. the ones that pop up on the right - now (0.166.0) - when an unhandled error occurs

In discussing with @park9140, the latter is something that begins to approximate “IDE” features. So it might be seen as an overreach of scope for the core.

But why haven’t I integrated go-plus with AtomLinter (golang is notably absent from the list of AtomLinter plugins, and it’s almost certainly because go-plus exists)?

  • Because it would further restrict my audience and increase the barrier to successful use of my package (they already have to install autocomplete-plus but we’re working on upstreaming that right now)
  • Because go-plus does much more than just linting

So there is value in having this functionality in the core (or rather, installed as a default package). Having functionality like this in the core with an API for each that I can integrate with ensures that I stop doing this in a custom way (and throw away a bunch of code!, particularly with regard to my atom-message-panel use).

What’s the right way forward? Split apart the two problem spaces? Build a truly fantastic package for a message panel that is an Atom package (as opposed to a node package, like atom-message-panel is), and then contribute it back to the atom organization? Evolve AtomLinter and contribute it back to the atom organization? Do nothing? We’ll only know if @nathansobo, @probablycorey, @kevinsawicki, @thedaniel, and others chime in.


#3

I think that AtomLinter is a great example community self-organization, and don’t think that there needs to be a linter included in core packages at the moment. We would be more likely to be open to additions to the API that make AtomLinter (and linters in general) easier to build and maintain.


#4

I moved 4 posts to a new topic: Specifying package dependencies


#8

This is all excellent stuff @joefitzgerald! This is just about what I was thinking, but put more eloquently. :smile: I think we’d need to involve the maintainers of AtomLinter too (not sure who they are on Discuss or I’d @-mention them) to find out what kinds of API changes would benefit the project.

  1. A registry of functions to run when files of a particular grammar are saved
  2. An API for publishing “messages” associated with tools that have been run
  • info / warning / error messages, with source, filename, line, column, message + gutter marker + click on error to go to the message’s location in an editor
  • tool output (i.e. stdout / stderr from running a tool) - this could also be used for build output, or to allow package authors to print informational text about their package
  • errors from atom itself (i.e. the ones that pop up on the right - now (0.166.0) - when an unhandled error occurs

So it seems like from what I can tell, these are exactly the functions that AtomLinter’s providing right now, but outside of core, and only for linters. So maybe the scope of this “canonical linter problem” should be broadened beyond linters (by including it in Core API)?


#9
  1. A registry of functions to run when files of a particular grammar are saved

If this were in the core, it would allow for potential optimizations to ensure that any such functions never slow down editing / save performance.

2. An API for publishing [and displaying] “messages” associated with tools that have been run

This really needs to be a separate package. I’m unaware of any example of a community-developed package being ‘absorbed’ into the https://github.com/atom organization after initial development, and included as an “installed by default” package.

Is there prior art? A process for submission / consideration / approval?

Edit: Added ‘and displaying’ to my original suggestion.


#10

Some tidbits here and there of my bug-report package were used for the implementation of the new automatic bug posting feature in the notifications package. But I can’t think of a package that has been included in toto. And no, I know of no process for this. I would suspect that the Atom team is going to be more conservative about adding new APIs to Atom the closer we get to 1.0.


#11

I propose the following name for the package that addresses 2. An API for publishing [and displaying] "messages" associated with tools that have been run:

omnipanel - it would:

  • Take inspiration from atom-message-panel, the display portion of https://atom.io/packages/linter, the display portion of https://atom.io/packages/omnisharp-atom
  • Provide an API (via service-hub of course) for publishing messages associated with content, or messages associated with a tool, or messages associated with a package
  • Manage a single panel which has sub-panels or tabs with messages, output, and potentially other panels/tabs
  • Allow ordering and sorting of messages
  • Allow clicking on a message (or using keybindings) to go to the source of the message (file / line / column)
  • Show gutter highlights for error / info / warning messages

Thoughts?


#12

The AtomLinter project definitely has a way to go. I really like @joefitzgerald’s suggestion for an omnipanel of sorts that could take some of the weight off of atom linter as far as focus of work. We have been working to adopt these sort of components as they come along. For example we have switched to the common overlay api that atom now provides for our error highlighting functionality. The less we have to build for just this module and can depend on core/community services based on service-hub the more we can focus on the core responsibility of AtomLinter.

In my mind the core responsibility of atom linter is to act as a unified manager for all code specific errors. If you have a plugin or library that can produce an error associated with a specific file/line of code the AtomLinter package should be able to act as your visualization of that error.

As has been mentioned many times in this and other discussions there is definitely trouble with the overall performance and quality of the different linter plugins that have been produced. We are still utilizing basically the same plugin architecture that was originally implemented when the first release happened almost a year ago now. In that time there have been leaps and bounds in the basic apis available to us, and the plugin architecture really needs a rewrite.

I have been discussing with @joefitzgerald, a similar issue for the autocomplete-plus project. Once we have produced a working draft of our plans for that api, It would be great to extend the concepts implemented there to help guide a revolutionary jump in api capabilities in the AtomLinter core.

Additionally, using service hub, if we come up with a common api for the ability to show and manage errors in the project, then many different plugins could implement it and be interchangible.


#13

One of the reasons I enjoy the atom-lint package is that all it does is place highlights in the file with tooltips for the messages. To be honest, I would not want to use a linter infrastructure that takes over a big portion of my Atom window with a message panel that is as complex as the one you’re proposing sounds.

I can definitely understand having a message panel that displays structured information … something like (or whatever the service-hub equivalent is):

messagePanel = new MessagePanel('bottom', ['file', 'line', 'column', 'info'])
messagePanel.add(file: 'foo/bar/baz', line: 50, column: 15, info: 'Somethings broke!')

I could even see being able to add a callback for when a message row is clicked that just passes back the structured info in that message row.

But the sub-panels with tabs and tabs that have panels with tabs and more panels … that sounds … tiring :laughing: And also sounds like you’re essentially duplicating some to a lot of what Atom already provides, depending on your implementation.


#14

@leedohm, I think you really just need to use go-plus, omnisharp-atom, or linter to truly grok what we’re proposing. Also, the panel aspect is just one feature which could be configurable (I.e. Don’t show panel), which is exactly what go-plus allows.

There’s at least two use cases where having a common panel (with associated APIs) could be useful:

  1. Displaying these messages we described which might also have context that is actionable (like file, line, column)
  2. Displaying log output from things like compilers, testers, or packages themselves

Don’t get hung up on the terminology I used regarding panels and tabs. Forest / trees.