Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c097974
feat(lint): add structure for deprectaed args - #1870
gigalasr Jul 9, 2026
9116b6e
feat(lint): only detect when deprectaed arg is present - #1870
gigalasr Jul 9, 2026
05e92b8
feat(lint): allow new metadata in functions as well - #1870
gigalasr Jul 10, 2026
a43d0bc
feat(lint): pretty print new deprecation info - #1870
gigalasr Jul 10, 2026
493606b
feat(lint): use source location of arg - #1870
gigalasr Jul 10, 2026
5efa7cc
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Jul 10, 2026
e59b179
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Jul 16, 2026
b4a79ba
feat-fix(lint): use new RRange util - #1870
gigalasr Jul 16, 2026
ae5965b
docs(eval): describe interface and deprecation state - #1870
gigalasr Jul 16, 2026
314adc7
feat(dep): cleaner config - #1870
gigalasr Jul 23, 2026
1172cd3
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Jul 23, 2026
2c89bc7
feat(dep): support for version checking - #1870
gigalasr Jul 24, 2026
118a07d
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Jul 24, 2026
6f0049e
feat(dep): version check for functions #1870
gigalasr Jul 24, 2026
e36782b
feat(lint): ifValue support for deprecated args - #1870
gigalasr Jul 24, 2026
7a80a2a
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Aug 6, 2026
6bb30fc
lint(linter): eslint fixes - #1870
gigalasr Aug 6, 2026
fa811e5
feat(lint): use identifier - #1870
gigalasr Aug 6, 2026
ae6c74f
feat(lint): try to fix derrived range - #1870
gigalasr Aug 7, 2026
f69a89b
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Aug 7, 2026
8d9cbfd
feat(depr): use guess-dep querry - #1870
gigalasr Aug 7, 2026
f05e5e0
Merge remote-tracking branch 'origin/main' into 1870-deprecated-args-…
gigalasr Aug 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
319 changes: 294 additions & 25 deletions src/linter/rules/deprecated-functions.ts

Large diffs are not rendered by default.

60 changes: 41 additions & 19 deletions src/linter/rules/function-finder-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/proces
import type { MergeableRecord } from '../../util/objects';
import { isNotUndefined } from '../../util/assert';
import { getArgumentStringValue } from '../../dataflow/eval/resolve/resolve-argument';
import type { DataflowGraphVertexFunctionCall } from '../../dataflow/graph/vertex';
import { FunctionCallVertex, VertexType } from '../../dataflow/graph/vertex';
import type { FunctionInfo } from '../../queries/catalog/dependencies-query/function-info/function-info';
import { Unknown } from '../../queries/catalog/dependencies-query/dependencies-query-format';
Expand All @@ -16,6 +17,7 @@ import { Identifier } from '../../dataflow/environments/identifier';
import { Ternary } from '../../util/logic';
import type { ReadonlyFlowrAnalysisProvider } from '../../project/flowr-analyzer';
import type { AsyncOrSync } from 'ts-essentials';
import type { DataflowGraph } from '../../dataflow/graph/graph';
import { Dataflow } from '../../dataflow/graph/df-helper';

