Skip to content

Commit

Permalink
Merge pull request #5 from icsharpcode/update/beta3
Browse files Browse the repository at this point in the history
Update/beta3
  • Loading branch information
jeffreye authored Dec 17, 2018
2 parents 4dd7442 + 3a742e7 commit 839da3a
Show file tree
Hide file tree
Showing 21 changed files with 368 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
<PackageReference Include="ICSharpCode.Decompiler" Version="4.0.0.4322-beta2-debug" />
<PackageReference Include="Mono.Cecil" Version="0.10.1" />
<PackageReference Include="ICSharpCode.Decompiler" Version="4.0.0.4447-beta3" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageReference Include="System.Runtime.Extensions" Version="4.3.0" />
<PackageReference Include="System.Runtime.Handles" Version="4.3.0" />
<PackageReference Include="System.Threading" Version="4.3.0" />
</ItemGroup>

</Project>
21 changes: 11 additions & 10 deletions ILSpy.Core/Analyzers/AnalyzerScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,17 @@ public IEnumerable<ITypeDefinition> GetTypesInScope(CancellationToken ct)
{
if (IsLocal) {
var typeSystem = new DecompilerTypeSystem(TypeScope.ParentModule.PEFile, TypeScope.ParentModule.PEFile.GetAssemblyResolver());
if (memberAccessibility == Accessibility.Private) {
foreach (var type in TreeTraversal.PreOrder(typeScope, t => t.NestedTypes)) {
yield return type;
}
} else {
foreach (var type in TreeTraversal.PreOrder(typeScope.DeclaringTypeDefinition, t => t.NestedTypes)) {
yield return type;
}
}
} else {
ITypeDefinition scope = typeScope;
if (memberAccessibility != Accessibility.Private && typeScope.DeclaringTypeDefinition != null)
{
scope = typeScope.DeclaringTypeDefinition;
}
foreach (var type in TreeTraversal.PreOrder(scope, t => t.NestedTypes))
{
yield return type;
}
}
else {
foreach (var module in GetModulesInScope(ct)) {
var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver());
foreach (var type in typeSystem.MainModule.TypeDefinitions) {
Expand Down
128 changes: 120 additions & 8 deletions ILSpy.Core/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.TypeSystem;

namespace ICSharpCode.ILSpy.Analyzers.Builtin
Expand All @@ -31,10 +32,121 @@ class AttributeAppliedToAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
if (!(analyzedSymbol is IEntity attributeEntity))
yield break;
if (!(analyzedSymbol is ITypeDefinition attributeType))
return Array.Empty<ISymbol>();
var scope = context.GetScopeOf(attributeType);
// TODO: DeclSecurity attributes are not supported.
if (!IsBuiltinAttribute(attributeType, out var knownAttribute))
{
return HandleCustomAttribute(attributeType, scope);
}
else
{
return HandleBuiltinAttribute(knownAttribute, scope).SelectMany(s => s);
}
}

var scope = context.GetScopeOf(attributeEntity);
bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute)
{
knownAttribute = attributeType.IsBuiltinAttribute();
switch (knownAttribute)
{
case KnownAttribute.Serializable:
case KnownAttribute.ComImport:
case KnownAttribute.StructLayout:
case KnownAttribute.DllImport:
case KnownAttribute.PreserveSig:
case KnownAttribute.MethodImpl:
case KnownAttribute.FieldOffset:
case KnownAttribute.NonSerialized:
case KnownAttribute.MarshalAs:
case KnownAttribute.PermissionSet:
case KnownAttribute.Optional:
case KnownAttribute.In:
case KnownAttribute.Out:
case KnownAttribute.IndexerName:
return true;
default:
return false;
}
}

IEnumerable<IEnumerable<ISymbol>> HandleBuiltinAttribute(KnownAttribute attribute, AnalyzerScope scope)
{
IEnumerable<ISymbol> ScanTypes(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.Where(t => t.HasAttribute(attribute));
}

IEnumerable<ISymbol> ScanMethods(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Members.OfType<IMethod>())
.Where(m => m.HasAttribute(attribute))
.Select(m => m.AccessorOwner ?? m);
}

IEnumerable<ISymbol> ScanFields(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Fields)
.Where(f => f.HasAttribute(attribute));
}

