Browse Source

Simplify ImplementInterfaceAction by using the TypeSystemAstBuilder.

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
56114fe865
  1. 195
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs
  2. 23
      ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs
  3. 68
      ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs

195
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs

@ -1,4 +1,4 @@
// //
// ImplementInterfaceAction.cs // ImplementInterfaceAction.cs
// //
// Author: // Author:
@ -68,7 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
foreach (var member in toImplement) { foreach (var member in toImplement) {
if (!nodes.ContainsKey(member.Item1.DeclaringType)) if (!nodes.ContainsKey(member.Item1.DeclaringType))
nodes [member.Item1.DeclaringType] = new List<AstNode>(); nodes [member.Item1.DeclaringType] = new List<AstNode>();
nodes [member.Item1.DeclaringType].Add(GenerateMemberImplementation(context, member)); nodes [member.Item1.DeclaringType].Add(GenerateMemberImplementation(context, member.Item1, member.Item2));
} }
foreach (var kv in nodes) { foreach (var kv in nodes) {
@ -89,188 +89,21 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
} }
static AstNode GenerateMemberImplementation(RefactoringContext context, Tuple<IMember, bool> member) static EntityDeclaration GenerateMemberImplementation(RefactoringContext context, IMember member, bool explicitImplementation)
{
switch (member.Item1.EntityType) {
case EntityType.Property:
return GenerateProperty(context, (IProperty)member.Item1, member.Item2);
case EntityType.Indexer:
return GenerateIndexer(context, (IProperty)member.Item1, member.Item2);
case EntityType.Event:
return GenerateEvent(context, (IEvent)member.Item1, member.Item2);
case EntityType.Method:
return GenerateMethod(context, (IMethod)member.Item1, member.Item2);
default:
throw new ArgumentOutOfRangeException();
}
}
static AstNode GenerateEvent(RefactoringContext context, IEvent evt, bool explicitImplementation)
{ {
if (!explicitImplementation) { var builder = context.CreateTypeSytemAstBuilder();
return new EventDeclaration() { builder.GenerateBody = true;
Modifiers = Modifiers.Public, builder.ShowConstantValues = !explicitImplementation;
Name = evt.Name, builder.ShowTypeParameterConstraints = !explicitImplementation;
ReturnType = context.CreateShortType (evt.ReturnType) builder.UseCustomEvents = explicitImplementation;
}; var decl = builder.ConvertEntity(member);
} if (explicitImplementation) {
return new CustomEventDeclaration() { decl.Modifiers = Modifiers.None;
Name = evt.Name, decl.AddChild(builder.ConvertType(member.DeclaringType), EntityDeclaration.PrivateImplementationTypeRole);
ReturnType = context.CreateShortType (evt.ReturnType),
PrivateImplementationType = context.CreateShortType(evt.DeclaringType),
AddAccessor = new Accessor {
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
},
RemoveAccessor = new Accessor {
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
}
};
}
static AstNode GenerateProperty(RefactoringContext context, IProperty property, bool explicitImplementation)
{
var result = new PropertyDeclaration() {
Name = property.Name,
ReturnType = context.CreateShortType (property.ReturnType)
};
if (!explicitImplementation) {
result.Modifiers = Modifiers.Public;
} else {
result.PrivateImplementationType = context.CreateShortType(property.DeclaringType);
}
if (property.CanGet) {
if (property.DeclaringType.Kind != TypeKind.Interface) {
result.Getter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
} else {
result.Getter = new Accessor();
}
}
if (property.CanSet) {
if (property.DeclaringType.Kind != TypeKind.Interface) {
result.Setter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
} else {
result.Setter = new Accessor();
}
}
return result;
}
static AstNode GenerateIndexer(RefactoringContext context, IProperty indexer, bool explicitImplementation)
{
var result = new IndexerDeclaration() {
ReturnType = context.CreateShortType (indexer.ReturnType)
};
if (!explicitImplementation) {
result.Modifiers = Modifiers.Public;
} else { } else {
result.PrivateImplementationType = context.CreateShortType(indexer.DeclaringType); decl.Modifiers = Modifiers.Public;
} }
return decl;
foreach (var p in indexer.Parameters) {
ParameterModifier modifier;
if (p.IsOut) {
modifier = ParameterModifier.Out;
} else if (p.IsRef) {
modifier = ParameterModifier.Ref;
} else if (p.IsParams) {
modifier = ParameterModifier.Params;
} else {
modifier = ParameterModifier.None;
}
result.Parameters.Add(new ParameterDeclaration(context.CreateShortType(p.Type), p.Name, modifier));
}
if (indexer.CanGet) {
result.Getter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
}
if (indexer.CanSet) {
result.Setter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
}
return result;
}
static AstNode GenerateMethod(RefactoringContext context, IMethod method, bool explicitImplementation)
{
var result = new MethodDeclaration() {
Name = method.Name,
ReturnType = context.CreateShortType (method.ReturnType),
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
if (!explicitImplementation) {
result.Modifiers = Modifiers.Public;
} else {
result.PrivateImplementationType = context.CreateShortType(method.DeclaringType);
}
foreach (var typeParam in method.TypeParameters) {
result.TypeParameters.Add(new TypeParameterDeclaration(typeParam.Name));
var constraint = new Constraint() {
TypeParameter = new SimpleType(typeParam.Name)
};
if (typeParam.HasDefaultConstructorConstraint) {
constraint.BaseTypes.Add(new PrimitiveType("new"));
} else if (typeParam.HasReferenceTypeConstraint) {
constraint.BaseTypes.Add(new PrimitiveType("class"));
} else if (typeParam.HasValueTypeConstraint) {
constraint.BaseTypes.Add(new PrimitiveType("struct"));
}
foreach (var type in typeParam.DirectBaseTypes) {
if (type.FullName == "System.Object")
continue;
if (type.FullName == "System.ValueType")
continue;
constraint.BaseTypes.Add(context.CreateShortType(type));
}
if (constraint.BaseTypes.Count == 0)
continue;
result.Constraints.Add(constraint);
}
foreach (var p in method.Parameters) {
ParameterModifier modifier;
if (p.IsOut) {
modifier = ParameterModifier.Out;
} else if (p.IsRef) {
modifier = ParameterModifier.Ref;
} else if (p.IsParams) {
modifier = ParameterModifier.Params;
} else {
modifier = ParameterModifier.None;
}
result.Parameters.Add(new ParameterDeclaration(context.CreateShortType(p.Type), p.Name, modifier));
}
return result;
} }
public static List<Tuple<IMember, bool>> CollectMembersToImplement(ITypeDefinition implementingType, IType interfaceType, bool explicitly) public static List<Tuple<IMember, bool>> CollectMembersToImplement(ITypeDefinition implementingType, IType interfaceType, bool explicitly)

23
ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs

@ -44,24 +44,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
public abstract TextLocation Location { get; } public abstract TextLocation Location { get; }
public virtual AstType CreateShortType (IType fullType) public TypeSystemAstBuilder CreateTypeSytemAstBuilder()
{ {
var csResolver = Resolver.GetResolverStateBefore(GetNode()); var csResolver = Resolver.GetResolverStateBefore(GetNode());
var builder = new TypeSystemAstBuilder(csResolver); return new TypeSystemAstBuilder(csResolver);
}
public virtual AstType CreateShortType (IType fullType)
{
var builder = CreateTypeSytemAstBuilder();
return builder.ConvertType(fullType); return builder.ConvertType(fullType);
} }
public AstType CreateShortType(string ns, string name, int typeParameterCount = 0) public virtual AstType CreateShortType(string ns, string name, int typeParameterCount = 0)
{ {
foreach (var asm in Compilation.Assemblies) { var builder = CreateTypeSytemAstBuilder();
var def = asm.GetTypeDefinition(ns, name, typeParameterCount); return builder.ConvertType(ns, name, typeParameterCount);
if (def != null) {
return CreateShortType(def);
}
}
return new MemberType(new SimpleType(ns), name);
} }
public virtual IEnumerable<AstNode> GetSelectedNodes() public virtual IEnumerable<AstNode> GetSelectedNodes()

68
ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -111,6 +111,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// The default value is <c>false</c>. /// The default value is <c>false</c>.
/// </summary> /// </summary>
public bool AlwaysUseShortTypeNames { get; set; } public bool AlwaysUseShortTypeNames { get; set; }
/// <summary>
/// Controls whether to generate a body that throws a <c>System.NotImplementedException</c>.
/// The default value is <c>false</c>.
/// </summary>
public bool GenerateBody { get; set; }
/// <summary>
/// Controls whether to generate custom events.
/// The default value is <c>false</c>.
/// </summary>
public bool UseCustomEvents { get; set; }
#endregion #endregion
#region Convert Type #region Convert Type
@ -124,6 +136,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return astType; return astType;
} }
public AstType ConvertType(string ns, string name, int typeParameterCount = 0)
{
if (resolver != null) {
foreach (var asm in resolver.Compilation.Assemblies) {
var def = asm.GetTypeDefinition(ns, name, typeParameterCount);
if (def != null) {
return ConvertType(def);
}
}
}
return new MemberType(new SimpleType(ns), name);
}
AstType ConvertTypeHelper(IType type) AstType ConvertTypeHelper(IType type)
{ {
TypeWithElementType typeWithElementType = type as TypeWithElementType; TypeWithElementType typeWithElementType = type as TypeWithElementType;
@ -557,12 +582,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return decl; return decl;
} }
BlockStatement GenerateBodyBlock()
{
if (GenerateBody) {
return new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(ConvertType("System", "NotImplementedException")))
};
} else {
return BlockStatement.Null;
}
}
Accessor ConvertAccessor(IMethod accessor) Accessor ConvertAccessor(IMethod accessor)
{ {
if (accessor == null) if (accessor == null)
return Accessor.Null; return Accessor.Null;
Accessor decl = new Accessor(); Accessor decl = new Accessor();
decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility); decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility);
decl.Body = GenerateBodyBlock();
return decl; return decl;
} }
@ -590,13 +627,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return decl; return decl;
} }
EventDeclaration ConvertEvent(IEvent ev) EntityDeclaration ConvertEvent(IEvent ev)
{ {
EventDeclaration decl = new EventDeclaration(); if (this.UseCustomEvents) {
decl.Modifiers = GetMemberModifiers(ev); CustomEventDeclaration decl = new CustomEventDeclaration();
decl.ReturnType = ConvertType(ev.ReturnType); decl.Modifiers = GetMemberModifiers(ev);
decl.Variables.Add(new VariableInitializer(ev.Name)); decl.ReturnType = ConvertType(ev.ReturnType);
return decl; decl.Name = ev.Name;
decl.AddAccessor = ConvertAccessor(ev.AddAccessor);
decl.RemoveAccessor = ConvertAccessor(ev.RemoveAccessor);
return decl;
} else {
EventDeclaration decl = new EventDeclaration();
decl.Modifiers = GetMemberModifiers(ev);
decl.ReturnType = ConvertType(ev.ReturnType);
decl.Variables.Add(new VariableInitializer(ev.Name));
return decl;
}
} }
MethodDeclaration ConvertMethod(IMethod method) MethodDeclaration ConvertMethod(IMethod method)
@ -625,6 +672,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
decl.Constraints.Add(constraint); decl.Constraints.Add(constraint);
} }
} }
decl.Body = GenerateBodyBlock();
return decl; return decl;
} }
@ -641,6 +689,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
foreach (IParameter p in op.Parameters) { foreach (IParameter p in op.Parameters) {
decl.Parameters.Add(ConvertParameter(p)); decl.Parameters.Add(ConvertParameter(p));
} }
decl.Body = GenerateBodyBlock();
return decl; return decl;
} }
@ -652,6 +701,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
foreach (IParameter p in ctor.Parameters) { foreach (IParameter p in ctor.Parameters) {
decl.Parameters.Add(ConvertParameter(p)); decl.Parameters.Add(ConvertParameter(p));
} }
decl.Body = GenerateBodyBlock();
return decl; return decl;
} }
@ -659,6 +709,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
DestructorDeclaration decl = new DestructorDeclaration(); DestructorDeclaration decl = new DestructorDeclaration();
decl.Name = dtor.DeclaringTypeDefinition.Name; decl.Name = dtor.DeclaringTypeDefinition.Name;
decl.Body = GenerateBodyBlock();
return decl; return decl;
} }
#endregion #endregion
@ -687,12 +738,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Modifiers GetMemberModifiers(IMember member) Modifiers GetMemberModifiers(IMember member)
{ {
Modifiers m = ModifierFromAccessibility(member.Accessibility); bool isInterfaceMember = member.DeclaringType.Kind == TypeKind.Interface;
Modifiers m = isInterfaceMember ? Modifiers.None : ModifierFromAccessibility(member.Accessibility);
if (this.ShowModifiers) { if (this.ShowModifiers) {
if (member.IsStatic) { if (member.IsStatic) {
m |= Modifiers.Static; m |= Modifiers.Static;
} else { } else {
if (member.IsAbstract) if (member.IsAbstract && !isInterfaceMember)
m |= Modifiers.Abstract; m |= Modifiers.Abstract;
if (member.IsOverride) if (member.IsOverride)
m |= Modifiers.Override; m |= Modifiers.Override;

Loading…
Cancel
Save