export interface FunctionsResult extends LintingResult {
Expand Down Expand Up @@ -105,35 +107,55 @@ export const functionFinderUtil = {
): Promise<Ternary> {
const dataflow = await analyzer.dataflow();
const identifier = Dataflow.qualify(element.node.info.id, dataflow.graph, true) ?? (element.node.lexeme !== undefined ? Identifier.parse(element.node.lexeme) : undefined);

/* if we have no additional info, we assume they always access the network */
if(identifier === undefined) {
if(identifier === undefined || requireValue === undefined) {
return Ternary.Always;
}

// we allow our function pool to contain non-namespaced functions
const info = pool.get(Identifier.toString(identifier)) ?? pool.get(Identifier.getName(identifier));
if(info === undefined) {
return Ternary.Always;
}

const vert = dataflow.graph.getVertex(element.node.info.id);
if(FunctionCallVertex.is(vert)){
const args = getArgumentStringValue(
analyzer.flowrConfig.solver.variables,
dataflow.graph,
vert,
info.argIdx,
info.argName,
info.resolveValue,
analyzer.inspectContext());
// we obtain all values, at least one of them has to trigger for the request
const argValues: string[] = args ? args.values().flatMap(s => Array.from(s)).filter(isNotUndefined).toArray() : [];
if(argValues.length === 0){
return Ternary.Maybe;
} else if(argValues.some(v => requireValue instanceof RegExp ? requireValue.test(v) : v === requireValue)){
return Ternary.Always;
} else if(argValues.some(v => v === Unknown)) {
return Ternary.Maybe;
}
if(FunctionCallVertex.is(vert)) {
return hasArgumentValue(requireValue, vert, analyzer, dataflow.graph, info.resolveValue, info.argName, info.argIdx);
}

return Ternary.Never;
}
};

/**
* Test if a function call has an argument with a specific value
*/
export function hasArgumentValue(

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 could be.. should be moved in to the Rargument helper object i think

test: RegExp | string,
fnVertex: DataflowGraphVertexFunctionCall,
analyzer: ReadonlyFlowrAnalysisProvider,
dataflow: DataflowGraph,
resolveValue: boolean | 'library' | undefined,
argName?: string,
argIdx?: number | 'unnamed'): Ternary {
const args = getArgumentStringValue(
analyzer.flowrConfig.solver.variables,
dataflow,
fnVertex,
argIdx,
argName,
resolveValue,
analyzer.inspectContext());
// we obtain all values, at least one of them has to trigger for the request
const argValues: string[] = args ? args.values().flatMap(s => Array.from(s)).filter(isNotUndefined).toArray() : [];
if(argValues.length === 0){
return Ternary.Maybe;
} else if(argValues.some(v => test instanceof RegExp ? test.test(v) : v === test)){
return Ternary.Always;
} else if(argValues.some(v => v === Unknown)) {
return Ternary.Maybe;
}

return Ternary.Never;
}
2 changes: 1 addition & 1 deletion src/linter/rules/naming-convention.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export function getMostUsedCasing(symbols: { detectedCasing: CasingConvention }[
map.set(symbol.detectedCasing, o + 1);
}

// Return element with most occurances
// Return element with most occurrences
return [...map].reduce((p, c) => p[1] > c[1] ? p : c)[0];
}

Expand Down
6 changes: 4 additions & 2 deletions src/linter/rules/network-functions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LintingResultCertainty, type LintingRule, LintingRuleCertainty } from '../linter-format';
import { functionFinderUtil, type FunctionsMetadata, type FunctionsResult } from './function-finder-util';
import type { FunctionsMetadata, FunctionsResult } from './function-finder-util';
import { functionFinderUtil } from './function-finder-util';
import { LintingRuleTag } from '../linter-tags';
import type { MergeableRecord } from '../../util/objects';
import { ReadFunctions } from '../../queries/catalog/dependencies-query/function-info/read-functions';
import type { FlowrSearchElement } from '../../search/flowr-search';
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
Expand All @@ -11,13 +11,15 @@ import { WriteFunctions } from '../../queries/catalog/dependencies-query/functio
import type { FunctionInfo } from '../../queries/catalog/dependencies-query/function-info/function-info';
import { Identifier } from '../../dataflow/environments/identifier';
import { Dataflow } from '../../dataflow/graph/df-helper';
import type { MergeableRecord } from '../../util/objects';

export interface NetworkFunctionsConfig extends MergeableRecord {
/**
* The list of function names or more detailed {@link NetworkFunction} information that should be marked in the given context if their arguments match.
*/
fns: readonly (Identifier | NetworkFunction)[]
}

export interface NetworkFunction extends MergeableRecord{
/**
* The name of the network function to find.
Expand Down
4 changes: 3 additions & 1 deletion test/functionality/_helper/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export function controlledSigDb(pkgOrPkgs: string | Record<string, readonly stri
}


type DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;

/**
* Asserts correct linting results while ignoring each linting result's {@link LintingRuleResult.involvedId}.
*/
Expand All @@ -72,7 +74,7 @@ export function assertLinter<Name extends LintingRuleNames>(
parser: KnownParser,
code: string,
ruleName: Name,
expected: Omit<LintingRuleResult<Name>, 'involvedId'>[] | ((df: DataflowInformation, ast: NormalizedAst) => Omit<LintingRuleResult<Name>, 'involvedId'>[]),
expected: DistributiveOmit<LintingRuleResult<Name>, 'involvedId'>[] | ((df: DataflowInformation, ast: NormalizedAst) => Omit<LintingRuleResult<Name>, 'involvedId'>[]),
expectedMetadata?: LintingRuleMetadata<Name>,
lintingRuleConfig?: DeepPartial<LintingRuleConfig<Name>> & LinterTestSetup
) {
Expand Down
Loading
Loading