33

I don't do much real programming, but I've recently been turned on to Atom, which has linter plugins for over 50 languages to make coding easier (most drawing on pre-existing lint-like programs).

In other languages, linters help me learn about operator precedence (unnecessary parentheses), good programming styles/techniques, and get warnings about code that may not have been intended. Is there something along these lines for Mathematica?

If not, is there a reason why not? At first glance it seems like a number of the suggestions/tips I pick up from reading answers here could be automated. For example, maybe the Mathematica linter would remind you to memoize your functions with f[n_]:=f[n]= if that setting is turned on.

Edit: For a couple days in November 2016 there was work on a linter for Atom for Mathematica on github, but the project seems to have died quickly and I couldn't get it to work.

Mark S.
  • 1,123
  • 10
  • 20
  • 2
    I wonder if you could make something like this get your features? http://mathematicaplugin.halirutan.de/ – Moo Apr 16 '16 at 12:11
  • 1
    How is this different from the little popups that appear over each command when you hover the mouse? Or the "context sensitive" help? – bill s Apr 16 '16 at 14:14
  • 1
    Like bill s I would say that a very strong capability along the lines you describe already exists in Mathematica. – m_goldberg Apr 16 '16 at 15:42
  • 8
    I don't know of one, but it would be cool to have warnings for private symbols that start with an uppercase letter, implicit multiplications at line boundaries, and unlocalized iterator variables in Table constructs within functions (just to name the first few ideas that popped into my head). The pitfalls post would be an excellent source of inspiration for checks to implement. I wonder if a bit of spelunking would turn up a way to extend the front-end's existing bare-bone checks? – WReach Apr 16 '16 at 16:03
  • 1
    @WReach Ideally this is what Workbench would do if version 3 ever comes out of beta. – Edmund Apr 16 '16 at 22:34

1 Answers1

46

I am a developer at Wolfram Research and I have been working on linter technology that I think would be nice to share publicly.

There are 2 paclets on the public paclet server that you can download and use for finding problems with WL code.

The two paclets you will need are CodeParser and CodeInspector:

In[1]:= PacletInstall["CodeParser"]
Out[1]= PacletObject[CodeParser,1.0,<>]

In[2]:= PacletInstall["CodeInspector"]
Out[2]= Paclet[CodeInspector,1.0,<>]

The CodeParser paclet provides functions for parsing WL code and returning syntax trees with interesting metadata attached, such as file and line information.

The CodeInspector paclet uses CodeParser and provides functions for scanning WL code and finding problems and reporting them.

Here is a demo of using the CodeInspector paclet.

First, load the CodeInspector` package:

Needs["CodeInspector`"]

Next, take a snippet of code that you are interested in linting.

code = "Which[a, b, a, b]";

Use CodeInspect to get a List of InspectionObjects:

lints = CodeInspect[code];

The InspectionObjects are interesting by themselves, but it would be nice to see them formatted within lines of the source code.

CodeInspectSummarize[code]

The report shows formatted lines that you can mouse over to see the problem descriptions.

I included a screenshot to better show the result.

summary of code linting

It is possible to also scan files with by doing CodeInspect[File[file]]

Both the parser and linter are open-sourced here:

https://github.com/WolframResearch/codeparser

https://github.com/WolframResearch/codeinspector

I hope you enjoy using them!

brenton
  • 521
  • 5
  • 8
  • 4
    When you solicit the community, you may want to look at things like the current "hot meta post" Linting - Code analysis for bugs, errors and style issues in the Wolfram Language – Mark S. Mar 06 '19 at 01:38
  • 2
    I find it limiting that it won't run on files containing non-ASCII characters. Many of my source files contain such characters in comments. When using any other editor than the FE, this is the only way to include accented (or non-Roman) letters. It would be great if the linter could somehow still do its job and only provide a warning instead of failing completely. – Szabolcs Mar 06 '19 at 10:50
  • 1
    There seem to be some problems with LintString on my machine (macOS, M11.3). The first example from the docs returns {}: str = "1+f[,2]"; lints = LintString[str] There are also discrepancies between LintFile and LintString: the former returns more warnings than the latter. Finally, LintFileReport seems to return an empty list in the situations I tried, even though LintFile did give a non-empty list of lints. – Szabolcs Mar 06 '19 at 10:58
  • 1
    This is the file I tried, after removing the non-ASCII characters. That's easy to do by opening and re-saving the file with the FE. There are warnings about a mis-use of :. The output of LintFile does not refer to the location within the file in a clear way, and I hoped that LintFileReport would give me this information. – Szabolcs Mar 06 '19 at 10:59
  • 2
    I figured out that LintFileReport does not give me all results because of the "SeverityExclusions" option, so that was an easy fix. Other comments: please support file names wrapped in File, and please add file name auto-completion to LineFile. – Szabolcs Mar 06 '19 at 11:03
  • 2
    This seems really cool! Thanks for sharing. I look forward to future updates. In the meantime, let me start running this on my files... – ktm Mar 06 '19 at 17:00
  • 4
    And, of course, the first thing I should have said is that having these tools is really great! Thanks for all your work. :-) – Szabolcs Mar 06 '19 at 19:24
  • 6
    Big +1, Have you considered putting it e.g. on GitHub? @Szabolcs would have more space for issues :) – Kuba Mar 06 '19 at 22:35
  • 3
    @MarkS. Thank you for the link.

    @Szabolcs Thank you for the comments. The current limitation to ASCII characters is a consequence of using RunProcess. This will be fixed in the next update of AST which will use LibraryLink.

    In general, handing the contents of a file to LintString is not equivalent to LintFile. Compare this with ToExpression["a\nb"], which returns only b, and ParseString["a\nb"] which returns only the node for b. Though this could possibly be made to work in the future.

    @Kuba We are working on getting this on GitHub in the near future.

    – brenton Mar 08 '19 at 18:10
  • @brenton Thanks for the explanation about LintString/LintFile, it makes sense now. As for non-ASCII characters, I think it is still very useful to warn about them, as they can cause trouble (they did for me). Could you update the post when the new version is available? – Szabolcs Mar 11 '19 at 12:11
  • Hi @brenton, it is nice to see this great work. I am currently implementing a language server for Wolfram Language hosted at https://github.com/kenkangxgwe/lsp-wl, and would like to use your AST and Lint paclets. But since your paclets are in their experimental stages, it might be more convenient if you could share a code repo so maybe I can track their updates or even somehow contribute to them. – kenkangxgwe May 26 '19 at 03:58
  • The talk at the Wolfram Tech Conference 2019 was useful and will likely be posted online shortly. – Ghersic Nov 04 '19 at 21:49
  • 6
    The CodeInspector has now been made available on GitHub: https://github.com/WolframResearch/codeinspector – brenton Apr 08 '20 at 19:06