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

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.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:
38
38
using System.IO;
39
39
using MonoDevelop.CSharp.Formatting;
40
40
using MonoDevelop.Ide;
 
41
using System.Threading.Tasks;
 
42
using MonoDevelop.Core.ProgressMonitoring;
 
43
using MonoDevelop.Ide.FindInFiles;
 
44
using MonoDevelop.Projects;
 
45
using ICSharpCode.NRefactory.CSharp.TypeSystem;
 
46
using MonoDevelop.Ide.Gui.Content;
41
47
 
42
48
namespace MonoDevelop.CSharp.Refactoring.CodeActions
43
49
{
44
50
        public class MDRefactoringScript : DocumentScript
45
51
        {
46
52
                readonly MDRefactoringContext context;
47
 
                readonly Document document;
48
53
                readonly IDisposable undoGroup;
 
54
                readonly ICSharpCode.NRefactory.Editor.ITextSourceVersion startVersion;
 
55
                int operationsRunning = 0;
49
56
 
50
 
                public MDRefactoringScript (MDRefactoringContext context, Document document, CSharpFormattingOptions formattingOptions) : base(document.Editor.Document, formattingOptions, document.Editor.CreateNRefactoryTextEditorOptions ())
 
57
                public MDRefactoringScript (MDRefactoringContext context, CSharpFormattingOptions formattingOptions) : base(context.TextEditor.Document, formattingOptions, context.TextEditor.CreateNRefactoryTextEditorOptions ())
51
58
                {
52
59
                        this.context = context;
53
 
                        this.document = document;
54
 
                        undoGroup  = this.document.Editor.OpenUndoGroup ();
 
60
                        undoGroup  = this.context.TextEditor.OpenUndoGroup ();
 
61
                        this.startVersion = this.context.TextEditor.Version;
 
62
 
 
63
                }
 
64
 
 
65
                void Rollback ()
 
66
                {
 
67
                        DisposeOnClose (true);
 
68
                        foreach (var ver in this.context.TextEditor.Version.GetChangesTo (this.startVersion)) {
 
69
                                context.TextEditor.Document.Replace (ver.Offset, ver.RemovalLength, ver.InsertedText.Text);
 
70
                        }
55
71
                }
56
72
 
57
73
                public override void Select (AstNode node)
58
74
                {
59
 
                        document.Editor.SelectionRange = new TextSegment (GetSegment (node));
 
75
                        context.TextEditor.SelectionRange = new TextSegment (GetSegment (node));
60
76
                }
61
77
 
62
 
                public override void InsertWithCursor (string operation, InsertPosition defaultPosition, IEnumerable<AstNode> nodes)
 
78
                public override Task InsertWithCursor (string operation, InsertPosition defaultPosition, IEnumerable<AstNode> nodes)
63
79
                {
64
 
                        var editor = document.Editor;
65
 
                        DocumentLocation loc = document.Editor.Caret.Location;
66
 
                        var declaringType = document.ParsedDocument.GetInnermostTypeDefinition (loc);
 
80
                        var tcs = new TaskCompletionSource<object> ();
 
81
                        var editor = context.TextEditor;
 
82
                        DocumentLocation loc = context.TextEditor.Caret.Location;
 
83
                        var declaringType = context.ParsedDocument.GetInnermostTypeDefinition (loc);
67
84
                        var mode = new InsertionCursorEditMode (
68
85
                                editor.Parent,
69
 
                                CodeGenerationService.GetInsertionPoints (document, declaringType));
 
86
                                CodeGenerationService.GetInsertionPoints (context.TextEditor, context.ParsedDocument, declaringType));
70
87
                        if (mode.InsertionPoints.Count == 0) {
71
88
                                MessageService.ShowError (
72
89
                                        GettextCatalog.GetString ("No valid insertion point can be found in type '{0}'.", declaringType.Name)
73
90
                                );
74
 
                                return;
 
91
                                return tcs.Task;
75
92
                        }
76
93
                        var helpWindow = new Mono.TextEditor.PopupWindow.InsertionCursorLayoutModeHelpWindow ();
77
94
                        helpWindow.TransientFor = MonoDevelop.Ide.IdeApp.Workbench.RootWindow;
78
95
                        helpWindow.TitleText = operation;
 
96
                        helpWindow.Shown += (s, a) => DesktopService.RemoveWindowShadow (helpWindow);
79
97
                        mode.HelpWindow = helpWindow;
80
98
                        
81
99
                        switch (defaultPosition) {
100
118
                                }
101
119
                                break;
102
120
                        }
103
 
                        
 
121
                        operationsRunning++;
104
122
                        mode.StartMode ();
 
123
                        DesktopService.RemoveWindowShadow (helpWindow);
105
124
                        mode.Exited += delegate(object s, InsertionCursorEventArgs iCArgs) {
106
125
                                if (iCArgs.Success) {
107
 
                                        foreach (var node in nodes) {
 
126
                                        if (iCArgs.InsertionPoint.LineAfter == NewLineInsertion.None && 
 
127
                                            iCArgs.InsertionPoint.LineBefore == NewLineInsertion.None && nodes.Count () > 1) {
 
128
                                                iCArgs.InsertionPoint.LineAfter = NewLineInsertion.BlankLine;
 
129
                                        }
 
130
                                        foreach (var node in nodes.Reverse ()) {
108
131
                                                var output = OutputNode (CodeGenerationService.CalculateBodyIndentLevel (declaringType), node);
109
 
                                                output.RegisterTrackedSegments (this, document.Editor.LocationToOffset (iCArgs.InsertionPoint.Location));
110
 
                                                iCArgs.InsertionPoint.Insert (editor, output.Text);
 
132
                                                var offset = context.TextEditor.LocationToOffset (iCArgs.InsertionPoint.Location);
 
133
                                                var delta = iCArgs.InsertionPoint.Insert (editor, output.Text);
 
134
                                                output.RegisterTrackedSegments (this, delta + offset);
111
135
                                        }
 
136
                                        tcs.SetResult (null);
 
137
                                } else {
 
138
                                        Rollback ();
112
139
                                }
 
140
                                DisposeOnClose (); 
113
141
                        };
 
142
                        return tcs.Task;
114
143
                }
115
144
 
116
 
                public override void InsertWithCursor (string operation, ITypeDefinition parentType, IEnumerable<AstNode> nodes)
 
145
                public override Task InsertWithCursor (string operation, ITypeDefinition parentType, IEnumerable<AstNode> nodes)
117
146
                {
 
147
                        var tcs = new TaskCompletionSource<object>();
 
148
                        if (parentType == null)
 
149
                                return tcs.Task;
118
150
                        var part = parentType.Parts.FirstOrDefault ();
119
151
                        if (part == null)
120
 
                                return;
 
152
                                return tcs.Task;
121
153
 
122
154
                        var loadedDocument = Ide.IdeApp.Workbench.OpenDocument (part.Region.FileName);
123
 
 
124
155
                        loadedDocument.RunWhenLoaded (delegate {
125
156
                                var editor = loadedDocument.Editor;
126
157
                                var loc = part.Region.Begin;
135
166
                                        );
136
167
                                        return;
137
168
                                }
 
169
                                if (declaringType.Kind == TypeKind.Enum) {
 
170
                                        foreach (var node in nodes.Reverse ()) {
 
171
                                                var output = OutputNode (CodeGenerationService.CalculateBodyIndentLevel (declaringType), node);
 
172
                                                var point = mode.InsertionPoints.First ();
 
173
                                                var offset = loadedDocument.Editor.LocationToOffset (point.Location);
 
174
                                                var text = output.Text + ",";
 
175
                                                var delta = point.Insert (editor, text);
 
176
                                                output.RegisterTrackedSegments (this, delta + offset);
 
177
                                        }
 
178
                                        tcs.SetResult (null);
 
179
                                        return;
 
180
                                }
 
181
 
 
182
 
138
183
                                var helpWindow = new Mono.TextEditor.PopupWindow.InsertionCursorLayoutModeHelpWindow ();
139
184
                                helpWindow.TransientFor = MonoDevelop.Ide.IdeApp.Workbench.RootWindow;
140
185
                                helpWindow.TitleText = operation;
 
186
                                helpWindow.Shown += (s, a) => DesktopService.RemoveWindowShadow (helpWindow);
141
187
                                mode.HelpWindow = helpWindow;
142
188
                                
143
189
                                mode.CurIndex = 0;
144
 
 
 
190
                                operationsRunning++;
145
191
                                mode.StartMode ();
146
192
                                mode.Exited += delegate(object s, InsertionCursorEventArgs iCArgs) {
147
193
                                        if (iCArgs.Success) {
148
 
                                                foreach (var node in nodes) {
 
194
                                                if (iCArgs.InsertionPoint.LineAfter == NewLineInsertion.None && 
 
195
                                                    iCArgs.InsertionPoint.LineBefore == NewLineInsertion.None && nodes.Count () > 1) {
 
196
                                                        iCArgs.InsertionPoint.LineAfter = NewLineInsertion.BlankLine;
 
197
                                                }
 
198
                                                foreach (var node in nodes.Reverse ()) {
149
199
                                                        var output = OutputNode (CodeGenerationService.CalculateBodyIndentLevel (declaringType), node);
150
 
                                                        output.RegisterTrackedSegments (this, loadedDocument.Editor.LocationToOffset (iCArgs.InsertionPoint.Location));
151
 
                                                        iCArgs.InsertionPoint.Insert (editor, output.Text);
 
200
                                                        var offset = loadedDocument.Editor.LocationToOffset (iCArgs.InsertionPoint.Location);
 
201
                                                        var text = output.Text;
 
202
                                                        var delta = iCArgs.InsertionPoint.Insert (editor, text);
 
203
                                                        output.RegisterTrackedSegments (this, delta + offset);
152
204
                                                }
 
205
                                                tcs.SetResult (null);
 
206
                                        } else {
 
207
                                                Rollback ();
153
208
                                        }
 
209
                                        DisposeOnClose (); 
154
210
                                };
155
211
                        });
 
212
                
 
213
                        return tcs.Task;
156
214
                }
