regexes <- list(
  assign = rex::rex("Use <-, not =, for assignment."),
  local_var = rex::rex("local variable"),
  quotes = rex::rex("Only use double-quotes."),
  trailing = rex::rex("Trailing blank lines are superfluous."),
  trailws = rex::rex("Trailing whitespace is superfluous."),
  indent = rex::rex("Indentation should be")
)

test_that("it handles dir", {
  file_pattern <- rex::rex(".R", one_of("html", "md", "nw", "rst", "tex", "txt"))

  lints <- lint_dir(path = "knitr_formats", pattern = file_pattern, parse_settings = FALSE)

  # For every file there should be at least 1 lint
  expect_identical(
    sort(unique(names(lints))),
    sort(list.files(test_path("knitr_formats"), pattern = file_pattern))
  )
})

test_that("it handles markdown", {
  expect_lint(
    file = test_path("knitr_formats", "test.Rmd"),
    checks = list(
      list(regexes[["assign"]], line_number = 9L),
      list(regexes[["local_var"]], line_number = 22L),
      list(regexes[["assign"]], line_number = 22L),
      list(regexes[["trailing"]], line_number = 24L)
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it handles quarto", {
  expect_lint(
    file = test_path("knitr_formats", "test.qmd"),
    checks = list(
      list(regexes[["assign"]], line_number = 9L),
      list(regexes[["local_var"]], line_number = 22L),
      list(regexes[["assign"]], line_number = 22L),
      list(regexes[["trailing"]], line_number = 24L)
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it handles Sweave", {
  expect_lint(
    file = test_path("knitr_formats", "test.Rnw"),
    checks = list(
      list(regexes[["assign"]], line_number = 12L),
      list(regexes[["local_var"]], line_number = 24L),
      list(regexes[["assign"]], line_number = 24L),
      list(regexes[["trailing"]], line_number = 26L)
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it handles reStructuredText", {
  expect_lint(
    file = test_path("knitr_formats", "test.Rrst"),
    checks = list(
      list(regexes[["assign"]], line_number = 10L),
      list(regexes[["local_var"]], line_number = 23L),
      list(regexes[["assign"]], line_number = 23L),
      list(regexes[["trailing"]], line_number = 25L)
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it handles HTML", {
  expect_lint(
    file = test_path("knitr_formats", "test.Rhtml"),
    checks = list(
      list(regexes[["assign"]], line_number = 15L),
      list(regexes[["local_var"]], line_number = 27L),
      list(regexes[["assign"]], line_number = 27L),
      list(regexes[["trailing"]], line_number = 29L)
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it handles tex", {
  expect_lint(
    file = test_path("knitr_formats", "test.Rtex"),
    checks = list(
      list(regexes[["indent"]], line_number = 11L),
      # TODO(AshesITR):
      # masking the Rtex escape char by whitespace causes false-positive indentation lints
      list(regexes[["assign"]], line_number = 11L),
      list(regexes[["indent"]], line_number = 22L),
      list(regexes[["local_var"]], line_number = 23L),
      list(regexes[["assign"]], line_number = 23L),
      list(regexes[["trailing"]], line_number = 25L),
      list(regexes[["trailws"]], line_number = 25L)
      # TODO(AshesITR): #1043
      # file_lines contains a whitespace on the final line for Rtex, because that is used to mark the Rtex escape char
      # "%" as well.
      # cf. get_source_expressions("tests/testthat/knitr_formats/test.Rtex")$lines[[25]]
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it handles asciidoc", {
  expect_lint(
    file = test_path("knitr_formats", "test.Rtxt"),
    checks = list(
      list(regexes[["assign"]], line_number = 9L),
      list(regexes[["local_var"]], line_number = 22L),
      list(regexes[["assign"]], line_number = 22L),
      list(regexes[["trailing"]], line_number = 24L)
    ),
    linters = default_linters,
    parse_settings = FALSE
  )
})

test_that("it does _not_ handle brew", {
  expect_lint("'<% a %>'\n",
    checks = list(
      regexes[["quotes"]],
      regexes[["trailing"]]
    ),
    default_linters
  )
})

test_that("it does _not_ error with inline \\Sexpr", {
  expect_lint(
    "#' text \\Sexpr{1 + 1} more text",
    NULL,
    default_linters
  )
})

test_that("it does lint .Rmd or .qmd file with malformed input", {
  expect_lint(
    file = test_path("knitr_malformed", "incomplete_r_block.Rmd"),
    checks = "Missing chunk end",
    linters = default_linters,
    parse_settings = FALSE
  )

  expect_lint(
    file = test_path("knitr_malformed", "incomplete_r_block.qmd"),
    checks = "Missing chunk end",
    linters = default_linters,
    parse_settings = FALSE
  )

  contents <- c(
    trim_some("
      ```{r chunk}
      lm(x ~ y)


      # some text

      ```
      bash some_script.sh
      ```
    "),
    trim_some("
      ```{r chunk-1}
      code <- 42

      # A heading
      Some text

      ```{r chunk-2}
      some_more_code <- 42
      ```
    "),
    trim_some("
      ```{r chunk-1}
      code <- 42
      ```

      # A heading
      Some text

      ```{r chunk-2}
      some_more_code <- 42
    ")
  )

  expected <- list(
    NULL, # This test case would require parsing all chunk fences, not just r chunks.
    "maybe starting at line 1",
    "maybe starting at line 8"
  )

  for (i in seq_along(contents)) {
    expect_lint(contents[[i]], expected[[i]], linters = list())
  }
})
