diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 3a0e7620bd..2a1bb44d82 100755 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -4976,37 +4976,32 @@ module private ScriptPreprocessClosure = match closureDirective with | ClosedSourceFile _ as csf -> [csf] | SourceFile(filename,m,source) -> - let filename = FileSystem.GetFullPathShim(filename) - if observedSources.HaveSeen(filename) then [] - else - observedSources.SetSeen(filename) - - let errors = ref [] - let warnings = ref [] - let errorLogger = - { new ErrorLogger("FindClosure") with - member x.ErrorSinkImpl(e) = errors := e :: !errors - member x.WarnSinkImpl(e) = warnings := e :: !warnings - member x.ErrorCount = (!errors).Length } - - use unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger) - let pathOfMetaCommandSource = Path.GetDirectoryName(filename) - match ParseScriptText(filename,source,!tcConfig,codeContext,lexResourceManager,errorLogger) with - | Some(input) -> - let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn !tcConfig (input,pathOfMetaCommandSource) - tcConfig := tcConfigResult + let errors = ref [] + let warnings = ref [] + let errorLogger = + { new ErrorLogger("FindClosure") with + member x.ErrorSinkImpl(e) = errors := e :: !errors + member x.WarnSinkImpl(e) = warnings := e :: !warnings + member x.ErrorCount = (!errors).Length } + + use unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger) + let pathOfMetaCommandSource = Path.GetDirectoryName(filename) + match ParseScriptText(filename,source,!tcConfig,codeContext,lexResourceManager,errorLogger) with + | Some(input) -> + let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn !tcConfig (input,pathOfMetaCommandSource) + tcConfig := tcConfigResult - let AddFileIfNotSeen(m,filename) = - if observedSources.HaveSeen(filename) then [] - else - if IsScript(filename) then SourceFileOfFilename(filename,m,tcConfigResult.inputCodePage) - else - observedSources.SetSeen(filename) - [ClosedSourceFile(filename,m,None,[],[],[])] // Don't traverse into .fs leafs. + let AddFileIfNotSeen(m,filename) = + if observedSources.HaveSeen(filename) then [] + else + observedSources.SetSeen(filename) + if IsScript(filename) then SourceFileOfFilename(filename,m,tcConfigResult.inputCodePage) + else [ClosedSourceFile(filename,m,None,[],[],[])] // Don't traverse into .fs leafs. - let loadedSources = (!tcConfig).GetAvailableLoadedSources() |> List.rev |> List.map AddFileIfNotSeen |> List.concat - ClosedSourceFile(filename,m,Some(input),!errors,!warnings,!noWarns) :: loadedSources |> List.map FindClosure |> List.concat // Final closure is in reverse order. Keep the closed source at the top. - | None -> [ClosedSourceFile(filename,m,None,!errors,!warnings,[])] + let loadedSources = (!tcConfig).GetAvailableLoadedSources() |> List.map AddFileIfNotSeen |> List.concat + (loadedSources |> List.map FindClosure |> List.concat) + @ [ClosedSourceFile(filename,m,Some(input),!errors,!warnings,!noWarns)] + | None -> [ClosedSourceFile(filename,m,None,!errors,!warnings,[])] closureDirectives |> List.map FindClosure |> List.concat, !tcConfig @@ -5024,7 +5019,7 @@ module private ScriptPreprocessClosure = let sourceFiles = ref [] let sourceInputs = ref [] let globalNoWarns = ref [] - for directive in closureDirectives do + for directive in List.rev closureDirectives do match directive with | ClosedSourceFile(filename,m,input,_,_,noWarns) -> let filename = FileSystem.GetFullPathShim(filename) diff --git a/tests/service/ProjectOptionsTests.fs b/tests/service/ProjectOptionsTests.fs index 245b0f482a..d56d9de02c 100644 --- a/tests/service/ProjectOptionsTests.fs +++ b/tests/service/ProjectOptionsTests.fs @@ -418,6 +418,22 @@ let ``Project file parsing -- report files``() = for f in Directory.EnumerateFiles(@"C:\Program Files (x86)\Microsoft SDKs\F#\4.0\","*",SearchOption.AllDirectories) do printfn "File: %s" f +[] +let ``Test ProjectFileNames order for GetProjectOptionsFromScript`` () = // See #594 + let test scriptName expected = + let scriptPath = __SOURCE_DIRECTORY__ + @"/data/ScriptProject/" + scriptName + ".fsx" + let scriptSource = File.ReadAllText scriptPath + let projOpts = + checker.GetProjectOptionsFromScript(scriptPath, scriptSource) + |> Async.RunSynchronously + projOpts.ProjectFileNames + |> Array.map Path.GetFileNameWithoutExtension + |> (=) expected + |> shouldEqual true + test "Main1" [|"BaseLib1"; "Lib1"; "Lib2"; "Main1"|] + test "Main2" [|"BaseLib1"; "Lib1"; "Lib2"; "Lib3"; "Main2"|] + test "Main3" [|"Lib3"; "Lib4"; "Main3"|] + test "Main4" [|"BaseLib2"; "Lib5"; "BaseLib1"; "Lib1"; "Lib2"; "Main4"|] #endif diff --git a/tests/service/data/ScriptProject/BaseLib1.fs b/tests/service/data/ScriptProject/BaseLib1.fs new file mode 100644 index 0000000000..d3be7d2a54 --- /dev/null +++ b/tests/service/data/ScriptProject/BaseLib1.fs @@ -0,0 +1,3 @@ +module BaseLib1 + +let add2 x = x + 2 \ No newline at end of file diff --git a/tests/service/data/ScriptProject/BaseLib2.fs b/tests/service/data/ScriptProject/BaseLib2.fs new file mode 100644 index 0000000000..3277193dd5 --- /dev/null +++ b/tests/service/data/ScriptProject/BaseLib2.fs @@ -0,0 +1,3 @@ +module BaseLib2 + +let add10 x = x + 10 \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Lib1.fsx b/tests/service/data/ScriptProject/Lib1.fsx new file mode 100644 index 0000000000..53833dc65c --- /dev/null +++ b/tests/service/data/ScriptProject/Lib1.fsx @@ -0,0 +1,2 @@ +#load "BaseLib1.fs" +let add3 = BaseLib1.add2 >> ((+) 1) \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Lib2.fsx b/tests/service/data/ScriptProject/Lib2.fsx new file mode 100644 index 0000000000..7f6261cf09 --- /dev/null +++ b/tests/service/data/ScriptProject/Lib2.fsx @@ -0,0 +1,2 @@ +#load "BaseLib1.fs" +let add4 = BaseLib1.add2 >> ((+) 2) \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Lib3.fs b/tests/service/data/ScriptProject/Lib3.fs new file mode 100644 index 0000000000..8524ace259 --- /dev/null +++ b/tests/service/data/ScriptProject/Lib3.fs @@ -0,0 +1,3 @@ +module Lib3 + +let add6 = ((+) 6) \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Lib4.fs b/tests/service/data/ScriptProject/Lib4.fs new file mode 100644 index 0000000000..108bfbc45d --- /dev/null +++ b/tests/service/data/ScriptProject/Lib4.fs @@ -0,0 +1,3 @@ +module Lib4 + +let add8 = ((+) 8) \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Lib5.fsx b/tests/service/data/ScriptProject/Lib5.fsx new file mode 100644 index 0000000000..ec2ecacb18 --- /dev/null +++ b/tests/service/data/ScriptProject/Lib5.fsx @@ -0,0 +1,2 @@ +#load "BaseLib2.fs" +let add12 = BaseLib2.add10 >> ((+) 2) \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Main1.fsx b/tests/service/data/ScriptProject/Main1.fsx new file mode 100644 index 0000000000..90086fc76d --- /dev/null +++ b/tests/service/data/ScriptProject/Main1.fsx @@ -0,0 +1,4 @@ +#load "Lib1.fsx" +#load "Lib2.fsx" +Lib1.add3 5 |> printfn "%i" +Lib2.add4 5 |> printfn "%i" \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Main2.fsx b/tests/service/data/ScriptProject/Main2.fsx new file mode 100644 index 0000000000..906fd5d19c --- /dev/null +++ b/tests/service/data/ScriptProject/Main2.fsx @@ -0,0 +1,6 @@ +#load "Lib1.fsx" +#load "Lib2.fsx" +#load "Lib3.fs" +Lib1.add3 5 |> printfn "%i" +Lib2.add4 5 |> printfn "%i" +Lib3.add6 5 |> printfn "%i" \ No newline at end of file diff --git a/tests/service/data/ScriptProject/Main3.fsx b/tests/service/data/ScriptProject/Main3.fsx new file mode 100644 index 0000000000..8df731bd95 --- /dev/null +++ b/tests/service/data/ScriptProject/Main3.fsx @@ -0,0 +1,4 @@ +#load "Lib3.fs" +#load "Lib4.fs" +Lib3.add6 5 |> printfn "%i" +Lib4.add8 5 |> printfn "%i" diff --git a/tests/service/data/ScriptProject/Main4.fsx b/tests/service/data/ScriptProject/Main4.fsx new file mode 100644 index 0000000000..6da860748f --- /dev/null +++ b/tests/service/data/ScriptProject/Main4.fsx @@ -0,0 +1,6 @@ +#load "Lib5.fsx" +#load "Lib1.fsx" +#load "Lib2.fsx" +Lib1.add3 5 |> printfn "%i" +Lib2.add4 5 |> printfn "%i" +Lib5.add12 5 |> printfn "%i"