Browse Source

use Is/IsNot for reference equality checks; add extension attribute for extension methods

pull/254/head
Siegfried Pammer 14 years ago
parent
commit
eb7948af70
  1. 89
      ILSpy/VB/ILSpyEnvironmentProvider.cs
  2. 38
      ILSpy/VB/VBLanguage.cs
  3. 4
      NRefactory/ICSharpCode.NRefactory.VB/Ast/Identifier.cs
  4. 19
      NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs
  5. 90
      NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs

89
ILSpy/VB/ILSpyEnvironmentProvider.cs

@ -17,8 +17,11 @@ @@ -17,8 +17,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.VB.Visitors;
using Mono.Cecil;
@ -33,6 +36,21 @@ namespace ICSharpCode.ILSpy.VB @@ -33,6 +36,21 @@ namespace ICSharpCode.ILSpy.VB
}
}
ITypeResolveContext context;
CecilLoader loader = new CecilLoader(false);
public ILSpyEnvironmentProvider(ITypeResolveContext context)
{
this.context = context;
}
public ITypeResolveContext ResolveContext {
get {
return context;
}
}
public string GetTypeNameForAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute)
{
return attribute.Type.Annotations
@ -41,6 +59,21 @@ namespace ICSharpCode.ILSpy.VB @@ -41,6 +59,21 @@ namespace ICSharpCode.ILSpy.VB
.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);
}
public ClassType GetClassTypeForAstType(ICSharpCode.NRefactory.CSharp.AstType type)
{
var definition = type.Annotations.OfType<TypeReference>().First().ResolveOrThrow();
@ -59,9 +92,61 @@ namespace ICSharpCode.ILSpy.VB @@ -59,9 +92,61 @@ namespace ICSharpCode.ILSpy.VB
return ClassType.Module;
}
public IType ResolveExpression(ICSharpCode.NRefactory.CSharp.Expression expression)
public TypeCode ResolveExpression(ICSharpCode.NRefactory.CSharp.Expression expression)
{
throw new NotImplementedException();
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
if (annotation == 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 Nullable<bool> IsReferenceType(ICSharpCode.NRefactory.CSharp.Expression expression)
{
if (expression is ICSharpCode.NRefactory.CSharp.NullReferenceExpression)
return true;
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
if (annotation == 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_") && !m.Name.StartsWith("set_"))) {
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);
}
}
}
}
}

38
ILSpy/VB/VBLanguage.cs

@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.Ast; @@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.VB;
using ICSharpCode.NRefactory.VB.Visitors;
using Mono.Cecil;
@ -121,7 +122,7 @@ namespace ICSharpCode.ILSpy.VB @@ -121,7 +122,7 @@ namespace ICSharpCode.ILSpy.VB
using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) {
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: assembly.AssemblyDefinition.MainModule);
codeDomBuilder.AddAssembly(assembly.AssemblyDefinition, onlyAssemblyLevel: !options.FullDecompilation);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, assembly.AssemblyDefinition.MainModule);
}
}
OnDecompilationFinished(null);
@ -303,7 +304,7 @@ namespace ICSharpCode.ILSpy.VB @@ -303,7 +304,7 @@ namespace ICSharpCode.ILSpy.VB
foreach (TypeDefinition type in file) {
codeDomBuilder.AddType(type);
}
RunTransformsAndGenerateCode(codeDomBuilder, new PlainTextOutput(w), options);
RunTransformsAndGenerateCode(codeDomBuilder, new PlainTextOutput(w), options, assembly.MainModule);
}
});
AstMethodBodyBuilder.PrintNumberOfUnhandledOpcodes();
@ -394,7 +395,7 @@ namespace ICSharpCode.ILSpy.VB @@ -394,7 +395,7 @@ namespace ICSharpCode.ILSpy.VB
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true);
codeDomBuilder.AddMethod(method);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, method.Module);
}
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
@ -402,7 +403,7 @@ namespace ICSharpCode.ILSpy.VB @@ -402,7 +403,7 @@ namespace ICSharpCode.ILSpy.VB
WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType, isSingleMember: true);
codeDomBuilder.AddProperty(property);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, property.Module);
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
@ -410,7 +411,7 @@ namespace ICSharpCode.ILSpy.VB @@ -410,7 +411,7 @@ namespace ICSharpCode.ILSpy.VB
WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: field.DeclaringType, isSingleMember: true);
codeDomBuilder.AddField(field);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, field.Module);
}
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
@ -418,14 +419,14 @@ namespace ICSharpCode.ILSpy.VB @@ -418,14 +419,14 @@ namespace ICSharpCode.ILSpy.VB
WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: ev.DeclaringType, isSingleMember: true);
codeDomBuilder.AddEvent(ev);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, ev.Module);
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
codeDomBuilder.AddType(type);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, type.Module);
}
public override bool ShowMember(MemberReference member)
@ -433,12 +434,12 @@ namespace ICSharpCode.ILSpy.VB @@ -433,12 +434,12 @@ namespace ICSharpCode.ILSpy.VB
return showAllMembers || !AstBuilder.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings);
}
void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options)
void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options, ModuleDefinition module)
{
astBuilder.RunTransformations(transformAbortCondition);
if (options.DecompilerSettings.ShowXmlDocumentation)
AddXmlDocTransform.Run(astBuilder.CompilationUnit);
var unit = astBuilder.CompilationUnit.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider()), null);
var unit = astBuilder.CompilationUnit.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider(CreateResolveContext(module))), null);
var outputFormatter = new VBTextOutputFormatter(output);
var formattingPolicy = new VBFormattingOptions();
unit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null);
@ -480,11 +481,28 @@ namespace ICSharpCode.ILSpy.VB @@ -480,11 +481,28 @@ namespace ICSharpCode.ILSpy.VB
return TypeToString(options, type, typeAttributes);
}
ITypeResolveContext CreateResolveContext(ModuleDefinition module)
{
IProjectContent projectContent = new CecilTypeResolveContext(module);
List<ITypeResolveContext> resolveContexts = new List<ITypeResolveContext>();
resolveContexts.Add(projectContent);
foreach (AssemblyNameReference r in module.AssemblyReferences) {
AssemblyDefinition d = module.AssemblyResolver.Resolve(r);
if (d != null) {
resolveContexts.Add(new CecilTypeResolveContext(d.MainModule));
}
}
return new CompositeTypeResolveContext(resolveContexts);
}
string TypeToString(ConvertTypeOptions options, TypeReference type, ICustomAttributeProvider typeAttributes = null)
{
var astType = AstBuilder
.ConvertType(type, typeAttributes, options)
.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider()), null);
.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider(CreateResolveContext(type.Resolve().Module))), null);
StringWriter w = new StringWriter();
// TODO
// if (type.IsByReference) {

