Skip to content

Commit

Permalink
- Issue #297: No support for nested //css_imp
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-shilo committed May 14, 2022
1 parent ece3704 commit fc10963
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 19 deletions.
19 changes: 12 additions & 7 deletions src/CSScriptLib/src/CSScriptLib/Evaluator.Roslyn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,12 +329,6 @@ override protected (byte[] asm, byte[] pdb) Compile(string scriptText, string sc
if (scriptText == null && scriptFile != null)
scriptText = File.ReadAllText(scriptFile);

if (!DisableReferencingFromCode)
{
var localDir = this.GetType().Assembly.Location().GetDirName();
ReferenceAssembliesFromCode(scriptText, localDir);
}

int scriptHash = base.GetHashFor(scriptText, scriptFile);

if (IsCachingEnabled)
Expand All @@ -355,6 +349,12 @@ override protected (byte[] asm, byte[] pdb) Compile(string scriptText, string sc

if (scriptFile == null && tempScriptFile == null)
{
if (!DisableReferencingFromCode)
{
var localDir = this.GetType().Assembly.Location().GetDirName();
ReferenceAssembliesFromCode(scriptText, localDir);
}

if (this.IsDebug)
{
tempScriptFile = CSScript.GetScriptTempFile();
Expand All @@ -366,7 +366,8 @@ override protected (byte[] asm, byte[] pdb) Compile(string scriptText, string sc
}
else
{
var parser = new ScriptParser(scriptFile ?? tempScriptFile, new[] { scriptFile?.GetDirName() }, false);
var searchDirs = new[] { scriptFile?.GetDirName(), this.GetType().Assembly.Location().GetDirName() };
var parser = new ScriptParser(scriptFile ?? tempScriptFile, searchDirs, false);

var importedSources = new Dictionary<string, (int, string[])>(); // file, usings count, code lines
var combinedScript = new List<string>();
Expand Down Expand Up @@ -402,6 +403,10 @@ void add_code(string file, string[] codeLines, int lineOffset)
}

scriptText = combinedScript.JoinBy(Environment.NewLine);

if (!DisableReferencingFromCode)
foreach (var asm in ProbeAssembliesOf(parser, searchDirs))
ReferenceAssembly(asm);
}

////////////////////////////////////////
Expand Down
39 changes: 34 additions & 5 deletions src/CSScriptLib/src/CSScriptLib/EvaluatorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -495,21 +495,50 @@ T invoker(params object[] args)
/// <returns>Array of the referenced assemblies</returns>
public string[] GetReferencedAssemblies(string code, params string[] searchDirs)
{
var retval = new List<string>();
var tempScriptFile = CSScript.GetScriptTempFile();
try
{
File.WriteAllText(tempScriptFile, code);
return GetReferencedAssembliesFromScript(tempScriptFile, searchDirs);
}
finally
{
File.Delete(tempScriptFile);
}
}

/// <summary>
/// Analyses the script file code and returns set of locations for the assemblies referenced from
/// the code with CS-Script directives (//css_ref).
/// </summary>
/// <param name="scriptFile">The script file.</param>
/// <param name="searchDirs">The assembly search/probing directories.</param>
/// <returns>
/// Array of the referenced assemblies
/// </returns>
public string[] GetReferencedAssembliesFromScript(string scriptFile, params string[] searchDirs)
{
var parser = new ScriptParser(scriptFile, searchDirs.ConcatWith(new[] { scriptFile.GetDirName() }), false);
return ProbeAssembliesOf(parser, searchDirs);
}

var parser = new CSharpParser(code);
internal string[] ProbeAssembliesOf(ScriptParser parser, string[] searchDirs)
{
var retval = new List<string>();

var globalProbingDirs = CSScript.GlobalSettings.SearchDirs
.Select(Environment.ExpandEnvironmentVariables)
.Where(x => x.Any());

var dirs = searchDirs.Concat(parser.ExtraSearchDirs)
var dirs = searchDirs.Concat(parser.SearchDirs)
.Concat(globalProbingDirs)
.Where(x => x.IsNotEmpty())
.Distinct()
.ToArray();

dirs = dirs.Select(x => Path.GetFullPath(x)).Distinct().ToArray();

var asms = new List<string>(parser.RefAssemblies);
var asms = new List<string>(parser.ReferencedAssemblies);
var unresolved_asms = new List<string>();

foreach (var asm in asms)
Expand All @@ -522,7 +551,7 @@ public string[] GetReferencedAssemblies(string code, params string[] searchDirs)
}

if (!parser.IgnoreNamespaces.Any(x => x == "*"))
foreach (var asm in parser.RefNamespaces.Except(parser.IgnoreNamespaces))
foreach (var asm in parser.ReferencedNamespaces.Except(parser.IgnoreNamespaces))
foreach (string asmFile in AssemblyResolver.FindAssembly(asm, dirs))
retval.Add(asmFile);

Expand Down
4 changes: 3 additions & 1 deletion src/CSScriptLib/src/CSScriptLib/csparser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ string[] GetRawStatements(string pattern, int endIndex)
return GetRawStatements(this.code, pattern, endIndex, false);
}

public string[] GetRawStatements(string codeToAnalyze, string pattern, int endIndex, bool ignoreComments)
internal string[] GetRawStatements(string codeToAnalyze, string pattern, int endIndex, bool ignoreComments)
{
List<string> retval = new List<string>();

Expand All @@ -899,6 +899,8 @@ public string[] GetRawStatements(string codeToAnalyze, string pattern, int endIn

if (endPos != -1)
retval.Add(codeToAnalyze.Substring(pos, endPos - pos).Trim());
else
retval.Add(codeToAnalyze.Substring(pos).Trim());
}
}
pos = codeToAnalyze.IndexOf(pattern, pos + 1);
Expand Down
36 changes: 36 additions & 0 deletions src/Tests.CSScriptLib/Evaluator.Api.Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace EvaluatorTests
{
[Collection("Sequential")]
public class API_CodeDom : API_Roslyn
{
public API_CodeDom()
Expand Down Expand Up @@ -51,6 +52,7 @@ public int Sum(int a, int b)
}
}

[Collection("Sequential")]
public class API_Roslyn
{
public string GetTempFileName(string seed)
Expand Down Expand Up @@ -128,6 +130,40 @@ public class Script
Assert.Equal(10, result);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void CompileCodeWithNestedImports(bool isRoslyn)
{
var dependencyScript1 = $"dep{nameof(CompileCodeWithNestedImports)}1.cs".GetFullPath();
var dependencyScript2 = $"dep{nameof(CompileCodeWithNestedImports)}2.cs".GetFullPath();

File.WriteAllText(dependencyScript2, @"
using System;
public class Calc
{
static public int Sum(int a, int b)
{
return a+b;
}
}");

File.WriteAllText(dependencyScript1, $"//css_inc {dependencyScript2}");

var evaluator = isRoslyn ? (IEvaluator)CSScript.RoslynEvaluator : (IEvaluator)CSScript.CodeDomEvaluator;

dynamic script = evaluator.LoadCode($@"//css_inc {dependencyScript1}
using System;
public class Script
{{
public int Sum(int a, int b) => Calc.Sum(a ,b);
}}");

var result = script.Sum(7, 3);

Assert.Equal(10, result);
}

[Fact]
public void CompileCodeWithRefs()
{
Expand Down
5 changes: 5 additions & 0 deletions src/Tests.CSScriptLib/Evaluator.CodeDom.Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace EvaluatorTests
{
[Collection("Sequential")]
public class Generic_CodeDom
{
[Fact]
Expand Down Expand Up @@ -172,6 +173,10 @@ public void use_resp_file()
{
Assert.Contains("Metadata file 'Foo.dll' could not be found", e.Message);
}
finally
{
CSScript.EvaluatorConfig.CompilerOptions = "";
}
}

[Fact]
Expand Down
13 changes: 10 additions & 3 deletions src/Tests.CSScriptLib/Evaluator.Roslyn.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ public interface IPrinter

namespace EvaluatorTests
{
[Collection("Sequential")]
public class Generic_Roslyn
{
[Fact(Skip = "xUnit runtime is incompatible. But test is valid"
)]
[Fact(Skip = "xUnit runtime is incompatible. But test is valid")]
public void call_UnloadAssembly()
{
// There is something strange happening under xUnit runtime. This very test runs fine
Expand Down Expand Up @@ -301,6 +301,12 @@ public void Issue_291()
string[] statements = parser.GetRawStatements(code, "//css_include", code.Length, false);

Assert.Single(statements);

code = @"//css_inc D:\dev\Galos\cs-script\src\Tests.CSScriptLib\bin\Debug\net6.0\depCompileCodeWithNestedImports2.cs";
parser = new CSharpParser(code);
statements = parser.GetRawStatements(code, "//css_inc", code.Length, false);

Assert.Single(statements);
}

[Fact]
Expand Down Expand Up @@ -342,7 +348,7 @@ public interface ICalc
int Sum(int a, int b);
}

public interface ICalc<TResult,TParam>
public interface ICalc<TResult, TParam>
{
TResult Sum(TParam a, TParam b);
}
Expand All @@ -353,6 +359,7 @@ public Wrapped(T value)
{
Value = value;
}

public T Value { get; set; }
}
}
15 changes: 15 additions & 0 deletions src/Tests.CSScriptLib/IssuesTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.IO;
using CSScriptLib;
using Xunit;

namespace Misc
{
[Collection("Sequential")]
public class IssuesTests
{
[Fact]
public void issue_nnn()
{
}
}
}
12 changes: 9 additions & 3 deletions src/cscs/ScriptParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ public ScriptParser(string fileName, string[] searchDirs, bool throwOnError)
/// </summary>
/// <param name="fileName">Script file name</param>
/// <param name="searchDirs">Extra ScriptLibrary directory(s)</param>

void Init(string fileName, string[] searchDirs)
{
if (fileName.IsValidPath())
Expand Down Expand Up @@ -247,7 +246,7 @@ void ProcessFile(ScriptInfo fileInfo)
{
var fileComparer = new FileParserComparer();

var importedFile = new FileParser(fileInfo.fileName, fileInfo.parseParams, false, true, this.SearchDirs, throwOnError); //do not parse it yet (the third param is false)
var importedFile = new FileParser(fileInfo.fileName, fileInfo.parseParams, true, true, this.SearchDirs, throwOnError); //do not parse it yet (the third param is false)

if (fileParsers.BinarySearch(importedFile, fileComparer) < 0)
{
Expand Down Expand Up @@ -437,7 +436,14 @@ public List<string> AgregateReferences(IEnumerable<string> searchDirs, IEnumerab
var refPkAsms = this.ResolvePackages(true); //suppressDownloading

var refCodeAsms = this.ReferencedAssemblies
.SelectMany(asm => AssemblyResolver.FindAssembly(asm.Replace("\"", ""), probingDirs)).ToArray();
.SelectMany(asm =>
{
var resolved = AssemblyResolver.FindAssembly(asm.Replace("\"", ""), probingDirs);
if (resolved.Any())
return resolved;
else
return new[] { asm.GetFullPath() }; // impotrtant to return not found assembly so it is reported by the compiler
}).ToArray();

// need to add default CLR assemblies as there will be no namespace->GAC assembly
// resolving as it is .NET Core
Expand Down

0 comments on commit fc10963

Please sign in to comment.