Skip to content

Implemented modes in AsynchronousFunctionNames rule#842

Merged
knocte merged 6 commits intofsprojects:masterfrom
webwarrior-ws:asynchronous-funtion-names-v2
Feb 11, 2026
Merged

Implemented modes in AsynchronousFunctionNames rule#842
knocte merged 6 commits intofsprojects:masterfrom
webwarrior-ws:asynchronous-funtion-names-v2

Conversation

@webwarrior-ws
Copy link
Contributor

Mode OnlyPublicAPIsInLibraries only runs in projects that are likely library projects.
Mode AnyPublicAPIs flags all public APIs like before.
Mode AllAPIs also flags (give violations about) internal, private, and nested APIs.

Contributes to #517.

To NamingHelper.fs because both SimpleAsyncComplementaryHelpers
and AsynchronousFunctionNames have to be able to access that
type.
@knocte
Copy link
Collaborator

knocte commented Feb 10, 2026

Missing change in docs.

@greptile-apps
Copy link

greptile-apps bot commented Feb 10, 2026

Greptile Overview

Confidence Score: 2/5

  • Not safe to merge until config defaulting is fixed
  • AsynchronousFunctionNames switched from EnabledConfig to RuleConfig<Config> but is still constructed via constructRuleWithConfig, which skips the rule entirely when config is omitted. The repository default fsharplint.json enables the rule without a config block, so the rule will be silently disabled by default after this change.
  • src/FSharpLint.Core/Application/Configuration.fs, src/FSharpLint.Core/fsharplint.json

Important Files Changed

Filename Overview
docs/content/how-tos/rules/FL0096.md Docs updated to show new mode config for FL0096; example disables the rule but now includes config.mode.
src/FSharpLint.Core/Application/Configuration.fs Changes AsynchronousFunctionNames config type to RuleConfig<...> and constructs it with constructRuleWithConfig, which currently skips the rule entirely when config is omitted (breaking { enabled: true } behavior and default config).
src/FSharpLint.Core/Rules/Conventions/Naming/AsynchronousFunctionNames.fs Adds Config.Mode and new modes logic (library heuristic + access level + nested behavior). Main functional risk is config defaulting handled elsewhere, not in this file.
src/FSharpLint.Core/Rules/Conventions/Naming/SimpleAsyncComplementaryHelpers.fs Moves AsynchronousFunctionsMode to shared helper and continues using Config.Mode; no functional logic changes in this PR diff.
src/FSharpLint.Core/Rules/NamingHelper.fs Introduces shared AsynchronousFunctionsMode DU under Helper.Naming.Asynchronous for reuse by multiple rules.
tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/AsynchronousFunctionNames.fs Updates tests to pass config to rule and adds new fixtures covering AllAPIs (non-public + nested bindings).
tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/SimpleAsyncComplementaryHelpers.fs Updates tests to use shared AsynchronousFunctionsMode and to pass Mode = AnyPublicAPIs explicitly.

Sequence Diagram

sequenceDiagram
    participant UserCfg as fsharplint.json
    participant Config as Configuration.fs
    participant Ctor as constructRuleWithConfig
    participant AFN as AsynchronousFunctionNames.rule
    participant Runner as AsynchronousFunctionNames.runner
    participant Heur as LibraryHeuristics

    UserCfg->>Config: Deserialize RuleConfig<AsynchronousFunctionNames.Config>
    Config->>Ctor: constructRuleWithConfig AFN.rule (if enabled)
    alt config block present
        Ctor->>AFN: rule(config)
        AFN->>Runner: Runner = runner config
        Runner->>Heur: howLikelyProjectIsLibrary(projectFileName)
        Runner-->>Config: Suggestions emitted/empty
    else config omitted (Config=None)
        Ctor-->>Config: returns None (rule not constructed)
        Note over Config,Ctor: Enabled rule becomes effectively disabled
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

7 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link

greptile-apps bot commented Feb 10, 2026

Additional Comments (2)