157
215
 
158
 
                public override void Link (params AstNode[] nodes)
 
216
                public override Task Link (params AstNode[] nodes)
159
217
                {
 
218
                        var tcs = new TaskCompletionSource<object> ();
160
219
                        var segments = new List<TextSegment> (nodes.Select (node => new TextSegment (GetSegment (node))).OrderBy (s => s.Offset));
161
 
 
 
220
                        
162
221
                        var link = new TextLink ("name");
163
222
                        segments.ForEach (s => link.AddLink (s));
164
223
                        var links = new List<TextLink> ();
165
224
                        links.Add (link);
166
 
                        var tle = new TextLinkEditMode (document.Editor.Parent, 0, links);
 
225
                        var tle = new TextLinkEditMode (context.TextEditor.Parent, 0, links);
167
226
                        tle.SetCaretPosition = false;
168
227
                        if (tle.ShouldStartTextLinkMode) {
169
 
                                document.Editor.Caret.Offset = segments [0].EndOffset;
170
 
                                tle.OldMode = document.Editor.CurrentMode;
 
228
                                operationsRunning++;
 
229
                                context.TextEditor.Caret.Offset = segments [0].EndOffset;
 
230
                                tle.OldMode = context.TextEditor.CurrentMode;
 
231
                                tle.Cancel += (sender, e) => Rollback ();
 
232
                                tle.Exited += (sender, e) => DisposeOnClose (); 
171
233
                                tle.StartMode ();
172
 
                                document.Editor.CurrentMode = tle;
 
234
                                context.TextEditor.CurrentMode = tle;
 
235
                                if (IdeApp.Workbench.ActiveDocument != null)
 
236
                                        IdeApp.Workbench.ActiveDocument.ReparseDocument ();
 
237
                        }
 
238
                        return tcs.Task;
 
239
                }
 
