Skip to content

Commit

Permalink
Make sure assembly search paths for #r directives include directory o…
Browse files Browse the repository at this point in the history
…f declaring source file

fixes #273
fixes #293
closes #306

commit c81e263
Author: latkin <latkin@microsoft.com>
Date:   Tue Mar 17 12:34:06 2015 -0700

    Add keep.lst file so that shared test lib file isn't whacked immediately

commit 7c02652
Author: latkin <latkin@microsoft.com>
Date:   Tue Mar 17 10:53:46 2015 -0700

    Add comments

commit a8201de
Author: latkin <latkin@microsoft.com>
Date:   Tue Mar 17 10:49:44 2015 -0700

    Expand testing to cover FSC and other scenarios

commit f5649e7
Author: latkin <latkin@microsoft.com>
Date:   Mon Mar 16 17:56:55 2015 -0700

    Add IDE unit tests

commit 1dc3e15
Author: latkin <latkin@microsoft.com>
Date:   Mon Mar 16 16:22:58 2015 -0700

    Add tests for fsi.exe

commit 83e2576
Author: latkin <latkin@microsoft.com>
Date:   Thu Mar 12 17:44:20 2015 -0700

    Make sure assembly search paths for #r directives include directory of declaring source file

    fixes #273
    fixes #293
  • Loading branch information
latkin committed Mar 19, 2015
1 parent c2b9aa7 commit 3ed163f
Show file tree
Hide file tree
Showing 16 changed files with 237 additions and 5 deletions.
16 changes: 13 additions & 3 deletions src/fsharp/build.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#r "./lib.dll"

module Foo =
let Y = 22
do
printfn "%O" (Lib.X())
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#r "lib.dll"

module Foo =
let Y = 22
do
printfn "%O" (Lib.X())
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#r "lib.dll"

module Foo =
let Y = 22
do
printfn "%O" (Lib.X())
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#r "../lib.dll"

module Foo =
let Y = 22
do
printfn "%O" (Lib.X())
Original file line number Diff line number Diff line change
@@ -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 ;;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#r "../lib.dll"

module Foo =
let Y = 22
do
printfn "%O" (Lib.X())
Original file line number Diff line number Diff line change
@@ -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 ;;
Original file line number Diff line number Diff line change
@@ -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 ;;
Original file line number Diff line number Diff line change
@@ -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 ;;
Original file line number Diff line number Diff line change
@@ -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 ;;
61 changes: 61 additions & 0 deletions tests/fsharpqa/Source/InteractiveSession/Misc/env.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions tests/fsharpqa/Source/InteractiveSession/Misc/keep.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aaa\lib.dll
2 changes: 2 additions & 0 deletions tests/fsharpqa/Source/InteractiveSession/Misc/lib.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module Lib
let X () = 42
6 changes: 5 additions & 1 deletion tests/fsharpqa/Source/run.pl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 75 additions & 1 deletion vsintegration/src/unittests/Tests.LanguageService.Script.fs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,81 @@ type ScriptTests() as this =
let code = ["#light";"#r @\"" + fullyqualifiepathtoddll + "\""]
let (project, _) = createSingleFileFsxFromLines code
AssertNoErrorsOrWarnings(project)


[<Test>]
[<Category("fsx closure")>]
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)

[<Test>]
[<Category("fsx closure")>]
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.
[<Test>]
member public this.``Fsx.NoError.HashLoad.Simple``() =
Expand Down

0 comments on commit 3ed163f

Please # to comment.