Skip to content

detect unused packages#2627

Open
lou7202 wants to merge 3 commits into
mainfrom
2626-linter-unused-import
Open

detect unused packages#2627
lou7202 wants to merge 3 commits into
mainfrom
2626-linter-unused-import

Conversation

@lou7202

@lou7202 lou7202 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

unused packages are detected by checking whether a 'library' function call has a reads|calls edge pointing towards it

unused packages are detected by checking whether a 'library' function call has a reads|calls edge pointing towards it
@lou7202 lou7202 linked an issue Jul 9, 2026 that may be closed by this pull request
16 tasks
Comment thread src/linter/rules/unused-import.ts Outdated

export type UnusedImportMetadata = MergeableRecord;

const LibraryLoadFunctions = new Set(['library', 'require', 'requireNamespace', 'loadNamespace', 'attachNamespace', 'load_all', 'use', 'p_load']);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do not harcode them here but use https://github.com/flowr-analysis/flowr/blob/main/src/queries/catalog/dependencies-query/function-info/library-functions.ts (the LibraryFunctions object) to match them package sensitive => also use Identifier.toQualified if possible please (

toQualified(this: void, origins: readonly Origin[] | undefined): Identifier | undefined {
)

Comment thread src/linter/rules/unused-import.ts Outdated
Comment thread src/linter/rules/unused-import.ts Outdated
elements.getElements()
.filter(element => {
//if can't export we don't know if it used or not
const unknownIds = new Set<string>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the NodeId type to collect any kind of node ids! not all of them are strings!

Comment thread src/linter/rules/unused-import.ts Outdated
}
if(unknownIds.size > 0) {
for(const [id, v] of dataflow.graph.verticesOfType(VertexType.FunctionCall)) {
if(LibraryLoadFunctions.has(Identifier.getName(v.name)) && unknownIds.has(String(id))) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we are detecting unused packages, why would we need this check?

Comment thread src/linter/rules/unused-import.ts Outdated
return false;
}
}
return isUndefined(dataflow.graph.ingoingEdges(element.node.info.id)) || dataflow.graph.ingoingEdges(element.node.info.id)?.values().filter(edge => edge.types === EdgeType.Calls + EdgeType.Reads).toArray().length === 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can take the ingoing edges but you can also iterate over all library calls identified by fromQuery and check whether they have an edge pointing to them.
Also id' argue that includesType of a read edge should suffice

Comment thread src/linter/rules/unused-import.ts Outdated
name: 'Unused Import',
tags: [LintingRuleTag.Smell, LintingRuleTag.Readability],
certainty: LintingRuleCertainty.BestEffort,
description: 'Checks whether an imported package is used.',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd invert this to focus on it highlights packages which are not required for the code to run

Comment thread src/linter/rules/unused-import.ts Outdated
certainty: LintingRuleCertainty.BestEffort,
description: 'Checks whether an imported package is used.',
defaultConfig: {
pkgDb: undefined

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is used nowhere? and please remove it here. flowR has a config for the pkgDB and you can control the used pkg db with the flowR config (https://github.com/flowr-analysis/flowr/wiki/package-database)! what we do need however, is the ability to whitelist imports (e.g. packages that do something on load that could be needed) which should not be marked as unused!

Comment thread src/linter/rules/unused-import.ts Outdated
import { Identifier } from '../../dataflow/environments/identifier';
import type { PkgDbSource } from '../../project/plugins/package-version-plugins/flowr-analyzer-package-versions-pkgdb-plugin';

export type UnusedImportResult = LintingResult;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output should also report which version of the package was used (from the package db) to mark it as unused because maybe it was useful in an older version etc. Also it

  • should be clarified in the doc that you need a package db for this to warn
  • only packages for which we have a package db entry (i.e., which are not marked as unknown) should be considered!

import { LintingResultCertainty } from '../../../src/linter/linter-format';

//const ggplot2Callable = ['+', 'ggplot', 'aes', 'geom_point', 'geom_line', 'theme_bw', 'coord_cartesian', 'ggsave', 'fortify', 'scale_type'];
/*const namespaceInfo = setCallable(FlowrNamespaceFile.from(new FlowrInlineTextFile('NAMESPACE', `S3method(fortify,data.frame)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is there a commented out test?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can know use the Pkgdb builder for this!

}
]); console.log(result.linter.results["unused-import"])
});*/
assertLinter('a', parser, 'library(ggplot2)', 'unused-import', [

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats the idea but please also add more complicated tests. e.g. one which uses some packages and does not use others!

@EagleoutIce

EagleoutIce commented Jul 9, 2026

Copy link
Copy Markdown
Member

Please also add documentation as described in https://github.com/flowr-analysis/flowr/wiki/create-linting-rules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Linter]: Unused Import

2 participants