Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 26 additions & 10 deletions src/FSharpLint.Core/Application/Lint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ module Lint =
GlobalConfig: Rules.GlobalRuleConfig
TypeCheckResults: FSharpCheckFileResults option
ProjectCheckResults: FSharpCheckProjectResults option
ProjectOptions: Lazy<FSharpProjectOptions option>
FilePath: string
FileContent: string
Lines: string[]
Expand All @@ -149,6 +150,7 @@ module Lint =
Lines = config.Lines
CheckInfo = config.TypeCheckResults
ProjectCheckInfo = config.ProjectCheckResults
ProjectOptions = config.ProjectOptions
GlobalConfig = config.GlobalConfig
}
// Build state for rules with context.
Expand Down Expand Up @@ -263,6 +265,10 @@ module Lint =
GlobalConfig = enabledRules.GlobalConfig
TypeCheckResults = fileInfo.TypeCheckResults
ProjectCheckResults = fileInfo.ProjectCheckResults
ProjectOptions = lazy(
fileInfo.ProjectCheckResults
|> Option.map _.ProjectContext.ProjectOptions
)
FilePath = fileInfo.File
FileContent = fileInfo.Text
Lines = lines
Expand Down Expand Up @@ -430,9 +436,9 @@ module Lint =

Option.iter (fun func -> func warning) optionalParams.ReceivedWarning

let checker = FSharpChecker.Create(keepAssemblyContents=true)
let checker = FSharpChecker.Create(keepAssemblyContents=true, parallelReferenceResolution=true)

