提交 2bfb53c7 编写于 作者: J Jared Parsons

Merge pull request #2680 from jaredpar/fixes

Centralize many of our reflection uses
......@@ -6317,7 +6317,7 @@ private StatementSyntax ParseStatementCore()
_recursionDepth++;
if (_recursionDepth > MaxUncheckedRecursionDepth)
{
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack();
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack();
}
if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNode is CSharp.Syntax.StatementSyntax)
......@@ -8262,7 +8262,7 @@ private ExpressionSyntax ParseSubExpression(uint precedence)
if (_recursionDepth > MaxUncheckedRecursionDepth)
{
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack();
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack();
}
var result = ParseSubExpressionCore(precedence);
......
......@@ -167,7 +167,6 @@
<Compile Include="DocumentationCommentId.cs" />
<Compile Include="Emit\EditAndContinue\SymbolMatcher.cs" />
<Compile Include="InternalUtilities\FailFast.cs" />
<Compile Include="InternalUtilities\FileStreamLightUp.cs" />
<Compile Include="InternalUtilities\InterlockedOperations.cs" />
<Compile Include="InternalUtilities\IReadOnlySet.cs" />
<Compile Include="Collections\KeyedStack.cs" />
......@@ -283,7 +282,6 @@
<Compile Include="InternalUtilities\ConsList`1.cs" />
<Compile Include="InternalUtilities\DecimalUtilities.cs" />
<Compile Include="InternalUtilities\DocumentationCommentXmlNames.cs" />
<Compile Include="InternalUtilities\EnsureSufficientExecutionStackLightUp.cs" />
<Compile Include="InternalUtilities\EnumerableExtensions.ComparisonComparer.cs" />
<Compile Include="InternalUtilities\EnumerableExtensions.cs" />
<Compile Include="InternalUtilities\EnumField.cs" />
......@@ -729,4 +727,4 @@
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -361,5 +361,30 @@ internal static DateTime GetFileTimeStamp(string fullPath)
throw new IOException(e.Message);
}
}
internal static Stream OpenFileStream(string path)
{
try
{
return PortableShim.File.OpenRead(path);
}
catch (ArgumentException)
{
throw;
}
catch (IOException e)
{
if (e.GetType().Name == "DirectoryNotFoundException")
{
throw new FileNotFoundException(e.Message, path, e);
}
throw;
}
catch (Exception e)
{
throw new IOException(e.Message, e);
}
}
}
}
// 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.Reflection;
namespace Roslyn.Utilities
{
internal static class EnsureSufficientExecutionStackLightUp
{
private readonly static Action s_ensureSufficientExecutionStack;
static EnsureSufficientExecutionStackLightUp()
{
// TODO (DevDiv workitem 966425): Replace with the RuntimeHelpers.EnsureSufficientExecutionStack API when available.
if (!TryGetEnsureSufficientExecutionStack(out s_ensureSufficientExecutionStack))
{
s_ensureSufficientExecutionStack = () => { };
}
}
private static bool TryGetEnsureSufficientExecutionStack(out Action ensureSufficientExecutionStack)
{
var type = typeof(object).GetTypeInfo().Assembly.GetType("System.Runtime.CompilerServices.RuntimeHelpers");
if (type == null)
{
ensureSufficientExecutionStack = null;
return false;
}
foreach (var methodInfo in type.GetTypeInfo().GetDeclaredMethods("EnsureSufficientExecutionStack"))
{
if (methodInfo.IsStatic && !methodInfo.ContainsGenericParameters && methodInfo.ReturnType == typeof(void) && methodInfo.GetParameters().Length == 0)
{
ensureSufficientExecutionStack = (Action)methodInfo.CreateDelegate(typeof(Action));
return true;
}
}
ensureSufficientExecutionStack = null;
return false;
}
public static void EnsureSufficientExecutionStack()
{
s_ensureSufficientExecutionStack();
}
}
}
// 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.IO;
using System.Reflection;
namespace Microsoft.CodeAnalysis.InternalUtilities
{
internal static class FileStreamLightUp
{
private static readonly Lazy<Func<string, Stream>> s_lazyFileOpenStreamMethod = new Lazy<Func<string, Stream>>(() =>
{
Type file;
try
{
// try contract name first:
file = Type.GetType("System.IO.File, System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
}
catch
{
file = null;
}
if (file == null)
{
try
{
// try corlib next:
file = typeof(object).GetTypeInfo().Assembly.GetType("System.IO.File");
}
catch
{
file = null;
}
}
try
{
var openRead = file?.GetTypeInfo().GetDeclaredMethod("OpenRead");
return (Func<string, Stream>)openRead?.CreateDelegate(typeof(Func<string, Stream>));
}
catch
{
return null;
}
});
internal static Stream OpenFileStream(string path)
{
var factory = s_lazyFileOpenStreamMethod.Value;
if (factory == null)
{
throw new PlatformNotSupportedException();
}
Stream fileStream;
try
{
fileStream = factory(path);
}
catch (ArgumentException)
{
throw;
}
catch (IOException e)
{
if (e.GetType().Name == "DirectoryNotFoundException")
{
throw new FileNotFoundException(e.Message, path, e);
}
throw;
}
catch (Exception e)
{
throw new IOException(e.Message, e);
}
return fileStream;
}
}
}
......@@ -64,29 +64,6 @@ private static void CopyAnnotations(XObject source, XObject target)
}
}
// TODO (DevDiv workitem 966425): replace with Portable profile API when available.
private static readonly Lazy<Func<XNode, string, IEnumerable<XElement>>> s_XPathNodeSelector = new Lazy<Func<XNode, string, IEnumerable<XElement>>>(() =>
{
Type type;
try
{
type = Type.GetType("System.Xml.XPath.Extensions, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", false);
}
catch (Exception)
{
type = Type.GetType("System.Xml.XPath.Extensions, System.Xml.XPath.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false);
}
MethodInfo method = (from m in type.GetTypeInfo().GetDeclaredMethods("XPathSelectElements")
let parameters = m.GetParameters()
where parameters.Length == 2 && parameters[0].ParameterType == typeof(XNode) && parameters[1].ParameterType == typeof(string)
select m).Single();
return (Func<XNode, string, IEnumerable<XElement>>)method.CreateDelegate(typeof(Func<XNode, string, IEnumerable<XElement>>));
});
internal static XElement[] TrySelectElements(XNode node, string xpath, out string errorMessage, out bool invalidXPath)
{
errorMessage = null;
......@@ -94,7 +71,7 @@ internal static XElement[] TrySelectElements(XNode node, string xpath, out strin
try
{
var xpathResult = s_XPathNodeSelector.Value(node, xpath);
var xpathResult = PortableShim.XPath.Extensions.XPathSelectElements(node, xpath);
// Throws InvalidOperationException if the result of the XPath is an XDocument:
return xpathResult?.ToArray();
......
......@@ -7,6 +7,7 @@
using System.Reflection;
using System.Reflection.PortableExecutable;
using Microsoft.CodeAnalysis.InternalUtilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis
{
......@@ -227,7 +228,7 @@ public MetadataReference WithProperties(MetadataReferenceProperties properties)
MetadataReferenceProperties properties = default(MetadataReferenceProperties),
DocumentationProvider documentation = null)
{
var peStream = FileStreamLightUp.OpenFileStream(path);
var peStream = FileUtilities.OpenFileStream(path);
// prefetch image, close stream to avoid locking it:
var module = ModuleMetadata.CreateFromStream(peStream, PEStreamOptions.PrefetchEntireImage);
......@@ -301,7 +302,7 @@ public static MetadataReference CreateFromAssembly(Assembly assembly)
}
string location = AssemblyLocationLightUp.GetAssemblyLocation(assembly);
Stream peStream = FileStreamLightUp.OpenFileStream(location);
Stream peStream = FileUtilities.OpenFileStream(location);
// The file is locked by the CLR assembly loader, so we can create a lazily read metadata,
// which might also lock the file until the reference is GC'd.
......
......@@ -7,7 +7,7 @@
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using Microsoft.CodeAnalysis.InternalUtilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis
{
......@@ -186,7 +186,7 @@ public static ModuleMetadata CreateFromStream(Stream peStream, PEStreamOptions o
/// <exception cref="NotSupportedException">Reading from a file path is not supported by the platform.</exception>
public static ModuleMetadata CreateFromFile(string path)
{
return CreateFromStream(FileStreamLightUp.OpenFileStream(path));
return CreateFromStream(FileUtilities.OpenFileStream(path));
}
/// <summary>
......
......@@ -8,6 +8,7 @@
using System.IO;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Xml.Linq;
namespace Roslyn.Utilities
{
......@@ -33,18 +34,28 @@ namespace Roslyn.Utilities
/// </summary>
internal static class PortableShim
{
private const string System_Diagnotsics_FileVersionInfo_Name = "System.Diagnostics.FileVersionInfo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string System_IO_FileSystem_Name = "System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string System_IO_FileSystem_Primitives_Name = "System.IO.FileSystem.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string System_Runtime_Extensions_Name = "System.Runtime.Extensions, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string System_Threading_Thread_Name = "System.Threading.Thread, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private static class CoreNames
{
internal const string System_Diagnotsics_FileVersionInfo = "System.Diagnostics.FileVersionInfo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_IO_FileSystem = "System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_IO_FileSystem_Primitives = "System.IO.FileSystem.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Runtime = "System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Runtime_Extensions = "System.Runtime.Extensions, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Threading_Thread = "System.Threading.Thread, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Xml_XPath_XDocument = "System.Xml.XPath.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
}
private static class DesktopNames
{
internal const string System_Xml_Linq = "System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
}
internal static class Environment
{
internal const string TypeName = "System.Environment";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_Runtime_Extensions_Name}",
contractName: $"{TypeName}, {CoreNames.System_Runtime_Extensions}",
desktopName: TypeName);
internal static Func<string, string> ExpandEnvironmentVariables = Type
......@@ -63,7 +74,7 @@ internal static class Path
internal const string TypeName = "System.IO.Path";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_Runtime_Extensions_Name}",
contractName: $"{TypeName}, {CoreNames.System_Runtime_Extensions}",
desktopName: TypeName);
internal static readonly char DirectorySeparatorChar = (char)Type
......@@ -92,7 +103,7 @@ internal static class File
internal const string TypeName = "System.IO.File";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem}",
desktopName: TypeName);
internal static readonly Func<string, DateTime> GetLastWriteTimeUtc = Type
......@@ -131,7 +142,7 @@ internal static class Directory
internal const string TypeName = "System.IO.Directory";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem}",
desktopName: TypeName);
private static readonly MethodInfo s_enumerateDirectories = Type
......@@ -163,7 +174,7 @@ internal static class FileMode
internal const string TypeName = "System.IO.FileMode";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Primitives_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem_Primitives}",
desktopName: TypeName);
internal static readonly object CreateNew = Enum.ToObject(Type, 1);
......@@ -184,7 +195,7 @@ internal static class FileAccess
internal const string TypeName = "System.IO.FileAccess";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Primitives_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem_Primitives}",
desktopName: TypeName);
internal static readonly object Read = Enum.ToObject(Type, 1);
......@@ -199,7 +210,7 @@ internal static class FileShare
internal const string TypeName = "System.IO.FileShare";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Primitives_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem_Primitives}",
desktopName: TypeName);
internal static readonly object None = Enum.ToObject(Type, 0);
......@@ -222,7 +233,7 @@ internal static class FileOptions
internal const string TypeName = "System.IO.FileOptions";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem}",
desktopName: TypeName);
internal static readonly object None = Enum.ToObject(Type, 0);
......@@ -235,7 +246,7 @@ internal static class SearchOption
internal const string TypeName = "System.IO.SearchOption";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_IO_FileSystem_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem}",
desktopName: TypeName);
internal static readonly object TopDirectoryOnly = Enum.ToObject(Type, 0);
......@@ -248,7 +259,7 @@ internal static class FileStream
internal const string TypeName = "System.IO.FileStream";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"${TypeName}, ${System_IO_FileSystem_Name}",
contractName: $"{TypeName}, {CoreNames.System_IO_FileSystem}",
desktopName: TypeName);
internal static readonly PropertyInfo Name = Type
......@@ -318,7 +329,7 @@ internal static class FileVersionInfo
internal static readonly string DesktopName = $"{TypeName}, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {System_Diagnotsics_FileVersionInfo_Name}",
contractName: $"{TypeName}, {CoreNames.System_Diagnotsics_FileVersionInfo}",
desktopName: DesktopName);
internal static readonly Func<string, object> GetVersionInfo = Type
......@@ -336,7 +347,7 @@ internal static class Thread
internal const string TypeName = "System.Threading.Thread";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"${TypeName}, ${System_Threading_Thread_Name}",
contractName: $"{TypeName}, {CoreNames.System_Threading_Thread}",
desktopName: TypeName);
internal static readonly PropertyInfo CurrentThread = Type
......@@ -348,6 +359,20 @@ internal static class Thread
.GetDeclaredProperty(nameof(CurrentUICulture));
}
internal static class RuntimeHelpers
{
internal const string TypeName = "System.Runtime.CompilerServices.RuntimeHelpers";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Runtime}",
desktopName: TypeName);
internal static readonly Action EnsureSufficientExecutionStack = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(EnsureSufficientExecutionStack), paramTypes: new Type[] { })
.CreateDelegate<Action>();
}
internal static class Encoding
{
internal static readonly Type Type = typeof(System.Text.Encoding);
......@@ -367,6 +392,33 @@ internal static class MemoryStream
.GetDeclaredMethod(nameof(GetBuffer));
}
internal static class XPath
{
internal static class Extensions
{
internal const string TypeName = "System.Xml.XPath.Extensions";
internal static readonly Type Type = ReflectionUtil.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Runtime}",
desktopName: $"{TypeName}, {DesktopNames.System_Xml_Linq}");
internal static readonly Func<XNode, string, IEnumerable<XElement>> XPathSelectElements = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(XPathSelectElements), new[] { typeof(XNode), typeof(string) })
.CreateDelegate<Func<XNode, string, IEnumerable<XElement>>>();
}
}
/// <summary>
/// APIs contained here are proposed for CoreFX but not yet finalized. Their contracts are
/// subject to change.
/// </summary>
internal static class Proposed
{
}
internal static class Misc
{
internal static string GetFileVersion(string path)
......
......@@ -66,6 +66,11 @@ internal static ConstructorInfo GetDeclaredConstructor(this TypeInfo typeInfo, p
public static T CreateDelegate<T>(this MethodInfo methodInfo)
{
if (methodInfo == null)
{
return default(T);
}
return (T)(object)methodInfo.CreateDelegate(typeof(T));
}
}
......
......@@ -51,7 +51,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Try
_recursionDepth += 1
If _recursionDepth >= _maxUncheckedRecursionDepth Then
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack()
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack()
End If
'// Note: this function will only ever return NULL if the flag "BailIfFirstTokenIsRejected" is set,
......
......@@ -857,7 +857,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Try
_recursionDepth += 1
If _recursionDepth >= _maxUncheckedRecursionDepth Then
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack()
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack()
End If
_hadImplicitLineContinuation = False
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册