2
// ImplementAbstractMembersAction.cs
5
// Mike Krüger <mkrueger@xamarin.com>
7
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
using ICSharpCode.NRefactory.TypeSystem;
28
using System.Threading;
29
using System.Collections.Generic;
32
namespace ICSharpCode.NRefactory.CSharp.Refactoring
34
[ContextAction("Implement abstract members", Description = "Implements abstract members from an abstract class.")]
35
public class ImplementAbstractMembersAction : ICodeActionProvider
37
public IEnumerable<CodeAction> GetActions(RefactoringContext context)
39
var type = context.GetNode<AstType>();
40
if (type == null || type.Role != Roles.BaseType)
42
var state = context.GetResolverStateBefore(type);
43
if (state.CurrentTypeDefinition == null)
46
var resolveResult = context.Resolve(type);
47
if (resolveResult.Type.Kind != TypeKind.Class || resolveResult.Type.GetDefinition() == null || !resolveResult.Type.GetDefinition().IsAbstract)
50
var toImplement = CollectMembersToImplement(state.CurrentTypeDefinition, resolveResult.Type);
51
if (toImplement.Count == 0)
54
yield return new CodeAction(context.TranslateString("Implement abstract members"), script => {
55
script.InsertWithCursor(
56
context.TranslateString("Implement abstract members"),
57
state.CurrentTypeDefinition,
58
ImplementInterfaceAction.GenerateImplementation (context, toImplement.Select (m => Tuple.Create (m, false))).Select (entity => {
59
var decl = entity as EntityDeclaration;
61
decl.Modifiers |= Modifiers.Override;
68
public static List<IMember> CollectMembersToImplement(ITypeDefinition implementingType, IType abstractType)
70
// var def = abstractType.GetDefinition();
71
var toImplement = new List<IMember>();
72
bool alreadyImplemented;
74
// Stub out non-implemented events defined by @iface
75
foreach (var ev in abstractType.GetEvents (e => !e.IsSynthetic && e.IsAbstract)) {
76
alreadyImplemented = implementingType.GetAllBaseTypeDefinitions().Any(
77
x => x.Kind != TypeKind.Interface && x.Events.Any (y => y.Name == ev.Name)
80
if (!alreadyImplemented)
84
// Stub out non-implemented methods defined by @iface
85
foreach (var method in abstractType.GetMethods (d => !d.IsSynthetic && d.IsAbstract)) {
86
alreadyImplemented = false;
88
foreach (var cmet in implementingType.GetMethods ()) {
89
if (!cmet.IsAbstract && ImplementInterfaceAction.CompareMethods(method, cmet)) {
90
alreadyImplemented = true;
93
if (!alreadyImplemented)
94
toImplement.Add(method);
97
// Stub out non-implemented properties defined by @iface
98
foreach (var prop in abstractType.GetProperties (p => !p.IsSynthetic && p.IsAbstract)) {
99
alreadyImplemented = false;
100
foreach (var t in implementingType.GetAllBaseTypeDefinitions ()) {
101
if (t.Kind == TypeKind.Interface)
103
foreach (IProperty cprop in t.Properties) {
104
if (!cprop.IsAbstract && cprop.Name == prop.Name) {
105
alreadyImplemented = true;
109
if (!alreadyImplemented)
110
toImplement.Add(prop);