4
NRefactory/ICSharpCode.NRefactory.VB/Ast/Identifier.cs

@ -89,8 +89,8 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -89,8 +89,8 @@ namespace ICSharpCode.NRefactory.VB.Ast
public override string ToString()
{
return string.Format("[Identifier Name={0}, StartLocation={1}, TypeCharacter{4}]",
name, startLocation, TypeCharacter);
return string.Format("{0}",
name);
}
}
}

19
NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.VB.Ast
{
@ -70,6 +71,24 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -70,6 +71,24 @@ namespace ICSharpCode.NRefactory.VB.Ast
return new ComposedType { BaseType = this }.MakeArrayType(rank);
}
public static AstType FromName(string fullName)
{
if (string.IsNullOrEmpty(fullName))
throw new ArgumentNullException("fullName");
fullName = fullName.Trim();
if (!fullName.Contains("."))
return new SimpleType(fullName);
string[] parts = fullName.Split('.');
AstType type = new SimpleType(parts.First());
foreach (var part in parts.Skip(1)) {
type = new QualifiedType(type, part);
}
return type;
}
/// <summary>
/// Builds an expression that can be used to access a static member on this type.
/// </summary>

90
NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs

@ -16,7 +16,10 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -16,7 +16,10 @@ namespace ICSharpCode.NRefactory.VB.Visitors
string RootNamespace { get; }
string GetTypeNameForAttribute(CSharp.Attribute attribute);
ClassType GetClassTypeForAstType(CSharp.AstType type);
IType ResolveExpression(CSharp.Expression expression);
TypeCode ResolveExpression(CSharp.Expression expression);
bool? IsReferenceType(CSharp.Expression expression);
ITypeResolveContext ResolveContext { get; }
IType ResolveType(AstType type, TypeDeclaration entity = null);
}
/// <summary>
@ -177,8 +180,6 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -177,8 +180,6 @@ namespace ICSharpCode.NRefactory.VB.Visitors
var op = BinaryOperatorType.None;
var right = (Expression)binaryOperatorExpression.Right.AcceptVisitor(this, data);
// TODO obj <> Nothing is wrong; correct would be obj IsNot Nothing
switch (binaryOperatorExpression.Operator) {
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseAnd:
op = BinaryOperatorType.BitwiseAnd;
@ -202,10 +203,16 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -202,10 +203,16 @@ namespace ICSharpCode.NRefactory.VB.Visitors
op = BinaryOperatorType.GreaterThanOrEqual;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Equality:
op = BinaryOperatorType.Equality;
if (IsReferentialEquality(binaryOperatorExpression))
op = BinaryOperatorType.ReferenceEquality;
else
op = BinaryOperatorType.Equality;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.InEquality:
op = BinaryOperatorType.InEquality;
if (IsReferentialEquality(binaryOperatorExpression))
op = BinaryOperatorType.ReferenceInequality;
else
op = BinaryOperatorType.InEquality;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThan:
op = BinaryOperatorType.LessThan;
@ -248,6 +255,17 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -248,6 +255,17 @@ namespace ICSharpCode.NRefactory.VB.Visitors
return EndNode(binaryOperatorExpression, new BinaryOperatorExpression(left, op, right));
}
bool IsReferentialEquality(CSharp.BinaryOperatorExpression binaryOperatorExpression)
{
var left = provider.IsReferenceType(binaryOperatorExpression.Left);
var right = provider.IsReferenceType(binaryOperatorExpression.Right);
var leftCode = provider.ResolveExpression(binaryOperatorExpression.Left);
var rightCode = provider.ResolveExpression(binaryOperatorExpression.Right);
return (left == true || right == true) && (leftCode != TypeCode.String && rightCode != TypeCode.String);
}
public AstNode VisitCastExpression(CSharp.CastExpression castExpression, object data)
{
var expr = new CastExpression();
@ -806,6 +824,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -806,6 +824,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
if (typeDeclaration.ClassType == ClassType.Enum) {
var type = new EnumDeclaration();
CopyAnnotations(typeDeclaration, type);
ConvertNodes(typeDeclaration.Attributes, type.Attributes);
ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens);
@ -823,6 +842,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -823,6 +842,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
return EndNode(typeDeclaration, type);
} else {
var type = new TypeDeclaration();
CopyAnnotations(typeDeclaration, type);
CSharp.Attribute stdModAttr;
@ -1417,6 +1437,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1417,6 +1437,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors
result.Name = evt.Name;
result.ReturnType = (AstType)eventDeclaration.ReturnType.AcceptVisitor(this, data);
// CreateImplementsClausesForEvent(result);
types.Peek().Members.Add(result);
}
@ -1441,7 +1463,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1441,7 +1463,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors
if (!customEventDeclaration.PrivateImplementationType.IsNull)
result.ImplementsClause.Add(
new InterfaceMemberSpecifier((AstType)customEventDeclaration.PrivateImplementationType.AcceptVisitor(this, data), customEventDeclaration.Name));
// else
// CreateImplementsClausesForEvent(result);
result.AddHandlerBlock = (Accessor)customEventDeclaration.AddAccessor.AcceptVisitor(this, data);
result.RemoveHandlerBlock = (Accessor)customEventDeclaration.RemoveAccessor.AcceptVisitor(this, data);
@ -1553,9 +1576,22 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1553,9 +1576,22 @@ namespace ICSharpCode.NRefactory.VB.Visitors
result.ImplementsClause.Add(
new InterfaceMemberSpecifier((AstType)methodDeclaration.PrivateImplementationType.AcceptVisitor(this, data),
methodDeclaration.Name));
// else
// CreateImplementsClausesForMethod(result);
if (!result.IsSub)
result.ReturnType = (AstType)methodDeclaration.ReturnType.AcceptVisitor(this, data);
if (methodDeclaration.IsExtensionMethod) {
result.Attributes.Add(
new AttributeBlock {
Attributes = {
new Ast.Attribute {
Type = AstType.FromName("System.Runtime.CompilerServices.ExtensionAttribute")
}
}
});
}
result.Body = (BlockStatement)methodDeclaration.Body.AcceptVisitor(this, data);
if (members.Pop().inIterator) {
@ -1566,6 +1602,38 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1566,6 +1602,38 @@ namespace ICSharpCode.NRefactory.VB.Visitors
}
}
void CreateImplementsClausesForMethod(MethodDeclaration result)
{
if (!types.Any()) return;
var current = types.Peek();
if (current.ClassType == ClassType.Interface)
return;
foreach (var type in current.ImplementsTypes) {
var resolved = provider.ResolveType(type, current);
var found = resolved.GetMembers(provider.ResolveContext, m => m.EntityType == EntityType.Method && m.Name == result.Name.Name);
if (found.FirstOrDefault() != null) {
result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name));
}
}
}
void CreateImplementsClausesForEvent(EventDeclaration result)
{
if (!types.Any()) return;
var current = types.Peek();
if (current.ClassType == ClassType.Interface)
return;
foreach (var type in current.ImplementsTypes) {
var resolved = provider.ResolveType(type, current);
var found = resolved.GetMembers(provider.ResolveContext, m => m.EntityType == EntityType.Event && m.Name == result.Name.Name);
if (found.FirstOrDefault() != null) {
result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name));
}
}
}
string ConvertAlias(CSharp.AstNodeCollection<CSharp.Expression> arguments)
{
var pattern = new CSharp.AssignmentExpression() {
@ -2106,8 +2174,18 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -2106,8 +2174,18 @@ namespace ICSharpCode.NRefactory.VB.Visitors
T EndNode<T>(CSharp.AstNode node, T result) where T : VB.AstNode
{
if (result != null) {
CopyAnnotations(node, result);
}
return result;
}
void CopyAnnotations<T>(CSharp.AstNode node, T result) where T : VB.AstNode
{
foreach (var ann in node.Annotations)
result.AddAnnotation(ann);
}
bool HasAttribute(CSharp.AstNodeCollection<CSharp.AttributeSection> attributes, string name, out CSharp.Attribute foundAttribute)
{

Loading…
Cancel
Save