forked from fsprojects/FSharpLint
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAsynchronousFunctionNames.fs
More file actions
104 lines (94 loc) · 4.07 KB
/
AsynchronousFunctionNames.fs
File metadata and controls
104 lines (94 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
module FSharpLint.Rules.AsynchronousFunctionNames
open System
open FSharpLint.Framework
open FSharpLint.Framework.Suggestion
open FSharpLint.Framework.Ast
open FSharpLint.Framework.Rules
open FSharpLint.Rules.Utilities.LibraryHeuristics
open Helper.Naming.Asynchronous
open Utilities.TypedTree
open FSharp.Compiler.Syntax
[<RequireQualifiedAccess>]
type Config = {
Mode: AsynchronousFunctionsMode
}
let runner (config: Config) (args: AstNodeRuleParams) =
let emitWarning range (newFunctionName: string) (returnTypeName: string) =
Array.singleton
{
Range = range
Message = String.Format(Resources.GetString "RulesAsynchronousFunctionNames", returnTypeName, newFunctionName)
SuggestedFix = None
TypeChecks = List.empty
}
let isAccessibilityLevelApplicable (accessibility: Option<SynAccess>) =
match accessibility with
| None
| Some(SynAccess.Public _) -> true
| _ -> config.Mode = AllAPIs
let likelyhoodOfBeingInLibrary =
match args.ProjectCheckInfo with
| Some projectInfo -> howLikelyProjectIsLibrary projectInfo.ProjectContext.ProjectOptions.ProjectFileName
| None -> Unlikely
if config.Mode = OnlyPublicAPIsInLibraries && likelyhoodOfBeingInLibrary <> Likely then
Array.empty
else
match args.AstNode with
| AstNode.Binding (SynBinding (_, _, _, _, attributes, _, _, SynPat.LongIdent(funcIdent, _, _, _, accessibility, identRange), returnInfo, _, _, _, _))
when isAccessibilityLevelApplicable accessibility && not <| Helper.Naming.isAttribute "Obsolete" attributes ->
let checkAsyncFunction () =
match funcIdent with
| HasAsyncPrefix _ ->
Array.empty
| HasAsyncSuffix name
| HasNoAsyncPrefixOrSuffix name ->
let nameWithAsync = asyncSuffixOrPrefix + name
emitWarning identRange nameWithAsync "Async"
let checkTaskFunction () =
match funcIdent with
| HasAsyncSuffix _ ->
Array.empty
| HasAsyncPrefix name
| HasNoAsyncPrefixOrSuffix name ->
let nameWithAsync = name + asyncSuffixOrPrefix
emitWarning identRange nameWithAsync "Task"
let parents = args.GetParents args.NodeIndex
let hasEnclosingFunctionOrMethod =
parents
|> List.exists
(fun node ->
match node with
| AstNode.Binding (SynBinding (_, _, _, _, _, _, _, SynPat.LongIdent(_), _, _, _, _, _)) -> true
| _ -> false)
if hasEnclosingFunctionOrMethod && config.Mode <> AllAPIs then
Array.empty
else
match returnInfo with
| Some ReturnsAsync -> checkAsyncFunction()
| Some ReturnsTask -> checkTaskFunction()
| None ->
match args.CheckInfo with
| Some checkInfo ->
match getFunctionReturnType checkInfo args.Lines funcIdent with
| Some returnType ->
match returnType with
| FSharpTypeAsync -> checkAsyncFunction()
| FSharpTypeTask
| FSharpTypeTaskNonGeneric -> checkTaskFunction()
| FSharpTypeNonAsync -> Array.empty
| None -> Array.empty
| None -> Array.empty
| _ ->
Array.empty
| _ -> Array.empty
let rule config =
AstNodeRule
{
Name = "AsynchronousFunctionNames"
Identifier = Identifiers.AsynchronousFunctionNames
RuleConfig =
{
AstNodeRuleConfig.Runner = runner config
Cleanup = ignore
}
}