IEnumerable<ISymbol> ScanProperties(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Properties)
.Where(p => p.HasAttribute(attribute));
}

IEnumerable<ISymbol> ScanParameters(DecompilerTypeSystem ts)
{
return ts.MainModule.TypeDefinitions
.SelectMany(t => t.Members.OfType<IMethod>())
.Where(m => m.Parameters.Any(p => p.HasAttribute(attribute)))
.Select(m => m.AccessorOwner ?? m);
}

foreach (Decompiler.Metadata.PEFile module in scope.GetAllModules())
{
var ts = new DecompilerTypeSystem(module, module.GetAssemblyResolver());

switch (attribute)
{
case KnownAttribute.Serializable:
case KnownAttribute.ComImport:
case KnownAttribute.StructLayout:
yield return ScanTypes(ts);
break;
case KnownAttribute.DllImport:
case KnownAttribute.PreserveSig:
case KnownAttribute.MethodImpl:
yield return ScanMethods(ts);
break;
case KnownAttribute.FieldOffset:
case KnownAttribute.NonSerialized:
yield return ScanFields(ts);
break;
case KnownAttribute.MarshalAs:
yield return ScanFields(ts);
yield return ScanParameters(ts);
goto case KnownAttribute.Out;
case KnownAttribute.Optional:
case KnownAttribute.In:
case KnownAttribute.Out:
yield return ScanParameters(ts);
break;
case KnownAttribute.IndexerName:
yield return ScanProperties(ts);
break;
}
}
}

