@@ -31,7 +31,7 @@ type ExitErrorCodes =
3131 | FscArgsCombinedWithMsBuildProperties = 17
3232 | FSharpCoreAssemblyLoadFailed = 18
3333 | ProjectAndFscArgs = 19
34- | InvalidGlob = 20
34+ | InvalidScriptArguments = 20
3535 | InvalidProjectArguments = 21
3636
3737type Arguments =
@@ -60,8 +60,8 @@ type Arguments =
6060 interface IArgParserTemplate with
6161 member s.Usage =
6262 match s with
63- | Project _ -> " List of paths to your .fsproj file."
64- | Script _ -> " List of paths to your .fsx file. Supports globs."
63+ | Project _ -> " List of paths to your .fsproj file. Cannot be combined with `--fsc-args`. "
64+ | Script _ -> " List of paths to your .fsx file. Supports globs. Cannot be combined with `--fsc-args`. "
6565 | Analyzers_ Path _ ->
6666 " List of path to a folder where your analyzers are located. This will search recursively."
6767 | Property _ -> " A key=value pair of an MSBuild property."
@@ -618,19 +618,26 @@ let main argv =
618618 let codeRoot = results.TryGetResult <@ Code_ Root @>
619619 let cwd = Directory.GetCurrentDirectory() |> DirectoryInfo
620620
621+ let beginsWithCurrentPath ( path : string ) =
622+ path.StartsWith( " ./" ) || path.StartsWith( " .\\ " )
623+
621624 let scripts =
622625 results.GetResult(<@ Script @>, [])
623626 |> List.collect( fun scriptGlob ->
624- if Path.IsPathRooted scriptGlob then
625- [ scriptGlob]
626- else
627- // TODO: need to discuss if this should fail fast or not
628- // also other path arguments take a `./` while this oen does not and feels inconsistent
629- if scriptGlob.StartsWith( '.' ) then
630- logger.LogCritical( " Starting a glob with \" .\" won't find files. You should remove this from the glob: {scriptGlob}" , scriptGlob)
631- exit ( int ExitErrorCodes.InvalidGlob)
632- cwd.GlobFiles( scriptGlob) |> Seq.toList |> List.map ( fun file -> file.FullName)
633-
627+ let root , scriptGlob =
628+ if Path.IsPathRooted scriptGlob then
629+ // Glob can't handle absolute paths, so we need to make sure the scriptGlob is a relative path
630+ let root = Path.GetPathRoot scriptGlob
631+ let glob = scriptGlob.Substring( root.Length)
632+ DirectoryInfo root, glob
633+ else if beginsWithCurrentPath scriptGlob then
634+ // Glob can't handle relative paths starting with "./" or ".\", so we need trim it
635+ let relativeGlob = scriptGlob.Substring( 2 ) // remove "./" or ".\"
636+ cwd, relativeGlob
637+ else
638+ cwd, scriptGlob
639+
640+ root.GlobFiles scriptGlob |> Seq.map ( fun file -> file.FullName) |> Seq.toList
634641 )
635642
636643 let exclInclFiles =
@@ -735,47 +742,72 @@ let main argv =
735742 None
736743 else
737744 match fscArgs with
738- // | None ->
739- // logger.LogError("No project given. Use `--project PATH_TO_FSPROJ`.")
740- // None
741745 | Some _ when projOpts |> List.isEmpty |> not ->
742746 logger.LogError( " `--project` and `--fsc-args` cannot be combined." )
743747 exit ( int ExitErrorCodes.ProjectAndFscArgs)
748+ | Some _ when scripts |> List.isEmpty |> not ->
749+ logger.LogError( " `--script` and `--fsc-args` cannot be combined." )
750+ exit ( int ExitErrorCodes.ProjectAndFscArgs)
744751 | Some fscArgs ->
745752 runFscArgs client fscArgs exclInclFiles severityMapping
746753 |> Async.RunSynchronously
747754 |> Some
748755 | None ->
749- let scriptOptions =
750- scripts
751- |> List.map( fun script ->
752- let fileContent = File.ReadAllText script
753- let sourceText = SourceText.ofString fileContent
754- let ( options , _diagnostics ) = fcs.GetProjectOptionsFromScript( script, sourceText) |> Async.RunSynchronously
755-
756- options
757- )
758-
759- let projects = projOpts
760- for projPath in projects do
761- if not ( File.Exists( projPath)) then
762- logger.LogError( " Invalid `--project` argument. File does not exist: '{projPath}'" , projPath)
763- exit ( int ExitErrorCodes.InvalidProjectArguments)
764- async {
765- let! loadedProjects = loadProjects toolsPath properties projects
766-
767- let loadedProjects = scriptOptions @ loadedProjects
768-
769- return !
770- loadedProjects
771- |> List.map ( fun ( projPath : FSharpProjectOptions ) ->
772- runProject client projPath exclInclFiles severityMapping
756+ match projOpts, scripts with
757+ | [], [] ->
758+ logger.LogError( " No projects or scripts were specified. Use `--project` or `--script` to specify them." )
759+ exit ( int ExitErrorCodes.EmptyFscArgs)
760+ | projects, scripts ->
761+
762+ for script in scripts do
763+ if not ( File.Exists( script)) then
764+ logger.LogError( " Invalid `--script` argument. File does not exist: '{script}'" , script)
765+ exit ( int ExitErrorCodes.InvalidProjectArguments)
766+
767+ let scriptOptions =
768+ scripts
769+ |> List.map( fun script -> async {
770+ let! fileContent = File.ReadAllTextAsync script |> Async.AwaitTask
771+ let sourceText = SourceText.ofString fileContent
772+ // GetProjectOptionsFromScript cannot be run in parallel, it is not thread-safe.
773+ let! options , diagnostics = fcs.GetProjectOptionsFromScript( script, sourceText)
774+ if not ( List.isEmpty diagnostics) then
775+ diagnostics
776+ |> List.iter ( fun d ->
777+ logger.LogError(
778+ " Script {0} has a diagnostic: {1} at {2}" ,
779+ script,
780+ d.Message,
781+ d.Range
782+ )
783+ )
784+ return options
785+ }
773786 )
774- |> Async.Parallel
775- }
776- |> Async.RunSynchronously
777- |> List.concat
778- |> Some
787+ |> Async.Sequential
788+
789+ for projPath in projects do
790+ if not ( File.Exists( projPath)) then
791+ logger.LogError( " Invalid `--project` argument. File does not exist: '{projPath}'" , projPath)
792+ exit ( int ExitErrorCodes.InvalidProjectArguments)
793+ async {
794+ let! scriptOptions = scriptOptions |> Async.StartChild
795+ let! loadedProjects = loadProjects toolsPath properties projects |> Async.StartChild
796+ let! loadedProjects = loadedProjects
797+ let! scriptOptions = scriptOptions
798+
799+ let loadedProjects = Array.toList scriptOptions @ loadedProjects
800+
801+ return !
802+ loadedProjects
803+ |> List.map ( fun ( projPath : FSharpProjectOptions ) ->
804+ runProject client projPath exclInclFiles severityMapping
805+ )
806+ |> Async.Parallel
807+ }
808+ |> Async.RunSynchronously
809+ |> List.concat
810+ |> Some
779811
780812 match results with
781813 | None -> - 1
0 commit comments