240
 
 
241
                bool isDisposed = false;
 
242
                void DisposeOnClose (bool force = false)
 
243
                {
 
244
                        if (isDisposed)
 
245
                                return;
 
246
                        if (force)
 
247
                                operationsRunning = 0;
 
248
                        if (operationsRunning-- == 0) {
 
249
                                isDisposed = true;
 
250
                                undoGroup.Dispose ();
 
251
                                base.Dispose ();
173
252
                        }
174
253
                }
175
254
                
176
255
                public override void Dispose ()
177
256
                {
178
 
                        undoGroup.Dispose ();
179
 
                        base.Dispose ();
 
257
                        DisposeOnClose ();
180
258
                }
181
259
 
182
260
                public override void Rename (IEntity entity, string name)
189
267
                        RenameRefactoring.RenameVariable (variable, name);
190
268
                }
191
269
 
 
270
                public override void Rename (INamespace ns, string name)
 
271
                {
 
272
                        RenameRefactoring.RenameNamespace (ns, name);
 
273
                }
 
274
 
192
275
                public override void RenameTypeParameter (IType typeParameter, string name = null)
193
276
                {
194
277
                        RenameRefactoring.RenameTypeParameter ((ITypeParameter)typeParameter, name);
195
278
                }
196
279
 
 
280
                public override void DoGlobalOperationOn (IEntity entity, Action<RefactoringContext, Script, AstNode> callback, string operationName = null)
 
