mirror of https://github.com/icsharpcode/ILSpy.git
5 changed files with 0 additions and 1468 deletions
@ -1,65 +0,0 @@
@@ -1,65 +0,0 @@
|
||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
using Mono.Cecil; |
||||
using Mono.Cecil.Cil; |
||||
using ArrayType = Mono.Cecil.ArrayType; |
||||
|
||||
namespace ICSharpCode.ILSpy.Cecil |
||||
{ |
||||
/// <summary>
|
||||
/// Cecil helper methods.
|
||||
/// </summary>
|
||||
public static class CecilExtensions |
||||
{ |
||||
public static HashSet<MethodDefinition> GetAccessorMethods(this TypeDefinition type) |
||||
{ |
||||
HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>(); |
||||
foreach (var property in type.Properties) { |
||||
accessorMethods.Add(property.GetMethod); |
||||
accessorMethods.Add(property.SetMethod); |
||||
if (property.HasOtherMethods) { |
||||
foreach (var m in property.OtherMethods) |
||||
accessorMethods.Add(m); |
||||
} |
||||
} |
||||
foreach (EventDefinition ev in type.Events) { |
||||
accessorMethods.Add(ev.AddMethod); |
||||
accessorMethods.Add(ev.RemoveMethod); |
||||
accessorMethods.Add(ev.InvokeMethod); |
||||
if (ev.HasOtherMethods) { |
||||
foreach (var m in ev.OtherMethods) |
||||
accessorMethods.Add(m); |
||||
} |
||||
} |
||||
return accessorMethods; |
||||
} |
||||
|
||||
public static TypeDefinition ResolveWithinSameModule(this TypeReference type) |
||||
{ |
||||
if (type != null && type.GetElementType().Module == type.Module) |
||||
return type.Resolve(); |
||||
else |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -1,525 +0,0 @@
@@ -1,525 +0,0 @@
|
||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using Mono.Cecil; |
||||
|
||||
namespace ICSharpCode.ILSpy.Cecil |
||||
{ |
||||
public static class TypesHierarchyHelpers |
||||
{ |
||||
public static bool IsBaseType(TypeDefinition baseType, TypeDefinition derivedType, bool resolveTypeArguments) |
||||
{ |
||||
if (resolveTypeArguments) |
||||
return BaseTypes(derivedType).Any(t => t.Item == baseType); |
||||
else { |
||||
var comparableBaseType = baseType.Resolve(); |
||||
if (comparableBaseType == null) |
||||
return false; |
||||
while (derivedType.BaseType != null) { |
||||
var resolvedBaseType = derivedType.BaseType.Resolve(); |
||||
if (resolvedBaseType == null) |
||||
return false; |
||||
if (comparableBaseType == resolvedBaseType) |
||||
return true; |
||||
derivedType = resolvedBaseType; |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Determines whether one method overrides or hides another method.
|
||||
/// </summary>
|
||||
/// <param name="parentMethod">The method declared in a base type.</param>
|
||||
/// <param name="childMethod">The method declared in a derived type.</param>
|
||||
/// <returns>true if <paramref name="childMethod"/> hides or overrides <paramref name="parentMethod"/>,
|
||||
/// otherwise false.</returns>
|
||||
public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod) |
||||
{ |
||||
if (parentMethod == null) |
||||
throw new ArgumentNullException(nameof(parentMethod)); |
||||
if (childMethod == null) |
||||
throw new ArgumentNullException(nameof(childMethod)); |
||||
|
||||
if (parentMethod.Name != childMethod.Name) |
||||
return false; |
||||
|
||||
if (parentMethod.HasParameters || childMethod.HasParameters) |
||||
if (!parentMethod.HasParameters || !childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count) |
||||
return false; |
||||
|
||||
return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.);
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Determines whether a property overrides or hides another property.
|
||||
/// </summary>
|
||||
/// <param name="parentProperty">The property declared in a base type.</param>
|
||||
/// <param name="childProperty">The property declared in a derived type.</param>
|
||||
/// <returns>true if the <paramref name="childProperty"/> hides or overrides <paramref name="parentProperty"/>,
|
||||
/// otherwise false.</returns>
|
||||
public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty) |
||||
{ |
||||
if (parentProperty == null) |
||||
throw new ArgumentNullException(nameof(parentProperty)); |
||||
if (childProperty == null) |
||||
throw new ArgumentNullException(nameof(childProperty)); |
||||
|
||||
if (parentProperty.Name != childProperty.Name) |
||||
return false; |
||||
|
||||
if (parentProperty.HasParameters || childProperty.HasParameters) |
||||
if (!parentProperty.HasParameters || !childProperty.HasParameters || parentProperty.Parameters.Count != childProperty.Parameters.Count) |
||||
return false; |
||||
|
||||
return FindBaseProperties(childProperty).Any(m => m == parentProperty); |
||||
} |
||||
|
||||
public static bool IsBaseEvent(EventDefinition parentEvent, EventDefinition childEvent) |
||||
{ |
||||
if (parentEvent.Name != childEvent.Name) |
||||
return false; |
||||
|
||||
return FindBaseEvents(childEvent).Any(m => m == parentEvent); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Finds all methods from base types overridden or hidden by the specified method.
|
||||
/// </summary>
|
||||
/// <param name="method">The method which overrides or hides methods from base types.</param>
|
||||
/// <returns>Methods overriden or hidden by the specified method.</returns>
|
||||
public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method) |
||||
{ |
||||
if (method == null) |
||||
throw new ArgumentNullException(nameof(method)); |
||||
|
||||
var typeContext = CreateGenericContext(method.DeclaringType); |
||||
var gMethod = typeContext.ApplyTo(method); |
||||
|
||||
foreach (var baseType in BaseTypes(method.DeclaringType)) |
||||
foreach (var baseMethod in baseType.Item.Methods) |
||||
if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisibleFromDerived(baseMethod, method.DeclaringType)) { |
||||
yield return baseMethod; |
||||
if (baseMethod.IsNewSlot == baseMethod.IsVirtual) |
||||
yield break; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Finds all properties from base types overridden or hidden by the specified property.
|
||||
/// </summary>
|
||||
/// <param name="property">The property which overrides or hides properties from base types.</param>
|
||||
/// <returns>Properties overriden or hidden by the specified property.</returns>
|
||||
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property) |
||||
{ |
||||
if (property == null) |
||||
throw new ArgumentNullException(nameof(property)); |
||||
|
||||
if ((property.GetMethod ?? property.SetMethod).HasOverrides) |
||||
yield break; |
||||
|
||||
var typeContext = CreateGenericContext(property.DeclaringType); |
||||
var gProperty = typeContext.ApplyTo(property); |
||||
bool isIndexer = property.IsIndexer(); |
||||
|
||||
foreach (var baseType in BaseTypes(property.DeclaringType)) |
||||
foreach (var baseProperty in baseType.Item.Properties) |
||||
if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty) |
||||
&& IsVisibleFromDerived(baseProperty, property.DeclaringType)) { |
||||
if (isIndexer != baseProperty.IsIndexer()) |
||||
continue; |
||||
yield return baseProperty; |
||||
var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod; |
||||
if (anyPropertyAccessor.IsNewSlot == anyPropertyAccessor.IsVirtual) |
||||
yield break; |
||||
} |
||||
} |
||||
|
||||
public static IEnumerable<EventDefinition> FindBaseEvents(EventDefinition eventDef) |
||||
{ |
||||
if (eventDef == null) |
||||
throw new ArgumentNullException(nameof(eventDef)); |
||||
|
||||
var typeContext = CreateGenericContext(eventDef.DeclaringType); |
||||
var gEvent = typeContext.ApplyTo(eventDef); |
||||
|
||||
foreach (var baseType in BaseTypes(eventDef.DeclaringType)) |
||||
foreach (var baseEvent in baseType.Item.Events) |
||||
if (MatchEvent(baseType.ApplyTo(baseEvent), gEvent) && IsVisibleFromDerived(baseEvent, eventDef.DeclaringType)) { |
||||
yield return baseEvent; |
||||
var anyEventAccessor = baseEvent.AddMethod ?? baseEvent.RemoveMethod; |
||||
if (anyEventAccessor.IsNewSlot == anyEventAccessor.IsVirtual) |
||||
yield break; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Determinates whether member of the base type is visible from a derived type.
|
||||
/// </summary>
|
||||
/// <param name="baseMember">The member which visibility is checked.</param>
|
||||
/// <param name="derivedType">The derived type.</param>
|
||||
/// <returns>true if the member is visible from derived type, othewise false.</returns>
|
||||
public static bool IsVisibleFromDerived(IMemberDefinition baseMember, TypeDefinition derivedType) |
||||
{ |
||||
if (baseMember == null) |
||||
throw new ArgumentNullException(nameof(baseMember)); |
||||
if (derivedType == null) |
||||
throw new ArgumentNullException(nameof(derivedType)); |
||||
|
||||
MethodAttributes attrs = GetAccessAttributes(baseMember) & MethodAttributes.MemberAccessMask; |
||||
if (attrs == MethodAttributes.Private) |
||||
return false; |
||||
|
||||
if (baseMember.DeclaringType.Module == derivedType.Module) |
||||
return true; |
||||
|
||||
if (attrs == MethodAttributes.Assembly || attrs == MethodAttributes.FamANDAssem) { |
||||
var derivedTypeAsm = derivedType.Module.Assembly; |
||||
var asm = baseMember.DeclaringType.Module.Assembly; |
||||
|
||||
if (asm.HasCustomAttributes) { |
||||
var attributes = asm.CustomAttributes |
||||
.Where(attr => attr.AttributeType.FullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute"); |
||||
foreach (var attribute in attributes) { |
||||
string assemblyName = attribute.ConstructorArguments[0].Value as string; |
||||
assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
|
||||
if (assemblyName == derivedTypeAsm.Name.Name) |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private static MethodAttributes GetAccessAttributes(IMemberDefinition member) |
||||
{ |
||||
var fld = member as FieldDefinition; |
||||
if (fld != null) |
||||
return (MethodAttributes)fld.Attributes; |
||||
|
||||
var method = member as MethodDefinition; |
||||
if (method != null) |
||||
return method.Attributes; |
||||
|
||||
var prop = member as PropertyDefinition; |
||||
if (prop != null) { |
||||
return (prop.GetMethod ?? prop.SetMethod).Attributes; |
||||
} |
||||
|
||||
var evnt = member as EventDefinition; |
||||
if (evnt != null) { |
||||
return (evnt.AddMethod ?? evnt.RemoveMethod).Attributes; |
||||
} |
||||
|
||||
var nestedType = member as TypeDefinition; |
||||
if (nestedType != null) { |
||||
if (nestedType.IsNestedPrivate) |
||||
return MethodAttributes.Private; |
||||
if (nestedType.IsNestedAssembly || nestedType.IsNestedFamilyAndAssembly) |
||||
return MethodAttributes.Assembly; |
||||
return MethodAttributes.Public; |
||||
} |
||||
|
||||
throw new NotSupportedException(); |
||||
} |
||||
|
||||
private static bool MatchMethod(GenericContext<MethodDefinition> candidate, GenericContext<MethodDefinition> method) |
||||
{ |
||||
var mCandidate = candidate.Item; |
||||
var mMethod = method.Item; |
||||
if (mCandidate.Name != mMethod.Name) |
||||
return false; |
||||
|
||||
if (mCandidate.HasOverrides) |
||||
return false; |
||||
|
||||
if (mCandidate.IsSpecialName != method.Item.IsSpecialName) |
||||
return false; |
||||
|
||||
if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) { |
||||
if (!mCandidate.HasGenericParameters || !mMethod.HasGenericParameters || mCandidate.GenericParameters.Count != mMethod.GenericParameters.Count) |
||||
return false; |
||||
} |
||||
|
||||
if (mCandidate.HasParameters || mMethod.HasParameters) { |
||||
if (!mCandidate.HasParameters || !mMethod.HasParameters || mCandidate.Parameters.Count != mMethod.Parameters.Count) |
||||
return false; |
||||
|
||||
for (int index = 0; index < mCandidate.Parameters.Count; index++) { |
||||
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), method.ApplyTo(mMethod.Parameters[index]))) |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public static bool MatchInterfaceMethod(MethodDefinition candidate, MethodDefinition method, TypeReference interfaceContextType) |
||||
{ |
||||
var candidateContext = CreateGenericContext(candidate.DeclaringType); |
||||
var gCandidate = candidateContext.ApplyTo(candidate); |
||||
|
||||
if (interfaceContextType is GenericInstanceType) { |
||||
var methodContext = new GenericContext<TypeDefinition>(interfaceContextType.Resolve(), ((GenericInstanceType)interfaceContextType).GenericArguments); |
||||
var gMethod = methodContext.ApplyTo(method); |
||||
return MatchMethod(gCandidate, gMethod); |
||||
} else { |
||||
var methodContext = CreateGenericContext(interfaceContextType.Resolve()); |
||||
var gMethod = candidateContext.ApplyTo(method); |
||||
return MatchMethod(gCandidate, gMethod); |
||||
} |
||||
} |
||||
|
||||
private static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property) |
||||
{ |
||||
var mCandidate = candidate.Item; |
||||
var mProperty = property.Item; |
||||
if (mCandidate.Name != mProperty.Name) |
||||
return false; |
||||
|
||||
if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides) |
||||
return false; |
||||
|
||||
if (mCandidate.HasParameters || mProperty.HasParameters) { |
||||
if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count) |
||||
return false; |
||||
|
||||
for (int index = 0; index < mCandidate.Parameters.Count; index++) { |
||||
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), property.ApplyTo(mProperty.Parameters[index]))) |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private static bool MatchEvent(GenericContext<EventDefinition> candidate, GenericContext<EventDefinition> ev) |
||||
{ |
||||
var mCandidate = candidate.Item; |
||||
var mEvent = ev.Item; |
||||
if (mCandidate.Name != mEvent.Name) |
||||
return false; |
||||
|
||||
if ((mCandidate.AddMethod ?? mCandidate.RemoveMethod).HasOverrides) |
||||
return false; |
||||
|
||||
if (!IsSameType(candidate.ResolveWithContext(mCandidate.EventType), ev.ResolveWithContext(mEvent.EventType))) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType) |
||||
{ |
||||
if (baseParameterType.Item.IsIn != parameterType.Item.IsIn || |
||||
baseParameterType.Item.IsOut != parameterType.Item.IsOut) |
||||
return false; |
||||
var baseParam = baseParameterType.ResolveWithContext(baseParameterType.Item.ParameterType); |
||||
var param = parameterType.ResolveWithContext(parameterType.Item.ParameterType); |
||||
return IsSameType(baseParam, param); |
||||
} |
||||
|
||||
private static bool IsSameType(TypeReference tr1, TypeReference tr2) |
||||
{ |
||||
if (tr1 == tr2) |
||||
return true; |
||||
if (tr1 == null || tr2 == null) |
||||
return false; |
||||
|
||||
if (tr1.GetType() != tr2.GetType()) |
||||
return false; |
||||
|
||||
if (tr1.Name == tr2.Name && tr1.FullName == tr2.FullName) |
||||
return true; |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(TypeDefinition type) |
||||
{ |
||||
return BaseTypes(CreateGenericContext(type)); |
||||
} |
||||
|
||||
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(GenericContext<TypeDefinition> type) |
||||
{ |
||||
while (type.Item.BaseType != null) { |
||||
var baseType = type.Item.BaseType; |
||||
var genericBaseType = baseType as GenericInstanceType; |
||||
if (genericBaseType != null) { |
||||
type = new GenericContext<TypeDefinition>(genericBaseType.ResolveOrThrow(), |
||||
genericBaseType.GenericArguments.Select(t => type.ResolveWithContext(t))); |
||||
} else |
||||
type = new GenericContext<TypeDefinition>(baseType.ResolveOrThrow()); |
||||
yield return type; |
||||
} |
||||
} |
||||
|
||||
private static GenericContext<TypeDefinition> CreateGenericContext(TypeDefinition type) |
||||
{ |
||||
return type.HasGenericParameters |
||||
? new GenericContext<TypeDefinition>(type, type.GenericParameters) |
||||
: new GenericContext<TypeDefinition>(type); |
||||
} |
||||
|
||||
struct GenericContext<T> where T : class |
||||
{ |
||||
private static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>()); |
||||
private static readonly GenericParameter UnresolvedGenericTypeParameter = |
||||
new DummyGenericParameterProvider(false).DummyParameter; |
||||
private static readonly GenericParameter UnresolvedGenericMethodParameter = |
||||
new DummyGenericParameterProvider(true).DummyParameter; |
||||
|
||||
public readonly T Item; |
||||
public readonly ReadOnlyCollection<TypeReference> TypeArguments; |
||||
|
||||
public GenericContext(T item) |
||||
{ |
||||
if (item == null) |
||||
throw new ArgumentNullException(nameof(item)); |
||||
|
||||
Item = item; |
||||
TypeArguments = Empty; |
||||
} |
||||
|
||||
public GenericContext(T item, IEnumerable<TypeReference> typeArguments) |
||||
{ |
||||
if (item == null) |
||||
throw new ArgumentNullException(nameof(item)); |
||||
|
||||
Item = item; |
||||
var list = new List<TypeReference>(); |
||||
foreach (var arg in typeArguments) { |
||||
var resolved = arg != null ? arg.Resolve() : arg; |
||||
list.Add(resolved != null ? resolved : arg); |
||||
} |
||||
TypeArguments = new ReadOnlyCollection<TypeReference>(list); |
||||
} |
||||
|
||||
private GenericContext(T item, ReadOnlyCollection<TypeReference> typeArguments) |
||||
{ |
||||
Item = item; |
||||
TypeArguments = typeArguments; |
||||
} |
||||
|
||||
public TypeReference ResolveWithContext(TypeReference type) |
||||
{ |
||||
var genericParameter = type as GenericParameter; |
||||
if (genericParameter != null) |
||||
if (genericParameter.Owner.GenericParameterType == GenericParameterType.Type) |
||||
return this.TypeArguments[genericParameter.Position]; |
||||
else |
||||
return genericParameter.Owner.GenericParameterType == GenericParameterType.Type |
||||
? UnresolvedGenericTypeParameter : UnresolvedGenericMethodParameter; |
||||
var typeSpecification = type as TypeSpecification; |
||||
if (typeSpecification != null) { |
||||
var resolvedElementType = ResolveWithContext(typeSpecification.ElementType); |
||||
return ReplaceElementType(typeSpecification, resolvedElementType); |
||||
} |
||||
return type.ResolveOrThrow(); |
||||
} |
||||
|
||||
private TypeReference ReplaceElementType(TypeSpecification ts, TypeReference newElementType) |
||||
{ |
||||
var arrayType = ts as Mono.Cecil.ArrayType; |
||||
if (arrayType != null) { |
||||
if (newElementType == arrayType.ElementType) |
||||
return arrayType; |
||||
var newArrayType = new Mono.Cecil.ArrayType(newElementType, arrayType.Rank); |
||||
for (int dimension = 0; dimension < arrayType.Rank; dimension++) |
||||
newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension]; |
||||
return newArrayType; |
||||
} |
||||
var byReferenceType = ts as Mono.Cecil.ByReferenceType; |
||||
if (byReferenceType != null) { |
||||
return new Mono.Cecil.ByReferenceType(newElementType); |
||||
} |
||||
// TODO: should we throw an exception instead calling Resolve method?
|
||||
return ts.ResolveOrThrow(); |
||||
} |
||||
|
||||
public GenericContext<T2> ApplyTo<T2>(T2 item) where T2 : class |
||||
{ |
||||
return new GenericContext<T2>(item, this.TypeArguments); |
||||
} |
||||
|
||||
private class DummyGenericParameterProvider : IGenericParameterProvider |
||||
{ |
||||
readonly Mono.Cecil.GenericParameterType type; |
||||
readonly Mono.Collections.Generic.Collection<GenericParameter> parameters; |
||||
|
||||
public DummyGenericParameterProvider(bool methodTypeParameter) |
||||
{ |
||||
type = methodTypeParameter ? Mono.Cecil.GenericParameterType.Method : |
||||
Mono.Cecil.GenericParameterType.Type; |
||||
parameters = new Mono.Collections.Generic.Collection<GenericParameter>(1); |
||||
parameters.Add(new GenericParameter(this)); |
||||
} |
||||
|
||||
public GenericParameter DummyParameter |
||||
{ |
||||
get { return parameters[0]; } |
||||
} |
||||
|
||||
bool IGenericParameterProvider.HasGenericParameters |
||||
{ |
||||
get { throw new NotImplementedException(); } |
||||
} |
||||
|
||||
bool IGenericParameterProvider.IsDefinition |
||||
{ |
||||
get { throw new NotImplementedException(); } |
||||
} |
||||
|
||||
ModuleDefinition IGenericParameterProvider.Module |
||||
{ |
||||
get { throw new NotImplementedException(); } |
||||
} |
||||
|
||||
Mono.Collections.Generic.Collection<GenericParameter> IGenericParameterProvider.GenericParameters |
||||
{ |
||||
get { return parameters; } |
||||
} |
||||
|
||||
GenericParameterType IGenericParameterProvider.GenericParameterType |
||||
{ |
||||
get { return type; } |
||||
} |
||||
|
||||
MetadataToken IMetadataTokenProvider.MetadataToken |
||||
{ |
||||
get |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
set |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,176 +0,0 @@
@@ -1,176 +0,0 @@
|
||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
using ICSharpCode.Decompiler; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.VB.Visitors; |
||||
using Mono.Cecil; |
||||
|
||||
namespace ICSharpCode.ILSpy.VB |
||||
{ |
||||
public class ILSpyEnvironmentProvider : IEnvironmentProvider |
||||
{ |
||||
public string RootNamespace { |
||||
get { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
//readonly CecilLoader loader = new CecilLoader();
|
||||
|
||||
public string GetTypeNameForAttribute(NRefactory.CSharp.Attribute attribute) |
||||
{ |
||||
return attribute.Type.Annotations |
||||
.OfType<Mono.Cecil.MemberReference>() |
||||
.First() |
||||
.FullName; |
||||
} |
||||
|
||||
public IType ResolveType(NRefactory.VB.Ast.AstType type, NRefactory.VB.Ast.TypeDeclaration entity = null) |
||||
{ |
||||
/* |
||||
var annotation = type.Annotation<TypeReference>(); |
||||
if (annotation == null ) |
||||
return null; |
||||
|
||||
IEntity current = null; |
||||
if (entity != null) { |
||||
var typeInfo = entity.Annotation<TypeReference>(); |
||||
current = loader.ReadTypeReference(typeInfo).Resolve(context).GetDefinition(); |
||||
} |
||||
|
||||
return loader.ReadTypeReference(annotation, entity: current).Resolve(context);*/ |
||||
return SpecialType.UnknownType; |
||||
} |
||||
|
||||
public TypeKind GetTypeKindForAstType(NRefactory.CSharp.AstType type) |
||||
{ |
||||
var annotation = type.Annotation<TypeReference>(); |
||||
if (annotation == null) |
||||
return TypeKind.Unknown; |
||||
|
||||
var definition = annotation.ResolveOrThrow(); |
||||
if (definition.IsClass) |
||||
return TypeKind.Class; |
||||
if (definition.IsInterface) |
||||
return TypeKind.Interface; |
||||
if (definition.IsEnum) |
||||
return TypeKind.Enum; |
||||
if (definition.IsFunctionPointer) |
||||
return TypeKind.Delegate; |
||||
if (definition.IsValueType) |
||||
return TypeKind.Struct; |
||||
|
||||
return TypeKind.Unknown; |
||||
} |
||||
|
||||
public TypeCode ResolveExpression(NRefactory.CSharp.Expression expression) |
||||
{ |
||||
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault(); |
||||
|
||||
if (annotation == null || annotation.InferredType == null) |
||||
return TypeCode.Object; |
||||
|
||||
var definition = annotation.InferredType.Resolve(); |
||||
|
||||
if (definition == null) |
||||
return TypeCode.Object; |
||||
|
||||
switch (definition.FullName) { |
||||
case "System.String": |
||||
return TypeCode.String; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
return TypeCode.Object; |
||||
} |
||||
|
||||
public bool? IsReferenceType(NRefactory.CSharp.Expression expression) |
||||
{ |
||||
if (expression is NRefactory.CSharp.NullReferenceExpression) |
||||
return true; |
||||
|
||||
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault(); |
||||
|
||||
if (annotation == null || annotation.InferredType == null) |
||||
return null; |
||||
|
||||
var definition = annotation.InferredType.Resolve(); |
||||
|
||||
if (definition == null) |
||||
return null; |
||||
|
||||
return !definition.IsValueType; |
||||
} |
||||
|
||||
public IEnumerable<NRefactory.VB.Ast.InterfaceMemberSpecifier> CreateMemberSpecifiersForInterfaces(IEnumerable<NRefactory.VB.Ast.AstType> interfaces) |
||||
{ |
||||
foreach (var type in interfaces) { |
||||
var def = type.Annotation<TypeReference>().Resolve(); |
||||
if (def == null) continue; |
||||
foreach (var method in def.Methods.Where(m => !m.Name.StartsWith("get_", StringComparison.Ordinal) && !m.Name.StartsWith("set_", StringComparison.Ordinal))) { |
||||
yield return new NRefactory.VB.Ast.InterfaceMemberSpecifier((NRefactory.VB.Ast.AstType)type.Clone(), method.Name); |
||||
} |
||||
|
||||
foreach (var property in def.Properties) { |
||||
yield return new NRefactory.VB.Ast.InterfaceMemberSpecifier((NRefactory.VB.Ast.AstType)type.Clone(), property.Name); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public bool HasEvent(NRefactory.VB.Ast.Expression expression) |
||||
{ |
||||
return expression.Annotation<EventDefinition>() != null; |
||||
} |
||||
|
||||
public bool IsMethodGroup(NRefactory.CSharp.Expression expression) |
||||
{ |
||||
var methodInfo = expression.Annotation<MethodReference>()?.Resolve(); |
||||
if (methodInfo != null) { |
||||
return !methodInfo.IsGetter && !methodInfo.IsSetter && !methodInfo.IsAddOn && !methodInfo.IsRemoveOn; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public NRefactory.CSharp.ParameterDeclaration[] GetParametersForProperty(NRefactory.CSharp.PropertyDeclaration property) |
||||
{ |
||||
var propInfo = property.Annotation<PropertyReference>(); |
||||
|
||||
if (propInfo == null) |
||||
return new NRefactory.CSharp.ParameterDeclaration[0]; |
||||
|
||||
return propInfo.Parameters.Select(p => new NRefactory.CSharp.ParameterDeclaration(AstBuilder.ConvertType(p.ParameterType), p.Name, GetModifiers(p))).ToArray(); |
||||
} |
||||
|
||||
NRefactory.CSharp.ParameterModifier GetModifiers(ParameterDefinition p) |
||||
{ |
||||
if (p.IsOut && p.IsIn) |
||||
return NRefactory.CSharp.ParameterModifier.Ref; |
||||
if (p.IsOut) |
||||
return NRefactory.CSharp.ParameterModifier.Out; |
||||
|
||||
return NRefactory.CSharp.ParameterModifier.None; |
||||
} |
||||
} |
||||
} |
||||
@ -1,448 +0,0 @@
@@ -1,448 +0,0 @@
|
||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel.Composition; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Threading.Tasks; |
||||
using System.Xml; |
||||
|
||||
using ICSharpCode.Decompiler; |
||||
using ICSharpCode.Decompiler.Ast.Transforms; |
||||
using ICSharpCode.ILSpy.XmlDoc; |
||||
using ICSharpCode.NRefactory.VB; |
||||
using ICSharpCode.NRefactory.VB.Visitors; |
||||
using Mono.Cecil; |
||||
using CSharp = ICSharpCode.NRefactory.CSharp; |
||||
|
||||
namespace ICSharpCode.ILSpy.VB |
||||
{ |
||||
/// <summary>
|
||||
/// Decompiler logic for VB.
|
||||
/// </summary>
|
||||
[Export(typeof(Language))] |
||||
public class VBLanguage : Language |
||||
{ |
||||
readonly Predicate<IAstTransform> transformAbortCondition = null; |
||||
bool showAllMembers = false; |
||||
|
||||
public VBLanguage() |
||||
{ |
||||
} |
||||
|
||||
public override string Name { |
||||
get { return "VB"; } |
||||
} |
||||
|
||||
public override string FileExtension { |
||||
get { return ".vb"; } |
||||
} |
||||
|
||||
public override string ProjectFileExtension { |
||||
get { return ".vbproj"; } |
||||
} |
||||
|
||||
public override void WriteCommentLine(ITextOutput output, string comment) |
||||
{ |
||||
output.WriteLine("' " + comment); |
||||
} |
||||
|
||||
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { |
||||
HashSet<string> directories = new HashSet<string>(StringComparer.OrdinalIgnoreCase); |
||||
var files = WriteCodeFilesInProject(assembly.ModuleDefinition, options, directories).ToList(); |
||||
files.AddRange(WriteResourceFilesInProject(assembly, options, directories)); |
||||
WriteProjectFile(new TextOutputWriter(output), files, assembly.ModuleDefinition); |
||||
} else { |
||||
base.DecompileAssembly(assembly, output, options); |
||||
output.WriteLine(); |
||||
ModuleDefinition mainModule = assembly.ModuleDefinition; |
||||
if (mainModule.Types.Count > 0) { |
||||
output.Write("' Global type: "); |
||||
output.WriteReference(mainModule.Types[0].FullName, mainModule.Types[0]); |
||||
output.WriteLine(); |
||||
} |
||||
if (mainModule.EntryPoint != null) { |
||||
output.Write("' Entry point: "); |
||||
output.WriteReference(mainModule.EntryPoint.DeclaringType.FullName + "." + mainModule.EntryPoint.Name, mainModule.EntryPoint); |
||||
output.WriteLine(); |
||||
} |
||||
WriteCommentLine(output, "Architecture: " + CSharpLanguage.GetPlatformDisplayName(mainModule)); |
||||
if ((mainModule.Attributes & ModuleAttributes.ILOnly) == 0) { |
||||
WriteCommentLine(output, "This assembly contains unmanaged code."); |
||||
} |
||||
switch (mainModule.Runtime) { |
||||
case TargetRuntime.Net_1_0: |
||||
WriteCommentLine(output, "Runtime: .NET 1.0"); |
||||
break; |
||||
case TargetRuntime.Net_1_1: |
||||
WriteCommentLine(output, "Runtime: .NET 1.1"); |
||||
break; |
||||
case TargetRuntime.Net_2_0: |
||||
WriteCommentLine(output, "Runtime: .NET 2.0"); |
||||
break; |
||||
case TargetRuntime.Net_4_0: |
||||
WriteCommentLine(output, "Runtime: .NET 4.0"); |
||||
break; |
||||
} |
||||
output.WriteLine(); |
||||
|
||||
// don't automatically load additional assemblies when an assembly node is selected in the tree view
|
||||
using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) { |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: assembly.ModuleDefinition); |
||||
codeDomBuilder.AddAssembly(assembly.ModuleDefinition, onlyAssemblyLevel: !options.FullDecompilation); |
||||
RunTransformsAndGenerateCode(codeDomBuilder, output, options, assembly.ModuleDefinition); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static readonly string[] projectImports = new[] { |
||||
"System.Diagnostics", |
||||
"Microsoft.VisualBasic", |
||||
"System", |
||||
"System.Collections", |
||||
"System.Collections.Generic" |
||||
}; |
||||
|
||||
#region WriteProjectFile
|
||||
void WriteProjectFile(TextWriter writer, IEnumerable<Tuple<string, string>> files, ModuleDefinition module) |
||||
{ |
||||
const string ns = "http://schemas.microsoft.com/developer/msbuild/2003"; |
||||
string platformName = CSharpLanguage.GetPlatformName(module); |
||||
Guid guid = App.CommandLineArguments.FixedGuid ?? Guid.NewGuid(); |
||||
using (XmlTextWriter w = new XmlTextWriter(writer)) { |
||||
w.Formatting = Formatting.Indented; |
||||
w.WriteStartDocument(); |
||||
w.WriteStartElement("Project", ns); |
||||
w.WriteAttributeString("ToolsVersion", "4.0"); |
||||
w.WriteAttributeString("DefaultTargets", "Build"); |
||||
|
||||
w.WriteStartElement("PropertyGroup"); |
||||
w.WriteElementString("ProjectGuid", guid.ToString("B").ToUpperInvariant()); |
||||
|
||||
w.WriteStartElement("Configuration"); |
||||
w.WriteAttributeString("Condition", " '$(Configuration)' == '' "); |
||||
w.WriteValue("Debug"); |
||||
w.WriteEndElement(); // </Configuration>
|
||||
|
||||
w.WriteStartElement("Platform"); |
||||
w.WriteAttributeString("Condition", " '$(Platform)' == '' "); |
||||
w.WriteValue(platformName); |
||||
w.WriteEndElement(); // </Platform>
|
||||
|
||||
switch (module.Kind) { |
||||
case ModuleKind.Windows: |
||||
w.WriteElementString("OutputType", "WinExe"); |
||||
break; |
||||
case ModuleKind.Console: |
||||
w.WriteElementString("OutputType", "Exe"); |
||||
break; |
||||
default: |
||||
w.WriteElementString("OutputType", "Library"); |
||||
break; |
||||
} |
||||
|
||||
w.WriteElementString("AssemblyName", module.Assembly.Name.Name); |
||||
bool useTargetFrameworkAttribute = false; |
||||
var targetFrameworkAttribute = module.Assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == "System.Runtime.Versioning.TargetFrameworkAttribute"); |
||||
if (targetFrameworkAttribute != null && targetFrameworkAttribute.ConstructorArguments.Any()) { |
||||
string frameworkName = (string)targetFrameworkAttribute.ConstructorArguments[0].Value; |
||||
string[] frameworkParts = frameworkName.Split(','); |
||||
string frameworkVersion = frameworkParts.FirstOrDefault(a => a.StartsWith("Version=")); |
||||
if (frameworkVersion != null) { |
||||
w.WriteElementString("TargetFrameworkVersion", frameworkVersion.Substring("Version=".Length)); |
||||
useTargetFrameworkAttribute = true; |
||||
} |
||||
string frameworkProfile = frameworkParts.FirstOrDefault(a => a.StartsWith("Profile=")); |
||||
if (frameworkProfile != null) |
||||
w.WriteElementString("TargetFrameworkProfile", frameworkProfile.Substring("Profile=".Length)); |
||||
} |
||||
if (!useTargetFrameworkAttribute) { |
||||
switch (module.Runtime) { |
||||
case TargetRuntime.Net_1_0: |
||||
w.WriteElementString("TargetFrameworkVersion", "v1.0"); |
||||
break; |
||||
case TargetRuntime.Net_1_1: |
||||
w.WriteElementString("TargetFrameworkVersion", "v1.1"); |
||||
break; |
||||
case TargetRuntime.Net_2_0: |
||||
w.WriteElementString("TargetFrameworkVersion", "v2.0"); |
||||
// TODO: Detect when .NET 3.0/3.5 is required
|
||||
break; |
||||
default: |
||||
w.WriteElementString("TargetFrameworkVersion", "v4.0"); |
||||
break; |
||||
} |
||||
} |
||||
w.WriteElementString("WarningLevel", "4"); |
||||
|
||||
w.WriteEndElement(); // </PropertyGroup>
|
||||
|
||||
w.WriteStartElement("PropertyGroup"); // platform-specific
|
||||
w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' "); |
||||
w.WriteElementString("PlatformTarget", platformName); |
||||
w.WriteEndElement(); // </PropertyGroup> (platform-specific)
|
||||
|
||||
w.WriteStartElement("PropertyGroup"); // Debug
|
||||
w.WriteAttributeString("Condition", " '$(Configuration)' == 'Debug' "); |
||||
w.WriteElementString("OutputPath", "bin\\Debug\\"); |
||||
w.WriteElementString("DebugSymbols", "true"); |
||||
w.WriteElementString("DebugType", "full"); |
||||
w.WriteElementString("Optimize", "false"); |
||||
w.WriteEndElement(); // </PropertyGroup> (Debug)
|
||||
|
||||
w.WriteStartElement("PropertyGroup"); // Release
|
||||
w.WriteAttributeString("Condition", " '$(Configuration)' == 'Release' "); |
||||
w.WriteElementString("OutputPath", "bin\\Release\\"); |
||||
w.WriteElementString("DebugSymbols", "true"); |
||||
w.WriteElementString("DebugType", "pdbonly"); |
||||
w.WriteElementString("Optimize", "true"); |
||||
w.WriteEndElement(); // </PropertyGroup> (Release)
|
||||
|
||||
|
||||
w.WriteStartElement("ItemGroup"); // References
|
||||
foreach (AssemblyNameReference r in module.AssemblyReferences) { |
||||
if (r.Name != "mscorlib") { |
||||
w.WriteStartElement("Reference"); |
||||
w.WriteAttributeString("Include", r.Name); |
||||
w.WriteEndElement(); |
||||
} |
||||
} |
||||
w.WriteEndElement(); // </ItemGroup> (References)
|
||||
|
||||
foreach (IGrouping<string, string> gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g)) { |
||||
w.WriteStartElement("ItemGroup"); |
||||
foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { |
||||
w.WriteStartElement(gr.Key); |
||||
w.WriteAttributeString("Include", file); |
||||
w.WriteEndElement(); |
||||
} |
||||
w.WriteEndElement(); |
||||
} |
||||
|
||||
w.WriteStartElement("ItemGroup"); // Imports
|
||||
foreach (var import in projectImports.OrderBy(x => x)) { |
||||
w.WriteStartElement("Import"); |
||||
w.WriteAttributeString("Include", import); |
||||
w.WriteEndElement(); |
||||
} |
||||
w.WriteEndElement(); // </ItemGroup> (Imports)
|
||||
|
||||
w.WriteStartElement("Import"); |
||||
w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.VisualBasic.targets"); |
||||
w.WriteEndElement(); |
||||
|
||||
w.WriteEndDocument(); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region WriteCodeFilesInProject
|
||||
bool IncludeTypeWhenDecompilingProject(TypeDefinition type, DecompilationOptions options) |
||||
{ |
||||
if (type.Name == "<Module>" || AstBuilder.MemberIsHidden(type, options.DecompilerSettings)) |
||||
return false; |
||||
if (type.Namespace == "XamlGeneratedNamespace" && type.Name == "GeneratedInternalTypeHelper") |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
IEnumerable<Tuple<string, string>> WriteAssemblyInfo(ModuleDefinition module, DecompilationOptions options, HashSet<string> directories) |
||||
{ |
||||
// don't automatically load additional assemblies when an assembly node is selected in the tree view
|
||||
using (LoadedAssembly.DisableAssemblyLoad()) |
||||
{ |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: module); |
||||
codeDomBuilder.AddAssembly(module, onlyAssemblyLevel: true); |
||||
codeDomBuilder.RunTransformations(transformAbortCondition); |
||||
|
||||
string prop = "Properties"; |
||||
if (directories.Add("Properties")) |
||||
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, prop)); |
||||
string assemblyInfo = Path.Combine(prop, "AssemblyInfo" + this.FileExtension); |
||||
using (StreamWriter w = new StreamWriter(Path.Combine(options.SaveAsProjectDirectory, assemblyInfo))) |
||||
codeDomBuilder.GenerateCode(new PlainTextOutput(w)); |
||||
return new Tuple<string, string>[] { Tuple.Create("Compile", assemblyInfo) }; |
||||
} |
||||
} |
||||
|
||||
IEnumerable<Tuple<string, string>> WriteCodeFilesInProject(ModuleDefinition module, DecompilationOptions options, HashSet<string> directories) |
||||
{ |
||||
var files = module.Types.Where(t => IncludeTypeWhenDecompilingProject(t, options)).GroupBy( |
||||
delegate(TypeDefinition type) { |
||||
string file = TextView.DecompilerTextView.CleanUpName(type.Name) + this.FileExtension; |
||||
if (string.IsNullOrEmpty(type.Namespace)) { |
||||
return file; |
||||
} else { |
||||
string dir = TextView.DecompilerTextView.CleanUpName(type.Namespace); |
||||
if (directories.Add(dir)) |
||||
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dir)); |
||||
return Path.Combine(dir, file); |
||||
} |
||||
}, StringComparer.OrdinalIgnoreCase).ToList(); |
||||
AstMethodBodyBuilder.ClearUnhandledOpcodes(); |
||||
Parallel.ForEach( |
||||
files, |
||||
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, |
||||
delegate(IGrouping<string, TypeDefinition> file) { |
||||
using (StreamWriter w = new StreamWriter(Path.Combine(options.SaveAsProjectDirectory, file.Key))) { |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: module); |
||||
foreach (TypeDefinition type in file) { |
||||
codeDomBuilder.AddType(type); |
||||
} |
||||
RunTransformsAndGenerateCode(codeDomBuilder, new PlainTextOutput(w), options, module); |
||||
} |
||||
}); |
||||
AstMethodBodyBuilder.PrintNumberOfUnhandledOpcodes(); |
||||
return files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(module, options, directories)); |
||||
} |
||||
#endregion
|
||||
|
||||
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true); |
||||
codeDomBuilder.AddMethod(method); |
||||
RunTransformsAndGenerateCode(codeDomBuilder, output, options, method.Module); |
||||
} |
||||
|
||||
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true)); |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType, isSingleMember: true); |
||||
codeDomBuilder.AddProperty(property); |
||||
RunTransformsAndGenerateCode(codeDomBuilder, output, options, property.Module); |
||||
} |
||||
|
||||
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true)); |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: field.DeclaringType, isSingleMember: true); |
||||
codeDomBuilder.AddField(field); |
||||
RunTransformsAndGenerateCode(codeDomBuilder, output, options, field.Module); |
||||
} |
||||
|
||||
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true)); |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: ev.DeclaringType, isSingleMember: true); |
||||
codeDomBuilder.AddEvent(ev); |
||||
RunTransformsAndGenerateCode(codeDomBuilder, output, options, ev.Module); |
||||
} |
||||
|
||||
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: type.Module); |
||||
codeDomBuilder.AddType(type); |
||||
RunTransformsAndGenerateCode(codeDomBuilder, output, options, type.Module); |
||||
} |
||||
|
||||
public override bool ShowMember(MemberReference member) |
||||
{ |
||||
return showAllMembers || !AstBuilder.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings); |
||||
} |
||||
|
||||
void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options, ModuleDefinition module) |
||||
{ |
||||
astBuilder.RunTransformations(transformAbortCondition); |
||||
if (options.DecompilerSettings.ShowXmlDocumentation) { |
||||
try { |
||||
AddXmlDocTransform.Run(astBuilder.SyntaxTree); |
||||
} catch (XmlException ex) { |
||||
string[] msg = (" Exception while reading XmlDoc: " + ex.ToString()).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); |
||||
var insertionPoint = astBuilder.SyntaxTree.FirstChild; |
||||
for (int i = 0; i < msg.Length; i++) |
||||
astBuilder.SyntaxTree.InsertChildBefore(insertionPoint, new CSharp.Comment(msg[i], CSharp.CommentType.Documentation), CSharp.Roles.Comment); |
||||
} |
||||
} |
||||
var csharpUnit = astBuilder.SyntaxTree; |
||||
csharpUnit.AcceptVisitor(new NRefactory.CSharp.InsertParenthesesVisitor() { InsertParenthesesForReadability = true }); |
||||
var unit = csharpUnit.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider()), null); |
||||
var outputFormatter = new VBTextOutputFormatter(output); |
||||
var formattingPolicy = new VBFormattingOptions(); |
||||
unit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null); |
||||
} |
||||
|
||||
AstBuilder CreateAstBuilder(DecompilationOptions options, ModuleDefinition currentModule = null, TypeDefinition currentType = null, bool isSingleMember = false) |
||||
{ |
||||
if (currentModule == null) |
||||
currentModule = currentType.Module; |
||||
DecompilerSettings settings = options.DecompilerSettings; |
||||
settings = settings.Clone(); |
||||
if (isSingleMember) |
||||
settings.UsingDeclarations = false; |
||||
settings.IntroduceIncrementAndDecrement = false; |
||||
settings.MakeAssignmentExpressions = false; |
||||
settings.QueryExpressions = false; |
||||
settings.AlwaysGenerateExceptionVariableForCatchBlocks = true; |
||||
return new AstBuilder( |
||||
new DecompilerContext(currentModule) { |
||||
CancellationToken = options.CancellationToken, |
||||
CurrentType = currentType, |
||||
Settings = settings |
||||
}); |
||||
} |
||||
|
||||
public override string FormatMethodName(MethodDefinition method) |
||||
{ |
||||
if (method == null) |
||||
throw new ArgumentNullException("method"); |
||||
|
||||
return (method.IsConstructor) ? method.DeclaringType.Name : method.Name; |
||||
} |
||||
|
||||
public override string FormatTypeName(TypeDefinition type) |
||||
{ |
||||
if (type == null) |
||||
throw new ArgumentNullException("type"); |
||||
|
||||
return TypeToString(ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions, type); |
||||
} |
||||
|
||||
public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null) |
||||
{ |
||||
ConvertTypeOptions options = ConvertTypeOptions.IncludeTypeParameterDefinitions; |
||||
if (includeNamespace) |
||||
options |= ConvertTypeOptions.IncludeNamespace; |
||||
|
||||
return TypeToString(options, type, typeAttributes); |
||||
} |
||||
|
||||
string TypeToString(ConvertTypeOptions options, TypeReference type, ICustomAttributeProvider typeAttributes = null) |
||||
{ |
||||
var envProvider = new ILSpyEnvironmentProvider(); |
||||
var converter = new CSharpToVBConverterVisitor(envProvider); |
||||
var astType = AstBuilder.ConvertType(type, typeAttributes, options); |
||||
StringWriter w = new StringWriter(); |
||||
|
||||
if (type.IsByReference) { |
||||
w.Write("ByRef "); |
||||
if (astType is NRefactory.CSharp.ComposedType && ((NRefactory.CSharp.ComposedType)astType).PointerRank > 0) |
||||
((NRefactory.CSharp.ComposedType)astType).PointerRank--; |
||||
} |
||||
|
||||
var vbAstType = astType.AcceptVisitor(converter, null); |
||||
|
||||
vbAstType.AcceptVisitor(new OutputVisitor(w, new VBFormattingOptions()), null); |
||||
return w.ToString(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,254 +0,0 @@
@@ -1,254 +0,0 @@
|
||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Decompiler; |
||||
using ICSharpCode.Decompiler.ILAst; |
||||
using ICSharpCode.NRefactory.VB; |
||||
using ICSharpCode.NRefactory.VB.Ast; |
||||
using Mono.Cecil; |
||||
|
||||
namespace ICSharpCode.ILSpy.VB |
||||
{ |
||||
/// <summary>
|
||||
/// Description of VBTextOutputFormatter.
|
||||
/// </summary>
|
||||
public class VBTextOutputFormatter : IOutputFormatter |
||||
{ |
||||
readonly ITextOutput output; |
||||
readonly Stack<AstNode> nodeStack = new Stack<AstNode>(); |
||||
|
||||
bool firstImport, lastImport; |
||||
|
||||
public VBTextOutputFormatter(ITextOutput output) |
||||
{ |
||||
if (output == null) |
||||
throw new ArgumentNullException("output"); |
||||
this.output = output; |
||||
} |
||||
|
||||
public void StartNode(AstNode node) |
||||
{ |
||||
// var ranges = node.Annotation<List<ILRange>>();
|
||||
// if (ranges != null && ranges.Count > 0)
|
||||
// {
|
||||
// // find the ancestor that has method mapping as annotation
|
||||
// if (node.Ancestors != null && node.Ancestors.Count() > 0)
|
||||
// {
|
||||
// var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
|
||||
// if (n != null) {
|
||||
// MemberMapping mapping = n.Annotation<MemberMapping>();
|
||||
//
|
||||
// // add all ranges
|
||||
// foreach (var range in ranges) {
|
||||
// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
|
||||
// ILInstructionOffset = range,
|
||||
// SourceCodeLine = output.CurrentLine,
|
||||
// MemberMapping = mapping
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (nodeStack.Count == 0) { |
||||
if (node is ImportsStatement) { |
||||
firstImport = !(node.PrevSibling is ImportsStatement); |
||||
lastImport = !(node.NextSibling is ImportsStatement); |
||||
} else { |
||||
firstImport = false; |
||||
lastImport = false; |
||||
} |
||||
} |
||||
nodeStack.Push(node); |
||||
} |
||||
|
||||
public void EndNode(AstNode node) |
||||
{ |
||||
if (nodeStack.Pop() != node) |
||||
throw new InvalidOperationException(); |
||||
} |
||||
|
||||
public void WriteIdentifier(string identifier) |
||||
{ |
||||
var definition = GetCurrentDefinition(); |
||||
if (definition != null) { |
||||
output.WriteDefinition(identifier, definition); |
||||
return; |
||||
} |
||||
|
||||
object memberRef = GetCurrentMemberReference(); |
||||
if (memberRef != null) { |
||||
output.WriteReference(identifier, memberRef); |
||||
return; |
||||
} |
||||
|
||||
definition = GetCurrentLocalDefinition(); |
||||
if (definition != null) { |
||||
output.WriteDefinition(identifier, definition); |
||||
return; |
||||
} |
||||
|
||||
memberRef = GetCurrentLocalReference(); |
||||
if (memberRef != null) { |
||||
output.WriteReference(identifier, memberRef, true); |
||||
return; |
||||
} |
||||
|
||||
if (firstImport) { |
||||
output.MarkFoldStart(defaultCollapsed: true); |
||||
firstImport = false; |
||||
} |
||||
|
||||
output.Write(identifier); |
||||
} |
||||
|
||||
MemberReference GetCurrentMemberReference() |
||||
{ |
||||
AstNode node = nodeStack.Peek(); |
||||
MemberReference memberRef = node.Annotation<MemberReference>(); |
||||
if (memberRef == null && node.Role == AstNode.Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreationExpression)) { |
||||
memberRef = node.Parent.Annotation<MemberReference>(); |
||||
} |
||||
return memberRef; |
||||
} |
||||
|
||||
object GetCurrentLocalReference() |
||||
{ |
||||
AstNode node = nodeStack.Peek(); |
||||
ILVariable variable = node.Annotation<ILVariable>(); |
||||
if (variable != null) { |
||||
if (variable.OriginalParameter != null) |
||||
return variable.OriginalParameter; |
||||
//if (variable.OriginalVariable != null)
|
||||
// return variable.OriginalVariable;
|
||||
return variable; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
object GetCurrentLocalDefinition() |
||||
{ |
||||
AstNode node = nodeStack.Peek(); |
||||
var parameterDef = node.Annotation<ParameterDefinition>(); |
||||
if (parameterDef != null) |
||||
return parameterDef; |
||||
|
||||
if (node is VariableInitializer || node is CatchBlock || node is ForEachStatement) { |
||||
var variable = node.Annotation<ILVariable>(); |
||||
if (variable != null) { |
||||
if (variable.OriginalParameter != null) |
||||
return variable.OriginalParameter; |
||||
//if (variable.OriginalVariable != null)
|
||||
// return variable.OriginalVariable;
|
||||
return variable; |
||||
} else { |
||||
|
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
object GetCurrentDefinition() |
||||
{ |
||||
if (nodeStack == null || nodeStack.Count == 0) |
||||
return null; |
||||
|
||||
var node = nodeStack.Peek(); |
||||
if (IsDefinition(node)) |
||||
return node.Annotation<MemberReference>(); |
||||
|
||||
node = node.Parent; |
||||
if (IsDefinition(node)) |
||||
return node.Annotation<MemberReference>(); |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public void WriteKeyword(string keyword) |
||||
{ |
||||
output.Write(keyword); |
||||
} |
||||
|
||||
public void WriteToken(string token) |
||||
{ |
||||
// Attach member reference to token only if there's no identifier in the current node.
|
||||
MemberReference memberRef = GetCurrentMemberReference(); |
||||
if (memberRef != null && nodeStack.Peek().GetChildByRole(AstNode.Roles.Identifier).IsNull) |
||||
output.WriteReference(token, memberRef); |
||||
else |
||||
output.Write(token); |
||||
} |
||||
|
||||
public void Space() |
||||
{ |
||||
output.Write(' '); |
||||
} |
||||
|
||||
public void Indent() |
||||
{ |
||||
output.Indent(); |
||||
} |
||||
|
||||
public void Unindent() |
||||
{ |
||||
output.Unindent(); |
||||
} |
||||
|
||||
public void NewLine() |
||||
{ |
||||
if (lastImport) { |
||||
output.MarkFoldEnd(); |
||||
lastImport = false; |
||||
} |
||||
output.WriteLine(); |
||||
} |
||||
|
||||
public void WriteComment(bool isDocumentation, string content) |
||||
{ |
||||
if (isDocumentation) |
||||
output.Write("'''"); |
||||
else |
||||
output.Write("'"); |
||||
output.WriteLine(content); |
||||
} |
||||
|
||||
public void MarkFoldStart() |
||||
{ |
||||
output.MarkFoldStart(); |
||||
} |
||||
|
||||
public void MarkFoldEnd() |
||||
{ |
||||
output.MarkFoldEnd(); |
||||
} |
||||
|
||||
private static bool IsDefinition(AstNode node) |
||||
{ |
||||
return |
||||
node is FieldDeclaration || |
||||
node is ConstructorDeclaration || |
||||
node is EventDeclaration || |
||||
node is DelegateDeclaration || |
||||
node is OperatorDeclaration|| |
||||
node is MemberDeclaration || |
||||
node is TypeDeclaration; |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue