-
Notifications
You must be signed in to change notification settings - Fork 13
[Linting Rule] Unclosed Connection
Generated from 'wiki-linter.ts' on 2026-08-18, 16:29:46 UTC (v2.14.0), please do not edit directly.
Unclosed Connection [overview]
This rule is a best-effort rule.
Flags connections that are opened but not closed on every path opening them.
This linting rule is implemented in src/linter/rules/unclosed-connection.ts.
Linting rules can be configured by passing a configuration object to the linter query as shown in the example below.
The unclosed-connection rule accepts the following configuration options:
-
closeFns
functions closing the connection they are handed, besides the ones flowR statesCallProp.Closesfor -
openFns
functions opening a connection, besides the ones flowR statesCallProp.Opensfor
con <- file("data.csv")
readLines(con)The linting query can be used to run this rule on the above example:
[ { "type": "linter", "rules": [ { "name": "unclosed-connection", "config": {} } ] } ]Results (prettified and summarized):
Query: linter (3 ms)
╰ Unclosed Connection (unclosed-connection):
╰ certain:
╰ Unclosed connection at 1.8-23 (1 quick fix(es) available)
╰ Metadata: totalOpened: 1, totalClosed: 0, searchTimeMs: 2, processTimeMs: 1
All queries together required ≈3 ms (1ms accuracy, total 4 ms)
Show Detailed Results as Json
The analysis required 4.4 ms (including parsing and normalization and the query) within the generation environment.
In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the Interface wiki page for more information on how to get those.
{
"linter": {
"results": {
"unclosed-connection": {
"results": [
{
"certainty": "certain",
"involvedId": 4,
"loc": [
1,
8,
1,
23
],
"quickFix": [
{
"type": "replace",
"loc": [
2,
15,
2,
14
],
"description": "Close the connection with `close(con)`",
"replacement": "\nclose(con)"
}
]
}
],
".meta": {
"totalOpened": 1,
"totalClosed": 0,
"searchTimeMs": 2,
"processTimeMs": 1
}
}
},
".meta": {
"timing": 3
}
},
".meta": {
"timing": 3
}
}These examples are synthesized from the test cases in: test/functionality/linter/lint-unclosed-connection.test.ts
Given the following input:
`a <- textConnection(A)
readLines(a, 2)
file <- file()
b <- textConnection(B)
close(a)
close(b)
close(file)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
close(file("x"))We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
a <- file("x")We expect the linter to report the following:
certainty: LintingResultCertainty.Certain,
loc: [1, 6, 1, 14],
quickFix: [{
type: 'replace',
loc: [1, 15, 1, 14],
description: 'Close the connection with `close(a)`',
replacement: '\nclose(a)'
}]See here for the test-case implementation.
Given the following input:
`read <- function(){
con <- file("x")
readLines(con)
}`We expect the linter to report the following:
certainty: LintingResultCertainty.Certain,
loc: [2, 9, 2, 17],
quickFix: [{
type: 'replace',
loc: [3, 16, 3, 15],
description: 'Close the connection with `close(con)`',
replacement: '\n close(con)'
}]See here for the test-case implementation.
Given the following input:
`a <- textConnection(AB)
b <- a
if(x){
b <- textConnection(LETTERS)
close(b)
close(b)
}
t <- 2`We expect the linter to report the following:
certainty: LintingResultCertainty.Certain,
loc: [1, 6, 1, 23],
quickFix: [{
type: 'replace',
loc: [2, 7, 2, 6],
description: 'Close the connection with `close(a)`',
replacement: '\nclose(a)'
}]See here for the test-case implementation.
Given the following input:
`a <- textConnection(AB)
b <- a
c <- b
close(c)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`shut <- function(con) close(con)
a <- textConnection(AB)
shut(a)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`make <- function() textConnection(AB)
a <- make()
close(a)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`a <- textConnection(AB)
if(x){
close(a)
} else {
close(a)
}`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`read <- function(){
con <- file("x")
on.exit(close(con))
readLines(con)
}
read()`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`con <- withr::local_connection(file("x"))
readLines(con)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`con <- DBI::dbConnect(drv)
DBI::dbDisconnect(con)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
con <- DBI::dbConnect(drv)We expect the linter to report the following:
certainty: LintingResultCertainty.Certain,
loc: [1, 8, 1, 26],
quickFix: [{
type: 'replace',
loc: [1, 27, 1, 26],
description: 'Close the connection with `close(con)`',
replacement: '\nclose(con)'
}]See here for the test-case implementation.
Given the following input:
`a <- myOpen("x")
b <- myOpen("y")
myClose(a)`And using the following configuration:
{ openFns: ['myOpen'], closeFns: ['myClose'] }We expect the linter to report the following:
certainty: LintingResultCertainty.Certain,
loc: [2, 6, 2, 16],
quickFix: [{
type: 'replace',
loc: [2, 17, 2, 16],
description: 'Close the connection with `close(b)`',
replacement: '\nclose(b)'
}]See here for the test-case implementation.
Given the following input:
`a <- textConnection(AB)
b <- textConnection(E)
if(x){
close(a)
}
t <- 2
close(b)`We expect the linter to report the following:
certainty: LintingResultCertainty.Uncertain,
loc: [1, 6, 1, 23]See here for the test-case implementation.
Given the following input:
`if(x){
a <- textConnection(A)
}
close(a)`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`a <- 4+3
if(x){
a <- textConnection(A)
b <- textConnection(B)
}
t <- 34
if(x){
close(a)
}
if(y){
close(b)
}`We expect the linter to report the following:
certainty: LintingResultCertainty.Uncertain,
loc: [3, 7, 3, 23]
},
{
certainty: LintingResultCertainty.Uncertain,
loc: [4, 7, 4, 23]See here for the test-case implementation.
Given the following input:
`a <- 4+3
if(x){
a <- textConnection(A)
b <- textConnection(B)
if(y){
close(a)
}
}`We expect the linter to report the following:
certainty: LintingResultCertainty.Uncertain,
loc: [3, 7, 3, 23]
},
{
certainty: LintingResultCertainty.Certain,
loc: [4, 7, 4, 23],
quickFix: [{
type: 'replace',
loc: [4, 24, 4, 23],
description: 'Close the connection with `close(b)`',
replacement: '\n close(b)'
}]See here for the test-case implementation.
Given the following input:
`for(f in files){
con <- file(f)
readLines(con)
close(con)
}`We expect the linter to report the following:
* no lintsSee here for the test-case implementation.
Given the following input:
`if(x){
a <- 4
while(a > 0){
b <- textConnection(A)
readLines(b, 2)
a <- a - 1
}
close(b)
}
else {
a <- textConnection(A)
close(a)
}`We expect the linter to report the following:
certainty: LintingResultCertainty.Uncertain,
loc: [4, 8, 4, 24]See here for the test-case implementation.
Currently maintained by Florian Sihler and Oliver Gerstl at Ulm University
Email | GitHub | Penguins | Portfolio
- 🧑💻 Developer Onboarding
- 💻 Setup
- 👓 Overview
- 🪟 Interfacing with flowR
- 🌋 Core
- 🧹 Testing & Linting (Benchmark Page)
⁉️ FAQ- ℹ️ Extra Information