281
                {
 
282
                        using (var monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (operationName ?? GettextCatalog.GetString ("Performing refactoring task..."), null)) {
 
283
                                var col = ReferenceFinder.FindReferences (entity, true, monitor);
 
284
 
 
285
                                string oldFileName = null;
 
286
                                MDRefactoringContext ctx = null;
 
287
                                MDRefactoringScript script = null;
 
288
                                TextEditorData data = null;
 
289
                                bool hadBom = false;
 
290
                                System.Text.Encoding encoding = null;
 
291
                                bool isOpen = true;
 
292
 
 
293
                                foreach (var r in col) {
 
294
                                        var memberRef = r as CSharpReferenceFinder.CSharpMemberReference;
 
295
                                        if (memberRef == null)
 
296
                                                continue;
 
297
 
 
298
                                        if (oldFileName != memberRef.FileName) {
 
299
                                                if (oldFileName != null && !isOpen) {
 
300
                                                        script.Dispose ();
 
301
                                                        Mono.TextEditor.Utils.TextFileUtility.WriteText (oldFileName, data.Text, encoding, hadBom);
 
302
                                                }
 
303
 
 
304
                                                data = TextFileProvider.Instance.GetTextEditorData (memberRef.FileName, out hadBom, out encoding, out isOpen);
 
305
                                                var project = memberRef.Project;
 
306
 
 
307
                                                ParsedDocument parsedDocument;
 
308
                                                using (var reader = new StreamReader (data.OpenStream ()))
 
309
                                                        parsedDocument = new MonoDevelop.CSharp.Parser.TypeSystemParser ().Parse (true, memberRef.FileName, reader, project);
 
310
                                                var resolver = new CSharpAstResolver (TypeSystemService.GetCompilation (project), memberRef.SyntaxTree, parsedDocument.ParsedFile as CSharpUnresolvedFile);
 
311
 
 
312
                                                ctx = new MDRefactoringContext (project as DotNetProject, data, parsedDocument, resolver, memberRef.AstNode.StartLocation, this.context.CancellationToken);
 
313
                                                script = new MDRefactoringScript (ctx, FormattingOptions);
 
314
                                                oldFileName = memberRef.FileName;
 
315
                                        }
 
316
 
 
317
                                        callback (ctx, script, memberRef.AstNode);
 
318
                                }
 
319
 
 
320
                                if (oldFileName != null && !isOpen) {
 
321
                                        script.Dispose ();
 
322
                                        Mono.TextEditor.Utils.TextFileUtility.WriteText (oldFileName, data.Text, encoding, hadBom);
 
323
                                }
 
324
                        }
 
325
                }
 
326
 
197
327
                public override void CreateNewType (AstNode newType, NewTypeContext ntctx)
198
328
                {
199
329
                        if (newType == null)
200
330
                                throw new System.ArgumentNullException ("newType");
201
331
                        var correctFileName = MoveTypeToFile.GetCorrectFileName (context, (EntityDeclaration)newType);
202
332
                        
203
 
                        var content = context.Document.Editor.Text;
 
333
                        var content = context.TextEditor.Text;
204
334
                        
205
 
                        var types = new List<TypeDeclaration> (context.Unit.GetTypes ());
 
335
                        var types = new List<EntityDeclaration> (context.Unit.GetTypes ());
206
336
                        types.Sort ((x, y) => y.StartLocation.CompareTo (x.StartLocation));
207
337
 
208
338
                        foreach (var removeType in types) {
212
342
                        }
213
343
                        
214
344
                        var insertLocation = types.Count > 0 ? context.GetOffset (types.Last ().StartLocation) : -1;
215
 
                        var formattingPolicy = this.document.GetFormattingPolicy ();
216
345
                        if (insertLocation < 0 || insertLocation > content.Length)
217
346
                                insertLocation = content.Length;
218
 
                        content = content.Substring (0, insertLocation) + newType.GetText (formattingPolicy.CreateOptions ()) + content.Substring (insertLocation);
219
 
 
220
 
                        var formatter = new CSharpFormatter ();
221
 
                        content = formatter.FormatText (formattingPolicy, null, CSharpFormatter.MimeType, content, 0, content.Length);
 
347
                        content = content.Substring (0, insertLocation) + newType.ToString (FormattingOptions) + content.Substring (insertLocation);
 
348
 
 
349
                        var formatter = new MonoDevelop.CSharp.Formatting.CSharpFormatter ();
 
350
                        var policy = context.Project.Policies.Get<CSharpFormattingPolicy> ();
 
351
                        var textPolicy = context.Project.Policies.Get<TextStylePolicy> ();
 
352
 
 
353
                        content = formatter.FormatText (policy, textPolicy, MonoDevelop.CSharp.Formatting.CSharpFormatter.MimeType, content, 0, content.Length);
222
354
 
223
355
                        File.WriteAllText (correctFileName, content);
224
 
                        document.Project.AddFile (correctFileName);
225
 
                        MonoDevelop.Ide.IdeApp.ProjectOperations.Save (document.Project);
226
 
                        MonoDevelop.Ide.IdeApp.Workbench.OpenDocument (correctFileName);
 
356
                        context.Project.AddFile (correctFileName);
 
357
                        IdeApp.ProjectOperations.Save (context.Project);
 
358
                        IdeApp.Workbench.OpenDocument (correctFileName);
227
359
                }
228
360
 
229
361
        }