src/FSharpLint.Core/Application/Configuration.fs
Rule silently disabled
constructRuleWithConfig only applies rule when ruleConfig.Config is Some, so enabling asynchronousFunctionNames without a config block results in the rule not being constructed at all (i.e., effectively disabled). This is a behavior change from the previous EnabledConfig version and currently affects the default fsharplint.json which has "asynchronousFunctionNames": { "enabled": true }.

This needs a default AsynchronousFunctionNames.Config (e.g. AnyPublicAPIs) similar to constructTypePrefixingRuleWithConfig so that { "enabled": true } still enables the rule.


src/FSharpLint.Core/fsharplint.json
Enabled rule missing config
asynchronousFunctionNames is enabled here but provides no config. With the updated config type (RuleConfig<AsynchronousFunctionNames.Config>), this will deserialize to Config = None and (via constructRuleWithConfig) the rule won’t be constructed at all.

Either add a default mode here or change rule construction to apply a default when config is omitted.

That has Mode member, which may be on of:
OnlyPublicAPIsInLibraries (default), AnyPublicAPIs, AllAPIs.
Mode OnlyPublicAPIsInLibraries only runs in projects that are
likely library projects.
Mode AnyPublicAPIs flags all public APIs like before.
Mode AllAPIs also flags (give violations about) internal,
private, and nested APIs.
@webwarrior-ws webwarrior-ws force-pushed the asynchronous-funtion-names-v2 branch from f88df9d to 7e125a6 Compare February 10, 2026 12:32
@webwarrior-ws
Copy link
Contributor Author

Missing change in docs.

Added new setting description to docs.

@knocte
Copy link
Collaborator

knocte commented Feb 10, 2026

Not safe to merge until config defaulting is fixed

Actually, instead of defaulting to a mode when not specifying the mode (like TypePrefixing rule does), I'd prefer if we throw an exception in this case because in this case the rule is new (in the case of TypePrefixing, the rule already existed when we added the mode).

@knocte knocte changed the title Implemented modes in AsynchronousFuntionNames rule Implemented modes in AsynchronousFunctionNames rule Feb 10, 2026
@webwarrior-ws webwarrior-ws force-pushed the asynchronous-funtion-names-v2 branch from b689dc2 to d2ebfb7 Compare February 10, 2026 13:06
To include info about mode setting.
@webwarrior-ws
Copy link
Contributor Author

Not safe to merge until config defaulting is fixed

Actually, instead of defaulting to a mode when not specifying the mode (like TypePrefixing rule does), I'd prefer if we throw an exception in this case because in this case the rule is new (in the case of TypePrefixing, the rule already existed when we added the mode).

The rule is constructed using constructRuleWithConfig, like most of rules that have config, and not like TypePrefixing which uses its own function constructTypePrefixingRuleWithConfig.

@knocte
Copy link
Collaborator

knocte commented Feb 11, 2026

Not safe to merge until config defaulting is fixed

Actually, instead of defaulting to a mode when not specifying the mode (like TypePrefixing rule does), I'd prefer if we throw an exception in this case because in this case the rule is new (in the case of TypePrefixing, the rule already existed when we added the mode).

The rule is constructed using constructRuleWithConfig, like most of rules that have config, and not like TypePrefixing which uses its own function constructTypePrefixingRuleWithConfig.

So?

@webwarrior-ws
Copy link
Contributor Author

Not safe to merge until config defaulting is fixed

Actually, instead of defaulting to a mode when not specifying the mode (like TypePrefixing rule does), I'd prefer if we throw an exception in this case because in this case the rule is new (in the case of TypePrefixing, the rule already existed when we added the mode).

The rule is constructed using constructRuleWithConfig, like most of rules that have config, and not like TypePrefixing which uses its own function constructTypePrefixingRuleWithConfig.

So?

So it is already functioning as you described, no need to change anything.

@knocte
Copy link
Collaborator

knocte commented Feb 11, 2026

Ok great.

@knocte
Copy link
Collaborator

knocte commented Feb 11, 2026

So it is already functioning as you described, no need to change anything.

Both rules yeah?

@webwarrior-ws
Copy link
Contributor Author

So it is already functioning as you described, no need to change anything.

Both rules yeah?

Yes.

@knocte knocte merged commit 4c701ea into fsprojects:master Feb 11, 2026
8 checks passed
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.

2 participants