let parseFilesInProject files projectOptions = async {
let parseFilesInProject files (projectOptions:FSharpProjectOptions) = async {
let lintInformation =
{ Configuration = config
CancellationToken = optionalParams.CancellationToken
Expand All @@ -446,21 +452,31 @@ module Lint =
Configuration.IgnoreFiles.shouldFileBeIgnored parsedIgnoreFiles filePath)
|> Option.defaultValue false

let! parsedFiles =
files
|> List.filter (not << isIgnoredFile)
let filesToLint = files |> List.filter (not << isIgnoredFile)

// Run project check and per-file parse+check concurrently.
// The project check warms the FCS incremental builder; parallel
// per-file checks share the builder and benefit from its warmed state.
let projectCheckAsync = checker.ParseAndCheckProject projectOptions
let perFileAsync =
filesToLint
|> List.map (fun file -> ParseFile.parseFile file checker (Some projectOptions))
|> Async.Sequential
|> Async.Parallel

let! results = Async.Parallel [|
async { let! r = projectCheckAsync in return box r }
async { let! r = perFileAsync in return box r }
|]
let projectCheckResults = results.[0] :?> FSharpCheckProjectResults
let parsedFiles = results.[1] :?> ParseFile.ParseFileResult<ParseFile.FileParseInfo>[]

let failedFiles = Array.choose getFailedFiles parsedFiles

if Array.isEmpty failedFiles then
let! projectCheckResults = checker.ParseAndCheckProject projectOptions

parsedFiles
|> Array.choose getParsedFiles
|> Array.iter (fun fileParseResult ->
lint
|> Array.iter (fun fileParseResult ->
lint
lintInformation
{ fileParseResult with ProjectCheckResults = Some projectCheckResults })

Expand Down
1 change: 1 addition & 0 deletions src/FSharpLint.Core/Application/Lint.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ module Lint =
GlobalConfig: Rules.GlobalRuleConfig
TypeCheckResults: FSharpCheckFileResults option
ProjectCheckResults: FSharpCheckProjectResults option
ProjectOptions: Lazy<FSharpProjectOptions option>
FilePath: string
FileContent: string
Lines: string[]
Expand Down
1 change: 1 addition & 0 deletions src/FSharpLint.Core/Framework/Rules.fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type AstNodeRuleParams =
Lines:string []
CheckInfo:FSharpCheckFileResults option
ProjectCheckInfo:FSharpCheckProjectResults option
ProjectOptions: Lazy<FSharpProjectOptions option>
GlobalConfig:GlobalRuleConfig }

type LineRuleParams =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ let runner (config: Config) (args: AstNodeRuleParams) =
| _ -> config.Mode = AllAPIs

let likelyhoodOfBeingInLibrary =
match args.ProjectCheckInfo with
| Some projectInfo -> howLikelyProjectIsLibrary projectInfo.ProjectContext.ProjectOptions.ProjectFileName
match args.ProjectOptions.Value with
| Some projectOptions -> howLikelyProjectIsLibrary projectOptions.ProjectFileName
| None -> Unlikely

if config.Mode = OnlyPublicAPIsInLibraries && likelyhoodOfBeingInLibrary <> Likely then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ let runner (config: Config) (args: AstNodeRuleParams) =
Array.append (checkFuncs asyncFuncs taskFuncs) (checkFuncs taskFuncs asyncFuncs)

let likelyhoodOfBeingInLibrary =
match args.ProjectCheckInfo with
| Some projectInfo -> howLikelyProjectIsLibrary projectInfo.ProjectContext.ProjectOptions.ProjectFileName
match args.ProjectOptions.Value with
| Some projectOptions -> howLikelyProjectIsLibrary projectOptions.ProjectFileName
| None -> Unlikely

if config.Mode = OnlyPublicAPIsInLibraries && likelyhoodOfBeingInLibrary <> Likely then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ let checkIfInLibrary (args: AstNodeRuleParams) (range: range) : array<WarningDet
let ruleNotApplicable =
isInObsoleteMethodOrFunction (args.GetParents args.NodeIndex)
||
match (args.CheckInfo, args.ProjectCheckInfo) with
| Some checkFileResults, Some checkProjectResults ->
let projectFile = System.IO.FileInfo checkProjectResults.ProjectContext.ProjectOptions.ProjectFileName
match (args.CheckInfo, args.ProjectOptions.Value) with
| Some checkFileResults, Some projectOptions ->
let projectFile = System.IO.FileInfo projectOptions.ProjectFileName
match howLikelyProjectIsLibrary projectFile.Name with
| Likely -> false
| Unlikely -> true
Expand Down
1 change: 1 addition & 0 deletions tests/FSharpLint.Core.Tests/Rules/TestAstNodeRule.fs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type TestAstNodeRuleBase (rule:Rule) =
GlobalConfig = resolvedGlobalConfig
TypeCheckResults = checkResult
ProjectCheckResults = None
ProjectOptions = Lazy<_>(None)
FilePath = (Option.defaultValue String.Empty maybeFileName)
FileContent = input
Lines = (input.Split("\n"))
Expand Down
1 change: 1 addition & 0 deletions tests/FSharpLint.Core.Tests/Rules/TestHintMatcherBase.fs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type TestHintMatcherBase () =
GlobalConfig = resolvedGlobalConfig
TypeCheckResults = checkResult
ProjectCheckResults = None
ProjectOptions = Lazy<_>()
FilePath = (Option.defaultValue String.Empty maybeFileName)
FileContent = input
Lines = (input.Split("\n"))
Expand Down
1 change: 1 addition & 0 deletions tests/FSharpLint.Core.Tests/Rules/TestIndentationRule.fs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type TestIndentationRuleBase (rule:Rule) =
GlobalConfig = resolvedGlobalConfig
TypeCheckResults = None
ProjectCheckResults = None
ProjectOptions = Lazy<_>(None)
FilePath = resolvedFileName
FileContent = input
Lines = lines
Expand Down
1 change: 1 addition & 0 deletions tests/FSharpLint.Core.Tests/Rules/TestLineRule.fs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type TestLineRuleBase (rule:Rule) =
GlobalConfig = resolvedGlobalConfig
TypeCheckResults = None
ProjectCheckResults = None
ProjectOptions = Lazy<_>(None)
FilePath = resolvedFileName
FileContent = input
Lines = lines
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type TestNoTabCharactersRuleBase (rule:Rule) =
GlobalConfig = resolvedGlobalConfig
TypeCheckResults = None
ProjectCheckResults = None
ProjectOptions = Lazy<_>()
FilePath = resolvedFileName
FileContent = input
Lines = lines
Expand Down
Loading