Skip to content

Linting code chunks in Rmd not working consistently with knitr #797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
renkun-ken opened this issue May 10, 2021 · 14 comments
Open

Linting code chunks in Rmd not working consistently with knitr #797

renkun-ken opened this issue May 10, 2021 · 14 comments
Assignees
Labels
feature a feature request or enhancement rmd

Comments

@renkun-ken
Copy link
Collaborator

renkun-ken commented May 10, 2021

Consider the following Rmd (saved to e.g. lintr-test.Rmd):

```{r}
x<-1
```

```{R}
x<-2
```

```{therom, name='test'}
x<-3
```

Linting the file has the following output:

> lintr::lint("lintr-test.Rmd")                                                                                                                             
/home/renkun/Workspaces/testR/lintr-test.Rmd:2:2: style: Put spaces around all infix operators.
x<-1
~^~~
/home/renkun/Workspaces/testR/lintr-test.Rmd:10:2: style: Put spaces around all infix operators.
x<-3
~^~~

To my understanding, it should lint the first two R chunks and ignores the third one.

However, the current chunk extraction does not seem to work consistently with knitr in that knitr treats r and R as the same. The theorem is brought up at REditorSupport/languageserver#421 where bookdown seems to provide some markdown extensions where additional engines are implemented (as introduced at https://bookdown.org/yihui/bookdown/markdown-extensions-by-bookdown.html).

I think the expected behavior should be linting the R or r chunks and ignores all other chunks.

@AshesITR
Copy link
Collaborator

Related to #796

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

Reproduced this:

```{R}
# "R" engine is a synonym for "r"
a<-1
a
```

This code block, when added to ./tests/testthat/knitr_formats/test.Rmd throws no assignment lints
But, the code block is evaluated by knitr when knitting to .html.

This seems to happen because "R" is one of knitr::knit_engines list, not because of case-insensitivity of the knitr engine-matching code

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

Also, lintr should attack any code blocks that have engine="Rscript"

```{Rscript}
# "Rscript" engine wraps the code in a block in a randomScript and calls
# `Rscript randomScript.R 2>&1`
#

b<-1
b
```

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

One area that I'm not sure how to handle are custom knitr engines

Some of these are used to run R code, and so should be linted, eg, details and targets

Other packages add custom knitr engines that don't run R code (eg, nomnoml; I believe this is the case for the tufte "marginfigure" engine mentioned in #796) and so should be ignored.

Perhaps the lintr config should allow the user to add additional engines whose code should be linted.

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

I agree re the bug for {therom} example:

```{notAnEngine}
a<-1
```

Throws an assignment lint in current master

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

So my thoughts:
If engine is r, R or Rscript then code block should be linted
If engine is defined in engines: c("targets") stub of .lintr it should be linted
Code blocks should be disregarded for all other engines, including those that are possible misspellings of the defined knitr engines (eg, there should be no error on a ```{Rscrypt}``` block)

@renkun-ken
Copy link
Collaborator Author

So my thoughts:
If engine is r, R or Rscript then code block should be linted
If engine is defined in engines: c("targets") stub of .lintr it should be linted
Code blocks should be disregarded for all other engines, including those that are possible misspellings of the defined knitr engines (eg, there should be no error on a ```{Rscrypt}``` block)

Makes perfect sense.

@russHyde russHyde self-assigned this Jun 9, 2021
@AshesITR
Copy link
Collaborator

AshesITR commented Jun 9, 2021

Sounds like a good idea. Maybe the option name should be more specific to rmd, e.g. rmd_engines?

Also we should use the existing default mechanism to set r, R, and Rscript as default rmd_engines.
This would allow the usecase of mixing regular r code chunks with R code chunks which are intentionally bad but still evaluated.
You could then put rmd_engines: "r"into .lintr to actively suppress linting of R code chunks without cluttering everything with #nolints.

@MichaelChirico
Copy link
Collaborator

I was going to suggest rmd_engines as well, so agree with that & everything. great suggestions!

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

Ha, I hadn't thought of using ```{R} bad-code-here ``` and ```{r} lint this code ```.
Do you know if the different engines are a specifically RMD thing?
Do .Rnw (etc) use these non-R engines?

@AshesITR
Copy link
Collaborator

AshesITR commented Jun 9, 2021

A quick google-fu turned up this gem from 2010.
So it seems to work via custom drivers.
knitr_engines might also be a good name, WDYT?

@russHyde
Copy link
Collaborator

russHyde commented Jun 9, 2021

knitr_engines seems more appropriate. Thanks everyone.

@russHyde
Copy link
Collaborator

russHyde commented Jun 10, 2021

Summary of aims:


With no knitr_engines configured (in either .lintr or the lint() arguments), {lintr} will lint all code blocks with "r", "R" or "Rscript" engines.


With a .lintr config like this (or with knitr_engines = ... in the lint() arguments):

// .lintr
knitr_engines: with_defaults("targets", default = default_knitr_engines)

{lintr} would lint all code blocks for "r", "R", "Rscript" and "targets" engines


With .lintr configured like this:

knitr_engines: c("r")
// or
knitr_engines: with_defaults(R = NULL, Rscript = NULL, default = default_knitr_engines)

{lintr} would only lint blocks with the "r" engine.

Does this seem OK everyone, @jimhester ?

@jimhester
Copy link
Member

sure, sounds good.

@AshesITR AshesITR added the feature a feature request or enhancement label Jul 9, 2021
IndrajeetPatil added a commit that referenced this issue Sep 24, 2022
IndrajeetPatil added a commit that referenced this issue Oct 7, 2022
* Anticipate raw HTML from extended knitr engines

Closes #796

Plus styling changes.

* Also include bookdown engines

##797

* don't piggyback; move tests to their own file

* also add test for bookdown engines; ignore file

* also update .lintr_new

* Update test-knitr_formats.R

* Update NEWS.md

* don't use bookdown vector

* address review comment

* Update test-knitr_extended_formats.R

* update comment

* fix tests

* Use `loadNamespace()` instead

* Update for tufte update

* Update NEWS.md

* extend/clarify comment

* qualify rex namespace, use test_path()

* use test_path()

* much-extended NEWS item

* grammar fix

Co-authored-by: Indrajeet Patil <patilindrajeet.science@gmail.com>

Co-authored-by: Michael Chirico <chiricom@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement rmd
Projects
None yet
Development

No branches or pull requests

5 participants