diff --git a/src/fsharp/build.fs b/src/fsharp/build.fs index 64316ad67b7..b837d970b33 100644 --- a/src/fsharp/build.fs +++ b/src/fsharp/build.fs @@ -2705,9 +2705,19 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) = let isNetModule = String.Compare(ext,".netmodule",StringComparison.OrdinalIgnoreCase)=0 if String.Compare(ext,".dll",StringComparison.OrdinalIgnoreCase)=0 || String.Compare(ext,".exe",StringComparison.OrdinalIgnoreCase)=0 - || isNetModule then - - let resolved = TryResolveFileUsingPaths(tcConfig.SearchPathsForLibraryFiles,m,nm) + || isNetModule then + + let searchPaths = + // if this is a #r reference (not from dummy range), make sure the directory of the declaring + // file is included in the search path. This should ideally already be one of the search paths, but + // during some global checks it won't be. We append to the end of the search list so that this is the last + // place that is checked. + if m <> range0 && m <> rangeStartup && m <> rangeCmdArgs && FileSystem.IsPathRootedShim m.FileName then + tcConfig.SearchPathsForLibraryFiles @ [Path.GetDirectoryName(m.FileName)] + else + tcConfig.SearchPathsForLibraryFiles + + let resolved = TryResolveFileUsingPaths(searchPaths,m,nm) match resolved with | Some(resolved) -> let sysdir = tcConfig.IsSystemAssembly resolved diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution02_2.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution02_2.fsx new file mode 100644 index 00000000000..f3d918aa570 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution02_2.fsx @@ -0,0 +1,6 @@ +#r "./lib.dll" + +module Foo = + let Y = 22 + do + printfn "%O" (Lib.X()) \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution03_2.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution03_2.fsx new file mode 100644 index 00000000000..578317e8545 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution03_2.fsx @@ -0,0 +1,6 @@ +#r "lib.dll" + +module Foo = + let Y = 22 + do + printfn "%O" (Lib.X()) \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution05_2.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution05_2.fsx new file mode 100644 index 00000000000..578317e8545 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/RelativeHashRResolution05_2.fsx @@ -0,0 +1,6 @@ +#r "lib.dll" + +module Foo = + let Y = 22 + do + printfn "%O" (Lib.X()) \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution01_2.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution01_2.fsx new file mode 100644 index 00000000000..e2c6124fb05 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution01_2.fsx @@ -0,0 +1,6 @@ +#r "../lib.dll" + +module Foo = + let Y = 22 + do + printfn "%O" (Lib.X()) \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution04_1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution04_1.fsx new file mode 100644 index 00000000000..700b7d91be3 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution04_1.fsx @@ -0,0 +1,10 @@ +#if PIPED_FROM_TEST_DIR +#load "aaa/bbb/RelativeHashRResolution04_2.fsx" +#else +#load "RelativeHashRResolution04_2.fsx" +#endif + +printfn "%O" (Lib.X()) +printfn "%O" RelativeHashRResolution04_2.Foo.Y + +#q ;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution04_2.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution04_2.fsx new file mode 100644 index 00000000000..e2c6124fb05 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution04_2.fsx @@ -0,0 +1,6 @@ +#r "../lib.dll" + +module Foo = + let Y = 22 + do + printfn "%O" (Lib.X()) \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution05_1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution05_1.fsx new file mode 100644 index 00000000000..14f74062d39 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/aaa/bbb/RelativeHashRResolution05_1.fsx @@ -0,0 +1,10 @@ +#if PIPED_FROM_TEST_DIR +#load "./aaa/RelativeHashRResolution05_2.fsx" +#else +#load "../RelativeHashRResolution05_2.fsx" +#endif + +printfn "%O" (Lib.X()) +printfn "%O" RelativeHashRResolution05_2.Foo.Y + +#q ;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution01_1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution01_1.fsx new file mode 100644 index 00000000000..207dcbe8577 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution01_1.fsx @@ -0,0 +1,10 @@ +#if PIPED_FROM_TEST_DIR +#load "aaa/bbb/RelativeHashRResolution01_2.fsx" +#else +#load "../aaa/bbb/RelativeHashRResolution01_2.fsx" +#endif + +printfn "%O" (Lib.X()) +printfn "%O" RelativeHashRResolution01_2.Foo.Y + +#q ;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution02_1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution02_1.fsx new file mode 100644 index 00000000000..09fb3a5a8d8 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution02_1.fsx @@ -0,0 +1,10 @@ +#if PIPED_FROM_TEST_DIR +#load "./aaa/RelativeHashRResolution02_2.fsx" +#else +#load "../aaa/RelativeHashRResolution02_2.fsx" +#endif + +printfn "%O" (Lib.X()) +printfn "%O" RelativeHashRResolution02_2.Foo.Y + +#q ;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution03_1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution03_1.fsx new file mode 100644 index 00000000000..90b4f08f8b2 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/ccc/RelativeHashRResolution03_1.fsx @@ -0,0 +1,10 @@ +#if PIPED_FROM_TEST_DIR +#load "aaa/RelativeHashRResolution03_2.fsx" +#else +#load "../aaa/RelativeHashRResolution03_2.fsx" +#endif + +printfn "%O" (Lib.X()) +printfn "%O" RelativeHashRResolution03_2.Foo.Y + +#q ;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst b/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst index 815a7cfd3fe..745988a680e 100644 --- a/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst @@ -100,3 +100,64 @@ NoMT SOURCE=E_NoNoFrameworkWithFSCore.fs COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="- SOURCE="ScriptTest\\LoadScriptResolution01.fsx" SCFLAGS="--nologo" # LoadScriptResolution01.fsx - fsc SOURCE="ScriptTest\\LoadScriptResolution01.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # LoadScriptResolution01.fsx - fsi + +#### relative paths used in #r references + +# create required reference library once + SOURCE=lib.fs COMPILE_ONLY=1 SCFLAGS="--nologo -a -o aaa\\lib.dll" # RelativeHashRResolution_makelib + +# via FSI, invoking like `fsi.exe --exec path\script.fsx` + SOURCE=ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution01_exec + SOURCE=ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution02_exec + SOURCE=ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution03_exec + SOURCE=aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution04_exec + SOURCE=aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution05_exec + +# via FSI, invoking like `fsi.exe --exec ..\path\path\script.fsx` + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution01_execrelative + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution02_execrelative + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution03_execrelative + SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution04_execrelative + SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution05_execrelative + +# via FSI, invoking like `fsi.exe --exec c:\full\path\script.fsx` + SOURCE="\$CWD\\ccc\\RelativeHashRResolution01_1.fsx" COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution01_execfull + SOURCE="\$CWD\\ccc\\RelativeHashRResolution02_1.fsx" COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution02_execfull + SOURCE="\$CWD\\ccc\\RelativeHashRResolution03_1.fsx" COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution03_execfull + SOURCE="\$CWD\\aaa\\bbb\\RelativeHashRResolution04_1.fsx" COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution04_execfull + SOURCE="\$CWD\\aaa\\bbb\\RelativeHashRResolution05_1.fsx" COMPILE_ONLY=1 FSIMODE=EXEC SCFLAGS="--nologo" # RelativeHashRResolution05_execfull + +# via FSI, invoking like `fsi.exe < path\script.fsx` + SOURCE=ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo --define:PIPED_FROM_TEST_DIR" # RelativeHashRResolution01_pipe + SOURCE=ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo --define:PIPED_FROM_TEST_DIR" # RelativeHashRResolution02_pipe + SOURCE=ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo --define:PIPED_FROM_TEST_DIR" # RelativeHashRResolution03_pipe + SOURCE=aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo --define:PIPED_FROM_TEST_DIR" # RelativeHashRResolution04_pipe + SOURCE=aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo --define:PIPED_FROM_TEST_DIR" # RelativeHashRResolution05_pipe + +# via FSC, invoking like `fsc.exe path\script.fsx` + SOURCE=ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution01_fsc + SOURCE=ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution02_fsc + SOURCE=ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution03_fsc + SOURCE=aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution04_fsc + SOURCE=aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution05_fsc + +# via FSC, invoking like `fsc.exe ..\path\path\script.fsx` + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution01_fscrelative + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution02_fscrelative + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution03_fscrelative + SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution04_fscrelative + SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo" # RelativeHashRResolution05_fscrelative + +# via FSC, invoking like `fsc.exe --simpleresolution path\script.fsx` + SOURCE=ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution01_fscsimple + SOURCE=ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution02_fscsimple + SOURCE=ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution03_fscsimple + SOURCE=aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution04_fscsimple + SOURCE=aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution05_fscsimple + +# via FSC, invoking like `fsc.exe ..\path\path\script.fsx` + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution01_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution01_fscrelativesimple + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution02_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution02_fscrelativesimple + SOURCE=..\\Misc\\ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution03_fscrelativesimple + SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution04_fscrelativesimple + SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:%FSCOREDLLPATH%" # RelativeHashRResolution05_fscrelativesimple diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/keep.lst b/tests/fsharpqa/Source/InteractiveSession/Misc/keep.lst new file mode 100644 index 00000000000..e202ae12c73 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/keep.lst @@ -0,0 +1 @@ +aaa\lib.dll \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/lib.fs b/tests/fsharpqa/Source/InteractiveSession/Misc/lib.fs new file mode 100644 index 00000000000..b73bc61fb99 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/lib.fs @@ -0,0 +1,2 @@ +module Lib +let X () = 42 \ No newline at end of file diff --git a/tests/fsharpqa/Source/run.pl b/tests/fsharpqa/Source/run.pl index eb34cab5d80..9fc5366378c 100644 --- a/tests/fsharpqa/Source/run.pl +++ b/tests/fsharpqa/Source/run.pl @@ -459,8 +459,12 @@ sub RunCommand { # GetSrc -- Find the source file to build # sub GetSrc() { + my $cwd = cwd(); + # The environment SOURCE var usually defines what to compile - my $source = $ENV{SOURCE}; + $_ = $ENV{SOURCE}; + s/\$CWD/$cwd/; + my $source = $_; return($source) if defined($source); # Or if there's only one source file in the directory diff --git a/vsintegration/src/unittests/Tests.LanguageService.Script.fs b/vsintegration/src/unittests/Tests.LanguageService.Script.fs index 260e47e8288..270428f94d2 100644 --- a/vsintegration/src/unittests/Tests.LanguageService.Script.fs +++ b/vsintegration/src/unittests/Tests.LanguageService.Script.fs @@ -593,7 +593,81 @@ type ScriptTests() as this = let code = ["#light";"#r @\"" + fullyqualifiepathtoddll + "\""] let (project, _) = createSingleFileFsxFromLines code AssertNoErrorsOrWarnings(project) - + + [] + [] + member public this.``Fsx.NoError.HashR.RelativePath1``() = + use _guard = this.UsingNewVS() + let solution = this.CreateSolution() + let project = CreateProject(solution,"testproject") + let file1 = AddFileFromText(project,"lib.fs", + ["module Lib" + "let X = 42" + ]) + + let bld = Build(project) + + let script1Dir = Path.Combine(ProjectDirectory(project), "ccc") + let script1Path = Path.Combine(script1Dir, "Script1.fsx") + let script2Dir = Path.Combine(ProjectDirectory(project), "aaa\\bbb") + let script2Path = Path.Combine(script2Dir, "Script2.fsx") + + Directory.CreateDirectory(script1Dir) |> ignore + Directory.CreateDirectory(script2Dir) |> ignore + File.Move(bld.ExecutableOutput, Path.Combine(ProjectDirectory(project), "aaa\\lib.exe")) + + let script1 = File.WriteAllLines(script1Path, + ["#load \"../aaa/bbb/Script2.fsx\"" + "printfn \"%O\" Lib.X" + ]) + let script2 = File.WriteAllLines(script2Path, + ["#r \"../lib.exe\"" + ]) + + let script1 = OpenFile(project, script1Path) + TakeCoffeeBreak(this.VS) + + MoveCursorToEndOfMarker(script1,"#load") + let ans = GetSquiggleAtCursor(script1) + AssertNoSquiggle(ans) + + [] + [] + member public this.``Fsx.NoError.HashR.RelativePath2``() = + use _guard = this.UsingNewVS() + let solution = this.CreateSolution() + let project = CreateProject(solution,"testproject") + let file1 = AddFileFromText(project,"lib.fs", + ["module Lib" + "let X = 42" + ]) + + let bld = Build(project) + + let script1Dir = Path.Combine(ProjectDirectory(project), "ccc") + let script1Path = Path.Combine(script1Dir, "Script1.fsx") + let script2Dir = Path.Combine(ProjectDirectory(project), "aaa") + let script2Path = Path.Combine(script2Dir, "Script2.fsx") + + Directory.CreateDirectory(script1Dir) |> ignore + Directory.CreateDirectory(script2Dir) |> ignore + File.Move(bld.ExecutableOutput, Path.Combine(ProjectDirectory(project), "aaa\\lib.exe")) + + let script1 = File.WriteAllLines(script1Path, + ["#load \"../aaa/Script2.fsx\"" + "printfn \"%O\" Lib.X" + ]) + let script2 = File.WriteAllLines(script2Path, + ["#r \"lib.exe\"" + ]) + + let script1 = OpenFile(project, script1Path) + TakeCoffeeBreak(this.VS) + + MoveCursorToEndOfMarker(script1,"#load") + let ans = GetSquiggleAtCursor(script1) + AssertNoSquiggle(ans) + /// FEATURE: #load in an .fsx file will include that file in the 'build' of the .fsx. [] member public this.``Fsx.NoError.HashLoad.Simple``() =