提交 1ddd3243 编写于 作者: C Charles Stoner

Merge pull request #4318 from cston/r

Refactor MetadataFileReferenceResolver classes
...@@ -81,7 +81,7 @@ public void Invariants() ...@@ -81,7 +81,7 @@ public void Invariants()
TestProperty((old, value) => old.WithExtendedCustomDebugInformation(value), opt => opt.ExtendedCustomDebugInformation, false); TestProperty((old, value) => old.WithExtendedCustomDebugInformation(value), opt => opt.ExtendedCustomDebugInformation, false);
TestProperty((old, value) => old.WithXmlReferenceResolver(value), opt => opt.XmlReferenceResolver, new XmlFileResolver(null)); TestProperty((old, value) => old.WithXmlReferenceResolver(value), opt => opt.XmlReferenceResolver, new XmlFileResolver(null));
TestProperty((old, value) => old.WithMetadataReferenceResolver(value), opt => opt.MetadataReferenceResolver, new AssemblyReferenceResolver(new MetadataFileReferenceResolver(new string[0], null), new MetadataFileReferenceProvider())); TestProperty((old, value) => old.WithMetadataReferenceResolver(value), opt => opt.MetadataReferenceResolver, new AssemblyReferenceResolver(MetadataFileReferenceResolver.Default, new MetadataFileReferenceProvider()));
TestProperty((old, value) => old.WithAssemblyIdentityComparer(value), opt => opt.AssemblyIdentityComparer, new DesktopAssemblyIdentityComparer(new AssemblyPortabilityPolicy())); TestProperty((old, value) => old.WithAssemblyIdentityComparer(value), opt => opt.AssemblyIdentityComparer, new DesktopAssemblyIdentityComparer(new AssemblyPortabilityPolicy()));
TestProperty((old, value) => old.WithStrongNameProvider(value), opt => opt.StrongNameProvider, new DesktopStrongNameProvider()); TestProperty((old, value) => old.WithStrongNameProvider(value), opt => opt.StrongNameProvider, new DesktopStrongNameProvider());
} }
...@@ -347,7 +347,7 @@ private static CSharpCompilationOptions CreateCSharpCompilationOptions() ...@@ -347,7 +347,7 @@ private static CSharpCompilationOptions CreateCSharpCompilationOptions()
bool extendedCustomDebugInformation = true; bool extendedCustomDebugInformation = true;
XmlReferenceResolver xmlReferenceResolver = new XmlFileResolver(null); XmlReferenceResolver xmlReferenceResolver = new XmlFileResolver(null);
SourceReferenceResolver sourceReferenceResolver = new SourceFileResolver(ImmutableArray<string>.Empty, null); SourceReferenceResolver sourceReferenceResolver = new SourceFileResolver(ImmutableArray<string>.Empty, null);
MetadataReferenceResolver metadataReferenceResolver = new AssemblyReferenceResolver(new MetadataFileReferenceResolver(ImmutableArray<string>.Empty, null), MetadataFileReferenceProvider.Default); MetadataReferenceResolver metadataReferenceResolver = new AssemblyReferenceResolver(MetadataFileReferenceResolver.Default, MetadataFileReferenceProvider.Default);
AssemblyIdentityComparer assemblyIdentityComparer = AssemblyIdentityComparer.Default; // Currently uses reference equality AssemblyIdentityComparer assemblyIdentityComparer = AssemblyIdentityComparer.Default; // Currently uses reference equality
StrongNameProvider strongNameProvider = new DesktopStrongNameProvider(); StrongNameProvider strongNameProvider = new DesktopStrongNameProvider();
MetadataImportOptions metadataImportOptions = 0; MetadataImportOptions metadataImportOptions = 0;
......
...@@ -1587,7 +1587,7 @@ public void ReferenceManagerReuse_WithMetadataReferenceResolver() ...@@ -1587,7 +1587,7 @@ public void ReferenceManagerReuse_WithMetadataReferenceResolver()
var c1 = CSharpCompilation.Create("c", options: TestOptions.ReleaseDll); var c1 = CSharpCompilation.Create("c", options: TestOptions.ReleaseDll);
var c2 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver( var c2 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver(
new AssemblyReferenceResolver(new MetadataFileReferenceResolver(ImmutableArray.Create<string>(), null), MetadataFileReferenceProvider.Default))); new AssemblyReferenceResolver(MetadataFileReferenceResolver.Default, MetadataFileReferenceProvider.Default)));
Assert.False(c1.ReferenceManagerEquals(c2)); Assert.False(c1.ReferenceManagerEquals(c2));
......
...@@ -2621,10 +2621,12 @@ public void AddRemoveReferences() ...@@ -2621,10 +2621,12 @@ public void AddRemoveReferences()
private sealed class Resolver : TestMetadataReferenceResolver private sealed class Resolver : TestMetadataReferenceResolver
{ {
private readonly RelativePathReferenceResolver _pathResolver;
private readonly string _data, _core, _system; private readonly string _data, _core, _system;
public Resolver(string data, string core, string system) public Resolver(string data, string core, string system)
{ {
_pathResolver = RelativePathReferenceResolver.Default;
_data = data; _data = data;
_core = core; _core = core;
_system = system; _system = system;
...@@ -2644,7 +2646,7 @@ public override string ResolveReference(string reference, string baseFileName) ...@@ -2644,7 +2646,7 @@ public override string ResolveReference(string reference, string baseFileName)
return _system; return _system;
default: default:
return base.ResolveReference(reference, baseFileName); return _pathResolver.ResolveReference(reference, baseFileName);
} }
} }
} }
......
...@@ -163,7 +163,7 @@ public void ResolvePath_Order() ...@@ -163,7 +163,7 @@ public void ResolvePath_Order()
var f1 = dir1.CreateFile("f.dll").Path; var f1 = dir1.CreateFile("f.dll").Path;
var f2 = dir2.CreateFile("f.dll").Path; var f2 = dir2.CreateFile("f.dll").Path;
var resolver = new MetadataFileReferenceResolver( var resolver = new RelativePathReferenceResolver(
ImmutableArray.Create(dir1.Path, dir2.Path), ImmutableArray.Create(dir1.Path, dir2.Path),
baseDirectory: null); baseDirectory: null);
......
...@@ -390,6 +390,7 @@ ...@@ -390,6 +390,7 @@
<Compile Include="FileSystem\PathKind.cs" /> <Compile Include="FileSystem\PathKind.cs" />
<Compile Include="FileSystem\PathUtilities.cs" /> <Compile Include="FileSystem\PathUtilities.cs" />
<Compile Include="FileSystem\FileUtilities.cs" /> <Compile Include="FileSystem\FileUtilities.cs" />
<Compile Include="RelativePathReferenceResolver.cs" />
<Compile Include="PEWriter\Blob.cs" /> <Compile Include="PEWriter\Blob.cs" />
<Compile Include="PEWriter\BlobWriter.cs" /> <Compile Include="PEWriter\BlobWriter.cs" />
<Compile Include="PEWriter\BlobWriterImpl.cs" /> <Compile Include="PEWriter\BlobWriterImpl.cs" />
......
...@@ -392,14 +392,10 @@ internal ImmutableArray<DiagnosticAnalyzer> ResolveAnalyzersFromArguments(string ...@@ -392,14 +392,10 @@ internal ImmutableArray<DiagnosticAnalyzer> ResolveAnalyzersFromArguments(string
private AnalyzerFileReference ResolveAnalyzerReference(CommandLineAnalyzerReference reference, IAnalyzerAssemblyLoader analyzerLoader) private AnalyzerFileReference ResolveAnalyzerReference(CommandLineAnalyzerReference reference, IAnalyzerAssemblyLoader analyzerLoader)
{ {
string resolvedPath = FileUtilities.ResolveRelativePath(reference.FilePath, basePath: null, baseDirectory: BaseDirectory, searchPaths: ReferencePaths, fileExists: PortableShim.File.Exists); string resolvedPath = FileUtilities.ResolveRelativePath(reference.FilePath, basePath: null, baseDirectory: BaseDirectory, searchPaths: ReferencePaths, fileExists: PortableShim.File.Exists);
if (PortableShim.File.Exists(resolvedPath)) if (resolvedPath != null)
{ {
resolvedPath = FileUtilities.TryNormalizeAbsolutePath(resolvedPath); resolvedPath = FileUtilities.TryNormalizeAbsolutePath(resolvedPath);
} }
else
{
resolvedPath = null;
}
if (resolvedPath != null) if (resolvedPath != null)
{ {
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using Roslyn.Utilities; using Roslyn.Utilities;
using Microsoft.VisualStudio.Shell.Interop;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
{ {
...@@ -16,25 +15,44 @@ internal abstract partial class CommonCompiler ...@@ -16,25 +15,44 @@ internal abstract partial class CommonCompiler
/// When scripts are included into a project we don't want #r's to reference other assemblies than those /// When scripts are included into a project we don't want #r's to reference other assemblies than those
/// specified explicitly in the project references. /// specified explicitly in the project references.
/// </summary> /// </summary>
internal sealed class ExistingReferencesResolver : LoggingMetadataReferencesResolver internal sealed class ExistingReferencesResolver : MetadataFileReferenceResolver
{ {
private readonly MetadataFileReferenceResolver _resolver;
private readonly ImmutableArray<PortableExecutableReference> _availableReferences; private readonly ImmutableArray<PortableExecutableReference> _availableReferences;
private readonly AssemblyIdentityComparer _assemblyIdentityComparer; private readonly AssemblyIdentityComparer _assemblyIdentityComparer;
public ExistingReferencesResolver( public ExistingReferencesResolver(
MetadataFileReferenceResolver resolver,
ImmutableArray<PortableExecutableReference> availableReferences, ImmutableArray<PortableExecutableReference> availableReferences,
ImmutableArray<string> referencePaths, AssemblyIdentityComparer assemblyIdentityComparer)
string baseDirectory,
AssemblyIdentityComparer assemblyIdentityComparer,
TouchedFileLogger logger)
: base(referencePaths, baseDirectory, logger)
{ {
Debug.Assert(!availableReferences.Any(r => r.Properties.Kind != MetadataImageKind.Assembly)); Debug.Assert(!availableReferences.Any(r => r.Properties.Kind != MetadataImageKind.Assembly));
_resolver = resolver;
_availableReferences = availableReferences; _availableReferences = availableReferences;
_assemblyIdentityComparer = assemblyIdentityComparer; _assemblyIdentityComparer = assemblyIdentityComparer;
} }
public override ImmutableArray<string> SearchPaths
{
get { return _resolver.SearchPaths; }
}
public override string BaseDirectory
{
get { return _resolver.BaseDirectory; }
}
internal override MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths)
{
return new ExistingReferencesResolver(_resolver.WithSearchPaths(searchPaths), _availableReferences, _assemblyIdentityComparer);
}
internal override MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory)
{
return new ExistingReferencesResolver(_resolver.WithBaseDirectory(baseDirectory), _availableReferences, _assemblyIdentityComparer);
}
public override string ResolveReference(string reference, string baseFilePath) public override string ResolveReference(string reference, string baseFilePath)
{ {
if (PathUtilities.IsFilePath(reference)) if (PathUtilities.IsFilePath(reference))
...@@ -69,7 +87,7 @@ private string ResolveAssemblyName(string displayName) ...@@ -69,7 +87,7 @@ private string ResolveAssemblyName(string displayName)
/// </summary> /// </summary>
private string ResolveMetadataFile(string path, string basePath) private string ResolveMetadataFile(string path, string basePath)
{ {
var fullPath = base.ResolveReference(path, basePath); var fullPath = _resolver.ResolveReference(path, basePath);
foreach (var fileReference in _availableReferences) foreach (var fileReference in _availableReferences)
{ {
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
{ {
internal abstract partial class CommonCompiler internal abstract partial class CommonCompiler
{ {
internal class LoggingMetadataReferencesResolver : MetadataFileReferenceResolver internal sealed class LoggingMetadataReferencesResolver : MetadataFileReferenceResolver
{ {
protected readonly TouchedFileLogger logger; private readonly MetadataFileReferenceResolver _resolver;
private readonly TouchedFileLogger _logger;
public LoggingMetadataReferencesResolver(ImmutableArray<string> searchPaths, string baseDirectory, TouchedFileLogger logger) public LoggingMetadataReferencesResolver(MetadataFileReferenceResolver resolver, TouchedFileLogger logger)
: base(searchPaths, baseDirectory)
{ {
this.logger = logger; Debug.Assert(logger != null);
_resolver = resolver;
_logger = logger;
} }
protected override bool FileExists(string fullPath) public override ImmutableArray<string> SearchPaths
{ {
if (logger != null && fullPath != null) get { return _resolver.SearchPaths; }
}
public override string BaseDirectory
{
get { return _resolver.BaseDirectory; }
}
internal override MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths)
{
return new LoggingMetadataReferencesResolver(_resolver.WithSearchPaths(searchPaths), _logger);
}
internal override MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory)
{
return new LoggingMetadataReferencesResolver(_resolver.WithBaseDirectory(baseDirectory), _logger);
}
public override string ResolveReference(string reference, string baseFilePath)
{
var path = _resolver.ResolveReference(reference, baseFilePath);
if (path != null)
{ {
logger.AddRead(fullPath); _logger.AddRead(path);
} }
return path;
return base.FileExists(fullPath);
} }
} }
} }
......
...@@ -86,7 +86,7 @@ internal virtual MetadataFileReferenceProvider GetMetadataProvider() ...@@ -86,7 +86,7 @@ internal virtual MetadataFileReferenceProvider GetMetadataProvider()
internal virtual MetadataFileReferenceResolver GetExternalMetadataResolver(TouchedFileLogger touchedFiles) internal virtual MetadataFileReferenceResolver GetExternalMetadataResolver(TouchedFileLogger touchedFiles)
{ {
return new LoggingMetadataReferencesResolver(Arguments.ReferencePaths, Arguments.BaseDirectory, touchedFiles); return CreateLoggingMetadataResolver(touchedFiles);
} }
/// <summary> /// <summary>
...@@ -111,16 +111,20 @@ internal virtual MetadataFileReferenceResolver GetExternalMetadataResolver(Touch ...@@ -111,16 +111,20 @@ internal virtual MetadataFileReferenceResolver GetExternalMetadataResolver(Touch
{ {
// when compiling into an assembly (csc/vbc) we only allow #r that match references given on command line: // when compiling into an assembly (csc/vbc) we only allow #r that match references given on command line:
referenceDirectiveResolver = new ExistingReferencesResolver( referenceDirectiveResolver = new ExistingReferencesResolver(
CreateLoggingMetadataResolver(touchedFiles),
resolved.Where(r => r.Properties.Kind == MetadataImageKind.Assembly).OfType<PortableExecutableReference>().AsImmutable(), resolved.Where(r => r.Properties.Kind == MetadataImageKind.Assembly).OfType<PortableExecutableReference>().AsImmutable(),
Arguments.ReferencePaths, assemblyIdentityComparer);
Arguments.BaseDirectory,
assemblyIdentityComparer,
touchedFiles);
} }
return resolved; return resolved;
} }
private MetadataFileReferenceResolver CreateLoggingMetadataResolver(TouchedFileLogger logger)
{
MetadataFileReferenceResolver resolver = new RelativePathReferenceResolver(Arguments.ReferencePaths, Arguments.BaseDirectory);
return (logger == null) ? resolver : new LoggingMetadataReferencesResolver(resolver, logger);
}
/// <summary> /// <summary>
/// Reads content of a source file. /// Reads content of a source file.
/// </summary> /// </summary>
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
namespace Roslyn.Utilities namespace Roslyn.Utilities
{ {
...@@ -34,7 +33,7 @@ internal static class FileUtilities ...@@ -34,7 +33,7 @@ internal static class FileUtilities
/// Method that tests existence of a file. /// Method that tests existence of a file.
/// </param> /// </param>
/// <returns> /// <returns>
/// The resolved path or null if the path can't be resolved. /// The resolved path or null if the path can't be resolved or does not exist.
/// </returns> /// </returns>
internal static string ResolveRelativePath( internal static string ResolveRelativePath(
string path, string path,
...@@ -47,6 +46,7 @@ internal static class FileUtilities ...@@ -47,6 +46,7 @@ internal static class FileUtilities
Debug.Assert(searchPaths != null); Debug.Assert(searchPaths != null);
Debug.Assert(fileExists != null); Debug.Assert(fileExists != null);
string combinedPath;
var kind = PathUtilities.GetPathKind(path); var kind = PathUtilities.GetPathKind(path);
if (kind == PathKind.Relative) if (kind == PathKind.Relative)
{ {
...@@ -54,10 +54,9 @@ internal static class FileUtilities ...@@ -54,10 +54,9 @@ internal static class FileUtilities
baseDirectory = GetBaseDirectory(basePath, baseDirectory); baseDirectory = GetBaseDirectory(basePath, baseDirectory);
if (baseDirectory != null) if (baseDirectory != null)
{ {
string combinedPath = PathUtilities.CombinePathsUnchecked(baseDirectory, path); combinedPath = PathUtilities.CombinePathsUnchecked(baseDirectory, path);
Debug.Assert(PathUtilities.IsAbsolute(combinedPath)); Debug.Assert(PathUtilities.IsAbsolute(combinedPath));
if (fileExists(combinedPath))
if (fileExists == null || fileExists(combinedPath))
{ {
return combinedPath; return combinedPath;
} }
...@@ -66,10 +65,9 @@ internal static class FileUtilities ...@@ -66,10 +65,9 @@ internal static class FileUtilities
// try search paths: // try search paths:
foreach (var searchPath in searchPaths) foreach (var searchPath in searchPaths)
{ {
string combinedPath = PathUtilities.CombinePathsUnchecked(searchPath, path); combinedPath = PathUtilities.CombinePathsUnchecked(searchPath, path);
Debug.Assert(PathUtilities.IsAbsolute(combinedPath)); Debug.Assert(PathUtilities.IsAbsolute(combinedPath));
if (fileExists == null || fileExists(combinedPath)) if (fileExists(combinedPath))
{ {
return combinedPath; return combinedPath;
} }
...@@ -78,7 +76,17 @@ internal static class FileUtilities ...@@ -78,7 +76,17 @@ internal static class FileUtilities
return null; return null;
} }
return ResolveRelativePath(kind, path, basePath, baseDirectory); combinedPath = ResolveRelativePath(kind, path, basePath, baseDirectory);
if (combinedPath != null)
{
Debug.Assert(PathUtilities.IsAbsolute(combinedPath));
if (fileExists(combinedPath))
{
return combinedPath;
}
}
return null;
} }
internal static string ResolveRelativePath(string path, string baseDirectory) internal static string ResolveRelativePath(string path, string baseDirectory)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -13,43 +9,9 @@ namespace Microsoft.CodeAnalysis ...@@ -13,43 +9,9 @@ namespace Microsoft.CodeAnalysis
/// <summary> /// <summary>
/// Resolves metadata references specified in source code (#r directives). /// Resolves metadata references specified in source code (#r directives).
/// </summary> /// </summary>
internal class MetadataFileReferenceResolver internal abstract class MetadataFileReferenceResolver
{ {
public static readonly MetadataFileReferenceResolver Default = new MetadataFileReferenceResolver(ImmutableArray<string>.Empty, baseDirectory: null); internal static readonly RelativePathReferenceResolver Default = new RelativePathReferenceResolver(ImmutableArray<string>.Empty, baseDirectory: null);
private readonly ImmutableArray<string> _searchPaths;
private readonly string _baseDirectory;
/// <summary>
/// Initializes a new instance of the <see cref="MetadataFileReferenceResolver"/> class.
/// </summary>
/// <param name="searchPaths">An ordered set of fully qualified
/// paths which are searched when resolving assembly names.</param>
/// <param name="baseDirectory">Directory used when resolving relative paths.</param>
public MetadataFileReferenceResolver(ImmutableArray<string> searchPaths, string baseDirectory)
{
ValidateSearchPaths(searchPaths, "searchPaths");
if (baseDirectory != null && PathUtilities.GetPathKind(baseDirectory) != PathKind.Absolute)
{
throw ExceptionUtilities.Unreachable;
////throw new ArgumentException(CodeAnalysisResources.AbsolutePathExpected, "baseDirectory");
}
_searchPaths = searchPaths;
_baseDirectory = baseDirectory;
}
/// <summary>
/// Initializes a new instance of the <see cref="MetadataFileReferenceResolver"/> class.
/// </summary>
/// <param name="searchPaths">An ordered set of fully qualified
/// paths which are searched when resolving assembly names.</param>
/// <param name="baseDirectory">Directory used when resolving relative paths.</param>
public MetadataFileReferenceResolver(IEnumerable<string> searchPaths, string baseDirectory)
: this(searchPaths.AsImmutableOrNull(), baseDirectory)
{
}
internal static void ValidateSearchPaths(ImmutableArray<string> paths, string argName) internal static void ValidateSearchPaths(ImmutableArray<string> paths, string argName)
{ {
...@@ -59,7 +21,7 @@ internal static void ValidateSearchPaths(ImmutableArray<string> paths, string ar ...@@ -59,7 +21,7 @@ internal static void ValidateSearchPaths(ImmutableArray<string> paths, string ar
////throw new ArgumentNullException(argName); ////throw new ArgumentNullException(argName);
} }
if (paths.Any(path => !PathUtilities.IsAbsolute(path))) if (!paths.All(PathUtilities.IsAbsolute))
{ {
throw ExceptionUtilities.Unreachable; throw ExceptionUtilities.Unreachable;
////throw new ArgumentException(CodeAnalysisResources.AbsolutePathExpected, argName); ////throw new ArgumentException(CodeAnalysisResources.AbsolutePathExpected, argName);
...@@ -72,9 +34,9 @@ internal static void ValidateSearchPaths(ImmutableArray<string> paths, string ar ...@@ -72,9 +34,9 @@ internal static void ValidateSearchPaths(ImmutableArray<string> paths, string ar
/// <remarks> /// <remarks>
/// All search paths are absolute. /// All search paths are absolute.
/// </remarks> /// </remarks>
public ImmutableArray<string> SearchPaths public abstract ImmutableArray<string> SearchPaths
{ {
get { return _searchPaths; } get;
} }
/// <summary> /// <summary>
...@@ -89,11 +51,15 @@ public ImmutableArray<string> SearchPaths ...@@ -89,11 +51,15 @@ public ImmutableArray<string> SearchPaths
/// ///
/// Resolution of a relative path that needs the base directory fails if the base directory is null. /// Resolution of a relative path that needs the base directory fails if the base directory is null.
/// </remarks> /// </remarks>
public string BaseDirectory public abstract string BaseDirectory
{ {
get { return _baseDirectory; } get;
} }
internal abstract MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths);
internal abstract MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory);
/// <summary> /// <summary>
/// Resolves a metadata reference that is a path or an assembly name. /// Resolves a metadata reference that is a path or an assembly name.
/// </summary> /// </summary>
...@@ -105,52 +71,6 @@ public string BaseDirectory ...@@ -105,52 +71,6 @@ public string BaseDirectory
/// <returns> /// <returns>
/// Normalized absolute path to the referenced file or null if it can't be resolved. /// Normalized absolute path to the referenced file or null if it can't be resolved.
/// </returns> /// </returns>
public virtual string ResolveReference(string reference, string baseFilePath) public abstract string ResolveReference(string reference, string baseFilePath);
{
string resolvedPath = FileUtilities.ResolveRelativePath(reference, baseFilePath, _baseDirectory, _searchPaths, FileExists);
if (!FileExists(resolvedPath))
{
return null;
}
return FileUtilities.TryNormalizeAbsolutePath(resolvedPath);
}
internal string ResolveReferenceChecked(string reference, string baseFilePath)
{
string fullPath = ResolveReference(reference, baseFilePath);
if (fullPath != null && !PathUtilities.IsAbsolute(fullPath))
{
throw ExceptionUtilities.Unreachable;
//// throw new InvalidOperationException(string.Format(CodeAnalysisResources.PathReturnedByResolveMetadataFileMustBeAbsolute, GetType().FullName, fullPath));
}
return fullPath;
}
protected virtual bool FileExists(string fullPath)
{
Debug.Assert(fullPath == null || PathUtilities.IsAbsolute(fullPath));
return PortableShim.File.Exists(fullPath);
}
public override bool Equals(object obj)
{
// Explicitly check that we're not comparing against a derived type
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var other = (MetadataFileReferenceResolver)obj;
return string.Equals(_baseDirectory, other._baseDirectory, StringComparison.Ordinal) &&
_searchPaths.SequenceEqual(other._searchPaths, StringComparer.Ordinal);
}
public override int GetHashCode()
{
return Hash.Combine(_baseDirectory != null ? StringComparer.Ordinal.GetHashCode(_baseDirectory) : 0,
Hash.CombineValues(_searchPaths, StringComparer.Ordinal));
}
} }
} }
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis
{
internal sealed class RelativePathReferenceResolver : MetadataFileReferenceResolver
{
private readonly ImmutableArray<string> _searchPaths;
private readonly string _baseDirectory;
private readonly Func<string, bool> _fileExists;
/// <summary>
/// Initializes a new instance of the <see cref="RelativePathReferenceResolver"/> class.
/// </summary>
/// <param name="searchPaths">An ordered set of fully qualified
/// paths which are searched when resolving assembly names.</param>
/// <param name="baseDirectory">Directory used when resolving relative paths.</param>
/// <param name="fileExists">Method that tests existence of a file.</param>
public RelativePathReferenceResolver(ImmutableArray<string> searchPaths, string baseDirectory, Func<string, bool> fileExists = null)
{
ValidateSearchPaths(searchPaths, "searchPaths");
if (baseDirectory != null && PathUtilities.GetPathKind(baseDirectory) != PathKind.Absolute)
{
throw ExceptionUtilities.Unreachable;
////throw new ArgumentException(CodeAnalysisResources.AbsolutePathExpected, "baseDirectory");
}
_searchPaths = searchPaths;
_baseDirectory = baseDirectory;
_fileExists = fileExists ?? FileExists;
}
public override ImmutableArray<string> SearchPaths
{
get { return _searchPaths; }
}
public override string BaseDirectory
{
get { return _baseDirectory; }
}
internal override MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths)
{
return new RelativePathReferenceResolver(searchPaths, _baseDirectory, _fileExists);
}
internal override MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory)
{
return new RelativePathReferenceResolver(_searchPaths, baseDirectory, _fileExists);
}
public override string ResolveReference(string reference, string baseFilePath)
{
string resolvedPath = FileUtilities.ResolveRelativePath(reference, baseFilePath, _baseDirectory, _searchPaths, _fileExists);
if (resolvedPath == null)
{
return null;
}
return FileUtilities.TryNormalizeAbsolutePath(resolvedPath);
}
private static bool FileExists(string fullPath)
{
Debug.Assert(fullPath != null);
Debug.Assert(PathUtilities.IsAbsolute(fullPath));
return PortableShim.File.Exists(fullPath);
}
public override bool Equals(object obj)
{
var other = obj as RelativePathReferenceResolver;
return (other != null) &&
string.Equals(_baseDirectory, other._baseDirectory, StringComparison.Ordinal) &&
_searchPaths.SequenceEqual(other._searchPaths, StringComparer.Ordinal);
}
public override int GetHashCode()
{
return Hash.Combine(_baseDirectory != null ? StringComparer.Ordinal.GetHashCode(_baseDirectory) : 0,
Hash.CombineValues(_searchPaths, StringComparer.Ordinal));
}
}
}
...@@ -59,8 +59,7 @@ public override string NormalizePath(string path, string baseFilePath) ...@@ -59,8 +59,7 @@ public override string NormalizePath(string path, string baseFilePath)
public override string ResolveReference(string path, string baseFilePath) public override string ResolveReference(string path, string baseFilePath)
{ {
string resolvedPath = FileUtilities.ResolveRelativePath(path, baseFilePath, _baseDirectory, _searchPaths, FileExists); string resolvedPath = FileUtilities.ResolveRelativePath(path, baseFilePath, _baseDirectory, _searchPaths, FileExists);
if (resolvedPath == null)
if (!FileExists(resolvedPath))
{ {
return null; return null;
} }
......
...@@ -44,7 +44,7 @@ private static bool CheckCore(string baseDirectory, IEnumerable<CommandLineAnaly ...@@ -44,7 +44,7 @@ private static bool CheckCore(string baseDirectory, IEnumerable<CommandLineAnaly
foreach (var analyzerReference in analyzerReferences) foreach (var analyzerReference in analyzerReferences)
{ {
string resolvedPath = FileUtilities.ResolveRelativePath(analyzerReference.FilePath, basePath: null, baseDirectory: baseDirectory, searchPaths: SpecializedCollections.EmptyEnumerable<string>(), fileExists: File.Exists); string resolvedPath = FileUtilities.ResolveRelativePath(analyzerReference.FilePath, basePath: null, baseDirectory: baseDirectory, searchPaths: SpecializedCollections.EmptyEnumerable<string>(), fileExists: File.Exists);
if (File.Exists(resolvedPath)) if (resolvedPath != null)
{ {
resolvedPath = FileUtilities.TryNormalizeAbsolutePath(resolvedPath); resolvedPath = FileUtilities.TryNormalizeAbsolutePath(resolvedPath);
if (resolvedPath != null) if (resolvedPath != null)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.CodeAnalysis;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Scripting namespace Microsoft.CodeAnalysis.Scripting
...@@ -14,7 +12,7 @@ namespace Microsoft.CodeAnalysis.Scripting ...@@ -14,7 +12,7 @@ namespace Microsoft.CodeAnalysis.Scripting
/// Extends MetadataFileReferenceResolver to enable resolution of assembly /// Extends MetadataFileReferenceResolver to enable resolution of assembly
/// simple names in the GAC. /// simple names in the GAC.
/// </summary> /// </summary>
internal sealed class GacFileResolver : MetadataFileReferenceResolver internal sealed class GacFileResolver
{ {
private readonly ImmutableArray<ProcessorArchitecture> _architectures; private readonly ImmutableArray<ProcessorArchitecture> _architectures;
private readonly CultureInfo _preferredCulture; private readonly CultureInfo _preferredCulture;
...@@ -23,27 +21,19 @@ internal sealed class GacFileResolver : MetadataFileReferenceResolver ...@@ -23,27 +21,19 @@ internal sealed class GacFileResolver : MetadataFileReferenceResolver
/// A resolver that is configured to resolve against the GAC associated /// A resolver that is configured to resolve against the GAC associated
/// with the bitness of the currently executing process. /// with the bitness of the currently executing process.
/// </summary> /// </summary>
internal new static GacFileResolver Default = new GacFileResolver( internal static GacFileResolver Default = new GacFileResolver(
assemblySearchPaths: ImmutableArray<string>.Empty,
baseDirectory: null,
architectures: GlobalAssemblyCache.CurrentArchitectures, architectures: GlobalAssemblyCache.CurrentArchitectures,
preferredCulture: null); preferredCulture: null);
/// <summary> /// <summary>
/// Constructs an instance of a <see cref="GacFileResolver"/> /// Constructs an instance of a <see cref="GacFileResolver"/>
/// </summary> /// </summary>
/// <param name="assemblySearchPaths">An ordered set of fully qualified
/// paths which are searched when resolving assembly names.</param>
/// <param name="baseDirectory">Directory used when resolving relative paths.</param>
/// <param name="architectures">Supported architectures used to filter GAC assemblies.</param> /// <param name="architectures">Supported architectures used to filter GAC assemblies.</param>
/// <param name="preferredCulture">A culture to use when choosing the best assembly from /// <param name="preferredCulture">A culture to use when choosing the best assembly from
/// among the set filtered by <paramref name="architectures"/></param> /// among the set filtered by <paramref name="architectures"/></param>
public GacFileResolver( public GacFileResolver(
IEnumerable<string> assemblySearchPaths,
string baseDirectory,
ImmutableArray<ProcessorArchitecture> architectures, ImmutableArray<ProcessorArchitecture> architectures,
CultureInfo preferredCulture) CultureInfo preferredCulture)
: base(assemblySearchPaths, baseDirectory)
{ {
_architectures = architectures; _architectures = architectures;
_preferredCulture = preferredCulture; _preferredCulture = preferredCulture;
...@@ -65,34 +55,29 @@ public CultureInfo PreferredCulture ...@@ -65,34 +55,29 @@ public CultureInfo PreferredCulture
get { return _preferredCulture; } get { return _preferredCulture; }
} }
public override string ResolveReference(string reference, string baseFilePath) public string ResolveReference(string reference)
{ {
if (PathUtilities.IsFilePath(reference)) if (PathUtilities.IsFilePath(reference))
{ {
return base.ResolveReference(reference, baseFilePath); return null;
} }
string path; string path;
GlobalAssemblyCache.ResolvePartialName(reference, out path, _architectures, this.PreferredCulture); GlobalAssemblyCache.ResolvePartialName(reference, out path, _architectures, this.PreferredCulture);
return FileExists(path) ? path : null; return (path != null && PortableShim.File.Exists(path)) ? path : null;
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (!base.Equals(obj)) var other = obj as GacFileResolver;
{ return (other != null) &&
return false; _architectures.SequenceEqual(other._architectures) &&
}
var other = (GacFileResolver)obj;
return _architectures.SequenceEqual(other._architectures) &&
_preferredCulture == other._preferredCulture; _preferredCulture == other._preferredCulture;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return Hash.Combine(base.GetHashCode(), return Hash.Combine(_preferredCulture, Hash.CombineValues(_architectures));
Hash.Combine(_preferredCulture, Hash.CombineValues(_architectures)));
} }
} }
} }
...@@ -1439,7 +1439,7 @@ End Class ...@@ -1439,7 +1439,7 @@ End Class
Dim c1 = VisualBasicCompilation.Create("c", options:=TestOptions.ReleaseDll) Dim c1 = VisualBasicCompilation.Create("c", options:=TestOptions.ReleaseDll)
Dim c2 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver( Dim c2 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver(
New AssemblyReferenceResolver(New MetadataFileReferenceResolver(ImmutableArray.Create(Of String)(), Nothing), MetadataFileReferenceProvider.Default))) New AssemblyReferenceResolver(MetadataFileReferenceResolver.Default, MetadataFileReferenceProvider.Default)))
Assert.False(c1.ReferenceManagerEquals(c2)) Assert.False(c1.ReferenceManagerEquals(c2))
Dim c3 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver(c1.Options.MetadataReferenceResolver)) Dim c3 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver(c1.Options.MetadataReferenceResolver))
......
...@@ -78,7 +78,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests ...@@ -78,7 +78,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
TestProperty(Function(old, value) old.WithXmlReferenceResolver(value), Function(opt) opt.XmlReferenceResolver, New XmlFileResolver(Nothing)) TestProperty(Function(old, value) old.WithXmlReferenceResolver(value), Function(opt) opt.XmlReferenceResolver, New XmlFileResolver(Nothing))
TestProperty(Function(old, value) old.WithSourceReferenceResolver(value), Function(opt) opt.SourceReferenceResolver, New SourceFileResolver(ImmutableArray(Of String).Empty, Nothing)) TestProperty(Function(old, value) old.WithSourceReferenceResolver(value), Function(opt) opt.SourceReferenceResolver, New SourceFileResolver(ImmutableArray(Of String).Empty, Nothing))
TestProperty(Function(old, value) old.WithMetadataReferenceResolver(value), Function(opt) opt.MetadataReferenceResolver, New AssemblyReferenceResolver(New MetadataFileReferenceResolver({}, Nothing), New MetadataFileReferenceProvider())) TestProperty(Function(old, value) old.WithMetadataReferenceResolver(value), Function(opt) opt.MetadataReferenceResolver, New AssemblyReferenceResolver(MetadataFileReferenceResolver.Default, New MetadataFileReferenceProvider()))
TestProperty(Function(old, value) old.WithAssemblyIdentityComparer(value), Function(opt) opt.AssemblyIdentityComparer, New DesktopAssemblyIdentityComparer(New AssemblyPortabilityPolicy())) TestProperty(Function(old, value) old.WithAssemblyIdentityComparer(value), Function(opt) opt.AssemblyIdentityComparer, New DesktopAssemblyIdentityComparer(New AssemblyPortabilityPolicy()))
TestProperty(Function(old, value) old.WithStrongNameProvider(value), Function(opt) opt.StrongNameProvider, New DesktopStrongNameProvider()) TestProperty(Function(old, value) old.WithStrongNameProvider(value), Function(opt) opt.StrongNameProvider, New DesktopStrongNameProvider())
End Sub End Sub
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
...@@ -712,7 +713,7 @@ public void TestWithReferenceDirective() ...@@ -712,7 +713,7 @@ public void TestWithReferenceDirective()
Expression", Expression",
parseOptions: GetScriptOptions(), parseOptions: GetScriptOptions(),
compilationOptions: TestOptions.ReleaseDll.WithMetadataReferenceResolver(new AssemblyReferenceResolver(new MetadataFileReferenceResolver(Array.Empty<string>(), null), MetadataFileReferenceProvider.Default)), compilationOptions: TestOptions.ReleaseDll.WithMetadataReferenceResolver(new AssemblyReferenceResolver(MetadataFileReferenceResolver.Default, MetadataFileReferenceProvider.Default)),
compareTokens: false); compareTokens: false);
} }
......
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.FileSystem;
using Microsoft.CodeAnalysis.Editor.Implementation.Interactive; using Microsoft.CodeAnalysis.Editor.Implementation.Interactive;
using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Interactive; using Microsoft.CodeAnalysis.Interactive;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Text.Classification;
...@@ -24,10 +26,10 @@ ...@@ -24,10 +26,10 @@
using Microsoft.VisualStudio.Utilities; using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.InteractiveWindow; using Microsoft.VisualStudio.InteractiveWindow;
using Microsoft.VisualStudio.InteractiveWindow.Commands; using Microsoft.VisualStudio.InteractiveWindow.Commands;
using Microsoft.CodeAnalysis.Scripting;
using Roslyn.Utilities; using Roslyn.Utilities;
using DesktopMetadataReferenceResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.DesktopMetadataReferenceResolver;
using GacFileResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.GacFileResolver; using GacFileResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.GacFileResolver;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.FileSystem; using NuGetPackageResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.NuGetPackageResolver;
namespace Microsoft.CodeAnalysis.Editor.Interactive namespace Microsoft.CodeAnalysis.Editor.Interactive
{ {
...@@ -45,7 +47,7 @@ public abstract class InteractiveEvaluator : IInteractiveEvaluator, ICurrentWork ...@@ -45,7 +47,7 @@ public abstract class InteractiveEvaluator : IInteractiveEvaluator, ICurrentWork
private readonly InteractiveWorkspace _workspace; private readonly InteractiveWorkspace _workspace;
private IInteractiveWindow _currentWindow; private IInteractiveWindow _currentWindow;
private ImmutableHashSet<MetadataReference> _references; private ImmutableHashSet<MetadataReference> _references;
private GacFileResolver _metadataReferenceResolver; private MetadataFileReferenceResolver _metadataReferenceResolver;
private ImmutableArray<string> _sourceSearchPaths; private ImmutableArray<string> _sourceSearchPaths;
private ProjectId _previousSubmissionProjectId; private ProjectId _previousSubmissionProjectId;
...@@ -201,12 +203,7 @@ private void ProcessStarting(InteractiveHostOptions options) ...@@ -201,12 +203,7 @@ private void ProcessStarting(InteractiveHostOptions options)
referencePaths = rspArguments.ReferencePaths; referencePaths = rspArguments.ReferencePaths;
// the base directory for references specified in the .rsp file is the .rsp file directory: // the base directory for references specified in the .rsp file is the .rsp file directory:
var rspMetadataReferenceResolver = new GacFileResolver( var rspMetadataReferenceResolver = CreateFileResolver(referencePaths, rspArguments.BaseDirectory);
referencePaths,
baseDirectory: rspArguments.BaseDirectory,
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: System.Globalization.CultureInfo.CurrentCulture); // TODO (tomat)
var metadataProvider = metadataService.GetProvider(); var metadataProvider = metadataService.GetProvider();
// ignore unresolved references, they will be reported in the interactive window: // ignore unresolved references, they will be reported in the interactive window:
...@@ -234,12 +231,7 @@ private void ProcessStarting(InteractiveHostOptions options) ...@@ -234,12 +231,7 @@ private void ProcessStarting(InteractiveHostOptions options)
} }
// reset search paths, working directory: // reset search paths, working directory:
_metadataReferenceResolver = new GacFileResolver( _metadataReferenceResolver = CreateFileResolver(referencePaths, _initialWorkingDirectory);
referencePaths,
baseDirectory: _initialWorkingDirectory,
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: System.Globalization.CultureInfo.CurrentCulture); // TODO (tomat)
_sourceSearchPaths = InteractiveHost.Service.DefaultSourceSearchPaths; _sourceSearchPaths = InteractiveHost.Service.DefaultSourceSearchPaths;
// create the first submission project in the workspace after reset: // create the first submission project in the workspace after reset:
...@@ -254,6 +246,16 @@ private Dispatcher Dispatcher ...@@ -254,6 +246,16 @@ private Dispatcher Dispatcher
get { return ((FrameworkElement)GetInteractiveWindow().TextView).Dispatcher; } get { return ((FrameworkElement)GetInteractiveWindow().TextView).Dispatcher; }
} }
private static MetadataFileReferenceResolver CreateFileResolver(ImmutableArray<string> referencePaths, string baseDirectory)
{
return new DesktopMetadataReferenceResolver(
new RelativePathReferenceResolver(referencePaths, baseDirectory),
NuGetPackageResolver.Instance,
new GacFileResolver(
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: System.Globalization.CultureInfo.CurrentCulture)); // TODO (tomat)
}
#endregion #endregion
#region Workspace #region Workspace
...@@ -563,11 +565,9 @@ public void UpdateLocalPaths(string[] newReferenceSearchPaths, string[] newSourc ...@@ -563,11 +565,9 @@ public void UpdateLocalPaths(string[] newReferenceSearchPaths, string[] newSourc
var changed = false; var changed = false;
if (newReferenceSearchPaths != null || newBaseDirectory != null) if (newReferenceSearchPaths != null || newBaseDirectory != null)
{ {
_metadataReferenceResolver = new GacFileResolver( _metadataReferenceResolver = CreateFileResolver(
(newReferenceSearchPaths == null) ? _metadataReferenceResolver.SearchPaths : newReferenceSearchPaths.AsImmutable(), (newReferenceSearchPaths == null) ? _metadataReferenceResolver.SearchPaths : newReferenceSearchPaths.AsImmutable(),
baseDirectory: newBaseDirectory ?? _metadataReferenceResolver.BaseDirectory, newBaseDirectory ?? _metadataReferenceResolver.BaseDirectory);
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: System.Globalization.CultureInfo.CurrentCulture); // TODO (tomat)
changed = true; changed = true;
} }
......
...@@ -69,6 +69,16 @@ internal TaskResult(ScriptOptions options, ScriptState<object> state) ...@@ -69,6 +69,16 @@ internal TaskResult(ScriptOptions options, ScriptState<object> state)
this.Options = options; this.Options = options;
this.State = state; this.State = state;
} }
internal TaskResult With(ScriptOptions options)
{
return new TaskResult(options, State);
}
internal TaskResult With(ScriptState<object> state)
{
return new TaskResult(Options, state);
}
} }
private static readonly ImmutableArray<string> s_systemNoShadowCopyDirectories = ImmutableArray.Create( private static readonly ImmutableArray<string> s_systemNoShadowCopyDirectories = ImmutableArray.Create(
...@@ -299,7 +309,6 @@ private static string GenerateUniqueChannelLocalName() ...@@ -299,7 +309,6 @@ private static string GenerateUniqueChannelLocalName()
{ {
var result = await ReportUnhandledExceptionIfAny(lastTask).ConfigureAwait(false); var result = await ReportUnhandledExceptionIfAny(lastTask).ConfigureAwait(false);
var options = result.Options; var options = result.Options;
var state = result.State;
try try
{ {
Directory.SetCurrentDirectory(baseDirectory); Directory.SetCurrentDirectory(baseDirectory);
...@@ -316,7 +325,7 @@ private static string GenerateUniqueChannelLocalName() ...@@ -316,7 +325,7 @@ private static string GenerateUniqueChannelLocalName()
{ {
operation.Completed(null); operation.Completed(null);
} }
return new TaskResult(options, state); return result.With(options);
} }
/// <summary> /// <summary>
...@@ -365,7 +374,6 @@ private async Task<TaskResult> AddReferenceAsync(Task<TaskResult> lastTask, Remo ...@@ -365,7 +374,6 @@ private async Task<TaskResult> AddReferenceAsync(Task<TaskResult> lastTask, Remo
var result = await ReportUnhandledExceptionIfAny(lastTask).ConfigureAwait(false); var result = await ReportUnhandledExceptionIfAny(lastTask).ConfigureAwait(false);
var success = false; var success = false;
var options = result.Options; var options = result.Options;
var state = result.State;
try try
{ {
string fullPath = ResolveReferencePath(options, reference, baseFilePath: null); string fullPath = ResolveReferencePath(options, reference, baseFilePath: null);
...@@ -386,7 +394,7 @@ private async Task<TaskResult> AddReferenceAsync(Task<TaskResult> lastTask, Remo ...@@ -386,7 +394,7 @@ private async Task<TaskResult> AddReferenceAsync(Task<TaskResult> lastTask, Remo
{ {
operation.Completed(success); operation.Completed(success);
} }
return new TaskResult(options, state); return result.With(options);
} }
/// <summary> /// <summary>
...@@ -505,7 +513,7 @@ private TaskResult CompleteExecution(TaskResult result, RemoteAsyncOperation<Rem ...@@ -505,7 +513,7 @@ private TaskResult CompleteExecution(TaskResult result, RemoteAsyncOperation<Rem
options = options.WithBaseDirectory(currentDirectory); options = options.WithBaseDirectory(currentDirectory);
operation.Completed(new RemoteExecutionResult(success, newSourcePaths, newReferencePaths, newWorkingDirectory, resolvedPath)); operation.Completed(new RemoteExecutionResult(success, newSourcePaths, newReferencePaths, newWorkingDirectory, resolvedPath));
return new TaskResult(options, result.State); return result.With(options);
} }
private static async Task<TaskResult> ReportUnhandledExceptionIfAny(Task<TaskResult> lastTask) private static async Task<TaskResult> ReportUnhandledExceptionIfAny(Task<TaskResult> lastTask)
...@@ -574,7 +582,8 @@ public void SetTestObjectFormattingOptions() ...@@ -574,7 +582,8 @@ public void SetTestObjectFormattingOptions()
// The base directory for relative paths is the directory that contains the .rsp file. // The base directory for relative paths is the directory that contains the .rsp file.
// Note that .rsp files included by this .rsp file will share the base directory (Dev10 behavior of csc/vbc). // Note that .rsp files included by this .rsp file will share the base directory (Dev10 behavior of csc/vbc).
var args = parser.Parse(new[] { "@" + initializationFileOpt }, Path.GetDirectoryName(initializationFileOpt), RuntimeEnvironment.GetRuntimeDirectory(), null /* TODO: pass a valid value*/); var rspDirectory = Path.GetDirectoryName(initializationFileOpt);
var args = parser.Parse(new[] { "@" + initializationFileOpt }, rspDirectory, RuntimeEnvironment.GetRuntimeDirectory(), null /* TODO: pass a valid value*/);
foreach (var error in args.Errors) foreach (var error in args.Errors)
{ {
...@@ -586,6 +595,10 @@ public void SetTestObjectFormattingOptions() ...@@ -586,6 +595,10 @@ public void SetTestObjectFormattingOptions()
{ {
// TODO (tomat): other arguments // TODO (tomat): other arguments
// TODO (tomat): parse options // TODO (tomat): parse options
var referencePaths = args.ReferencePaths;
result = result.With(result.Options.AddSearchPaths(referencePaths));
_hostObject.ReferencePaths.Clear();
_hostObject.ReferencePaths.AddRange(referencePaths);
// TODO (tomat): consolidate with other reference resolving // TODO (tomat): consolidate with other reference resolving
foreach (CommandLineReference cmdLineReference in args.MetadataReferences) foreach (CommandLineReference cmdLineReference in args.MetadataReferences)
...@@ -596,10 +609,9 @@ public void SetTestObjectFormattingOptions() ...@@ -596,10 +609,9 @@ public void SetTestObjectFormattingOptions()
var options = result.Options; var options = result.Options;
string fullPath = ResolveReferencePath(options, cmdLineReference.Reference, baseFilePath: null); string fullPath = ResolveReferencePath(options, cmdLineReference.Reference, baseFilePath: null);
LoadReference(fullPath, suppressWarnings: true, addReference: true, options: ref options); LoadReference(fullPath, suppressWarnings: true, addReference: true, options: ref options);
result = new TaskResult(options, result.State); result = result.With(options);
} }
var rspDirectory = Path.GetDirectoryName(initializationFileOpt);
foreach (CommandLineSourceFile file in args.SourceFiles) foreach (CommandLineSourceFile file in args.SourceFiles)
{ {
// execute all files as scripts (matches csi/vbi semantics) // execute all files as scripts (matches csi/vbi semantics)
...@@ -703,14 +715,13 @@ public SerializableAssemblyLoadResult LoadReferenceThrowing(string reference, bo ...@@ -703,14 +715,13 @@ public SerializableAssemblyLoadResult LoadReferenceThrowing(string reference, bo
{ {
var result = ReportUnhandledExceptionIfAny(_lastTask).Result; var result = ReportUnhandledExceptionIfAny(_lastTask).Result;
var options = result.Options; var options = result.Options;
var state = result.State;
var fullPath = ResolveReferencePath(options, reference, baseFilePath: null); var fullPath = ResolveReferencePath(options, reference, baseFilePath: null);
if (fullPath == null) if (fullPath == null)
{ {
throw new FileNotFoundException(message: null, fileName: reference); throw new FileNotFoundException(message: null, fileName: reference);
} }
var loadResult = LoadFromPathThrowing(fullPath, addReference, ref options); var loadResult = LoadFromPathThrowing(fullPath, addReference, ref options);
_lastTask = Task.FromResult(new TaskResult(options, state)); _lastTask = Task.FromResult(result.With(options));
return loadResult; return loadResult;
} }
} }
...@@ -874,12 +885,11 @@ private async Task<ExecuteResult> ExecuteOnUIThread(TaskResult result, Script<ob ...@@ -874,12 +885,11 @@ private async Task<ExecuteResult> ExecuteOnUIThread(TaskResult result, Script<ob
{ {
try try
{ {
var options = result.Options;
var state = result.State; var state = result.State;
var globals = state ?? (object)_hostObject; var globals = state ?? (object)_hostObject;
state = script.RunAsync(globals, CancellationToken.None); state = script.RunAsync(globals, CancellationToken.None);
var value = await state.ReturnValue.ConfigureAwait(false); var value = await state.ReturnValue.ConfigureAwait(false);
return new ExecuteResult(new TaskResult(options, state), value, null, true); return new ExecuteResult(result.With(state), value, null, true);
} }
catch (Exception e) catch (Exception e)
{ {
......
...@@ -45,7 +45,7 @@ public InteractiveHostTests() ...@@ -45,7 +45,7 @@ public InteractiveHostTests()
remoteService.SetTestObjectFormattingOptions(); remoteService.SetTestObjectFormattingOptions();
// assert and remove logo: // assert and remove logo:
var output = ReadOutputToEnd().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); var output = SplitLines(ReadOutputToEnd());
var errorOutput = ReadErrorOutputToEnd(); var errorOutput = ReadErrorOutputToEnd();
Assert.Equal("", errorOutput); Assert.Equal("", errorOutput);
...@@ -153,13 +153,8 @@ private class CompiledFile ...@@ -153,13 +153,8 @@ private class CompiledFile
public ImmutableArray<byte> Image; public ImmutableArray<byte> Image;
} }
private CompiledFile CompileLibrary(TempDirectory dir, string fileName, string assemblyName, string source, params MetadataReference[] references) private static CompiledFile CompileLibrary(TempDirectory dir, string fileName, string assemblyName, string source, params MetadataReference[] references)
{ {
const string Prefix = "RoslynTestFile_";
fileName = Prefix + fileName;
assemblyName = Prefix + assemblyName;
var file = dir.CreateFile(fileName); var file = dir.CreateFile(fileName);
var compilation = CreateCompilation( var compilation = CreateCompilation(
new[] { source }, new[] { source },
...@@ -742,7 +737,7 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity() ...@@ -742,7 +737,7 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity()
//// var task = Host.InitializeContextAsync(rspFile.Path, isRestarting: false, killProcess: true); //// var task = Host.InitializeContextAsync(rspFile.Path, isRestarting: false, killProcess: true);
//// task.Wait(); //// task.Wait();
//// var output = ReadOutputToEnd().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); //// var output = SplitLines(ReadOutputToEnd());
//// var errorOutput = ReadErrorOutputToEnd(); //// var errorOutput = ReadErrorOutputToEnd();
//// Assert.Equal(4, output.Length); //// Assert.Equal(4, output.Length);
...@@ -755,7 +750,7 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity() ...@@ -755,7 +750,7 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity()
//// Host.InitializeContextAsync(rspFile.Path).Wait(); //// Host.InitializeContextAsync(rspFile.Path).Wait();
//// output = ReadOutputToEnd().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); //// output = SplitLines(ReadOutputToEnd());
//// errorOutput = ReadErrorOutputToEnd(); //// errorOutput = ReadErrorOutputToEnd();
//// Assert.True(2 == output.Length, "Output is: '" + string.Join("<NewLine>", output) + "'. Expecting 2 lines."); //// Assert.True(2 == output.Length, "Output is: '" + string.Join("<NewLine>", output) + "'. Expecting 2 lines.");
...@@ -793,7 +788,7 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity() ...@@ -793,7 +788,7 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity()
//// var errorOutput = ReadErrorOutputToEnd(); //// var errorOutput = ReadErrorOutputToEnd();
//// Assert.Equal("", errorOutput); //// Assert.Equal("", errorOutput);
//// var output = ReadOutputToEnd().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); //// var output = SplitLines(ReadOutputToEnd());
//// Assert.Equal(4, output.Length); //// Assert.Equal(4, output.Length);
//// Assert.Equal("Microsoft (R) Roslyn C# Compiler version " + FileVersionInfo.GetVersionInfo(Host.GetType().Assembly.Location).FileVersion, output[0]); //// Assert.Equal("Microsoft (R) Roslyn C# Compiler version " + FileVersionInfo.GetVersionInfo(Host.GetType().Assembly.Location).FileVersion, output[0]);
//// Assert.Equal("Loading context from '" + Path.GetFileName(rspFile.Path) + "'.", output[1]); //// Assert.Equal("Loading context from '" + Path.GetFileName(rspFile.Path) + "'.", output[1]);
...@@ -801,6 +796,25 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity() ...@@ -801,6 +796,25 @@ public void AddReference_MultipleReferencesWithSameWeakIdentity()
//// Assert.Equal("13", output[3]); //// Assert.Equal("13", output[3]);
//// } //// }
[Fact]
public void ReferencePaths()
{
var directory = Temp.CreateDirectory();
var assemblyName = GetUniqueName();
CompileLibrary(directory, assemblyName + ".dll", assemblyName, @"public class C { }");
var rspFile = Temp.CreateFile();
rspFile.WriteAllText("/rp:" + directory.Path);
var task = Host.ResetAsync(InteractiveHostOptions.Default.WithInitializationFile(rspFile.Path));
task.Wait();
Execute(
$@"#r ""{assemblyName}.dll""
typeof(C).Assembly.GetName()");
var output = SplitLines(ReadOutputToEnd());
Assert.Equal(2, output.Length);
Assert.Equal("Loading context from '" + Path.GetFileName(rspFile.Path) + "'.", output[0]);
Assert.Equal($"[{assemblyName}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]", output[1]);
}
[Fact] [Fact]
public void ReferenceDirectives() public void ReferenceDirectives()
{ {
...@@ -972,5 +986,10 @@ public void SubmissionResult_PrintingVoid() ...@@ -972,5 +986,10 @@ public void SubmissionResult_PrintingVoid()
} }
#endregion #endregion
private static ImmutableArray<string> SplitLines(string text)
{
return ImmutableArray.Create(text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
}
} }
} }
...@@ -7,11 +7,9 @@ ...@@ -7,11 +7,9 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.CodeAnalysis.Scripting; using Microsoft.CodeAnalysis.Scripting;
using Roslyn.Utilities; using Microsoft.VisualStudio.Shell.Interop;
namespace CSharpInteractive namespace CSharpInteractive
{ {
...@@ -41,7 +39,10 @@ internal static int Main(string[] args) ...@@ -41,7 +39,10 @@ internal static int Main(string[] args)
internal override MetadataFileReferenceResolver GetExternalMetadataResolver(TouchedFileLogger touchedFiles) internal override MetadataFileReferenceResolver GetExternalMetadataResolver(TouchedFileLogger touchedFiles)
{ {
// We don't log touched files atm. // We don't log touched files atm.
return new GacFileResolver(Arguments.ReferencePaths, Arguments.BaseDirectory, GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture); return new DesktopMetadataReferenceResolver(
new RelativePathReferenceResolver(Arguments.ReferencePaths, Arguments.BaseDirectory),
null,
new GacFileResolver(GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture));
} }
public override void PrintLogo(TextWriter consoleOutput) public override void PrintLogo(TextWriter consoleOutput)
......
...@@ -5,9 +5,9 @@ Imports System.IO ...@@ -5,9 +5,9 @@ Imports System.IO
Imports System.Reflection Imports System.Reflection
Imports System.Runtime.InteropServices Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Scripting
Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.VisualStudio.Shell.Interop Imports Microsoft.VisualStudio.Shell.Interop
Imports Microsoft.CodeAnalysis.Scripting
Friend NotInheritable Class Vbi Friend NotInheritable Class Vbi
Inherits VisualBasicCompiler Inherits VisualBasicCompiler
...@@ -30,7 +30,10 @@ Friend NotInheritable Class Vbi ...@@ -30,7 +30,10 @@ Friend NotInheritable Class Vbi
Friend Overrides Function GetExternalMetadataResolver(touchedFiles As TouchedFileLogger) As MetadataFileReferenceResolver Friend Overrides Function GetExternalMetadataResolver(touchedFiles As TouchedFileLogger) As MetadataFileReferenceResolver
' We don't log touched files atm. ' We don't log touched files atm.
Return New GacFileResolver(Arguments.ReferencePaths, Arguments.BaseDirectory, GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture) Return New DesktopMetadataReferenceResolver(
New RelativePathReferenceResolver(Arguments.ReferencePaths, Arguments.BaseDirectory),
Nothing,
New GacFileResolver(GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture))
End Function End Function
Public Overrides Sub PrintLogo(consoleOutput As TextWriter) Public Overrides Sub PrintLogo(consoleOutput As TextWriter)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Scripting
{
internal sealed class DesktopMetadataReferenceResolver : MetadataFileReferenceResolver
{
private readonly MetadataFileReferenceResolver _pathResolver;
private readonly NuGetPackageResolver _packageResolver;
private readonly GacFileResolver _gacFileResolver;
internal DesktopMetadataReferenceResolver(
MetadataFileReferenceResolver pathResolver,
NuGetPackageResolver packageResolver,
GacFileResolver gacFileResolver)
{
_pathResolver = pathResolver;
_packageResolver = packageResolver;
_gacFileResolver = gacFileResolver;
}
public override ImmutableArray<string> SearchPaths
{
get { return _pathResolver.SearchPaths; }
}
public override string BaseDirectory
{
get { return _pathResolver.BaseDirectory; }
}
internal override MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths)
{
return new DesktopMetadataReferenceResolver(_pathResolver.WithSearchPaths(searchPaths), _packageResolver, _gacFileResolver);
}
internal override MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory)
{
return new DesktopMetadataReferenceResolver(_pathResolver.WithBaseDirectory(baseDirectory), _packageResolver, _gacFileResolver);
}
public override string ResolveReference(string reference, string baseFilePath)
{
if (PathUtilities.IsFilePath(reference))
{
return _pathResolver.ResolveReference(reference, baseFilePath);
}
if (_packageResolver != null)
{
string path = _packageResolver.ResolveNuGetPackage(reference);
if (path != null && PortableShim.File.Exists(path))
{
return path;
}
}
if (_gacFileResolver != null)
{
return _gacFileResolver.ResolveReference(reference);
}
return null;
}
public override bool Equals(object obj)
{
var other = obj as DesktopMetadataReferenceResolver;
return (other != null) &&
object.Equals(_pathResolver, other._pathResolver) &&
object.Equals(_packageResolver, other._packageResolver) &&
object.Equals(_gacFileResolver, other._gacFileResolver);
}
public override int GetHashCode()
{
int result = _pathResolver.GetHashCode();
if (_packageResolver != null)
{
result = Hash.Combine(result, _packageResolver.GetHashCode());
}
if (_gacFileResolver != null)
{
result = Hash.Combine(result, _gacFileResolver.GetHashCode());
}
return result;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Scripting
{
internal sealed class NuGetPackageResolver
{
internal static readonly NuGetPackageResolver Instance = new NuGetPackageResolver();
private NuGetPackageResolver()
{
}
internal string ResolveNuGetPackage(string reference)
{
if (PathUtilities.IsFilePath(reference))
{
return null;
}
var assemblyName = GetPackageAssemblyName(reference);
if (assemblyName == null)
{
return null;
}
// Expecting {package}{version}\lib\{arch}\{package}.dll.
var resolvedPath = PathUtilities.CombineAbsoluteAndRelativePaths(reference, "lib");
if (!PortableShim.Directory.Exists(resolvedPath))
{
return null;
}
// We're not validating the architecture currently
// so fail if there's not exactly one architecture.
resolvedPath = PortableShim.Directory.EnumerateDirectories(resolvedPath, "*", PortableShim.SearchOption.TopDirectoryOnly).SingleOrDefault();
if (resolvedPath == null)
{
return null;
}
return PathUtilities.CombineAbsoluteAndRelativePaths(resolvedPath, assemblyName);
}
private static string GetPackageAssemblyName(string reference)
{
// Assembly name is <id/> in .nuspec file.
// For now, simply strip off any version #, etc.
var name = PathUtilities.GetFileName(reference);
int offset = 0;
while ((offset = name.IndexOf('.', offset)) >= 0)
{
if ((offset < name.Length - 1) && char.IsDigit(name[offset + 1]))
{
return name.Substring(0, offset) + ".dll";
}
offset += 1;
}
return null;
}
}
}
...@@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.Scripting ...@@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.Scripting
/// <summary> /// <summary>
/// Options for creating and running scripts. /// Options for creating and running scripts.
/// </summary> /// </summary>
public class ScriptOptions public sealed class ScriptOptions
{ {
private readonly ImmutableArray<MetadataReference> _references; private readonly ImmutableArray<MetadataReference> _references;
private readonly ImmutableArray<string> _namespaces; private readonly ImmutableArray<string> _namespaces;
...@@ -23,7 +23,12 @@ public class ScriptOptions ...@@ -23,7 +23,12 @@ public class ScriptOptions
public ScriptOptions() public ScriptOptions()
: this(ImmutableArray<MetadataReference>.Empty, : this(ImmutableArray<MetadataReference>.Empty,
ImmutableArray<string>.Empty, ImmutableArray<string>.Empty,
new AssemblyReferenceResolver(GacFileResolver.Default, MetadataFileReferenceProvider.Default), new AssemblyReferenceResolver(
new DesktopMetadataReferenceResolver(
MetadataFileReferenceResolver.Default,
null,
GacFileResolver.Default),
MetadataFileReferenceProvider.Default),
isInteractive: true) isInteractive: true)
{ {
} }
...@@ -342,25 +347,10 @@ public ScriptOptions WithSearchPaths(IEnumerable<string> searchPaths) ...@@ -342,25 +347,10 @@ public ScriptOptions WithSearchPaths(IEnumerable<string> searchPaths)
else else
{ {
// TODO: // TODO:
var gacResolver = _referenceResolver.PathResolver as GacFileResolver; var resolver = new AssemblyReferenceResolver(
if (gacResolver != null) _referenceResolver.PathResolver.WithSearchPaths(searchPaths.AsImmutableOrEmpty()),
{ _referenceResolver.Provider);
return With(resolver: new AssemblyReferenceResolver( return With(resolver: resolver);
new GacFileResolver(
searchPaths,
gacResolver.BaseDirectory,
gacResolver.Architectures,
gacResolver.PreferredCulture),
_referenceResolver.Provider));
}
else
{
return With(resolver: new AssemblyReferenceResolver(
new MetadataFileReferenceResolver(
searchPaths,
_referenceResolver.PathResolver.BaseDirectory),
_referenceResolver.Provider));
}
} }
} }
...@@ -407,25 +397,10 @@ public ScriptOptions WithBaseDirectory(string baseDirectory) ...@@ -407,25 +397,10 @@ public ScriptOptions WithBaseDirectory(string baseDirectory)
else else
{ {
// TODO: // TODO:
var gacResolver = _referenceResolver.PathResolver as GacFileResolver; var resolver = new AssemblyReferenceResolver(
if (gacResolver != null) _referenceResolver.PathResolver.WithBaseDirectory(baseDirectory),
{ _referenceResolver.Provider);
return With(resolver: new AssemblyReferenceResolver( return With(resolver: resolver);
new GacFileResolver(
_referenceResolver.PathResolver.SearchPaths,
baseDirectory,
gacResolver.Architectures,
gacResolver.PreferredCulture),
_referenceResolver.Provider));
}
else
{
return With(resolver: new AssemblyReferenceResolver(
new MetadataFileReferenceResolver(
_referenceResolver.PathResolver.SearchPaths,
baseDirectory),
_referenceResolver.Provider));
}
} }
} }
...@@ -434,7 +409,7 @@ public ScriptOptions WithBaseDirectory(string baseDirectory) ...@@ -434,7 +409,7 @@ public ScriptOptions WithBaseDirectory(string baseDirectory)
/// </summary> /// </summary>
internal ScriptOptions WithReferenceResolver(MetadataFileReferenceResolver resolver) internal ScriptOptions WithReferenceResolver(MetadataFileReferenceResolver resolver)
{ {
if (resolver == _referenceResolver.PathResolver) if (resolver.Equals(_referenceResolver.PathResolver))
{ {
return this; return this;
} }
...@@ -447,7 +422,7 @@ internal ScriptOptions WithReferenceResolver(MetadataFileReferenceResolver resol ...@@ -447,7 +422,7 @@ internal ScriptOptions WithReferenceResolver(MetadataFileReferenceResolver resol
/// </summary> /// </summary>
internal ScriptOptions WithReferenceProvider(MetadataFileReferenceProvider provider) internal ScriptOptions WithReferenceProvider(MetadataFileReferenceProvider provider)
{ {
if (provider == _referenceResolver.Provider) if (provider.Equals(_referenceResolver.Provider))
{ {
return this; return this;
} }
......
...@@ -147,9 +147,11 @@ ...@@ -147,9 +147,11 @@
<Link>GlobalAssemblyCache.cs</Link> <Link>GlobalAssemblyCache.cs</Link>
</Compile> </Compile>
<Compile Include="AssemblyLoadResult.cs" /> <Compile Include="AssemblyLoadResult.cs" />
<Compile Include="DesktopMetadataReferenceResolver.cs" />
<Compile Include="InteractiveAssemblyLoader.cs" /> <Compile Include="InteractiveAssemblyLoader.cs" />
<Compile Include="MetadataShadowCopy.cs" /> <Compile Include="MetadataShadowCopy.cs" />
<Compile Include="MetadataShadowCopyProvider.cs" /> <Compile Include="MetadataShadowCopyProvider.cs" />
<Compile Include="NuGetPackageResolver.cs" />
<Compile Include="ScriptCompilerUtil.cs" /> <Compile Include="ScriptCompilerUtil.cs" />
<Compile Include="ShadowCopy.cs" /> <Compile Include="ShadowCopy.cs" />
<Compile Include="ObjectFormatter.cs" /> <Compile Include="ObjectFormatter.cs" />
...@@ -203,4 +205,4 @@ ...@@ -203,4 +205,4 @@
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" /> <Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" /> <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup> </ImportGroup>
</Project> </Project>
\ No newline at end of file
...@@ -40,14 +40,6 @@ public ScriptEngine Engine ...@@ -40,14 +40,6 @@ public ScriptEngine Engine
get { return _engine; } get { return _engine; }
} }
internal MetadataFileReferenceResolver MetadataReferenceResolver
{
get
{
return _options.AssemblyResolver.PathResolver;
}
}
internal Type HostObjectType internal Type HostObjectType
{ {
get { return _globalsType; } get { return _globalsType; }
......
...@@ -14,10 +14,29 @@ namespace Roslyn.Test.Utilities ...@@ -14,10 +14,29 @@ namespace Roslyn.Test.Utilities
/// </summary> /// </summary>
internal abstract class TestMetadataReferenceResolver : MetadataFileReferenceResolver internal abstract class TestMetadataReferenceResolver : MetadataFileReferenceResolver
{ {
public TestMetadataReferenceResolver() public override string ResolveReference(string reference, string baseFilePath)
: base(searchPaths: ImmutableArray.Create<string>(), {
baseDirectory: null) return null;
}
public override ImmutableArray<string> SearchPaths
{ {
get { return ImmutableArray<string>.Empty; }
}
public override string BaseDirectory
{
get { return null; }
}
internal override MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths)
{
throw new NotImplementedException();
}
internal override MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory)
{
throw new NotImplementedException();
} }
} }
...@@ -52,22 +71,48 @@ public override string ResolveReference(string reference, string baseFilePath) ...@@ -52,22 +71,48 @@ public override string ResolveReference(string reference, string baseFilePath)
} }
} }
internal class VirtualizedFileReferenceResolver : MetadataFileReferenceResolver internal sealed class VirtualizedFileReferenceResolver : MetadataFileReferenceResolver
{ {
private readonly RelativePathReferenceResolver _resolver;
private readonly HashSet<string> _existingFullPaths; private readonly HashSet<string> _existingFullPaths;
public VirtualizedFileReferenceResolver( public VirtualizedFileReferenceResolver(
IEnumerable<string> existingFullPaths = null, IEnumerable<string> existingFullPaths = null,
string baseDirectory = null, string baseDirectory = null,
ImmutableArray<string> searchPaths = default(ImmutableArray<string>)) ImmutableArray<string> searchPaths = default(ImmutableArray<string>))
: base(searchPaths.NullToEmpty(), baseDirectory)
{ {
_resolver = new RelativePathReferenceResolver(searchPaths.NullToEmpty(), baseDirectory, FileExists);
_existingFullPaths = new HashSet<string>(existingFullPaths, StringComparer.OrdinalIgnoreCase); _existingFullPaths = new HashSet<string>(existingFullPaths, StringComparer.OrdinalIgnoreCase);
} }
protected override bool FileExists(string fullPath) public override ImmutableArray<string> SearchPaths
{
get { return _resolver.SearchPaths; }
}
public override string BaseDirectory
{
get { return _resolver.BaseDirectory; }
}
internal override MetadataFileReferenceResolver WithSearchPaths(ImmutableArray<string> searchPaths)
{
throw new NotImplementedException();
}
internal override MetadataFileReferenceResolver WithBaseDirectory(string baseDirectory)
{
throw new NotImplementedException();
}
public override string ResolveReference(string reference, string baseFilePath)
{
return _resolver.ResolveReference(reference, baseFilePath);
}
private bool FileExists(string fullPath)
{ {
return fullPath != null && _existingFullPaths != null && _existingFullPaths.Contains(FileUtilities.NormalizeAbsolutePath(fullPath)); return _existingFullPaths.Contains(FileUtilities.NormalizeAbsolutePath(fullPath));
} }
} }
} }
...@@ -183,7 +183,7 @@ protected override CSharpCompilationOptions CreateCompilationOptions() ...@@ -183,7 +183,7 @@ protected override CSharpCompilationOptions CreateCompilationOptions()
if (this.Workspace != null) if (this.Workspace != null)
{ {
referenceResolver = new AssemblyReferenceResolver( referenceResolver = new AssemblyReferenceResolver(
new MetadataFileReferenceResolver(referenceSearchPaths, projectDirectory), new RelativePathReferenceResolver(referenceSearchPaths, projectDirectory),
this.Workspace.CurrentSolution.Services.MetadataService.GetProvider()); this.Workspace.CurrentSolution.Services.MetadataService.GetProvider());
} }
else else
......
...@@ -1267,7 +1267,7 @@ private static MetadataFileReferenceResolver CreateMetadataReferenceResolver(str ...@@ -1267,7 +1267,7 @@ private static MetadataFileReferenceResolver CreateMetadataReferenceResolver(str
assemblySearchPaths = ImmutableArray.Create(outputDirectory); assemblySearchPaths = ImmutableArray.Create(outputDirectory);
} }
return new MetadataFileReferenceResolver(assemblySearchPaths, baseDirectory: projectDirectory); return new RelativePathReferenceResolver(assemblySearchPaths, baseDirectory: projectDirectory);
} }
private bool TryGetOutputPathFromBuildManager(out string binOutputPath) private bool TryGetOutputPathFromBuildManager(out string binOutputPath)
......
...@@ -34,7 +34,7 @@ public static ProjectInfo CreateProjectInfo(string projectName, string language, ...@@ -34,7 +34,7 @@ public static ProjectInfo CreateProjectInfo(string projectName, string language,
var commandLineArguments = commandLineParser.Parse(commandLineArgs, projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory()); var commandLineArguments = commandLineParser.Parse(commandLineArgs, projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());
// TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's // TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's
var referenceResolver = new MetadataFileReferenceResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory); var referenceResolver = new RelativePathReferenceResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory);
var referenceProvider = tmpWorkspace.Services.GetRequiredService<IMetadataService>().GetProvider(); var referenceProvider = tmpWorkspace.Services.GetRequiredService<IMetadataService>().GetProvider();
var analyzerLoader = tmpWorkspace.Services.GetRequiredService<IAnalyzerService>().GetLoader(); var analyzerLoader = tmpWorkspace.Services.GetRequiredService<IAnalyzerService>().GetLoader();
var xmlFileResolver = new XmlFileResolver(commandLineArguments.BaseDirectory); var xmlFileResolver = new XmlFileResolver(commandLineArguments.BaseDirectory);
......
...@@ -361,7 +361,7 @@ private async Task<ProjectId> LoadProjectAsync(string projectFilePath, IProjectF ...@@ -361,7 +361,7 @@ private async Task<ProjectId> LoadProjectAsync(string projectFilePath, IProjectF
isInteractive: false, isInteractive: false,
sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory()); sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());
var resolver = new MetadataFileReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory); var resolver = new RelativePathReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory);
var metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, metadataService.GetProvider())); var metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, metadataService.GetProvider()));
var analyzerLoader = analyzerService.GetLoader(); var analyzerLoader = analyzerService.GetLoader();
...@@ -449,7 +449,7 @@ private async Task<ProjectId> LoadProjectAsync(string projectFilePath, IProjectF ...@@ -449,7 +449,7 @@ private async Task<ProjectId> LoadProjectAsync(string projectFilePath, IProjectF
.WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray<string>.Empty, projectDirectory)) .WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray<string>.Empty, projectDirectory))
.WithMetadataReferenceResolver( .WithMetadataReferenceResolver(
new AssemblyReferenceResolver( new AssemblyReferenceResolver(
new MetadataFileReferenceResolver(ImmutableArray<string>.Empty, projectDirectory), new RelativePathReferenceResolver(ImmutableArray<string>.Empty, projectDirectory),
MetadataFileReferenceProvider.Default)) MetadataFileReferenceProvider.Default))
.WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath))) .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath)))
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default); .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);
......
...@@ -86,6 +86,12 @@ ...@@ -86,6 +86,12 @@
<Compile Include="..\..\..\Compilers\Helpers\SimpleAnalyzerAssemblyLoader.cs"> <Compile Include="..\..\..\Compilers\Helpers\SimpleAnalyzerAssemblyLoader.cs">
<Link>InternalUtilities\SimpleAnalyzerAssemblyLoader.cs</Link> <Link>InternalUtilities\SimpleAnalyzerAssemblyLoader.cs</Link>
</Compile> </Compile>
<Compile Include="..\..\..\Scripting\Core\DesktopMetadataReferenceResolver.cs">
<Link>InternalUtilities\DesktopMetadataReferenceResolver.cs</Link>
</Compile>
<Compile Include="..\..\..\Scripting\Core\NuGetPackageResolver.cs">
<Link>InternalUtilities\NuGetPackageResolver.cs</Link>
</Compile>
<Compile Include="Options\ExportOptionAttribute.cs" /> <Compile Include="Options\ExportOptionAttribute.cs" />
<Compile Include="InternalUtilities\FilePathUtilities.cs" /> <Compile Include="InternalUtilities\FilePathUtilities.cs" />
<Compile Include="Log\EtwLogger.cs" /> <Compile Include="Log\EtwLogger.cs" />
......
...@@ -248,6 +248,9 @@ ...@@ -248,6 +248,9 @@
<Compile Include="..\..\..\Compilers\Core\Portable\MetadataFileReferenceResolver.cs"> <Compile Include="..\..\..\Compilers\Core\Portable\MetadataFileReferenceResolver.cs">
<Link>InternalUtilities\MetadataFileReferenceResolver.cs</Link> <Link>InternalUtilities\MetadataFileReferenceResolver.cs</Link>
</Compile> </Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\RelativePathReferenceResolver.cs">
<Link>InternalUtilities\RelativePathReferenceResolver.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\ReflectionUtilities.cs"> <Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\ReflectionUtilities.cs">
<Link>InternalUtilities\ReflectionUtilities.cs</Link> <Link>InternalUtilities\ReflectionUtilities.cs</Link>
</Compile> </Compile>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册