IEnumerable<ISymbol> HandleCustomAttribute(ITypeDefinition attributeType, AnalyzerScope scope)
{
var genericContext = new GenericContext(); // type arguments do not matter for this analyzer.

foreach (var module in scope.GetAllModules()) {
Expand All @@ -44,9 +156,9 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
var customAttribute = module.Metadata.GetCustomAttribute(h);
var attributeCtor = ts.MainModule.ResolveMethod(customAttribute.Constructor, genericContext);
if (attributeCtor.DeclaringTypeDefinition != null
&& attributeCtor.ParentModule.PEFile == attributeEntity.ParentModule.PEFile
&& attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeEntity.MetadataToken) {
if (customAttribute.Parent.Kind == HandleKind.Parameter) {
&& attributeCtor.ParentModule.PEFile == attributeType.ParentModule.PEFile
&& attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeType.MetadataToken) {
if (customAttribute.Parent.Kind == HandleKind.Parameter) {
referencedParameters.Add((ParameterHandle)customAttribute.Parent);
} else {
var parent = GetParentEntity(ts, customAttribute);
Expand Down
20 changes: 18 additions & 2 deletions ILSpy.Core/Analyzers/Builtin/MethodUsedByAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlo
ILOpCode opCode;
try {
opCode = blob.DecodeOpCode();
if (opCode != ILOpCode.Call && opCode != ILOpCode.Callvirt && opCode != ILOpCode.Ldtoken) {
if (!IsSupportedOpCode(opCode)) {
ILParser.SkipOperand(ref blob, opCode);
continue;
}
Expand Down Expand Up @@ -132,7 +132,23 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlo
return false;
}

static bool IsSameMember(IMember analyzedMethod, IMember m)
static bool IsSupportedOpCode(ILOpCode opCode)
{
switch (opCode)
{
case ILOpCode.Call:
case ILOpCode.Callvirt:
case ILOpCode.Ldtoken:
case ILOpCode.Ldftn:
case ILOpCode.Ldvirtftn:
case ILOpCode.Newobj:
return true;
default:
return false;
}
}

static bool IsSameMember(IMember analyzedMethod, IMember m)
{
return m.MetadataToken == analyzedMethod.MetadataToken
&& m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile;
Expand Down
3 changes: 2 additions & 1 deletion ILSpy.Core/DecompilationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public DecompilationOptions(LanguageVersion version, Options.DecompilerSettings
ShowXmlDocumentation = settings.ShowXmlDocumentation,
UseDebugSymbols = settings.UseDebugSymbols,
UsingDeclarations = settings.UsingDeclarations,
};
ApplyWindowsRuntimeProjections = settings.ApplyWindowsRuntimeProjections,
};
}
}
}
4 changes: 2 additions & 2 deletions ILSpy.Core/ILSpy.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ICSharpCode.Decompiler" Version="4.0.0.4322-beta2-debug" />
<PackageReference Include="ICSharpCode.Decompiler" Version="4.0.0.4447-beta3" />
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="15.8.98" />
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="NuGet.Client" Version="4.2.0" />
Expand Down Expand Up @@ -56,7 +56,7 @@
<Content Include="Images\*.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Images\ILSpy.png;Images\PrivateInternal.png">
<EmbeddedResource Include="Images\ILSpy.png;Images\PrivateInternal.png;Images\Search.png;;Images\ClearSearch.png;">
</EmbeddedResource>
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions ILSpy.Core/Languages/CSharpHighlightingTokenWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public override void WritePrimitiveType(string type)
case "ulong":
color = valueTypeKeywordsColor;
break;
case "class":
case "object":
case "string":
case "void":
Expand Down
3 changes: 2 additions & 1 deletion ILSpy.Core/Languages/CSharpLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options)
{
CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings);
decompiler.CancellationToken = options.CancellationToken;
while (decompiler.AstTransforms.Count > transformCount)
decompiler.DebugInfoProvider = module.GetDebugInfoOrNull();
while (decompiler.AstTransforms.Count > transformCount)
decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1);
return decompiler;
}
Expand Down
18 changes: 10 additions & 8 deletions ILSpy.Core/Languages/Language.cs
Original file line number Diff line number Diff line change
Expand Up @@ -503,15 +503,17 @@ public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, SRM.EntityHandl
public static string GetPlatformDisplayName(PEFile module)
{
var architecture = module.Reader.PEHeaders.CoffHeader.Machine;
var flags = module.Reader.PEHeaders.CorHeader.Flags;
switch (architecture) {
var characteristics = module.Reader.PEHeaders.CoffHeader.Characteristics;
var corflags = module.Reader.PEHeaders.CorHeader.Flags;
switch (architecture) {
case Machine.I386:
if ((flags & CorFlags.Prefers32Bit) != 0)
return "AnyCPU (32-bit preferred)";
else if ((flags & CorFlags.Requires32Bit) != 0)
return "x86";
else
return "AnyCPU (64-bit preferred)";
if ((corflags & CorFlags.Prefers32Bit) != 0)
return "AnyCPU (32-bit preferred)";
// According to ECMA-335, II.25.3.3.1 CorFlags.Requires32Bit and Characteristics.Bit32Machine must be in sync
// for assemblies containing managed code. However, this is not true for C++/CLI assemblies.
if ((corflags & CorFlags.Requires32Bit) != 0 || (characteristics & Characteristics.Bit32Machine) != 0)
return "x86";
return "AnyCPU (64-bit preferred)";
case Machine.Amd64:
return "x64";
case Machine.IA64:
Expand Down
23 changes: 12 additions & 11 deletions ILSpy.Core/LoadedAssembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,17 @@ PEFile LoadAssembly(object state)
// runs on background thread
if (stream != null)
{
// Read the module from a precrafted stream
module = new PEFile(fileName, stream);
}
else
// Read the module from a precrafted stream
module = new PEFile(fileName, stream, metadataOptions: DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None);
}
else
{
// Read the module from disk (by default)
module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), PEStreamOptions.PrefetchEntireImage);
}
// Read the module from disk (by default)
module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), PEStreamOptions.PrefetchEntireImage,
metadataOptions: DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None);
}

if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) {
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) {
try {
LoadSymbols(module);
} catch (IOException) {
Expand Down Expand Up @@ -323,9 +324,9 @@ public LoadedAssembly LookupReferencedModule(PEFile mainModule, string moduleNam
class MyUniversalResolver : UniversalAssemblyResolver
{
public MyUniversalResolver(LoadedAssembly assembly)
: base(assembly.FileName, false, assembly.GetTargetFrameworkIdAsync().Result, PEStreamOptions.PrefetchEntireImage)
{
}
: base(assembly.FileName, false, assembly.GetTargetFrameworkIdAsync().Result, PEStreamOptions.PrefetchEntireImage, DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None)
{
}
}

static Dictionary<string, LoadedAssembly> loadingAssemblies = new Dictionary<string, LoadedAssembly>();
Expand Down
Loading

0 comments on commit 839da3a

Please sign in to comment.