~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractFieldAction.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
// ExtractFieldAction.cs
 
3
//  
 
4
// Author:
 
5
//       Nieve <>
 
6
// 
 
7
// Copyright (c) 2012 Nieve
 
8
// 
 
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:
 
15
// 
 
16
// The above copyright notice and this permission notice shall be included in
 
17
// all copies or substantial portions of the Software.
 
18
// 
 
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
 
25
// THE SOFTWARE.
 
26
using System;
 
27
using System.Collections.Generic;
 
28
using System.Linq;
 
29
using ICSharpCode.NRefactory.PatternMatching;
 
30
using Mono.CSharp;
 
31
using ICSharpCode.NRefactory.TypeSystem;
 
32
 
 
33
namespace ICSharpCode.NRefactory.CSharp.Refactoring
 
34
{
 
35
        [ContextAction("Extract field", Description = "Extracts a field from a local variable declaration.")]
 
36
        public class ExtractFieldAction : ICodeActionProvider
 
37
        {
 
38
                static readonly AstType varType = new SimpleType ("var");
 
39
 
 
40
                public IEnumerable<CodeAction> GetActions(RefactoringContext context)
 
41
                {
 
42
                        //TODO: implement variable assignment & ctor param
 
43
                        var varInit = context.GetNode<VariableInitializer>();
 
44
                        if (varInit != null) {
 
45
                                AstType type = varInit.GetPrevNode() as AstType;
 
46
                                if (type == null) yield break;
 
47
                                if (varInit.Parent is FieldDeclaration) yield break;
 
48
                                if (CannotExtractField(context, varInit)) yield break;
 
49
                                
 
50
                                yield return new CodeAction(context.TranslateString("Assign to new field"), s=>{
 
51
                                        var name = varInit.Name;
 
52
 
 
53
                                        AstType extractedType;
 
54
                                        if (type.IsMatch (varType)) {
 
55
                                                IType resolvedType = context.Resolve(varInit.Initializer).Type;
 
56
                                                extractedType = context.CreateShortType(resolvedType);
 
57
                                        }
 
58
                                        else {
 
59
                                                extractedType = (AstType) type.Clone();
 
60
                                        }
 
61
 
 
62
                                        AstNode entityDeclarationNode = varInit.Parent;
 
63
                                        while (!(entityDeclarationNode is EntityDeclaration) || (entityDeclarationNode is Accessor)) {
 
64
                                                entityDeclarationNode = entityDeclarationNode.Parent;
 
65
                                        }
 
66
                                        var entity = (EntityDeclaration) entityDeclarationNode;
 
67
                                        bool isStatic = entity.HasModifier(Modifiers.Static);
 
68
 
 
69
                                        FieldDeclaration field = new FieldDeclaration(){
 
70
                                                Modifiers = isStatic ? Modifiers.Static : Modifiers.None,
 
71
                                                ReturnType = extractedType,
 
72
                                                Variables = { new VariableInitializer(name) }
 
73
                                        };
 
74
                                        AstNode nodeToRemove = RemoveDeclaration(varInit) ? varInit.Parent : type;
 
75
                                        s.Remove(nodeToRemove, true);
 
76
                                        s.InsertWithCursor(context.TranslateString("Insert new field"),Script.InsertPosition.Before,field);
 
77
                                        s.FormatText(varInit.Parent);
 
78
                                }, varInit);
 
79
                        }
 
80
                        
 
81
                        var idntf = context.GetNode<Identifier>();
 
82
                        if (idntf == null) yield break;
 
83
                        var paramDec = idntf.Parent as ParameterDeclaration;
 
84
                        if (paramDec != null) {
 
85
                                var ctor = paramDec.Parent as ConstructorDeclaration;
 
86
                                if (ctor == null) yield break;
 
87
                                MemberReferenceExpression thisField = new MemberReferenceExpression(new ThisReferenceExpression(), idntf.Name, new AstType[]{});
 
88
                                var assign = new AssignmentExpression(thisField, AssignmentOperatorType.Assign, new IdentifierExpression(idntf.Name));
 
89
                                var statement = new ExpressionStatement(assign);
 
90
                                var type = (idntf.GetPrevNode() as AstType).Clone();
 
91
                                FieldDeclaration field = new FieldDeclaration(){
 
92
                                        ReturnType = type.Clone(),
 
93
                                        Variables = { new VariableInitializer(idntf.Name) }
 
94
                                };
 
95
                                yield return new CodeAction(context.TranslateString("Assign to new field"), s=>{
 
96
                                        s.InsertWithCursor(context.TranslateString("Insert new field"),Script.InsertPosition.Before,field);
 
97
                                        s.AddTo(ctor.Body, statement);
 
98
                                }, paramDec);
 
99
                        }
 
100
                }
 
101
                
 
102
                static bool RemoveDeclaration (VariableInitializer varInit){
 
103
                        var result = varInit.Parent as VariableDeclarationStatement;
 
104
                        return result.Variables.First ().Initializer.IsNull;
 
105
                }
 
106
                
 
107
                static bool CannotExtractField (RefactoringContext context, VariableInitializer varInit)
 
108
                {
 
109
                        var result = varInit.Parent as VariableDeclarationStatement;
 
110
                        return result == null || result.Variables.Count != 1 || ContainsAnonymousType(context.Resolve(varInit.Initializer).Type);
 
111
                }
 
112
 
 
113
                static bool ContainsAnonymousType (IType type)
 
114
                {
 
115
                        if (type.Kind == TypeKind.Anonymous)
 
116
                                return true;
 
117
 
 
118
                        var arrayType = type as ArrayType;
 
119
                        return arrayType != null && ContainsAnonymousType (arrayType.ElementType);
 
120
                }
 
121
        }
 
122
}
 
123